program ztest_bcalv_edit_03.
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
* Purpose:
* ~~~~~~~~
* In this example the user may change values of fields
* SEATSOCC (occupied seats) and/or PLANETYPE. The report checks
* the input value(s) semantically and provides protocol
* messages in case of error.
*-----------------------------------------------------------------
* To check program behavior
* ~~~~~~~~~~~~~~~~~~~~~~~~~
* Change values of the column "occupied seats" or "Planetype" or
* both (in the same line). Try to provocate errors.
* Click on the check symbol or press return to initiate checking.
* (ALV also checks input before any functions like sorting,
* filtering or doubleclick are processed. These functions are
* only active if the input does not contain any errors).
* The ALV Grid Control first checks if the input is correct
* according to DDIC-Information (Type, lenght). Then semantic
* checks are made by the application using event handler method
* HANDLE_DATA_CHANGED.
*-----------------------------------------------------------------
* Essential steps (search for '§')
* ~~~~~~~~~~~~~~~
* 1.Set status of columns PLANETYPE and SEATSOCC to editable.
* 2.Optionally restrict generic functions to 'change only'.
* (The user shall not be able to add new lines).
* 3.Optionally register ENTER to raise event DATA_CHANGED.
* (Per default the user may check data by using the check icon).
* 4.Define and implement event handler to handle event DATA_CHANGED.
* 5.Loop over table MT_GOOD_CELLS to check all values that are
* valid due to checks according to information of the DDIC.
* 6.Within a check cycle:
* 6a.Get new cell value to check it using method GET_CELL_VALUE.
* (In this case SEATSOCC).
* 6b.If the value is valid you may want to change values of
* other cells.
* 6c.If the value is not valid create an protocol entry in
* the application log.
* 6d.To access old values (which where not changed in this check cycle)
* use your output table GT_OUTTAB.
* 7.Display application log if an error has occured.
*-----------------------------------------------------------------------
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
data: ok_code like sy-ucomm,
save_ok like sy-ucomm,
g_container type scrfname value 'BCALV_GRID_DEMO_0100_CONT1',
g_grid type ref to cl_gui_alv_grid,
g_custom_container type ref to cl_gui_custom_container,
gt_fieldcat type lvc_t_fcat,
gs_layout type lvc_s_layo,
g_max type i value 100.
* local class to handle semantic checks
class lcl_event_receiver definition deferred.
data: g_event_receiver type ref to lcl_event_receiver.
data: gt_outtab type table of sflight.
**************************************************************
* LOCAL CLASS Definition
**************************************************************
*§4.Define and implement event handler to handle event DATA_CHANGED.
*
class lcl_event_receiver definition.
public section.
methods:
handle_data_changed
for event data_changed of cl_gui_alv_grid
importing er_data_changed.
private section.
* This flag is set if any error occured in one of the
* following methods:
data: error_in_data type c.
* Methods to modularize event handler method HANDLE_DATA_CHANGED:
methods: check_planetype
importing
ps_good_planetype type lvc_s_modi
pr_data_changed type ref to cl_alv_changed_data_protocol.
methods: ch_new_plane_v_new_seatsocc
importing
psg_plane type lvc_s_modi
psg_socc type lvc_s_modi
ps_saplane type saplane
pr_data_changed type ref to cl_alv_changed_data_protocol.
methods: ch_new_plane_v_old_seatsocc
importing
psg_plane type lvc_s_modi
ps_saplane type saplane
pr_data_changed type ref to cl_alv_changed_data_protocol.
methods: check_seatsocc
importing
ps_good type lvc_s_modi
pr_data_changed type ref to cl_alv_changed_data_protocol.
*....................................................................
* This is a suggestion how you could comment your checks in each method:
*.....
* CHECK: fieldname(old/new value) !<comp> fieldname(old/new value)
* IF NOT: (What to tell the user is wrong about the input)
*......
* Remarks:
* fieldname: fieldname of table for the corresponding column
* (old/new value): ckeck with value of GT_OUTTAB or MT_GOOD_CELLS.
* !<comp> : the value is valid if the condition <comp> holds.
*
* Example:
* CHECK seatsocc(new) !>= seatsmax(old)
* IF NOT: There are not enough number of seats according to this
* planetype.
*.......................................................................
endclass.
*---------------------------------------------------------
class lcl_event_receiver implementation.
method handle_data_changed.
BREAK-POINT.
data: ls_good type lvc_s_modi.
error_in_data = space.
* semantic checks
* Identify columns which were changed and check input
* against output table gt_outtab or other new input values of one row.
* Table er_data_changed->mt_good_cells holds all cells that
* are valid according to checks against their DDIC data.
* No matter in which order the input was made this table is
* ordered by rows (row_id). For each row, the entries are
* sorted by columns according to their order in the fieldcatalog
* (not the defined order using field COL_POS but the order
* given by the position of the record in the fieldcatalog).
* The order is relevant if new inputs in several columns of
* the same row are dependent. In this example,
* method 'ch_new_plane_v_new_seatsocc' needs only to be called
* once since we know that the corresponding check is already done
* when checking column PLANETYPE (see also method 'check_seatsocc').
*§5.Loop over table MT_GOOD_CELLS to check all values that are
* valid due to checks according to information of the DDIC.
loop at er_data_changed->mt_good_cells into ls_good.
case ls_good-fieldname.
* check if column PLANETYPE of this row was changed
when 'PLANETYPE'.
call method check_planetype
exporting
ps_good_planetype = ls_good
pr_data_changed = er_data_changed.
* check if column SEATSOCC of this row was changed
when 'SEATSOCC'.
call method check_seatsocc
exporting
ps_good = ls_good
pr_data_changed = er_data_changed.
endcase.
endloop.
*§7.Display application log if an error has occured.
if error_in_data eq 'X'.
call method er_data_changed->display_protocol.
endif.
endmethod.
*--------------------------------------------------------------------
method check_planetype.
*..................................................
* Overview of checks according to field PLANETYPE
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* a) Does the Planetype exists? (check against check table SAPLANE)
* b) Are the number of seats (SEATSMAX) of the new planetype
* sufficient to fullfill requested bookings (SEATSOCC)?
* b1) SEATSOCC (occupied seats) also changed within
* this check cycle.
* b2) SEATSOCC has not changed within this cycle.
*
*...................................................
data: l_planetype type s_planetye,
ls_saplane type saplane,
ls_good_seatsocc type lvc_s_modi.
* Get new cell value to check it.
* (In this case: PLANETYPE).
call method pr_data_changed->get_cell_value
exporting i_row_id = ps_good_planetype-row_id
i_fieldname = ps_good_planetype-fieldname
importing e_value = l_planetype.
* existence check: Does the plane exists?
select single * from saplane into ls_saplane where
planetype = l_planetype.
if sy-subrc ne 0.
* In case of error, create a protocol entry in the application log.
* Possible values for message type ('i_msgty'):
*
* 'A': Abort (Stop sign)
* 'E': Error (red LED)
* 'W': Warning (yellow LED)
* 'I': Information (green LED)
*
call method pr_data_changed->add_protocol_entry
exporting
i_msgid = '0K' i_msgno = '000' i_msgty = 'E'
i_msgv1 = text-m03 "Flugzeugtyp
i_msgv2 = l_planetype
i_msgv3 = text-m05 "exitstiert nicht
i_fieldname = ps_good_planetype-fieldname
i_row_id = ps_good_planetype-row_id.
error_in_data = 'X'.
exit. "plane does not exit, so we're finished here!
endif.
* Check if other relevant fields of this row have been changed, too.
read table pr_data_changed->mt_good_cells into ls_good_seatsocc
with key row_id = ps_good_planetype-row_id
fieldname = 'SEATSOCC'.
if sy-subrc = 0.
call method ch_new_plane_v_new_seatsocc
exporting
psg_plane = ps_good_planetype
psg_socc = ls_good_seatsocc
ps_saplane = ls_saplane
pr_data_changed = pr_data_changed.
else.
call method ch_new_plane_v_old_seatsocc
exporting
psg_plane = ps_good_planetype
ps_saplane = ls_saplane
pr_data_changed = pr_data_changed.
endif.
endmethod. " CHECK_PLANETYPE
*---------------------------------------------------------------------*
method ch_new_plane_v_new_seatsocc.
data: l_seatsocc type s_seatsocc.
*§5a.Get new cell value to check it using method GET_CELL_VALUE.
* (In this case SEATSOCC).
call method pr_data_changed->get_cell_value
exporting i_row_id = psg_socc-row_id
i_fieldname = psg_socc-fieldname
importing e_value = l_seatsocc.
*----------------------------------------------------------------
* CHECK: SEATSMAX(of new planetype) !>= SEATSOCC(new value)
* IF NOT: Message for wrong planetype
*----------------------------------------------------------------
if ps_saplane-seatsmax ge l_seatsocc.
*§5b.If the value is valid you may want to change values of
* other cells.
call method pr_data_changed->modify_cell
exporting i_row_id = psg_plane-row_id
i_fieldname = 'SEATSMAX'
i_value = ps_saplane-seatsmax.
else.
*§5c.If the value is not valid create an protocol entry in
* the application log.
* Possible values for message type ('i_msgty'):
*
* 'A': Abort (Stop sign)
* 'E': Error (red LED)
* 'W': Warning (yellow LED)
* 'I': Information (green LED)
*
call method pr_data_changed->add_protocol_entry
exporting
i_msgid = '0K' i_msgno = '000' i_msgty = 'E'
i_msgv1 = text-m03 "Flugzeugtyp
i_msgv2 = ps_saplane-planetype
i_msgv3 = text-m04 "hat nicht genug Sitzpl#tze
i_fieldname = psg_plane-fieldname
i_row_id = psg_plane-row_id.
error_in_data = 'X'.
endif.
endmethod.
*---------------------------------------------------------------------*
method ch_new_plane_v_old_seatsocc.
data: l_old_seatsocc type s_seatsocc,
ls_outtab type sflight.
*§5d.To access old values (which where not changed in this check cycle)
* use your output table GT_OUTTAB.
read table gt_outtab into ls_outtab index psg_plane-row_id.
l_old_seatsocc = ls_outtab-seatsocc.
*----------------------------------------------------------------
* CHECK: SEATSMAX(of new planetype) !>= SEATSOCC(old value)
* IF NOT: Message for wrong planetype
*----------------------------------------------------------------
if ps_saplane-seatsmax ge l_old_seatsocc.
* ok->field seatsmax can be changed
call method pr_data_changed->modify_cell
exporting i_row_id = psg_plane-row_id
i_fieldname = 'SEATSMAX'
i_value = ps_saplane-seatsmax.
else.
call method pr_data_changed->add_protocol_entry
exporting
i_msgid = '0K' i_msgno = '000' i_msgty = 'E'
i_msgv1 = text-m03 "Flugzeugtyp
i_msgv2 = ps_saplane-planetype
i_msgv3 = text-m04 "hat nicht genug Sitzpl#tze
i_fieldname = psg_plane-fieldname
i_row_id = psg_plane-row_id.
error_in_data = 'X'.
endif.
endmethod.
*&---------------------------------------------------------------------*
*& Form CHECK_SEATSOCC
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_LS_GOOD text
* -->P_ER_DATA_CHANGED text
*----------------------------------------------------------------------*
method check_seatsocc.
data: l_seatsocc type s_seatsocc,
l_old_seatsmax type s_seatsmax,
ls_outtab type sflight,
ls_good type lvc_s_modi.
*.................................................................
* Check if the planetype has changed, too.
*.................................................................
read table pr_data_changed->mt_good_cells into ls_good
with key row_id = ps_good-row_id
fieldname = 'PLANETYPE'.
if sy-subrc eq 0.
*....................................................
* remark: the check
* seatsocc (new value) <= seatsmax (new value)
* was already handled by form 'ch_new_plane_v_new_seatsocc'.
* so we are finished here.
*.................................................
exit.
endif.
*.....................................................
* CHECK: seatsocc (new value) <= seatsmax (old value)
* IF NOT: Message that SEATSOCC is to high.
*.....................................................
* get new cell value of SEATSOCC.
call method pr_data_changed->get_cell_value
exporting i_row_id = ps_good-row_id
i_fieldname = ps_good-fieldname
importing e_value = l_seatsocc.
* get old cell value of SEATSMAX
read table gt_outtab into ls_outtab index ps_good-row_id.
l_old_seatsmax = ls_outtab-seatsmax.
if l_seatsocc > l_old_seatsmax.
call method pr_data_changed->add_protocol_entry
exporting
i_msgid = '0K' i_msgno = '000' i_msgty = 'E'
i_msgv1 = text-m01 "Die Anzahl der belegten Pl#tze
i_msgv2 = text-m02 "übersteigt die Kapazit#t des Flugzeugs
i_msgv3 = ls_outtab-planetype
i_fieldname = ps_good-fieldname
i_row_id = ps_good-row_id.
error_in_data = 'X'.
endif.
endmethod. " CHECK_SEATSOCC
endclass.
***************************************************************
*---------------------------------------------------------------------*
* MAIN *
*---------------------------------------------------------------------*
end-of-selection.
call screen 100.
*---------------------------------------------------------------------*
* MODULE PBO OUTPUT *
*---------------------------------------------------------------------*
module pbo output.
set pf-status 'MAIN100'.
set titlebar 'MAIN100'.
if g_custom_container is initial.
perform create_and_init_alv changing gt_outtab
gt_fieldcat
gs_layout.
endif.
endmodule.
*---------------------------------------------------------------------*
* MODULE PAI INPUT *
*---------------------------------------------------------------------*
module pai input.
save_ok = ok_code.
clear ok_code.
case save_ok.
when 'EXIT'.
perform exit_program.
when others.
* do nothing
endcase.
endmodule.
*---------------------------------------------------------------------*
* FORM EXIT_PROGRAM *
*---------------------------------------------------------------------*
form exit_program.
leave program.
endform.
*&---------------------------------------------------------------------*
*& Form BUILD_FIELDCAT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* <--P_GT_FIELDCAT text
*----------------------------------------------------------------------*
form build_fieldcat changing pt_fieldcat type lvc_t_fcat.
data ls_fcat type lvc_s_fcat.
BREAK-POINT.
call function 'LVC_FIELDCATALOG_MERGE'
exporting
i_structure_name = 'SFLIGHT'
changing
ct_fieldcat = pt_fieldcat.
loop at pt_fieldcat into ls_fcat.
if ls_fcat-fieldname eq 'PLANETYPE'
or ls_fcat-fieldname eq 'SEATSOCC'.
*§1.Set status of columns PLANETYPE and SEATSOCC to editable.
ls_fcat-edit = 'X'.
* Field 'checktable' is set to avoid shortdumps that are caused
* by inconsistend data in check tables. You may comment this out
* when the test data of the flight model is consistent in your system.
ls_fcat-checktable = '!'. "do not check foreign keys
modify pt_fieldcat from ls_fcat.
endif.
endloop.
endform.
*&---------------------------------------------------------------------*
*& Form CREATE_AND_INIT_ALV
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* <--P_GT_OUTTAB text
* <--P_GT_FIELDCAT text
* <--P_GS_LAYOUT text
*----------------------------------------------------------------------*
form create_and_init_alv changing pt_outtab like gt_outtab[]
pt_fieldcat type lvc_t_fcat
ps_layout type lvc_s_layo.
data: lt_exclude type ui_functions.
create object g_custom_container
exporting container_name = g_container.
create object g_grid
exporting i_parent = g_custom_container.
* Build fieldcat and set columns PLANETYPE and SEATSOCC
* edit enabled.
perform build_fieldcat changing pt_fieldcat.
*§2.Optionally restrict generic functions to 'change only'.
* (The user shall not be able to add new lines).
perform exclude_tb_functions changing lt_exclude.
select * from sflight into table pt_outtab up to g_max rows.
call method g_grid->set_table_for_first_display
exporting is_layout = ps_layout
it_toolbar_excluding = lt_exclude
changing it_fieldcatalog = pt_fieldcat
it_outtab = pt_outtab.
* set editable cells to ready for input
CALL METHOD g_grid->set_ready_for_input
EXPORTING
I_READY_FOR_INPUT = 1.
*§3.Optionally register ENTER to raise event DATA_CHANGED.
* (Per default the user may check data by using the check icon).
call method g_grid->register_edit_event
exporting
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
create object g_event_receiver.
set handler g_event_receiver->handle_data_changed for g_grid.
endform. "CREATE_AND_INIT_ALV
*&---------------------------------------------------------------------*
*& Form EXCLUDE_TB_FUNCTIONS
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* <--P_LT_EXCLUDE text
*----------------------------------------------------------------------*
form exclude_tb_functions changing pt_exclude type ui_functions.
* Only allow to change data not to create new entries (exclude
* generic functions).
data ls_exclude type ui_func.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_copy_row.
append ls_exclude to pt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_delete_row.
append ls_exclude to pt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_append_row.
append ls_exclude to pt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_insert_row.
append ls_exclude to pt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_move_row.
append ls_exclude to pt_exclude.
endform. " EXCLUDE_TB_FUNCTIONS
标签:good,data,changed,ls,ALV,type,change,row
From: https://blog.51cto.com/u_8215601/7508981