ABAP为动态编程提供了RTTI技术,我们可以通过一系列descriptor获取DDIC对象的属性,也能通过这些属性创建DDIC对象。根据这个特性,我们就可以根据输入的透明表名,动态地生成可编辑地ALV。
输入界面,动态地输入表名。
生成效果示例(这里用了一个自建表来展示效果)。
事务代码SE16可以看到数据已成功维护进了透明表(这里用了一个自建表来展示效果)。
代码如下:
(注意: 本程序使用了自定义的pf_status,如果其他人希望本程序运行,需要在自己的pf_status中增加&SAVE, &ADD, &DEL等按钮 )
*&---------------------------------------------------------------------*
*& Report ZYREPO1_PREPARE
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zyrepo1_prepare.
TABLES:
dd02l, "Table Names
dd03l. "Table Fields
DATA:
g_flag TYPE i VALUE 0,
lr_table TYPE REF TO data,
lr_tab01 TYPE REF TO data,
lr_str01 TYPE REF TO data,
lo_table TYPE REF TO cl_abap_tabledescr, "Source table descr
lo_tab01 TYPE REF TO cl_abap_tabledescr, "Target table descr
lo_struc TYPE REF TO cl_abap_structdescr,"Source structure descr
lo_str01 TYPE REF TO cl_abap_structdescr."Target Structure descr
DATA:
lt_list TYPE ddfields, "field list
wa_list LIKE LINE OF lt_list, "components
lt_comp TYPE abap_component_tab.
FIELD-SYMBOLS:
<ft_table> TYPE STANDARD TABLE,
<ft_tab01> TYPE STANDARD TABLE,
<fs_line> TYPE any,
<fs_field> TYPE any.
DATA:
gt_fieldcat TYPE lvc_t_fcat,
gs_fieldcat TYPE lvc_s_fcat,
gs_layout TYPE lvc_s_layo.
SELECTION-SCREEN BEGIN OF BLOCK b1.
PARAMETERS:
p_tabnam TYPE dd02l-tabname OBLIGATORY.
SELECTION-SCREEN END OF BLOCK b1.
AT SELECTION-SCREEN.
"Only customizing table are
allowed to be modified for security
IF p_tabnam IS NOT INITIAL AND p_tabnam+0(1) <> ‘Z‘.
MESSAGE ‘只有自建表可供维护‘ TYPE ‘I‘ DISPLAY LIKE ‘E‘.
LEAVE PROGRAM.
ENDIF.
START-OF-SELECTION.
PERFORM get_tab_info.
PERFORM set_fieldcat.
PERFORM show_alv.
FORM get_tab_info.
"Create source table
CREATE DATA lr_table TYPE TABLE OF (p_tabnam).
ASSIGN lr_table->* TO <ft_table>.
"Fill source table if value exist
SELECT *
FROM (p_tabnam)
INTO CORRESPONDING FIELDS OF TABLE <ft_table>.
"Get structure, field, component info from source table
lo_table ?= cl_abap_typedescr=>describe_by_data( <ft_table> ).
lo_struc ?= lo_table->get_table_line_type( ).
lt_list = lo_struc->get_ddic_field_list( ).
lt_comp = lo_struc->get_components( ).
"Create target table
lo_tab01 = cl_abap_tabledescr=>create( p_line_type = lo_struc ).
CREATE DATA lr_tab01 TYPE HANDLE lo_tab01.
ASSIGN lr_tab01->* TO <ft_tab01>.
"Assign records from source table to target table
IF lines( <ft_table> ) > 0.
LOOP AT <ft_table> ASSIGNING <fs_line>.
APPEND <fs_line> TO <ft_tab01>.
ENDLOOP.
ENDIF.
"Give an extra void line to target table
lo_str01 = cl_abap_structdescr=>create( lt_comp ).
CREATE DATA lr_str01 TYPE HANDLE lo_str01.
ASSIGN lr_str01->* TO <fs_line>.
APPEND <fs_line> TO <ft_tab01>.
ENDFORM.
FORM set_fieldcat.
"Generate fieldcat dynamically
IF lt_list IS NOT INITIAL.
LOOP AT lt_list INTO wa_list.
gs_fieldcat-fieldname = wa_list-fieldname.
gs_fieldcat-seltext = wa_list-fieldtext.
gs_fieldcat-coltext = gs_fieldcat-seltext.
gs_fieldcat-col_opt = ‘X‘.
gs_fieldcat-edit = ‘X‘.
APPEND gs_fieldcat TO gt_fieldcat.
CLEAR gs_fieldcat.
ENDLOOP.
ENDIF.
ENDFORM.
FORM show_alv.
CALL FUNCTION ‘REUSE_ALV_GRID_DISPLAY_LVC‘
EXPORTING
i_callback_program = sy-repid
is_layout_lvc = gs_layout
it_fieldcat_lvc = gt_fieldcat[]
i_callback_user_command = ‘ALV_COMMAND‘
i_callback_pf_status_set = ‘ALV_PF_STATUS‘
i_save = ‘A‘
"i_grid_title = g_title
"it_sort_lvc = gt_sort[]
"it_events = gt_events[]
TABLES
t_outtab = <ft_tab01>
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDFORM.
FORM alv_pf_status USING rt_extab TYPE slis_t_extab.
DATA:
fcode LIKE LINE OF rt_extab.
"Customizing pf_status
SET PF-STATUS ‘PF_STATUS1‘ EXCLUDING rt_extab.
ENDFORM.
FORM alv_command
USING ucomm LIKE sy-ucomm
selfield TYPE slis_selfield.
DATA:
ref_grid TYPE REF TO cl_gui_alv_grid,
lt_filtered TYPE lvc_t_fidx,
stbl TYPE lvc_s_stbl,
l_index LIKE LINE OF lt_filtered.
"Get ALV grid
CALL FUNCTION ‘GET_GLOBALS_FROM_SLVC_FULLSCR‘
IMPORTING
e_grid = ref_grid.
CALL METHOD ref_grid->check_changed_data.
"React to command
CASE ucomm.
WHEN ‘&SAVE‘.
PERFORM save_data.
WHEN ‘&ADD‘.
PERFORM add_line.
WHEN ‘&DEL‘.
PERFORM del_line USING selfield-tabindex.
ENDCASE.
"Refresh
IF ref_grid IS NOT INITIAL.
CALL METHOD ref_grid->check_changed_data.
stbl-row = ‘X‘.
stbl-col = ‘X‘.
CALL METHOD ref_grid->refresh_table_display
EXPORTING
is_stable = stbl.
ENDIF.
ENDFORM.
FORM save_data.
DATA:
l_success TYPE i VALUE 0.
LOOP AT <ft_tab01> ASSIGNING <fs_line>.
IF <fs_line> IS NOT INITIAL.
MODIFY (p_tabnam)
FROM <fs_line>.
IF sy-subrc = 0.
ELSE.
l_success = sy-subrc.
EXIT.
ENDIF.
ENDIF.
ENDLOOP.
IF l_success = 0.
COMMIT WORK AND WAIT.
MESSAGE ‘更新数据成功‘ TYPE ‘S‘.
ELSE.
ROLLBACK WORK.
MESSAGE ‘更新失败,已回滚‘ TYPE ‘S‘ DISPLAY LIKE ‘E‘.
ENDIF.
ENDFORM.
FORM add_line.
ASSIGN lr_str01->* TO <fs_line>.
APPEND <fs_line> TO <ft_tab01>.
ENDFORM.
FORM del_line USING tab_index.
READ TABLE <ft_tab01> ASSIGNING <fs_line> INDEX tab_index.
DELETE (p_tabnam) FROM <fs_line>.
DELETE <ft_tab01> INDEX tab_index.
ENDFORM.
用RTTI实现动态可维护ALV表的DEMO - Intercalaryland
原文:https://www.cnblogs.com/Intercalaryland/p/12036270.html