目录
概述
一直以来,不论是新的项目或运维期间,进行得最多的开发可能就是ALV报表了。常规的报表开发方式总是需要自己写一大堆东西,而且每个报表写一遍,重复性的工作太多了。尽管可以复制粘贴,但总归还是非常不爽的,做一个资深的老码农,这一点是无法忍受的 。
东西早就有了,只是最近才有时间再整理一下分享出来。
在程序完成取数逻辑之后,只需要一句话即可完成ALV展示。如果需要进一步的扩展,比如自定义status、layout、fieldcat或者其他sort、event也都是没问题的。总体能去掉传统ALV展示开发90%的工作量。
效果展示
几乎能实现标准ALV 90%以上的功能,满足绝大部分日常所需。
使用方法
1. 纯显示ALV
1.1 ALV结构定义
SE11定义用于ALV显示的结构,比较推荐用这种方式,可以避免多坑。比如:数量字段与单位字段的关联关系、有conversion字段的显示等等。而且在自定义结果事,可以自定义给出alv显示的列标题,如下图。
1.2 ALV调用
在报表程序中,完成数据读取和整理之后,存入内表(如:GT_DATA),然后按如下方式调用ALV显示的funciton。对于纯显示的报表,这一句就够了。
CALL FUNCTION 'ZFUNC_ALV_BASE'
EXPORTING
iv_internal_tabname = 'GT_DATA' ""内表名
iv_alv_struct = ' ZSVC_CONFIG_003_ALV'."" ALV结构名
2. 自定义PBO(可选)
程序里自己写一个form,里面自己写自己的逻辑就行了
*&---> custom PBO
FORM frm_pbo USING p_rt_extab.
ENDFORM.
3. 自定义PAI(可选)
程序里自己写一个form,里面自己写自己的逻辑就行了
*&---> custom PAI
FORM frm_pai USING r_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.” TYPE slis_t_event.
ENDFORM.
4. 自定义layout(可选)
对于需要自定义layout的报表,就在程序里自己写一个form,里面自己写自己的逻辑就行了
*&---> custom layout
FORM frm_set_layout_palv CHANGING ls_layout type lvc_s_layo.
ENDFORM.
5. 自定义fieldcat(可选)
程序里自己写一个form,里面自己写自己的逻辑就行了
*&---> custom fieldcat
FORM frm_set_fcat TABLES lt_fcat STRUCTURE lvc_s_fcat.
ENDFORM.
6. 自定义SORT(可选)
程序里自己写一个form,里面自己写自己的逻辑就行了
*&---> custom SORT
FORM frm_set_sort TABLES lt_sort TYPE lvc_t_sort.
ENDFORM.
7. 自定义event(可选)
程序里自己写一个form,里面自己写自己的逻辑就行了
*&---> custom EVENT
FORM frm_set_events TABLES lt_event TYPE slis_t_event.
ENDFORM.
代码实现
1. Function
新建一个function,名字自取。
FUNCTION zfunc_alv_base.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" VALUE(IV_INTERNAL_TABNAME) TYPE TABNAME
*" VALUE(IV_ALV_STRUCT) TYPE TABNAME
*"----------------------------------------------------------------------
DATA:
lv_tabname TYPE tabname,
lv_title TYPE lvc_title,
ls_layout TYPE lvc_s_layo,
lt_fcat TYPE lvc_t_fcat,
lt_event TYPE slis_t_event,
lt_sort TYPE lvc_t_sort.
FIELD-SYMBOLS:
<ft_data> TYPE STANDARD TABLE.
lv_tabname = |({ sy-cprog }){ iv_internal_tabname }|.
ASSIGN (lv_tabname) TO <ft_data>.
CHECK <ft_data> IS NOT INITIAL.
*&---> layout
ls_layout-cwidth_opt = 'X'.
ls_layout-zebra = 'X'.
PERFORM frm_set_layout_palv IN PROGRAM (sy-cprog) IF FOUND
CHANGING ls_layout.
"" Sample
* FORM frm_set_layout_palv CHANGING ls_layout type lvc_s_layo.
*
* ENDFORM.
*&---> fieldcat
PERFORM frm_set_fieldcat TABLES lt_fcat
USING iv_alv_struct.
PERFORM frm_set_fcat IN PROGRAM (sy-cprog) IF FOUND
TABLES lt_fcat.
"" Sample
* FORM frm_set_fcat TABLES lt_fcat STRUCTURE lvc_s_fcat.
*
** DELETE lt_fcat WHERE fieldname+0(4) = 'UPD_'.
*
* ENDFORM.
*&---> Event
PERFORM frm_set_events IN PROGRAM (sy-cprog) IF FOUND
TABLES lt_event.
"" Sample
* FORM frm_set_events TABLES lt_event TYPE slis_t_event.
*
* ENDFORM.
PERFORM frm_set_sort IN PROGRAM (sy-cprog) IF FOUND
TABLES lt_sort.
"" Sample
* FORM frm_set_sort TABLES lt_sort TYPE lvc_t_sort.
*lt_sort-fieldname = 'BUKRS'.
* lt_sort-spos = 1.
* lt_sort-up = abap_true.
* lt_sort-subtot = abap_true.
* APPEND lt_sort.
* ENDFORM.
*&---> Show ALV
CLEAR gcl_alv_base.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = sy-repid
i_grid_title = lv_title
is_layout_lvc = ls_layout
it_fieldcat_lvc = lt_fcat
it_events = lt_event
it_sort_lvc = lt_sort
i_callback_pf_status_set = 'USERSTATUS'
i_callback_user_command = 'USERCOMMAND'
i_save = 'A'
TABLES
t_outtab = <ft_data>.
ENDFUNCTION.
*&---------------------------------------------------------------------*
*& Form userstatus
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_RT_EXTAB text
*----------------------------------------------------------------------*
FORM userstatus USING p_rt_extab.
* DATA: gl_alv TYPE REF TO cl_gui_alv_grid.
SET PF-STATUS 'STATUS_BASE'.
PERFORM frm_pbo IN PROGRAM (sy-cprog) IF FOUND
USING p_rt_extab.
IF gcl_alv_base IS INITIAL.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = gcl_alv_base.
CALL METHOD gcl_alv_base->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_modified.
CALL METHOD gcl_alv_base->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
ENDIF.
"" Sample
* FORM frm_pbo USING p_rt_extab.
* IF gv_grid IS INITIAL .
* CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
* IMPORTING
* e_grid = gv_grid.
*
* CALL METHOD gv_grid->register_edit_event
* EXPORTING
* i_event_id = cl_gui_alv_grid=>mc_evt_modified.
*
* CALL METHOD gv_grid->register_edit_event
* EXPORTING
* i_event_id = cl_gui_alv_grid=>mc_evt_enter.
* ENDIF.
* CASE ck_test.
* WHEN 'X'.
* SET TITLEBAR 'TITLE_TEST'.
* WHEN OTHERS.
* SET TITLEBAR 'TITLE_001'.
* ENDCASE.
*
* ENDFORM.
ENDFORM. "USERSTATUS
*&---------------------------------------------------------------------*
*& Form usercommand
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->R_UCOMM text
* -->RS_SELFIELD text
*----------------------------------------------------------------------*
FORM usercommand USING r_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.
rs_selfield-refresh = 'X' .
rs_selfield-col_stable = 'X' .
rs_selfield-row_stable = 'X' .
CALL METHOD gcl_alv_base->check_changed_data( ).
PERFORM frm_pai IN PROGRAM (sy-cprog) IF FOUND
USING r_ucomm
rs_selfield .
"" Sample
*FORM frm_pai USING r_ucomm LIKE sy-ucomm
* rs_selfield TYPE slis_selfield.
* IF r_ucomm EQ '&IC1'.
*
* CHECK rs_selfield-value IS NOT INITIAL.
*
* CASE rs_selfield-fieldname .
* WHEN 'VBELN'.
* SET PARAMETER ID 'AUN' FIELD rs_selfield-value .
* CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN .
* WHEN OTHERS.
* ENDCASE.
* ENDIF.
*ENDFORM.
ENDFORM . "usercommand
*&---------------------------------------------------------------------*
*& Form frm_set_fieldcat
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->LT_FCAT text
* -->LV_FNAME text
*----------------------------------------------------------------------*
FORM frm_set_fieldcat TABLES lt_fcat STRUCTURE lvc_s_fcat
USING lv_fname.
DATA: lv_struc_ty TYPE REF TO cl_abap_structdescr, "" struct
lt_fldlist TYPE TABLE OF dfies INITIAL SIZE 0
WITH HEADER LINE,"" fields
lv_sname TYPE tabname." struc name
lv_sname = lv_fname.
CLEAR lt_fcat .
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = lv_sname
i_client_never_display = 'X'
CHANGING
ct_fieldcat = lt_fcat[]
EXCEPTIONS
OTHERS = 1.
"" 读取结构属性
lv_struc_ty ?= cl_abap_typedescr=>describe_by_name( lv_fname ).
CALL METHOD lv_struc_ty->get_ddic_field_list
EXPORTING
p_including_substructres = 'X'
RECEIVING
p_field_list = lt_fldlist[]
EXCEPTIONS
not_found = 1
no_ddic_type = 2
OTHERS = 3.
SORT lt_fldlist BY fieldname.
LOOP AT lt_fcat.
lt_fcat-col_opt = 'X'.””自动优化列宽,适用于可编辑ALV
IF lt_fcat-domname IS NOT INITIAL.
READ TABLE lt_fldlist BINARY SEARCH
WITH KEY fieldname = lt_fcat-fieldname.
CHECK sy-subrc EQ 0.
lt_fcat-reptext = lt_fldlist-fieldtext.
lt_fcat-coltext = lt_fldlist-fieldtext.
lt_fcat-scrtext_l = lt_fldlist-fieldtext.
lt_fcat-scrtext_m = lt_fldlist-fieldtext.
lt_fcat-scrtext_s = lt_fldlist-fieldtext.
ENDIF.
MODIFY lt_fcat.
ENDLOOP.
ENDFORM. "frm_get_struct_fields
2. TOP文件
DATA:
gcl_alv_base TYPE REF TO cl_gui_alv_grid.
3. STATUS
直接引用标准的就行了。