我的需求
和DeveloperMrMeng老师的需求差不多,我只是想做一个展示deep structure的方法,一个程序能够接受内存传值,然后这个程序能够解析内存传值的数据,当然alv展示的是内表,我需要对内存传的值做下处理,将它始终转换成内表,alv的抬头仅展示字段名称即可,因此我添加了DISPLAY_DEEP_STRUCTURE_COMPDES(展示内存传值转换的内表的方法),HOTSPOT_CLICK_COMPDESCR(热点点击纵深结构的方法),_GET_TYPE_HANDLE_COMPDESCR(构造某一层级alv展示内表的方法),_FILL_CONDENSED_DATA_COMPDESCR(填充某一层级alv展示内表的方法),_GET_LINE_COMPDESCR(获取某一层级alv展示内表构成元素的方法),_BUILD_FIELDCAT_COMPDESCR(构造fieldcat的方法)
视频效果
Deep Structure ALV
贴代码(ZDEEP_ALV类)
*class ZDEEP_ALV definition
* public
* final
* create public .
*
*public section.
*protected section.
*private section.
*ENDCLASS.
*
*
*
*CLASS ZDEEP_ALV IMPLEMENTATION.
*ENDCLASS.
CLASS zdeep_alv DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
METHODS constructor .
METHODS display_deep_structure
IMPORTING
VALUE(i_table) TYPE ANY TABLE
VALUE(i_callback_user_command) TYPE slis_formname OPTIONAL
VALUE(i_callback_pf_status_set) TYPE slis_formname OPTIONAL
VALUE(i_custom_fcat) TYPE lvc_t_fcat OPTIONAL
VALUE(i_custom_layo) TYPE lvc_s_layo OPTIONAL .
METHODS display_deep_structure_compdes
IMPORTING
VALUE(i_table) TYPE ANY TABLE
VALUE(i_callback_user_command) TYPE slis_formname OPTIONAL
VALUE(i_callback_pf_status_set) TYPE slis_formname OPTIONAL
VALUE(i_custom_fcat) TYPE lvc_t_fcat OPTIONAL
VALUE(i_custom_layo) TYPE lvc_s_layo OPTIONAL .
METHODS hotspot_click
IMPORTING
VALUE(i_selfield) TYPE slis_selfield .
METHODS hotspot_click_compdescr
IMPORTING
VALUE(i_selfield) TYPE slis_selfield .
METHODS back_click .
PROTECTED SECTION.
PRIVATE SECTION.
DATA mv_callback_pf_status_set TYPE slis_formname .
DATA mv_callback_user_command TYPE slis_formname .
DATA:
mo_display_stack TYPE STANDARD TABLE OF REF TO data .
CONSTANTS mc_stack_go TYPE char1 VALUE '1' ##NO_TEXT.
CONSTANTS mc_stack_back TYPE char1 VALUE '2' ##NO_TEXT.
DATA mt_components TYPE abap_component_tab .
DATA mt_custom_fcat TYPE lvc_t_fcat .
DATA mt_compdescr TYPE abap_compdescr_tab .
METHODS _update_display_stack
IMPORTING
!table TYPE ANY TABLE OPTIONAL
!operation TYPE char1
EXCEPTIONS
no_data .
METHODS _get_type_handle
IMPORTING
!table TYPE ANY TABLE
RETURNING
VALUE(new_table) TYPE REF TO data .
METHODS _get_type_handle_compdescr
IMPORTING
!table TYPE ANY TABLE
RETURNING
VALUE(new_table) TYPE REF TO data .
METHODS _fill_condensed_data
IMPORTING
VALUE(table) TYPE ANY TABLE
CHANGING
!condensed_data TYPE ANY TABLE .
METHODS _fill_condensed_data_compdescr
IMPORTING
VALUE(table) TYPE ANY TABLE
CHANGING
!condensed_data TYPE ANY TABLE .
METHODS _display_condensed_alv
IMPORTING
VALUE(condensed_data) TYPE ANY TABLE
!pf_status_set TYPE slis_formname OPTIONAL
!user_command TYPE slis_formname OPTIONAL
!custom_fieldcat_lvc TYPE lvc_t_fcat OPTIONAL
CHANGING
!fieldcat_lvc TYPE lvc_t_fcat OPTIONAL
!layout_lvc TYPE lvc_s_layo OPTIONAL .
METHODS _get_line_compdescr
IMPORTING
VALUE(table) TYPE ANY TABLE
RETURNING
VALUE(compdescr_table) TYPE abap_compdescr_tab .
METHODS _get_line_component
IMPORTING
VALUE(table) TYPE ANY TABLE
RETURNING
VALUE(component_table) TYPE abap_component_tab .
METHODS _build_fieldcat
IMPORTING
!table TYPE ANY TABLE
RETURNING
VALUE(fieldcat) TYPE lvc_t_fcat .
METHODS _build_fieldcat_compdescr
IMPORTING
!table TYPE ANY TABLE
RETURNING
VALUE(fieldcat) TYPE lvc_t_fcat .
ENDCLASS.
CLASS zdeep_alv IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZDEEP_ALV->BACK_CLICK
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD back_click.
_update_display_stack( operation = mc_stack_back ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZDEEP_ALV->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD constructor.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZDEEP_ALV->DISPLAY_DEEP_STRUCTURE
* +-------------------------------------------------------------------------------------------------+
* | [--->] I_TABLE TYPE ANY TABLE
* | [--->] I_CALLBACK_USER_COMMAND TYPE SLIS_FORMNAME(optional)
* | [--->] I_CALLBACK_PF_STATUS_SET TYPE SLIS_FORMNAME(optional)
* | [--->] I_CUSTOM_FCAT TYPE LVC_T_FCAT(optional)
* | [--->] I_CUSTOM_LAYO TYPE LVC_S_LAYO(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD display_deep_structure.
FIELD-SYMBOLS:<fs_new_data> TYPE STANDARD TABLE.
DATA:lt_fieldcat TYPE lvc_t_fcat.
* 将展示数据使用堆栈管理
_update_display_stack( table = i_table operation = mc_stack_go ).
* 绑定全局变量
IF i_callback_pf_status_set IS NOT INITIAL.
mv_callback_pf_status_set = i_callback_pf_status_set.
ENDIF.
IF i_callback_user_command IS NOT INITIAL.
mv_callback_user_command = i_callback_user_command.
ENDIF.
IF i_custom_fcat IS NOT INITIAL.
mt_custom_fcat = i_custom_fcat.
ENDIF.
CLEAR mt_components.
mt_components = _get_line_component( table = i_table ).
* 判断是否包含表类型或者结构类型字段
LOOP AT mt_components TRANSPORTING NO FIELDS
WHERE ( type->type_kind = cl_abap_elemdescr=>typekind_table
OR type->type_kind = cl_abap_elemdescr=>typekind_struct2
"OR type->type_kind = cl_abap_elemdescr=>typekind_struct1
)
.
EXIT.
ENDLOOP.
* 如果存在表类型字段
IF sy-subrc = 0.
* 构建新的扁平类型的内表
DATA(lo_new_data_ref) = _get_type_handle( i_table ).
ASSIGN lo_new_data_ref->* TO <fs_new_data>.
* 填充新的扁平类型的内表
_fill_condensed_data( EXPORTING table = i_table
CHANGING condensed_data = <fs_new_data> ).
ELSE.
ASSIGN i_table TO <fs_new_data>.
ENDIF.
* 构建fieldcat内表
lt_fieldcat = _build_fieldcat( table = i_table ).
* 展示ALV
me->_display_condensed_alv(
EXPORTING
condensed_data = <fs_new_data>
pf_status_set = mv_callback_pf_status_set
user_command = mv_callback_user_command
custom_fieldcat_lvc = mt_custom_fcat
CHANGING
fieldcat_lvc = lt_fieldcat
layout_lvc = i_custom_layo
).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZDEEP_ALV->HOTSPOT_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] I_SELFIELD TYPE SLIS_SELFIELD
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD hotspot_click.
FIELD-SYMBOLS:
<fs_current_display> TYPE INDEX TABLE,
<fs_table> TYPE STANDARD TABLE,
<fs_struc> TYPE any.
DATA:
lo_current_display TYPE REF TO data,
lv_obj_type TYPE char1,
lo_data TYPE REF TO data.
* 获取当前界面展示扁平内表对应的原始内表(深层内表)
READ TABLE mo_display_stack INTO lo_current_display INDEX 1.
ASSIGN lo_current_display->* TO <fs_current_display>.
READ TABLE <fs_current_display> INDEX i_selfield-tabindex ASSIGNING FIELD-SYMBOL(<fs_current_row>).
IF <fs_current_row> IS ASSIGNED.
* 获取点击单元格数据内容
ASSIGN COMPONENT i_selfield-fieldname OF STRUCTURE <fs_current_row> TO FIELD-SYMBOL(<fs_deep_field>).
* 获取点击单元格数据类型
lv_obj_type = cl_abap_tabledescr=>describe_by_data( <fs_deep_field> )->type_kind.
CASE lv_obj_type.
* 表类型
WHEN cl_abap_elemdescr=>typekind_table.
ASSIGN <fs_deep_field> TO <fs_table>.
* 深层结构或者扁平结构
WHEN cl_abap_elemdescr=>typekind_struct2 OR cl_abap_elemdescr=>typekind_struct1.
CREATE DATA lo_data LIKE TABLE OF <fs_deep_field>.
ASSIGN lo_data->* TO <fs_table>.
APPEND <fs_deep_field> TO <fs_table>.
WHEN OTHERS.
ENDCASE.
IF <fs_table> IS ASSIGNED.
IF <fs_table> IS NOT INITIAL.
display_deep_structure( i_table = <fs_table>
i_callback_user_command = mv_callback_user_command ).
ELSE.
MESSAGE 'No Data!' TYPE 'S'.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_BUILD_FIELDCAT
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-()] FIELDCAT TYPE LVC_T_FCAT
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _build_fieldcat.
DATA:
lv_struc_name TYPE tabname,
ls_fieldcat TYPE lvc_s_fcat.
* 获取行类型结构名
DATA(lv_structure) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( table ) )->get_table_line_type( )->get_relative_name( ).
lv_struc_name = lv_structure.
* 获取fieldcat信息
SELECT
a~tabname,
a~fieldname,
a~position,
a~rollname,
a~inttype,
a~datatype,
a~leng,
a~domname,
a~comptype,
b~reftable,
b~reffield,
b~reptext,
b~scrtext_s,
b~scrtext_m,
b~scrtext_l,
c~lowercase,
c~convexit,
d~ddtext AS d_ddtext,
e~ddtext AS t_ddtext,
f~ddtext AS s_ddtext
FROM dd03l AS a
LEFT OUTER JOIN dd03vt AS b
ON a~tabname = b~tabname
AND a~fieldname = b~fieldname
AND a~position = b~position
AND a~comptype = b~comptype
AND b~ddlanguage = @sy-langu
LEFT OUTER JOIN dd04l AS c
ON a~rollname = c~rollname
AND a~as4local = c~as4local
LEFT OUTER JOIN dd03t AS d
ON a~tabname = d~tabname
AND a~as4local = d~as4local
AND a~fieldname = d~fieldname
AND d~ddlanguage = @sy-langu
LEFT OUTER JOIN dd40t AS e
ON a~rollname = e~typename
AND e~ddlanguage = @sy-langu
LEFT OUTER JOIN dd02t AS f
ON a~rollname = f~tabname
AND f~ddlanguage = @sy-langu
WHERE a~tabname = @lv_struc_name
AND a~as4local = 'A'
AND a~depth = ''
* AND a~comptype NE 'S'
ORDER BY a~position
INTO TABLE @DATA(lt_fieldinfo).
LOOP AT lt_fieldinfo INTO DATA(ls_fieldinfo).
ls_fieldcat-col_pos = ls_fieldinfo-position.
ls_fieldcat-fieldname = ls_fieldinfo-fieldname.
CASE ls_fieldinfo-datatype.
* 数量类型
WHEN 'QUAN'.
ls_fieldcat-qfieldname = ls_fieldinfo-reffield.
* 金额类型
WHEN 'CURR'.
ls_fieldcat-cfieldname = ls_fieldinfo-reffield.
WHEN OTHERS.
ENDCASE.
ls_fieldcat-convexit = ls_fieldinfo-convexit.
ls_fieldcat-datatype = ls_fieldinfo-datatype.
ls_fieldcat-inttype = ls_fieldinfo-inttype.
ls_fieldcat-intlen = ls_fieldinfo-leng.
ls_fieldcat-lowercase = ls_fieldinfo-lowercase.
ls_fieldcat-reptext = ls_fieldinfo-fieldname && '(' && ls_fieldinfo-reptext && ')'.
CASE ls_fieldinfo-comptype.
* 内置类型
WHEN ''.
ls_fieldcat-reptext = ls_fieldinfo-fieldname && '(' && ls_fieldinfo-d_ddtext && ')'.
* 表类型
WHEN 'L'.
ls_fieldcat-hotspot = 'X'.
ls_fieldcat-reptext = ls_fieldinfo-fieldname && '(' && ls_fieldinfo-t_ddtext && ')'.
ls_fieldcat-just = 'L'.
* 结构
WHEN 'S'.
ls_fieldcat-hotspot = 'X'.
ls_fieldcat-reptext = ls_fieldinfo-fieldname && '(' && ls_fieldinfo-s_ddtext && ')'.
ls_fieldcat-just = 'L'.
WHEN OTHERS.
ENDCASE.
ls_fieldcat-domname = ls_fieldinfo-domname.
ls_fieldcat-ref_table = lv_struc_name.
ls_fieldcat-dd_outlen = ls_fieldinfo-leng.
* ls_fieldcat-scrtext_s = ls_fieldinfo-scrtext_s.
* ls_fieldcat-scrtext_m = ls_fieldinfo-scrtext_m.
* ls_fieldcat-scrtext_l = ls_fieldinfo-scrtext_l.
ls_fieldcat-scrtext_s = ls_fieldcat-reptext.
ls_fieldcat-scrtext_m = ls_fieldcat-reptext.
ls_fieldcat-scrtext_l = ls_fieldcat-reptext.
APPEND ls_fieldcat TO fieldcat.
CLEAR ls_fieldcat.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_DISPLAY_CONDENSED_ALV
* +-------------------------------------------------------------------------------------------------+
* | [--->] CONDENSED_DATA TYPE ANY TABLE
* | [--->] PF_STATUS_SET TYPE SLIS_FORMNAME(optional)
* | [--->] USER_COMMAND TYPE SLIS_FORMNAME(optional)
* | [--->] CUSTOM_FIELDCAT_LVC TYPE LVC_T_FCAT(optional)
* | [<-->] FIELDCAT_LVC TYPE LVC_T_FCAT(optional)
* | [<-->] LAYOUT_LVC TYPE LVC_S_LAYO(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _display_condensed_alv.
DATA:
lv_tabix TYPE i,
lv_index TYPE i.
DATA:
lt_event_exit TYPE slis_t_event_exit,
ls_event_exit TYPE slis_event_exit.
FIELD-SYMBOLS <fs_alv> TYPE STANDARD TABLE.
* 设置默认布局控制
IF layout_lvc IS INITIAL.
layout_lvc-zebra = 'X'. "颜色间隔
layout_lvc-sel_mode = 'D'. "选择模式
layout_lvc-cwidth_opt = 'A'. "列宽自适应
ENDIF.
* 如果存在自定义字段设置,将其与标准获取的字段设置合并
IF custom_fieldcat_lvc IS NOT INITIAL.
LOOP AT custom_fieldcat_lvc INTO DATA(ls_cus_fcat).
READ TABLE fieldcat_lvc ASSIGNING FIELD-SYMBOL(<fs_fieldcat>)
WITH KEY fieldname = ls_cus_fcat-fieldname
ref_table = ls_cus_fcat-ref_table.
IF sy-subrc = 0.
DO.
ADD 1 TO lv_index.
ASSIGN COMPONENT lv_index OF STRUCTURE ls_cus_fcat TO FIELD-SYMBOL(<fs_cus_fcat>).
IF <fs_cus_fcat> IS ASSIGNED.
ASSIGN COMPONENT lv_index OF STRUCTURE <fs_fieldcat> TO FIELD-SYMBOL(<fs_fcat>).
IF <fs_cus_fcat> <> <fs_fcat> AND <fs_cus_fcat> IS NOT INITIAL.
<fs_fcat> = <fs_cus_fcat>.
ENDIF.
ELSE.
EXIT.
ENDIF.
UNASSIGN:
<fs_cus_fcat>,
<fs_fcat>.
ENDDO.
CLEAR lv_index.
ENDIF.
ENDLOOP.
ENDIF.
ASSIGN condensed_data TO <fs_alv>.
* 使标准按钮->"返回",可以触发用户自定义USER_COMMAND回调函数
ls_event_exit-ucomm = '&F03'.
ls_event_exit-after = 'X'.
APPEND ls_event_exit TO lt_event_exit.
* 展示ALV
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = sy-cprog
i_callback_pf_status_set = pf_status_set
i_callback_user_command = user_command
is_layout_lvc = layout_lvc
it_fieldcat_lvc = fieldcat_lvc
i_save = 'A'
it_event_exit = lt_event_exit
TABLES
t_outtab = <fs_alv>
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_FILL_CONDENSED_DATA
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-->] CONDENSED_DATA TYPE ANY TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _fill_condensed_data.
FIELD-SYMBOLS:
<fs_table> TYPE ANY TABLE.
LOOP AT table ASSIGNING FIELD-SYMBOL(<fs_line>).
INSERT INITIAL LINE INTO TABLE condensed_data ASSIGNING FIELD-SYMBOL(<fs_new_line>).
LOOP AT mt_components ASSIGNING FIELD-SYMBOL(<fs_component>).
CASE <fs_component>-type->type_kind.
* 表类型
WHEN cl_abap_elemdescr=>typekind_table.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_line> TO <fs_table>.
IF <fs_table> IS ASSIGNED.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_new_line> TO FIELD-SYMBOL(<fs_tab_desc>).
IF <fs_tab_desc> IS ASSIGNED.
* <fs_tab_desc> = |{ icon_list }Items[ { lines( <fs_table> ) } ]|.
<fs_tab_desc> = |{ icon_list }{ <fs_component>-name }[ { lines( <fs_table> ) } ]|.
UNASSIGN:
<fs_tab_desc>,
<fs_table>.
ENDIF.
ENDIF.
* 结构类型 或 扁平结构
WHEN cl_abap_elemdescr=>typekind_struct2 OR cl_abap_elemdescr=>typekind_struct1.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_struc>).
IF <fs_struc> IS ASSIGNED.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_new_line> TO <fs_tab_desc>.
IF <fs_tab_desc> IS ASSIGNED.
<fs_tab_desc> = |{ icon_structure }{ <fs_component>-name }|.
UNASSIGN:
<fs_tab_desc>,
<fs_struc>.
ENDIF.
ENDIF.
* "扁平结构
* WHEN cl_abap_elemdescr=>typekind_struct1.
* ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_struc1>).
* IF <fs_struc1> IS ASSIGNED.
* ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_new_line> TO <fs_tab_desc>.
* IF <fs_tab_desc> IS ASSIGNED.
* <fs_tab_desc> = icon_structure.
* UNASSIGN:
* <fs_tab_desc>,
* <fs_struc1>.
* ENDIF.
* ENDIF.
* 其他类型
WHEN OTHERS.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_value>).
IF <fs_value> IS ASSIGNED.
ASSIGN COMPONENT <fs_component>-name OF STRUCTURE <fs_new_line> TO FIELD-SYMBOL(<fs_value_new>).
IF <fs_value_new> IS ASSIGNED.
<fs_value_new> = <fs_value>.
UNASSIGN:
<fs_value>,
<fs_value_new>.
ENDIF.
ENDIF.
ENDCASE.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_GET_LINE_COMPONENT
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-()] COMPONENT_TABLE TYPE ABAP_COMPONENT_TAB
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _get_line_component.
component_table = CAST cl_abap_structdescr(
CAST cl_abap_tabledescr(
cl_abap_tabledescr=>describe_by_data( table )
)->get_table_line_type( )
)->get_components( ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_GET_TYPE_HANDLE
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-()] NEW_TABLE TYPE REF TO DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _get_type_handle.
* 创建新的扁平类型对象,将表类型或者深层结构字段替换为CHAR类型
DATA(lo_new_tab) = cl_abap_tabledescr=>create(
p_line_type = cl_abap_structdescr=>create(
VALUE #( FOR wa IN mt_components
( SWITCH #(
wa-type->type_kind
* 表类型
WHEN cl_abap_elemdescr=>typekind_table
THEN VALUE #( name = wa-name type = cl_abap_elemdescr=>get_c( p_length = 70 ) )
* 深层结构或扁平结构
WHEN cl_abap_elemdescr=>typekind_struct2 "OR cl_abap_elemdescr=>typekind_struct1
THEN VALUE #( name = wa-name type = cl_abap_elemdescr=>get_c( p_length = 70 ) )
ELSE VALUE #( name = wa-name type = wa-type ) )
)
)
)
p_table_kind = cl_abap_tabledescr=>tablekind_std
p_unique = abap_false
).
CREATE DATA new_table TYPE HANDLE lo_new_tab.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_UPDATE_DISPLAY_STACK
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE(optional)
* | [--->] OPERATION TYPE CHAR1
* | [EXC!] NO_DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _update_display_stack.
DATA:lo_curr_disp TYPE REF TO data.
FIELD-SYMBOLS:<table> TYPE ANY TABLE.
CASE operation.
WHEN mc_stack_back.
DELETE mo_display_stack INDEX 1.
WHEN mc_stack_go.
IF table IS NOT SUPPLIED.
RAISE no_data.
ELSE.
* 获取类型对象
DATA(lo_handle) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( table ) ).
* 基于类型对象创建数据
CREATE DATA lo_curr_disp TYPE HANDLE lo_handle.
* 指针分配
ASSIGN lo_curr_disp->* TO <table>.
* LOOP AT table ASSIGNING FIELD-SYMBOL(<line>).
* INSERT INITIAL LINE INTO TABLE <table> ASSIGNING FIELD-SYMBOL(<new_line>).
* <new_line> = CORRESPONDING #( <line> ).
* ENDLOOP.
<table> = table.
* 将数据保存至堆栈最上层
INSERT lo_curr_disp INTO mo_display_stack INDEX 1.
ENDIF.
ENDCASE.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZDEEP_ALV->DISPLAY_DEEP_STRUCTURE_COMPDES
* +-------------------------------------------------------------------------------------------------+
* | [--->] I_TABLE TYPE ANY TABLE
* | [--->] I_CALLBACK_USER_COMMAND TYPE SLIS_FORMNAME(optional)
* | [--->] I_CALLBACK_PF_STATUS_SET TYPE SLIS_FORMNAME(optional)
* | [--->] I_CUSTOM_FCAT TYPE LVC_T_FCAT(optional)
* | [--->] I_CUSTOM_LAYO TYPE LVC_S_LAYO(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD display_deep_structure_compdes.
FIELD-SYMBOLS:<fs_new_data> TYPE STANDARD TABLE.
DATA:lt_fieldcat TYPE lvc_t_fcat.
* 将展示数据使用堆栈管理
_update_display_stack( table = i_table operation = mc_stack_go ).
* 绑定全局变量
IF i_callback_pf_status_set IS NOT INITIAL.
mv_callback_pf_status_set = i_callback_pf_status_set.
ENDIF.
IF i_callback_user_command IS NOT INITIAL.
mv_callback_user_command = i_callback_user_command.
ENDIF.
IF i_custom_fcat IS NOT INITIAL.
mt_custom_fcat = i_custom_fcat.
ENDIF.
CLEAR:mt_compdescr,mt_components.
mt_compdescr = _get_line_compdescr( table = i_table ).
mt_components = _get_line_component( table = i_table ).
* 判断是否包含表类型或者结构类型字段
LOOP AT mt_compdescr TRANSPORTING NO FIELDS
WHERE ( type_kind = cl_abap_elemdescr=>typekind_table
OR type_kind = cl_abap_elemdescr=>typekind_struct2
OR type_kind = cl_abap_elemdescr=>typekind_struct1
)
.
EXIT.
ENDLOOP.
* 如果存在表类型字段
IF sy-subrc = 0.
* 构建新的扁平类型的内表
DATA(lo_new_data_ref) = _get_type_handle_compdescr( i_table ).
ASSIGN lo_new_data_ref->* TO <fs_new_data>.
* 填充新的扁平类型的内表
_fill_condensed_data_compdescr( EXPORTING table = i_table CHANGING condensed_data = <fs_new_data> ).
ELSE.
ASSIGN i_table TO <fs_new_data>.
ENDIF.
* 构建fieldcat内表
lt_fieldcat = _build_fieldcat_compdescr( table = i_table ).
* 展示ALV
me->_display_condensed_alv(
EXPORTING
condensed_data = <fs_new_data>
pf_status_set = mv_callback_pf_status_set
user_command = mv_callback_user_command
custom_fieldcat_lvc = mt_custom_fcat
CHANGING
fieldcat_lvc = lt_fieldcat
layout_lvc = i_custom_layo
).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZDEEP_ALV->HOTSPOT_CLICK_COMPDESCR
* +-------------------------------------------------------------------------------------------------+
* | [--->] I_SELFIELD TYPE SLIS_SELFIELD
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD hotspot_click_compdescr.
FIELD-SYMBOLS:
<fs_current_display> TYPE INDEX TABLE,
<fs_table> TYPE STANDARD TABLE,
<fs_struc> TYPE any.
DATA:
lo_current_display TYPE REF TO data,
lv_obj_type TYPE char1,
lo_data TYPE REF TO data.
* 获取当前界面展示扁平内表对应的原始内表(深层内表)
READ TABLE mo_display_stack INTO lo_current_display INDEX 1.
ASSIGN lo_current_display->* TO <fs_current_display>.
READ TABLE <fs_current_display> INDEX i_selfield-tabindex ASSIGNING FIELD-SYMBOL(<fs_current_row>).
IF <fs_current_row> IS ASSIGNED.
* 获取点击单元格数据内容
ASSIGN COMPONENT i_selfield-fieldname OF STRUCTURE <fs_current_row> TO FIELD-SYMBOL(<fs_deep_field>).
* 获取点击单元格数据类型
lv_obj_type = cl_abap_tabledescr=>describe_by_data( <fs_deep_field> )->type_kind.
CASE lv_obj_type.
* 表类型
WHEN cl_abap_elemdescr=>typekind_table.
ASSIGN <fs_deep_field> TO <fs_table>.
* 深层结构或者扁平结构
WHEN cl_abap_elemdescr=>typekind_struct2 OR cl_abap_elemdescr=>typekind_struct1.
CREATE DATA lo_data LIKE TABLE OF <fs_deep_field>.
ASSIGN lo_data->* TO <fs_table>.
APPEND <fs_deep_field> TO <fs_table>.
WHEN OTHERS.
ENDCASE.
IF <fs_table> IS ASSIGNED.
IF <fs_table> IS NOT INITIAL.
display_deep_structure_compdes( i_table = <fs_table> i_callback_user_command = mv_callback_user_command ).
ELSE.
MESSAGE 'No Data!' TYPE 'S'.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_BUILD_FIELDCAT_COMPDESCR
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-()] FIELDCAT TYPE LVC_T_FCAT
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _build_fieldcat_compdescr.
DATA:lv_struc_name TYPE tabname,
ls_fieldcat TYPE lvc_s_fcat,
position TYPE dd03l-position.
* 获取行类型结构名
DATA(lv_structure) = CAST cl_abap_tabledescr( cl_abap_tabledescr=>describe_by_data( table ) )->get_table_line_type( )->get_relative_name( ).
lv_struc_name = lv_structure.
DATA(compdescr_tab) = CAST cl_abap_structdescr(
CAST cl_abap_tabledescr(
cl_abap_tabledescr=>describe_by_data( table )
)->get_table_line_type( )
)->components.
CLEAR:position.
LOOP AT compdescr_tab INTO DATA(ls_fieldinfo).
ADD 1 TO position.
ls_fieldcat-col_pos = position.
ls_fieldcat-fieldname = ls_fieldinfo-name.
* CASE ls_fieldinfo-datatype.
** 数量类型
* WHEN 'QUAN'.
* ls_fieldcat-qfieldname = ls_fieldinfo-reffield.
** 金额类型
* WHEN 'CURR'.
* ls_fieldcat-cfieldname = ls_fieldinfo-reffield.
* WHEN OTHERS.
* ENDCASE.
* ls_fieldcat-convexit = ls_fieldinfo-convexit.
* ls_fieldcat-datatype = ls_fieldinfo-datatype.
* ls_fieldcat-inttype = ls_fieldinfo-inttype.
ls_fieldcat-intlen = ls_fieldinfo-length.
* ls_fieldcat-lowercase = ls_fieldinfo-lowercase.
ls_fieldcat-reptext = ls_fieldinfo-name.
CASE ls_fieldinfo-type_kind.
* 表
WHEN 'h'.
ls_fieldcat-hotspot = 'X'.
ls_fieldcat-reptext = ls_fieldinfo-name.
ls_fieldcat-just = 'L'.
* 纵深结构
WHEN 'v'.
ls_fieldcat-hotspot = 'X'.
ls_fieldcat-reptext = ls_fieldinfo-name.
ls_fieldcat-just = 'L'.
* 扁平结构
WHEN 'u'.
ls_fieldcat-hotspot = 'X'.
ls_fieldcat-reptext = ls_fieldinfo-name.
ls_fieldcat-just = 'L'.
WHEN OTHERS.
ENDCASE.
* ls_fieldcat-domname = ls_fieldinfo-domname.
ls_fieldcat-ref_table = lv_struc_name.
ls_fieldcat-dd_outlen = ls_fieldinfo-length.
ls_fieldcat-scrtext_s = ls_fieldcat-reptext.
ls_fieldcat-scrtext_m = ls_fieldcat-reptext.
ls_fieldcat-scrtext_l = ls_fieldcat-reptext.
APPEND ls_fieldcat TO fieldcat.
CLEAR ls_fieldcat.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_FILL_CONDENSED_DATA_COMPDESCR
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-->] CONDENSED_DATA TYPE ANY TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _fill_condensed_data_compdescr.
FIELD-SYMBOLS:<fs_table> TYPE ANY TABLE.
LOOP AT table ASSIGNING FIELD-SYMBOL(<fs_line>).
INSERT INITIAL LINE INTO TABLE condensed_data ASSIGNING FIELD-SYMBOL(<fs_new_line>).
LOOP AT mt_compdescr ASSIGNING FIELD-SYMBOL(<fs_compdescr>).
CASE <fs_compdescr>-type_kind.
* 表类型
WHEN cl_abap_elemdescr=>typekind_table.
ASSIGN COMPONENT <fs_compdescr>-name OF STRUCTURE <fs_line> TO <fs_table>.
IF <fs_table> IS ASSIGNED.
ASSIGN COMPONENT <fs_compdescr>-name OF STRUCTURE <fs_new_line> TO FIELD-SYMBOL(<fs_tab_desc>).
IF <fs_tab_desc> IS ASSIGNED.
* <fs_tab_desc> = |{ icon_list }Items[ { lines( <fs_table> ) } ]|.
<fs_tab_desc> = |{ icon_list }{ <fs_compdescr>-name }[ { lines( <fs_table> ) } ]|.
UNASSIGN:
<fs_tab_desc>,
<fs_table>.
ENDIF.
ENDIF.
* 结构类型 或 扁平结构
WHEN cl_abap_elemdescr=>typekind_struct2 OR cl_abap_elemdescr=>typekind_struct1.
ASSIGN COMPONENT <fs_compdescr>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_struc>).
IF <fs_struc> IS ASSIGNED.
ASSIGN COMPONENT <fs_compdescr>-name OF STRUCTURE <fs_new_line> TO <fs_tab_desc>.
IF <fs_tab_desc> IS ASSIGNED.
<fs_tab_desc> = |{ icon_structure }{ <fs_compdescr>-name }|.
UNASSIGN:
<fs_tab_desc>,
<fs_struc>.
ENDIF.
ENDIF.
* 其他类型
WHEN OTHERS.
ASSIGN COMPONENT <fs_compdescr>-name OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_value>).
IF <fs_value> IS ASSIGNED.
ASSIGN COMPONENT <fs_compdescr>-name OF STRUCTURE <fs_new_line> TO FIELD-SYMBOL(<fs_value_new>).
IF <fs_value_new> IS ASSIGNED.
<fs_value_new> = <fs_value>.
UNASSIGN:
<fs_value>,
<fs_value_new>.
ENDIF.
ENDIF.
ENDCASE.
ENDLOOP.
ENDLOOP.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_GET_LINE_COMPDESCR
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-()] COMPDESCR_TABLE TYPE ABAP_COMPDESCR_TAB
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _get_line_compdescr.
compdescr_table = CAST cl_abap_structdescr(
CAST cl_abap_tabledescr(
cl_abap_tabledescr=>describe_by_data( table )
)->get_table_line_type( )
)->components.
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZDEEP_ALV->_GET_TYPE_HANDLE_COMPDESCR
* +-------------------------------------------------------------------------------------------------+
* | [--->] TABLE TYPE ANY TABLE
* | [<-()] NEW_TABLE TYPE REF TO DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD _get_type_handle_compdescr.
* 创建新的扁平类型对象,将表类型或者深层结构字段替换为CHAR类型
DATA:componentdescr TYPE abap_componentdescr,
componentdescr_tab TYPE abap_component_tab.
LOOP AT mt_compdescr ASSIGNING FIELD-SYMBOL(<mt_compdescr>).
CLEAR:componentdescr.
componentdescr-name = <mt_compdescr>-name.
CASE <mt_compdescr>-type_kind.
WHEN cl_abap_elemdescr=>typekind_table.
READ TABLE mt_components INTO DATA(wa_mt_components) WITH KEY name = <mt_compdescr>-name.
IF sy-subrc EQ 0.
componentdescr-type ?= cl_abap_elemdescr=>get_c( p_length = 70 ).
ELSE.
CONTINUE.
ENDIF.
WHEN cl_abap_elemdescr=>typekind_struct2 OR cl_abap_elemdescr=>typekind_struct1.
componentdescr-type ?= cl_abap_elemdescr=>get_c( p_length = 70 ).
WHEN OTHERS.
* TRY.
* componentdescr-type ?= cl_abap_elemdescr=>describe_by_name( p_name = <mt_compdescr>-name ).
* CATCH type_not_found.
componentdescr-type ?= cl_abap_elemdescr=>get_by_kind( p_type_kind = <mt_compdescr>-type_kind p_length = <mt_compdescr>-length p_decimals = <mt_compdescr>-decimals ).
* ENDTRY.
ENDCASE.
APPEND componentdescr TO componentdescr_tab.
ENDLOOP.
DATA(lo_new_tab) = cl_abap_tabledescr=>create(
p_line_type = cl_abap_structdescr=>create( componentdescr_tab )
p_table_kind = cl_abap_tabledescr=>tablekind_std
p_unique = abap_false
).
CREATE DATA new_table TYPE HANDLE lo_new_tab.
ENDMETHOD.
ENDCLASS.
贴代码(ALV展示Deep Structure)
*&---------------------------------------------------------------------*
*& Report ZDEEP_ALV
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zdeep_alv.
DATA:go_deep_alv TYPE REF TO zdeep_alv.
FIELD-SYMBOLS:<tab> TYPE STANDARD TABLE.
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE t1.
PARAMETERS:p_stru TYPE rs38l_typ NO-DISPLAY,
p_kind TYPE abap_typecategory NO-DISPLAY.
SELECTION-SCREEN END OF BLOCK b1.
START-OF-SELECTION.
PERFORM frm_show_deep_alv.
*&---------------------------------------------------------------------*
*& Form FRM_SHOW_DEEP_ALV
*&---------------------------------------------------------------------*
*& 展示ALV
*&---------------------------------------------------------------------*
FORM frm_show_deep_alv .
DATA:dref TYPE REF TO data,
dref_tab TYPE REF TO data,
data_type TYPE REF TO cl_abap_datadescr.
UNASSIGN <tab>.
CHECK p_stru IS NOT INITIAL.
TRY.
data_type ?= cl_abap_datadescr=>describe_by_name( p_name = p_stru ).
CATCH cx_sy_move_cast_error.
EXIT.
ENDTRY.
IF p_kind = 'T'."表的话按照p_stru的类型来创建内表
IF data_type->kind = 'T'.
CREATE DATA dref_tab TYPE (p_stru).
ELSE.
CREATE DATA dref_tab TYPE TABLE OF (p_stru).
ENDIF.
IF dref_tab IS BOUND.
ASSIGN dref_tab->* TO <tab>.
ENDIF.
CHECK <tab> IS ASSIGNED.
TRY.
IMPORT data = <tab> FROM MEMORY ID 'ZDEEP_ALV'.
CATCH cx_sy_import_mismatch_error.
MESSAGE s000(oo) WITH '结构未匹配' DISPLAY LIKE 'E'.
RETURN.
ENDTRY.
IF sy-subrc EQ 0.
FREE MEMORY ID 'ZDEEP_ALV'.
ENDIF.
ELSE."导入、导出、更改得判断下p_stru到底是结构还是表
CREATE DATA dref TYPE HANDLE data_type.
IF dref IS BOUND.
ASSIGN dref->* TO FIELD-SYMBOL(<dref>).
ENDIF.
CHECK <dref> IS ASSIGNED.
TRY.
IMPORT data = <dref> FROM MEMORY ID 'ZDEEP_ALV'.
CATCH cx_sy_import_mismatch_error.
MESSAGE s000(oo) WITH '结构未匹配' DISPLAY LIKE 'E'.
RETURN.
ENDTRY.
IF sy-subrc EQ 0.
FREE MEMORY ID 'ZDEEP_ALV'.
ENDIF.
IF data_type->kind = 'T'.
ASSIGN <dref> TO <tab>.
ELSE.
CREATE DATA dref_tab TYPE TABLE OF (p_stru).
IF dref_tab IS BOUND.
ASSIGN dref_tab->* TO <tab>.
ENDIF.
CHECK <tab> IS ASSIGNED.
APPEND <dref> TO <tab>.
ENDIF.
ENDIF.
CHECK <tab> IS NOT INITIAL.
CREATE OBJECT go_deep_alv.
go_deep_alv->display_deep_structure_compdes(
i_table = <tab>
i_callback_pf_status_set = 'FRM_STATUS_SET'
i_callback_user_command = 'FRM_USER_COMMAND'
).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_STATUS_SET
*&---------------------------------------------------------------------*
*& GUI状态栏设置
*&---------------------------------------------------------------------*
*& --> RT_EXTAB 排除按钮
*&---------------------------------------------------------------------*
FORM frm_status_set USING rt_extab TYPE slis_t_extab.
SET PF-STATUS 'STANDARD'." EXCLUDING RT_EXTAB.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_USER_COMMAND
*&---------------------------------------------------------------------*
*& 用户按钮事件响应
*&---------------------------------------------------------------------*
*& --> R_UCOMM 事件码
*& --> RS_SELFIELD 操作数据字段信息
*&---------------------------------------------------------------------*
FORM frm_user_command USING r_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.
CASE r_ucomm.
WHEN '&IC1'.
go_deep_alv->hotspot_click_compdescr( i_selfield = rs_selfield ).
WHEN '&F03'.
go_deep_alv->back_click( ).
WHEN OTHERS.
ENDCASE.
ENDFORM.