实现Table Maintain
通过类CL_GUI_ALV_GRID,实现Table Maintain功能。
实现效果:
1.创建Program;
2.创建空Screen 100;
3.创建GUI Status;
Program:实例代码
"cl_gui_alv_grid事件
CLASS zcl_tabm_event_handler DEFINITION.
PUBLIC SECTION.
"user command
CLASS-METHODS:m_user_command FOR EVENT user_command OF cl_gui_alv_grid
IMPORTING e_ucomm.
"data changed
CLASS-METHODS:m_data_changed FOR EVENT data_changed OF cl_gui_alv_grid
IMPORTING er_data_changed
e_onf4
e_onf4_before
e_onf4_after
e_ucomm.
ENDCLASS.
CLASS zcl_tabm_event_handler IMPLEMENTATION.
METHOD m_user_command.
DATA:lv_mes TYPE string.
lv_mes = 'function:' && e_ucomm.
MESSAGE lv_mes TYPE 'I'.
ENDMETHOD.
METHOD m_data_changed.
DATA:lt_mod_data TYPE lvc_t_modi.
DATA:ls_mod_data TYPE lvc_s_modi.
lt_mod_data = er_data_changed->mt_mod_cells.
"循環更改數據
LOOP AT lt_mod_data INTO ls_mod_data.
* "設置錯誤信息
* er_data_changed->add_protocol_entry(
* EXPORTING
* i_msgid = '00'
* i_msgty = 'E'
* i_msgno = '001'
* i_msgv1 = '錯誤信息!'
* i_fieldname = ls_mod_data-fieldname
* ).
"更新數據表
er_data_changed->modify_cell(
EXPORTING
i_row_id = ls_mod_data-row_id
i_fieldname = ls_mod_data-fieldname
i_value = ls_mod_data-value
).
ENDLOOP.
ENDMETHOD.
ENDCLASS.
CLASS zcl_tab_maintain DEFINITION.
PUBLIC SECTION.
"table name
DATA:lv_tabname TYPE ddobjname.
DATA:lo_container TYPE REF TO cl_gui_docking_container.
DATA:lo_alv TYPE REF TO cl_gui_alv_grid.
"table data
DATA:lo_table TYPE REF TO DATA.
"alv field字段
DATA:lt_fcat TYPE lvc_t_fcat.
DATA:ls_fcat TYPE lvc_s_fcat.
"alv layout
DATA:ls_layout TYPE lvc_s_layo.
"table status
DATA:lv_tab_status TYPE C LENGTH 1. "C為修改,空為顯示,A為添加
"保存table結構類型,line結構體類型
DATA:lo_tabledescr TYPE REF TO cl_abap_tabledescr.
DATA:lo_structdescr TYPE REF TO cl_abap_structdescr.
METHODS:constructor IMPORTING iv_tabname TYPE ddobjname.
METHODS:m_init_alv.
METHODS:m_show_alv.
METHODS:m_get_fcat RETURNING VALUE(et_fcat) TYPE lvc_t_fcat.
METHODS:m_set_fcat IMPORTING it_fcat TYPE lvc_t_fcat.
METHODS:m_get_layout RETURNING VALUE(es_layout) TYPE lvc_s_layo.
METHODS:m_set_layout IMPORTING is_layout TYPE lvc_s_layo.
METHODS:m_set_status IMPORTING iv_status TYPE char1.
METHODS:m_get_status RETURNING VALUE(ev_status) TYPE char1.
METHODS:m_refresh_alv.
"some action
METHODS:m_edit_action.
METHODS:m_add_action.
METHODS:m_del_action.
METHODS:m_save_action.
PRIVATE SECTION.
METHODS:m_get_data IMPORTING iv_tab_name TYPE ddobjname.
METHODS:m_build_filedcat IMPORTING iv_structure_name TYPE ddobjname.
METHODS:m_build_layout.
METHODS:m_set_events.
ENDCLASS.
CLASS zcl_tab_maintain IMPLEMENTATION.
METHOD:constructor.
DATA:lv_msg TYPE string.
DATA:lo_struct_type TYPE REF TO cl_abap_structdescr.
DATA:lo_table_type TYPE REF TO cl_abap_tabledescr.
"自定義字段component
DATA:lt_comp_tab TYPE cl_abap_structdescr=>component_table.
DATA:ls_comp_tab LIKE LINE OF lt_comp_tab.
DATA:lo_exception TYPE REF TO cx_root.
DATA:lv_gotstate TYPE ddgotstate.
TRY.
"創建表名
lv_tabname = iv_tabname.
"檢查table是否存在
CALL FUNCTION 'DDIF_TABL_GET'
EXPORTING
NAME = lv_tabname
IMPORTING
GOTSTATE = lv_gotstate.
IF SY-SUBRC <> 0 OR lv_gotstate IS INITIAL.
lv_msg = 'Table:' && lv_tabname && ` do not exist!`.
MESSAGE lv_msg TYPE 'E'.
ENDIF.
"創建table
lo_struct_type ?= cl_abap_typedescr=>describe_by_name( lv_tabname ).
lt_comp_tab = lo_struct_type->get_components( ).
"最終結構創建table
lo_structdescr = cl_abap_structdescr=>create( lt_comp_tab ).
lo_tabledescr = cl_abap_tabledescr=>create( lo_structdescr ).
"創建table
CREATE DATA lo_table TYPE HANDLE lo_tabledescr.
CATCH cx_root INTO lo_exception.
lv_msg = lo_exception->get_text( ).
MESSAGE lv_msg TYPE 'E'.
ENDTRY.
ENDMETHOD.
METHOD:m_init_alv.
"創建容器
CREATE OBJECT lo_container
EXPORTING
dynnr = '100'
repid = sy-repid
extension = 1000.
"創建alv
IF lo_alv IS INITIAL.
CREATE OBJECT lo_alv
EXPORTING i_parent = lo_container.
ENDIF.
"獲取數據
me->m_get_data( lv_tabname ).
"fieldcat設置
me->m_build_filedcat( lv_tabname ).
"layout設置
me->m_build_layout( ).
"設置event
me->m_set_events( ).
ENDMETHOD.
METHOD:m_show_alv.
FIELD-SYMBOLS:<f_table> TYPE STANDARD TABLE.
ASSIGN lo_table->* TO <f_table>.
"顯示alv
lo_alv->set_table_for_first_display(
EXPORTING
"layout
is_layout = ls_layout
CHANGING
it_fieldcatalog = lt_fcat
it_outtab = <f_table> ).
ENDMETHOD.
"獲取,設置fieldcat
METHOD:m_get_fcat.
et_fcat = lt_fcat.
ENDMETHOD.
METHOD:m_set_fcat.
lt_fcat = it_fcat.
ENDMETHOD.
"獲取,設置layout
METHOD:m_get_layout.
es_layout = ls_layout.
ENDMETHOD.
METHOD:m_set_layout.
ls_layout = is_layout.
ENDMETHOD.
"獲取table status
METHOD:m_set_status.
lv_tab_status = iv_status.
ENDMETHOD.
METHOD:m_get_status.
ev_status = lv_tab_status.
ENDMETHOD.
"獲取table數據
METHOD:m_get_data.
FIELD-SYMBOLS:<f_table> TYPE STANDARD TABLE.
ASSIGN lo_table->* TO <f_table>.
"查詢數據
SELECT * INTO CORRESPONDING FIELDS OF TABLE <f_table> FROM (iv_tab_name).
ENDMETHOD.
"自動生成fieldcat
METHOD:m_build_filedcat.
DATA:lv_index TYPE I.
FIELD-SYMBOLS:<f_fcat> TYPE lvc_s_fcat.
"fieldcat使用用戶設置
IF lt_fcat IS NOT INITIAL.
RETURN.
ENDIF.
"獲取fieldcatalog
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = iv_structure_name
CHANGING
ct_fieldcat = lt_fcat
EXCEPTIONS
inconsistent_interface = 1
program_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
MESSAGE 'Get fieldcatlog failed!' TYPE 'E'.
RETURN.
ENDIF.
LOOP AT lt_fcat ASSIGNING <f_fcat>.
lv_index = sy-tabix.
<f_fcat>-col_pos = lv_index.
<f_fcat>-tabname = iv_structure_name.
ENDLOOP.
ENDMETHOD.
"自動生成layout
METHOD:m_build_layout.
"編輯設置
ls_layout-edit = ''. "是否可編輯,整體控制
"顯示設置
ls_layout-cwidth_opt = 'X'. "是否自動列寬
ls_layout-no_toolbar = ''. "是否隱藏toolbar.
"選擇模式,默認單選,A:行,列選擇;B:單行選擇;C:多行選擇;D:單元格選擇
ls_layout-sel_mode = 'A'.
ENDMETHOD.
METHOD:m_set_events.
"設置function相應事件
SET HANDLER zcl_tabm_event_handler=>m_user_command FOR lo_alv.
SET HANDLER zcl_tabm_event_handler=>m_data_changed FOR lo_alv.
"註冊enter事件
lo_alv->register_edit_event(
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter
).
"註冊修改單元格事件
lo_alv->register_edit_event(
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_modified
).
ENDMETHOD.
METHOD:m_refresh_alv.
lo_alv->refresh_table_display( ).
ENDMETHOD.
"edit action
METHOD:m_edit_action.
"alv field字段
FIELD-SYMBOLS:<f_fcat> TYPE lvc_s_fcat.
"修改edit狀態
LOOP AT lt_fcat ASSIGNING <f_fcat>.
"特定欄位控制
* IF <f_fcat>-fieldname = ''.
* <f_fcat>-edit = 'X'.
* ENDIF.
IF lv_tab_status = ''.
<f_fcat>-edit = 'X'.
ELSEIF lv_tab_status = 'C'.
<f_fcat>-edit = ''.
ENDIF.
ENDLOOP.
"設置status
IF lv_tab_status = ''.
lv_tab_status = 'C'.
ELSEIF lv_tab_status = 'C'.
lv_tab_status = ''.
ENDIF.
"刷新
me->m_show_alv( ).
ENDMETHOD.
"添加空行
METHOD:m_add_action.
DATA:lo_line TYPE REF TO DATA.
FIELD-SYMBOLS:<f_table> TYPE STANDARD TABLE.
FIELD-SYMBOLS:<f_line> TYPE ANY.
"alv field字段
FIELD-SYMBOLS:<f_fcat> TYPE lvc_s_fcat.
ASSIGN lo_table->* TO <f_table>.
CREATE DATA lo_line LIKE LINE OF <f_table>.
ASSIGN lo_line->* TO <f_line>.
INSERT <f_line> INTO <f_table> INDEX 1.
"設置編輯狀態
lv_tab_status = 'A'.
"修改edit狀態
LOOP AT lt_fcat ASSIGNING <f_fcat>.
"特定欄位控制
* IF <f_fcat>-fieldname = ''.
* <f_fcat>-edit = 'X'.
* ENDIF.
IF <f_fcat>-edit = 'X'.
EXIT.
ENDIF.
<f_fcat>-edit = 'X'.
ENDLOOP.
"刷新
me->m_show_alv( ).
ENDMETHOD.
"刪除操作
METHOD:m_del_action.
FIELD-SYMBOLS:<f_table> TYPE STANDARD TABLE.
FIELD-SYMBOLS:<f_del_table> TYPE STANDARD TABLE.
FIELD-SYMBOLS:<f_line> TYPE ANY.
DATA:lt_rows TYPE lvc_t_row.
DATA:ls_rows TYPE lvc_s_row.
DATA:lo_del_table TYPE REF TO DATA.
"創建table
CREATE DATA lo_del_table TYPE HANDLE lo_tabledescr.
"獲取選擇行
lo_alv->get_selected_rows(
IMPORTING
et_index_rows = lt_rows
).
"獲取table,刪除選擇行
ASSIGN lo_table->* TO <f_table>.
ASSIGN lo_del_table->* TO <f_del_table>.
"獲取刪除內表
LOOP AT lt_rows INTO ls_rows.
READ TABLE <f_table> INDEX ls_rows-index ASSIGNING <f_line>.
APPEND <f_line> TO <f_del_table>.
ENDLOOP.
"刪除當前內表
LOOP AT lt_rows INTO ls_rows.
DELETE <f_table> INDEX ls_rows-index.
ENDLOOP.
DELETE (lv_tabname) FROM TABLE <f_del_table>.
"刷新
me->m_show_alv( ).
ENDMETHOD.
"保存操作
METHOD:m_save_action.
FIELD-SYMBOLS:<f_table> TYPE STANDARD TABLE.
"alv field字段
FIELD-SYMBOLS:<f_fcat> TYPE lvc_s_fcat.
"檢查邏輯
"會調用data changed事件
"會彈出檢查相關錯誤信息
"lo_alv->check_changed_data( ).
"獲取table
ASSIGN lo_table->* TO <f_table>.
"更新數據表
MODIFY (lv_tabname) FROM TABLE <f_table>.
IF sy-subrc = 0.
MESSAGE 'Save success!' TYPE 'S'.
ENDIF.
"設置編輯狀態
lv_tab_status = ''.
"修改edit狀態
LOOP AT lt_fcat ASSIGNING <f_fcat>.
"特定欄位控制
* IF <f_fcat>-fieldname = ''.
* <f_fcat>-edit = 'X'.
* ENDIF.
<f_fcat>-edit = ''.
ENDLOOP.
"刷新
me->m_show_alv( ).
ENDMETHOD.
ENDCLASS.
"table maintain類對象
DATA:lo_tab_maintain TYPE REF TO zcl_tab_maintain.
SELECTION-SCREEN BEGIN OF BLOCK blk1 WITH FRAME TITLE text-001.
PARAMETERS:p_tab TYPE ddobjname. "maintain table name
SELECTION-SCREEN END OF BLOCK blk1.
START-OF-SELECTION.
PERFORM f_show_alv.
FORM f_show_alv.
CREATE OBJECT lo_tab_maintain
EXPORTING
iv_tabname = p_tab.
lo_tab_maintain->m_init_alv( ).
lo_tab_maintain->m_show_alv( ).
CALL SCREEN 100.
ENDFORM.
*&---------------------------------------------------------------------*
*& Module STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE STATUS_0100 OUTPUT.
SET PF-STATUS 'STATUS_100'.
* SET TITLEBAR 'xxx'.
ENDMODULE. " STATUS_0100 OUTPUT
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_0100 INPUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
MODULE USER_COMMAND_0100 INPUT.
DATA:g_ok_code TYPE sy-ucomm.
CASE g_ok_code.
WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
LEAVE PROGRAM.
WHEN 'EDIT'.
PERFORM f_edit_action.
WHEN 'ADD'.
PERFORM f_add_action.
WHEN 'DELETE'.
PERFORM f_delete_action.
WHEN 'SAVE'.
PERFORM f_save_action.
WHEN OTHERS.
ENDCASE.
ENDMODULE. " USER_COMMAND_0100 INPUT
"edit action
FORM f_edit_action.
lo_tab_maintain->m_edit_action( ).
ENDFORM.
"add action
FORM f_add_action.
lo_tab_maintain->m_add_action( ).
ENDFORM.
"delete action
FORM f_delete_action.
lo_tab_maintain->m_del_action( ).
ENDFORM.
"save action
FORM f_save_action.
lo_tab_maintain->m_save_action( ).
ENDFORM.