Code: Alles auswählen.
*---------------------------------------------------------------------*
* Sample program for table edit through ALV
* with check against duplicate keys, protocol and delta update
*---------------------------------------------------------------------*
* Steps to create this program in your system:
*
* 1. SE38: create executable program (type 1)
*
* 2. SE80: create screen 0100
*
* 3. Screen Painter: on the screen 0100 create 'Custom control'
* CONT1_0100
*
* 4. SE80: for screen 0100 set the variable OK_CODE for the element OK
*
* 5. SE80: create calls to PBO and PAI in the flow logic of screen 0100:
*
* PROCESS BEFORE OUTPUT.
* MODULE pbo_0100.
* PROCESS AFTER INPUT.
* MODULE pai_0100.
*
* 6. SE80: create GUI Status STAT_0100, assign functions EXIT and SAVE
* to standard icons, eventually create your own toolbar button
PROGRAM z_alv_edit_save.
TYPE-POOLS: slis.
TYPES: BEGIN OF ts_data.
INCLUDE STRUCTURE mara.
TYPES: mod_type TYPE string. " type of modification (for protocol)
TYPES: verified TYPE C. " flag for verification
TYPES: celltab TYPE lvc_t_styl.
TYPES: END OF ts_data.
TYPES: tt_data TYPE STANDARD TABLE OF ts_data WITH NON-UNIQUE DEFAULT KEY.
CLASS cl_event_handler DEFINITION DEFERRED.
DATA: gt_data TYPE tt_data,
go_grid TYPE REF TO cl_gui_alv_grid,
go_cont TYPE REF TO cl_gui_custom_container,
gt_fcat TYPE lvc_t_fcat,
ok_code LIKE sy-ucomm,
go_event_handler TYPE REF TO cl_event_handler.
*----------------------------------------------------------------------*
* CLASS cl_event_handler DEFINITION
*----------------------------------------------------------------------*
CLASS cl_event_handler DEFINITION.
PUBLIC SECTION.
CLASS-DATA: data_changed_error TYPE I, " error flag
protocol_tab TYPE tt_data. " protocol of changes since last save
METHODS handle_toolbar
FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING e_object
e_interactive.
METHODS handle_user_command
FOR EVENT user_command OF cl_gui_alv_grid
IMPORTING e_ucomm.
METHODS handle_data_changed
FOR EVENT data_changed OF cl_gui_alv_grid
IMPORTING er_data_changed.
METHODS protocol_add
IMPORTING pi_tabix TYPE I
er_data_changed TYPE REF TO cl_alv_changed_data_protocol.
ENDCLASS. "cl_event_handler DEFINITION
*----------------------------------------------------------------------*
* CLASS cl_event_handler IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS cl_event_handler IMPLEMENTATION.
*&---------------------------------------------------------------------*
*& METHOD handle_toolbar
*&---------------------------------------------------------------------*
METHOD handle_toolbar.
FIELD-SYMBOLS:
<fs_button> TYPE stb_button.
* replace the standard function 'check' with own one
READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>
WITH KEY FUNCTION = cl_gui_alv_grid=>mc_fc_check. " '&CHECK'.
<fs_button>-FUNCTION = 'CHECK'.
** deactivate the 'copy row' function
** (not necessary in the logic of this program)
*
* READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>
* WITH KEY function = cl_gui_alv_grid=>mc_fc_loc_copy_row. " '&LOCAL©_ROW'.
* <fs_button>-disabled = 'X'.
ENDMETHOD. "handle_toolbar
*&---------------------------------------------------------------------*
*& METHOD handle_user_command
*&---------------------------------------------------------------------*
METHOD handle_user_command.
* force PAI processing with user function as ok_code
cl_gui_cfw=>set_new_ok_code( e_ucomm ).
ENDMETHOD. "handle_user_command
*&---------------------------------------------------------------------*
*& METHOD handle_data_changed
*&---------------------------------------------------------------------*
*& validate changes against duplicate keys and collect the protocol
*& of the changes for further db update or transport of changes
*&---------------------------------------------------------------------*
METHOD handle_data_changed.
DATA: ls_row TYPE lvc_s_moce,
ls_cell TYPE lvc_s_modi,
lt_data TYPE tt_data,
ls_data TYPE ts_data,
ls_data2 TYPE ts_data,
lv_tabix TYPE I,
lv_tabix2 TYPE I,
lv_new TYPE I.
FIELD-SYMBOLS: <ft_data> TYPE tt_data,
<fs_cell> TYPE lvc_s_modi.
ASSIGN er_data_changed->mp_mod_rows->* TO <ft_data>.
* consider present error messages from standard data checks
IF LINES( er_data_changed->mt_protocol ) = 0.
data_changed_error = 0.
ELSE.
data_changed_error = 1.
ENDIF.
* 1. collect the deleted rows (no checks needed)
LOOP AT er_data_changed->mt_deleted_rows INTO ls_row.
READ TABLE gt_data INTO ls_data INDEX ls_row-row_id.
ls_data-mod_type = 'DELETE'.
APPEND ls_data TO protocol_tab.
ENDLOOP.
* 2. collect the 'old' changed rows (no changes on key fields)
LOOP AT <ft_data> INTO ls_data
WHERE verified = 'X'.
ls_data-mod_type = 'UPDATE'.
APPEND ls_data TO protocol_tab.
ENDLOOP.
* 3. check the new rows against the old, verified rows
LOOP AT <ft_data> INTO ls_data
WHERE verified = ''.
lv_tabix = sy-tabix.
ADD 1 TO lv_new.
READ TABLE gt_data TRANSPORTING NO FIELDS
WITH KEY matnr = ls_data-matnr.
CHECK sy-subrc = 0.
data_changed_error = 1.
CALL METHOD protocol_add
EXPORTING
pi_tabix = lv_tabix
er_data_changed = er_data_changed.
ENDLOOP.
* 4. check the new rows among themselves
IF lv_new > 1.
LOOP AT <ft_data> INTO ls_data
WHERE verified = ''.
lv_tabix = sy-tabix.
LOOP AT <ft_data> INTO ls_data2
WHERE verified = ''.
lv_tabix2 = sy-tabix.
CHECK lv_tabix2 <> lv_tabix.
CHECK ls_data2-matnr = ls_data-matnr.
data_changed_error = 1.
CALL METHOD protocol_add
EXPORTING
pi_tabix = lv_tabix
er_data_changed = er_data_changed.
CALL METHOD protocol_add
EXPORTING
pi_tabix = lv_tabix2
er_data_changed = er_data_changed.
ENDLOOP.
ENDLOOP.
ENDIF.
* 5. last aktivities in event DATA_CHANGED
LOOP AT <ft_data> INTO ls_data
WHERE verified = ''.
lv_tabix = sy-tabix.
READ TABLE er_data_changed->mt_mod_cells INTO ls_cell WITH KEY tabix = sy-tabix.
READ TABLE er_data_changed->mt_protocol TRANSPORTING NO FIELDS WITH KEY row_id = ls_cell-row_id.
* if check against duplicate key was ok
CHECK sy-subrc <> 0.
* collect new rows
ls_data-mod_type = 'INSERT'.
APPEND ls_data TO protocol_tab.
* Schl#ssel-Felder schliessen
LOOP AT er_data_changed->mt_good_cells ASSIGNING <fs_cell>
WHERE tabix = lv_tabix.
READ TABLE gt_fcat TRANSPORTING NO FIELDS WITH KEY fieldname = <fs_cell>-fieldname
KEY = 'X'.
CHECK sy-subrc = 0.
<fs_cell>-style = cl_gui_alv_grid=>mc_style_disabled.
ENDLOOP.
ENDLOOP.
** 6. activate the copied rows
** (not necessary in the logic of this program)
*
* DATA:
* ls_cell TYPE lvc_s_modi.
*
* LOOP AT er_data_changed->mt_inserted_rows INTO ls_row.
*
* LOOP AT er_data_changed->mt_mod_cells INTO ls_cell
* WHERE row_id = ls_row-row_id.
*
* CALL METHOD er_data_changed->modify_style
* EXPORTING
* i_row_id = ls_cell-row_id
* i_fieldname = ls_cell-fieldname
* i_style = cl_gui_alv_grid=>mc_style_enabled.
* ENDLOOP.
* ENDLOOP.
ENDMETHOD. "handle_data_changed
*&---------------------------------------------------------------------*
*& METHOD protocol_add
*&---------------------------------------------------------------------*
METHOD protocol_add.
DATA: ls_cell TYPE lvc_s_modi,
ls_fcat TYPE lvc_s_fcat,
lv_string TYPE string,
lv_msgv1 TYPE symsgv,
lv_msgv2 TYPE symsgv,
ls_roid_front TYPE lvc_s_roid,
lv_row_id TYPE I.
LOOP AT er_data_changed->mt_mod_cells INTO ls_cell
WHERE tabix = pi_tabix.
* report only key fields
READ TABLE gt_fcat INTO ls_fcat WITH KEY fieldname = ls_cell-fieldname.
CHECK ls_fcat-KEY = 'X'.
* report only once
READ TABLE er_data_changed->mt_protocol TRANSPORTING NO FIELDS
WITH KEY fieldname = ls_cell-fieldname
row_id = ls_cell-row_id.
CHECK sy-subrc <> 0.
* map the row id between frontend and internal tables for the message
READ TABLE er_data_changed->mt_roid_front INTO ls_roid_front
WITH KEY row_id = ls_cell-row_id.
lv_row_id = sy-tabix.
lv_msgv1 = 'Row &1:'.
lv_string = lv_row_id.
REPLACE SUBSTRING '&1' IN lv_msgv1 WITH lv_string.
lv_msgv2 = 'Duplicate key with value ''&1'''.
lv_string = ls_cell-VALUE.
REPLACE SUBSTRING '&1' IN lv_msgv2 WITH lv_string.
CALL METHOD er_data_changed->add_protocol_entry
EXPORTING
i_msgid = '0K'
i_msgno = '000'
i_msgty = 'E'
i_msgv1 = lv_msgv1
i_msgv2 = lv_msgv2
i_fieldname = ls_cell-fieldname
i_row_id = ls_cell-row_id. " pass the row id without mapping here
ENDLOOP.
ENDMETHOD. "protocol_add
ENDCLASS. "cl_event_handler IMPLEMENTATION
*&---------------------------------------------------------------------*
*& START-OF-SELECTION
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM data_load CHANGING gt_data.
* initially check all rows as verified
PERFORM data_verified_set CHANGING gt_data.
PERFORM fieldcat_create CHANGING gt_fcat.
PERFORM data_key_readonly_set USING gt_fcat CHANGING gt_data.
CALL SCREEN 0100.
*&---------------------------------------------------------------------*
*& Form data_load
*&---------------------------------------------------------------------*
FORM data_load CHANGING pt_data TYPE tt_data.
SELECT *
INTO CORRESPONDING FIELDS OF TABLE pt_data
FROM mara
UP TO 10 rows.
ENDFORM. "data_load
*&---------------------------------------------------------------------*
*& Form fieldcat_create
*&---------------------------------------------------------------------*
FORM fieldcat_create CHANGING pt_fcat TYPE lvc_t_fcat.
FIELD-SYMBOLS: <fs_fcat> TYPE lvc_s_fcat.
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'MARA'
CHANGING
ct_fieldcat = gt_fcat.
LOOP AT gt_fcat ASSIGNING <fs_fcat>.
<fs_fcat>-EDIT = 'X'.
* key fields
IF <fs_fcat>-fieldname = 'MATNR'.
<fs_fcat>-KEY = 'X'.
ELSE.
<fs_fcat>-KEY = ''.
ENDIF.
ENDLOOP.
ENDFORM. "fieldcat_create
*&---------------------------------------------------------------------*
*& Form data_key_readonly_set
*&---------------------------------------------------------------------*
FORM data_key_readonly_set USING pt_fcat TYPE lvc_t_fcat
CHANGING pt_data TYPE tt_data.
DATA: lt_style TYPE lvc_t_styl,
ls_style TYPE lvc_s_styl,
ls_fcat TYPE lvc_s_fcat.
FIELD-SYMBOLS: <fs_data> TYPE ts_data.
* the following construct works well for function 'copy row' (MC_FC_LOC_COPY_ROW)
* (the style of the whole row is not copied and the key fields are open for change)
* first deactivate complete row for edit
ls_style-style = cl_gui_alv_grid=>mc_style_disabled.
INSERT ls_style INTO TABLE lt_style.
LOOP AT pt_fcat INTO ls_fcat
WHERE NOT KEY = 'X'.
* then activate non-key fields
ls_style-fieldname = ls_fcat-fieldname.
ls_style-style = cl_gui_alv_grid=>mc_style_enabled.
INSERT ls_style INTO TABLE lt_style.
ENDLOOP.
LOOP AT pt_data ASSIGNING <fs_data>.
<fs_data>-celltab = lt_style.
ENDLOOP.
ENDFORM. "data_key_readonly_set
*&---------------------------------------------------------------------*
*& Form data_verified_set
*&---------------------------------------------------------------------*
FORM data_verified_set CHANGING pt_data TYPE tt_data.
FIELD-SYMBOLS: <fs_data> TYPE ts_data.
LOOP AT pt_data ASSIGNING <fs_data>
WHERE verified = ''.
<fs_data>-verified = 'X'.
ENDLOOP.
ENDFORM. "data_verified_set
*&---------------------------------------------------------------------*
*& Form data_change_post_processing
*&---------------------------------------------------------------------*
FORM data_change_post_processing CHANGING pt_data TYPE tt_data.
* check all rows as verified
PERFORM data_verified_set CHANGING pt_data.
* deactivate edit mode of key fields
PERFORM data_key_readonly_set USING gt_fcat
CHANGING pt_data.
* refresh ALV grid from internal table
CALL METHOD go_grid->refresh_table_display.
ENDFORM. "data_change_post_processing
*&---------------------------------------------------------------------*
*& Form data_save
*&---------------------------------------------------------------------*
FORM data_save.
DATA: ls_data TYPE ts_data,
ls_db_data TYPE mara.
LOOP AT cl_event_handler=>protocol_tab INTO ls_data.
MOVE-CORRESPONDING ls_data TO ls_db_data.
CASE ls_data-mod_type.
WHEN 'INSERT'.
INSERT mara FROM ls_db_data.
WHEN 'UPDATE'.
UPDATE mara FROM ls_db_data.
WHEN 'DELETE'.
DELETE mara FROM ls_db_data.
ENDCASE.
ENDLOOP.
COMMIT WORK.
MESSAGE S999(B1) WITH 'Data saved'.
ENDFORM. "data_save
*&---------------------------------------------------------------------*
*& Form alv_init
*&---------------------------------------------------------------------*
FORM alv_init.
DATA: ls_layout TYPE lvc_s_layo.
IF go_cont IS INITIAL.
SET PF-STATUS 'STAT_0100'.
CREATE OBJECT go_cont
EXPORTING
container_name = 'CONT1_0100'.
CREATE OBJECT go_grid
EXPORTING
i_parent = go_cont.
CREATE OBJECT go_event_handler.
SET HANDLER go_event_handler->handle_toolbar FOR go_grid.
SET HANDLER go_event_handler->handle_user_command FOR go_grid.
SET HANDLER go_event_handler->handle_data_changed FOR go_grid.
ls_layout-stylefname = 'CELLTAB'.
CALL METHOD go_grid->set_table_for_first_display
EXPORTING
is_layout = ls_layout
CHANGING
it_fieldcatalog = gt_fcat
it_outtab = gt_data.
** if you need event DATA_CHANGED after function 'copy row'
** (not necessary in the logic of this program)
*
* CALL METHOD go_grid->register_edit_event
* EXPORTING
* i_event_id = cl_gui_alv_grid=>mc_evt_modified.
ENDIF.
ENDFORM. "alv_init
*&---------------------------------------------------------------------*
*& Form user_command
*&---------------------------------------------------------------------*
FORM user_command.
CALL METHOD cl_gui_cfw=>dispatch.
CASE ok_code.
WHEN 'BACK'.
LEAVE PROGRAM.
WHEN 'EXIT'.
LEAVE PROGRAM.
WHEN 'CHECK'.
* 1. synchronize the internal table and check against duplicate keys
CALL METHOD go_grid->check_changed_data.
* 2. if there are no duplicated keys
CHECK cl_event_handler=>data_changed_error = 0.
* post processing after successful synchronization
PERFORM data_change_post_processing CHANGING gt_data.
WHEN 'SAVE'.
* 1. synchronize the internal table
CALL METHOD go_grid->check_changed_data.
* 2. if there are no duplicated keys
CHECK cl_event_handler=>data_changed_error = 0.
* post processing after successful synchronization
PERFORM data_change_post_processing CHANGING gt_data.
* 3. if the data was changed
CHECK NOT cl_event_handler=>protocol_tab IS INITIAL.
* save the delta changes in database
PERFORM data_save.
* clear the protocol
CLEAR cl_event_handler=>protocol_tab.
ENDCASE.
CLEAR ok_code.
ENDFORM. "user_command
*----------------------------------------------------------------------*
* MODULE pbo_0100 OUTPUT
*----------------------------------------------------------------------*
MODULE pbo_0100 OUTPUT.
PERFORM alv_init.
ENDMODULE. "pbo_0100 OUTPUT
*----------------------------------------------------------------------*
* MODULE pai_0100 INPUT
*----------------------------------------------------------------------*
MODULE pai_0100 INPUT.
PERFORM user_command.
ENDMODULE. "pai_0100 INPUT
Code: Alles auswählen.
DATA: ls_layout TYPE lvc_s_layo,
lt_exclude TYPE ui_functions,
ls_exclude TYPE ui_func.
* ls_layout-no_rowins = 'X'.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_insert_row.
APPEND ls_exclude TO lt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_append_row.
APPEND ls_exclude TO lt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_copy_row.
APPEND ls_exclude TO lt_exclude.
ls_exclude = cl_gui_alv_grid=>mc_fc_loc_paste_new_row.
APPEND ls_exclude TO lt_exclude.
CALL METHOD go_grid->set_table_for_first_display
EXPORTING
is_layout = ls_layout
it_toolbar_excluding = lt_exclude
CHANGING
it_fieldcatalog = gt_fcat
it_outtab = gt_data.
Code: Alles auswählen.
CLASS cl_event_handler DEFINITION.
PUBLIC SECTION.
...
METHODS handle_toolbar
FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING e_object
e_interactive.
...
ENDCLASS.
Code: Alles auswählen.
METHOD handle_toolbar.
FIELD-SYMBOLS: <fs_button> TYPE stb_button.
* Es unmöglich machen, Zeilen einzufügen
READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>
WITH KEY function = cl_gui_alv_grid=>mc_fc_loc_copy_row.
<fs_button>-disabled = 'X'.
READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>
WITH KEY FUNCTION = cl_gui_alv_grid=>mc_fc_loc_insert_row.
<fs_button>-disabled = 'X'.
READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>
WITH KEY FUNCTION = cl_gui_alv_grid=>mc_fc_loc_append_row.
<fs_button>-disabled = 'X'.
READ TABLE e_object->mt_toolbar ASSIGNING <fs_button>
WITH KEY FUNCTION = cl_gui_alv_grid=>mc_fc_loc_paste_new_row.
<fs_button>-disabled = 'X'.
ENDMETHOD.
Code: Alles auswählen.
FORM alv_init.
...
CREATE OBJECT go_event_handler.
SET HANDLER go_event_handler->handle_toolbar FOR go_grid.
...
ENDFORM.