Validate data entered via code in an editable ALV
Recently I had trouble with and editable ALV. The problem was that when loading data via code and showing it in the editable ALV, I could not manage to force the validations on the new records. So when the user hit save, the invalid records were save to the database.
I found a workaround to this issue in the following way:
After calling the method to display the ALV, I appended a number of rows equals to the number of the new records with method “append_rows” of the alv object and immediately after that I call method “check_changed_data”. Then in the method that handles the data changed, I update the new empty rows in the parameter internal table “er_data_changed->mp_mod_rows” with the new data.
I am pasting a example source code, I hope you find it helpful.
Also, you might want to look into how to update records via code, for example, if you want to display the name of a customer and you only let the user fill the customer number. In this example code, the user can fill in a cell a vendor number, and then the ALV automatically displays the vendor name in the next cell.
This is also solved in the method you define to handle the data changed. In this code example this method is called handle_data_changed. After the user modifies a cell with a vendor number, the method handle_data_changed is called and there you have to update the parameter internal table “er_data_changed->mp_mod_rows” with the vendor name, then also you need to add a row in parameters “er_data_changed->mt_mod_cells” and “er_data_changed->mt_good_cells” with the information of cells of the vendors names.
*———————————————————————-*
*Declaring types
*———————————————————————-*
TYPE-POOLS : slis.
TYPES: BEGIN OF ty_data.
INCLUDE TYPE zptp_sourcing_alv2.
TYPES: mod_type TYPE string. ” type of modification (for protocol)
TYPES: verified(1) TYPE c. ” flag for verification
TYPES: celltab TYPE lvc_t_styl.
TYPES: END OF ty_data.
TYPES:
ty_t_data TYPE STANDARD TABLE OF ty_data WITH NON-UNIQUE DEFAULT KEY.
TYPES: BEGIN OF ty_lfa1,
lifnr TYPE lfa1-lifnr,
name1 TYPE lfa1-name1,
END OF ty_lfa1.
CLASS cl_event_handler DEFINITION DEFERRED.
*———————————————————————-*
* Constants *
*———————————————————————-*
CONSTANTS:
c_back_command TYPE sy-ucomm VALUE ‘BACK’,
c_exit_command TYPE sy-ucomm VALUE ‘EXIT’,
c_plant_prefix TYPE c VALUE ‘P’,
c_matnr(5) TYPE c VALUE ‘MATNR’,
c_werks(5) TYPE c VALUE ‘WERKS’,
c_ekorg(5) TYPE c VALUE ‘EKORG’,
c_vdatu(5) TYPE c VALUE ‘VDATU’,
c_bdatu(5) TYPE c VALUE ‘BDATU’,
c_insert(6) TYPE c VALUE ‘INSERT’,
c_update(6) TYPE c VALUE ‘UPDATE’,
c_delete(6) TYPE c VALUE ‘DELETE’,
c_check_command(5) TYPE c VALUE ‘CHECK’,
c_save_command(4) TYPE c VALUE ‘SAVE’,
c_vendor1_name(12) TYPE c VALUE ‘VENDOR1_NAME’,
c_vendor2_name(12) TYPE c VALUE ‘VENDOR2_NAME’,
c_vendor3_name(12) TYPE c VALUE ‘VENDOR3_NAME’.
“ALV variables
DATA:
i_alv_data TYPE ty_t_data,
i_alv_data_new_rec TYPE ty_t_data,
o_grid TYPE REF TO cl_gui_alv_grid,
o_cont TYPE REF TO cl_gui_custom_container,
i_fcat TYPE lvc_t_fcat,
ok_code LIKE sy-ucomm,
o_event_handler TYPE REF TO cl_event_handler.
“Internal tables and work areas
DATA:
i_zptp_sourcing TYPE TABLE OF zptp_sourcing,
wa_zptp_sourcing LIKE LINE OF i_zptp_sourcing,
wa_xord TYPE zptp_xord,
wa_variant TYPE disvariant,
wa_alv_data TYPE ty_data.
“variables
DATA:
g_matnr TYPE mara-matnr,
g_werks TYPE marc-werks,
g_updatable TYPE boolean.
*———————————————————————-*
* CLASS cl_event_handler DEFINITION
*———————————————————————-*
CLASS cl_event_handler DEFINITION FINAL.
PUBLIC SECTION.
CLASS-DATA:
data_changed_error TYPE i, ” error flag
protocol_tab TYPE ty_t_data. ” protocol of changes since last save
METHODS handle_toolbar
FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING
e_object
e_interactive ##needed.
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
im_tabix TYPE i
im_data_changed TYPE REF TO cl_alv_changed_data_protocol.
METHODS wrong_dates
IMPORTING
im_tabix TYPE i
im_data_changed TYPE REF TO cl_alv_changed_data_protocol.
METHODS required_field
IMPORTING
im_tabix TYPE i
im_data_changed TYPE REF TO cl_alv_changed_data_protocol
im_fieldname TYPE lvc_fname.
ENDCLASS. “cl_event_handler DEFINITION
*———————————————————————-*
* MODULE pbo_0100 OUTPUT
*———————————————————————-*
MODULE pbo_0100 OUTPUT.
PERFORM f_alv_init.
ENDMODULE. “pbo_0100 OUTPUT
*———————————————————————-*
* MODULE pai_0100 INPUT
*———————————————————————-*
MODULE pai_0100 INPUT.
PERFORM f_user_command.
ENDMODULE. “pai_0100 INPUT
*———————————————————————-*
* CLASS cl_event_handler IMPLEMENTATION
*———————————————————————-*
CLASS cl_event_handler IMPLEMENTATION.
*&———————————————————————*
*& METHOD handle_toolbar
*&———————————————————————*
METHOD handle_toolbar.
FIELD-SYMBOLS:
IF g_updatable EQ abap_true.
* replace the standard function ‘check’ with own one
READ TABLE e_object->mt_toolbar ASSIGNING
WITH KEY function = cl_gui_alv_grid=>mc_fc_check. ” ‘&CHECK’.
“QA note: small table and internal of alv object, not sorting is necesary
ENDIF.
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:
l_wa_row TYPE lvc_s_moce,
l_wa_cell TYPE lvc_s_modi,
l_wa_mod_cell TYPE lvc_s_modi,
l_wa_data TYPE ty_data,
l_wa_data2 TYPE ty_data,
lv_tabix TYPE i,
lv_tabix2 TYPE i,
lv_new TYPE i.
FIELD-SYMBOLS:
ASSIGN er_data_changed->mp_mod_rows->* TO
“If there are initial records that don’t exist in database to be inserted in grid
IF i_alv_data_new_rec IS NOT INITIAL.
LOOP AT i_alv_data_new_rec
INTO wa_alv_data.
MODIFY
FROM wa_alv_data
INDEX sy-tabix.
ENDLOOP.
REFRESH i_alv_data_new_rec.
ENDIF.
* 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.
* “Fill additional information
PERFORM f_vendors_name CHANGING
LOOP AT
INTO wa_alv_data.
lv_tabix = sy-tabix.
CLEAR l_wa_mod_cell.
READ TABLE er_data_changed->mt_mod_cells INTO l_wa_cell WITH KEY tabix = lv_tabix.
IF sy-subrc EQ 0.
l_wa_mod_cell-fieldname = c_vendor1_name.
l_wa_mod_cell-row_id = l_wa_cell-row_id.
l_wa_mod_cell-tabix = lv_tabix.
APPEND l_wa_mod_cell TO er_data_changed->mt_mod_cells.
APPEND l_wa_mod_cell TO er_data_changed->mt_good_cells.
l_wa_mod_cell-fieldname = c_vendor2_name.
APPEND l_wa_mod_cell TO er_data_changed->mt_mod_cells.
APPEND l_wa_mod_cell TO er_data_changed->mt_good_cells.
l_wa_mod_cell-fieldname = c_vendor3_name.
APPEND l_wa_mod_cell TO er_data_changed->mt_mod_cells.
APPEND l_wa_mod_cell TO er_data_changed->mt_good_cells.
ENDIF.
ENDLOOP.
* 1. collect the deleted rows (no checks needed)
LOOP AT er_data_changed->mt_deleted_rows INTO l_wa_row.
READ TABLE i_alv_data INTO l_wa_data INDEX l_wa_row-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table
l_wa_data-mod_type = ‘DELETE’.
APPEND l_wa_data TO protocol_tab.
ENDLOOP.
* 2. collect the ‘old’ changed rows (no changes on key fields)
LOOP AT
WHERE verified = abap_true.
l_wa_data-mod_type = ‘UPDATE’.
APPEND l_wa_data TO protocol_tab.
ENDLOOP.
* 3. check the new rows against the old, verified rows (verified once, which means keys are correct
* “and we can find them in the alv table )
LOOP AT
WHERE verified NE abap_true.
lv_tabix = sy-tabix.
ADD 1 TO lv_new.
READ TABLE i_alv_data TRANSPORTING NO FIELDS
WITH KEY ekorg = l_wa_data-ekorg
vdatu = l_wa_data-vdatu
bdatu = l_wa_data-bdatu.
* “QA note: Not using binary search, in order to not interfere with current sorting of table
CHECK sy-subrc = 0.
* data_changed_error = 1.
CALL METHOD protocol_add
EXPORTING
im_tabix = lv_tabix
im_data_changed = er_data_changed.
ENDLOOP.
* 4. check the new rows among themselves
IF lv_new > 1.
LOOP AT
WHERE verified NE abap_true.
lv_tabix = sy-tabix.
LOOP AT
WHERE verified NE abap_true.
lv_tabix2 = sy-tabix.
CHECK lv_tabix2 <> lv_tabix.
CHECK l_wa_data2-ekorg = l_wa_data-ekorg
AND l_wa_data2-vdatu = l_wa_data-vdatu
AND l_wa_data2-bdatu = l_wa_data-bdatu.
* data_changed_error = 1.
CALL METHOD protocol_add
EXPORTING
im_tabix = lv_tabix
im_data_changed = er_data_changed.
CALL METHOD protocol_add
EXPORTING
im_tabix = lv_tabix2
im_data_changed = er_data_changed.
ENDLOOP.
ENDLOOP.
ENDIF.
* “Other validations
LOOP AT
WHERE verified NE abap_true.
lv_tabix = sy-tabix.
IF l_wa_data-vdatu IS INITIAL.
CALL METHOD required_field
EXPORTING
im_tabix = lv_tabix
im_data_changed = er_data_changed
im_fieldname = ‘VDATU’.
ENDIF.
IF l_wa_data-bdatu IS INITIAL.
CALL METHOD required_field
EXPORTING
im_tabix = lv_tabix
im_data_changed = er_data_changed
im_fieldname = ‘BDATU’.
ENDIF.
IF l_wa_data-ekorg IS INITIAL.
CALL METHOD required_field
EXPORTING
im_tabix = lv_tabix
im_data_changed = er_data_changed
im_fieldname = ‘EKORG’.
ENDIF.
IF l_wa_data-vdatu GT l_wa_data-bdatu.
CALL METHOD wrong_dates
EXPORTING
im_tabix = lv_tabix
im_data_changed = er_data_changed.
ENDIF.
ENDLOOP.
* 5. last aktivities in event DATA_CHANGED
LOOP AT
WHERE verified NE abap_true.
lv_tabix = sy-tabix.
* “looking for a modified cell of row
READ TABLE er_data_changed->mt_mod_cells INTO l_wa_cell WITH KEY tabix = sy-tabix.
* “QA note: Not using binary search, in order to not interfere with current sorting of table
CHECK sy-subrc EQ 0.
“looking for errors of this record
READ TABLE er_data_changed->mt_protocol TRANSPORTING NO FIELDS WITH KEY row_id = l_wa_cell-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table
CHECK sy-subrc <> 0.
* if there are no errors
* collect new rows
l_wa_data-mod_type = ‘INSERT’.
APPEND l_wa_data TO protocol_tab.
* Disable key fields
LOOP AT er_data_changed->mt_good_cells ASSIGNING
WHERE tabix = lv_tabix.
READ TABLE i_fcat TRANSPORTING NO FIELDS WITH KEY fieldname =
key = abap_true.
* “QA note: Not using binary search, in order to not interfere with current sorting of table
CHECK sy-subrc = 0.
ENDLOOP.
ENDLOOP.
ENDMETHOD. “handle_data_changed
*&———————————————————————*
*& METHOD protocol_add
*&———————————————————————*
METHOD protocol_add.
DATA:
l_wa_cell TYPE lvc_s_modi,
l_wa_fcat TYPE lvc_s_fcat,
lv_string TYPE string,
lv_msgv1 TYPE symsgv,
lv_msgv2 TYPE symsgv,
l_wa_roid_front TYPE lvc_s_roid,
lv_row_id TYPE i.
LOOP AT im_data_changed->mt_mod_cells INTO l_wa_cell
WHERE tabix = im_tabix.
* report only key fields
READ TABLE i_fcat INTO l_wa_fcat WITH KEY fieldname = l_wa_cell-fieldname.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
CHECK l_wa_fcat-key = abap_true.
* report only once
READ TABLE im_data_changed->mt_protocol TRANSPORTING NO FIELDS
WITH KEY fieldname = l_wa_cell-fieldname
row_id = l_wa_cell-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
CHECK sy-subrc <> 0.
* map the row id between frontend and internal tables for the message
READ TABLE im_data_changed->mt_roid_front INTO l_wa_roid_front
WITH KEY row_id = l_wa_cell-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
lv_row_id = sy-tabix.
lv_msgv1 = ‘Row &1:'(005).
lv_string = lv_row_id.
REPLACE SUBSTRING ‘&1’ IN lv_msgv1 WITH lv_string.
lv_msgv2 = ‘Duplicate key with value “&1″‘(006).
lv_string = l_wa_cell-value.
REPLACE SUBSTRING ‘&1’ IN lv_msgv2 WITH lv_string.
data_changed_error = 1.
CALL METHOD im_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 = l_wa_cell-fieldname
i_row_id = l_wa_cell-row_id. ” pass the row id without mapping here
ENDLOOP.
ENDMETHOD. “protocol_add
*&———————————————————————*
*& METHOD required_field
*&———————————————————————*
METHOD required_field.
DATA:
l_wa_cell TYPE lvc_s_modi,
lv_string TYPE string,
lv_msgv1 TYPE symsgv,
lv_msgv2 TYPE symsgv,
l_wa_roid_front TYPE lvc_s_roid,
lv_row_id TYPE i.
READ TABLE im_data_changed->mt_mod_cells
INTO l_wa_cell
WITH KEY tabix = im_tabix
fieldname = im_fieldname.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
IF sy-subrc EQ 0.
* map the row id between frontend and internal tables for the message
READ TABLE im_data_changed->mt_roid_front
INTO l_wa_roid_front
WITH KEY row_id = l_wa_cell-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
IF sy-subrc EQ 0.
lv_row_id = sy-tabix.
lv_msgv1 = ‘Row &1:'(005).
lv_string = lv_row_id.
REPLACE SUBSTRING ‘&1’ IN lv_msgv1 WITH lv_string.
lv_msgv2 = ‘Please fill this field'(007).
data_changed_error = 1.
CALL METHOD im_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 = l_wa_cell-fieldname
i_row_id = l_wa_cell-row_id. ” pass the row id without mapping here
ENDIF.
ENDIF.
ENDMETHOD. “required_field
*&———————————————————————*
*& METHOD wrong_dates
*&———————————————————————*
METHOD wrong_dates.
DATA:
l_wa_cell TYPE lvc_s_modi,
lv_string TYPE string,
lv_msgv1 TYPE symsgv,
lv_msgv2 TYPE symsgv,
l_wa_roid_front TYPE lvc_s_roid,
lv_row_id TYPE i.
READ TABLE im_data_changed->mt_mod_cells
INTO l_wa_cell
WITH KEY tabix = im_tabix
fieldname = ‘VDATU’.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
IF sy-subrc EQ 0.
* map the row id between frontend and internal tables for the message
READ TABLE im_data_changed->mt_roid_front
INTO l_wa_roid_front
WITH KEY row_id = l_wa_cell-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
IF sy-subrc EQ 0.
lv_row_id = sy-tabix.
lv_msgv1 = ‘Row &1:'(005).
lv_string = lv_row_id.
REPLACE SUBSTRING ‘&1’ IN lv_msgv1 WITH lv_string.
lv_msgv2 = ‘Initial date can not be greater than end date'(008).
data_changed_error = 1.
CALL METHOD im_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 = l_wa_cell-fieldname
i_row_id = l_wa_cell-row_id. ” pass the row id without mapping here
ENDIF.
ENDIF.
READ TABLE im_data_changed->mt_mod_cells
INTO l_wa_cell
WITH KEY tabix = im_tabix
fieldname = ‘BDATU’.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
IF sy-subrc EQ 0.
* map the row id between frontend and internal tables for the message
READ TABLE im_data_changed->mt_roid_front
INTO l_wa_roid_front
WITH KEY row_id = l_wa_cell-row_id.
* “QA note: Not using binary search, in order to not interfere with current sorting of table,
* “and is a small table
IF sy-subrc EQ 0.
lv_row_id = sy-tabix.
lv_msgv1 = ‘Row &1:'(005).
lv_string = lv_row_id.
REPLACE SUBSTRING ‘&1’ IN lv_msgv1 WITH lv_string.
lv_msgv2 = ‘Initial date can not be greater than end date'(008).
CALL METHOD im_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 = l_wa_cell-fieldname
i_row_id = l_wa_cell-row_id. ” pass the row id without mapping here
ENDIF.
ENDIF.
ENDMETHOD. “wrong_dates
ENDCLASS. “cl_event_handler IMPLEMENTATION
*&———————————————————————*
*& Form F_GET_DEFAULT_VARI
*&———————————————————————*
* Get Default Variant
*———————————————————————-*
FORM f_get_default_vari .
CLEAR:wa_variant.
wa_variant-report = sy-repid.
CALL FUNCTION ‘REUSE_ALV_VARIANT_DEFAULT_GET’
EXPORTING
i_save = ‘A’
CHANGING
cs_variant = wa_variant
EXCEPTIONS
not_found = 2.
IF sy-subrc NE 0.
CLEAR wa_variant-variant.
ENDIF.
ENDFORM. ” F_GET_DEFAULT_VARI
*&———————————————————————*
*& Form f_fieldcat_create
*&———————————————————————*
FORM f_fieldcat_create.
FIELD-SYMBOLS:
CALL FUNCTION ‘LVC_FIELDCATALOG_MERGE’
EXPORTING
i_structure_name = ‘ZPTP_SOURCING_ALV2’
CHANGING
ct_fieldcat = i_fcat.
LOOP AT i_fcat ASSIGNING
IF g_updatable EQ abap_true.
IF
AND
AND
ENDIF.
ENDIF.
IF
OR
ENDIF.
* key fields
IF
OR
OR
OR
OR
ELSE.
ENDIF.
ENDLOOP.
ENDFORM. “f_fieldcat_create
*&———————————————————————*
*& Form f_data_key_readonly_set
*&———————————————————————*
FORM f_data_key_readonly_set USING fp_fcat TYPE lvc_t_fcat
CHANGING fp_data TYPE ty_t_data.
DATA:
lt_style TYPE lvc_t_styl,
l_wa_style TYPE lvc_s_styl,
l_wa_fcat TYPE lvc_s_fcat.
FIELD-SYMBOLS:
* 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
l_wa_style-style = cl_gui_alv_grid=>mc_style_disabled.
INSERT l_wa_style INTO TABLE lt_style.
LOOP AT fp_fcat INTO l_wa_fcat
WHERE NOT key = abap_true.
* then activate non-key fields that should be editable
IF l_wa_fcat-fieldname NE c_vendor1_name”‘vendor1_name’
AND l_wa_fcat-fieldname NE c_vendor2_name”‘vendor2_name’.
AND l_wa_fcat-fieldname NE c_vendor3_name.”‘vendor3_name’.
l_wa_style-fieldname = l_wa_fcat-fieldname.
l_wa_style-style = cl_gui_alv_grid=>mc_style_enabled.
INSERT l_wa_style INTO TABLE lt_style.
ENDIF.
ENDLOOP.
LOOP AT fp_data ASSIGNING
ENDLOOP.
ENDFORM. “f_data_key_readonly_set
*&———————————————————————*
*& Form f_data_verified_set
*&———————————————————————*
FORM f_data_verified_set CHANGING fp_data TYPE ty_t_data.
FIELD-SYMBOLS:
LOOP AT fp_data ASSIGNING
WHERE verified NE abap_true.
ENDLOOP.
ENDFORM. “f_data_verified_set
*&———————————————————————*
*& Form f_data_change_post_processing
*&———————————————————————*
FORM f_data_change_post_processing CHANGING fp_data TYPE ty_t_data.
* check all rows as verified
PERFORM f_data_verified_set CHANGING fp_data.
* deactivate edit mode of key fields
PERFORM f_data_key_readonly_set USING i_fcat
CHANGING fp_data.
* refresh ALV grid from internal table
CALL METHOD o_grid->refresh_table_display.
ENDFORM. “f_data_change_post_processing
*&———————————————————————*
*& Form f_data_save
*&———————————————————————*
FORM f_data_save.
DATA:
l_wa_data TYPE ty_data,
l_wa_db_data TYPE zptp_sourcing.
LOOP AT cl_event_handler=>protocol_tab INTO l_wa_data.
* “Global values
l_wa_db_data-matnr = g_matnr.
l_wa_db_data-werks = g_werks.
* “Updated values
l_wa_db_data-ekorg = l_wa_data-ekorg.
l_wa_db_data-vdatu = l_wa_data-vdatu.
l_wa_db_data-bdatu = l_wa_data-bdatu.
l_wa_db_data-vendor1 = l_wa_data-vendor1.
l_wa_db_data-vendor2 = l_wa_data-vendor2.
l_wa_db_data-vendor3 = l_wa_data-vendor3.
l_wa_db_data-text = l_wa_data-text.
CASE l_wa_data-mod_type.
WHEN c_insert.”‘INSERT’.
INSERT zptp_sourcing FROM l_wa_db_data.
WHEN c_update.”‘UPDATE’.
UPDATE zptp_sourcing FROM l_wa_db_data.
WHEN c_delete.”‘DELETE’.
DELETE zptp_sourcing FROM l_wa_db_data.
ENDCASE.
ENDLOOP.
COMMIT WORK.
MESSAGE s010 WITH ‘Data saved'(001).
ENDFORM. “f_data_save
*&———————————————————————*
*& Form f_alv_init
*&———————————————————————*
FORM f_alv_init.
DATA:
l_wa_layout TYPE lvc_s_layo.
IF o_cont IS INITIAL.
SET TITLEBAR ‘ZZSOURCING’.
IF g_updatable EQ abap_true.
SET PF-STATUS ‘ZZSOURCING’.
ELSE.
SET PF-STATUS ‘ZZSOURCING’
EXCLUDING c_save_command.
ENDIF.
CREATE OBJECT o_cont
EXPORTING
container_name = ‘CONT1_0100’.
CREATE OBJECT o_grid
EXPORTING
i_parent = o_cont.
CREATE OBJECT o_event_handler.
SET HANDLER o_event_handler->handle_toolbar FOR o_grid.
SET HANDLER o_event_handler->handle_user_command FOR o_grid.
SET HANDLER o_event_handler->handle_data_changed FOR o_grid.
l_wa_layout-stylefname = ‘CELLTAB’.
l_wa_layout-val_data = ‘C’.
CALL METHOD o_grid->set_table_for_first_display
EXPORTING
is_layout = l_wa_layout
is_variant = wa_variant
i_save = ‘A’
CHANGING
it_fieldcatalog = i_fcat
it_outtab = i_alv_data.
CALL METHOD o_grid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
* “add rows that don’t exist in data base to grid
IF i_alv_data_new_rec IS NOT INITIAL.
CALL METHOD o_grid->append_rows
EXPORTING
i_row_count = lines( i_alv_data_new_rec ).
CALL METHOD o_grid->check_changed_data.
ENDIF.
ENDIF.
ENDFORM. “f_alv_init
*&———————————————————————*
*& Form f_user_command
*&———————————————————————*
FORM f_user_command.
DATA:
l_v_ans TYPE c.
CALL METHOD cl_gui_cfw=>dispatch.
CASE ok_code.
WHEN c_exit_command OR
c_back_command.
IF g_updatable EQ abap_true.
* 1. synchronize the internal table
CALL METHOD o_grid->check_changed_data.
* 2. if the data was changed
“If there are changes, ask wheter user wants to save
IF NOT cl_event_handler=>protocol_tab IS INITIAL.
PERFORM f_confirm_if_user_wants_save CHANGING l_v_ans.
CASE l_v_ans.
WHEN ‘J’.
* 3. if there are no duplicated keys
IF cl_event_handler=>data_changed_error = 0.
* post processing after successful synchronization
PERFORM f_data_change_post_processing CHANGING i_alv_data.
* * save the delta changes in database
PERFORM f_data_save.
* * clear the protocol
CLEAR cl_event_handler=>protocol_tab.
ENDIF.
WHEN OTHERS.
SET SCREEN 0.
LEAVE SCREEN.
ENDCASE.
ELSE.
SET SCREEN 0.
LEAVE SCREEN.
ENDIF.
ELSE.
SET SCREEN 0.
LEAVE SCREEN.
ENDIF.
WHEN c_check_command.”‘CHECK’.
IF g_updatable EQ abap_true.
* 1. synchronize the internal table and check against duplicate keys
CALL METHOD o_grid->check_changed_data.
* 2. if there are no duplicated keys
IF cl_event_handler=>data_changed_error = 0.
* post processing after successful synchronization
PERFORM f_data_change_post_processing CHANGING i_alv_data.
MESSAGE i010 WITH ‘There are no data inconsistencies'(004).
ENDIF.
ENDIF.
WHEN c_save_command.”‘SAVE’.
IF g_updatable EQ abap_true.
* 1. synchronize the internal table
CALL METHOD o_grid->check_changed_data.
* 2. if there are no duplicated keys
IF cl_event_handler=>data_changed_error = 0.
* post processing after successful synchronization
PERFORM f_data_change_post_processing CHANGING i_alv_data.
* 3. if the data was changed
IF NOT cl_event_handler=>protocol_tab IS INITIAL.
* save the delta changes in database
PERFORM f_data_save.
* clear the protocol
CLEAR cl_event_handler=>protocol_tab.
ELSE.
MESSAGE i010 WITH ‘There is no data to update'(003).
ENDIF.
ENDIF.
ENDIF.
ENDCASE.
CLEAR ok_code.