随着产业日渐成熟,客户对于需求也越来困难,ABAPER 为了生存不可避免也必须不断精进自我,而这篇文章也是自己在学习路上的一份积累。
报表程式是 ABAP 中最常开发的功能之一,其中 ALV 报表必是ABAPER 无法避免的课题,在使用者没有要求时,大多会CALL Function 来呈现,下方列出部分常用 ALV fcnction:
然而在部分需求中,如:搜寻条件要与 ALV 报表在相同介面时,此时便须要ALV-OO 才能达成目的
实现介面如下
在开始介绍範例程式时,会运用到下方观念
Dynamic programDialog programOOP 基础概念如想更加了解此类型程式执行方式,可以往此方向做研究。
首先先附上程式码
TOP 区
TYPE-POOLS:abap.DATA: lt_table LIKE TABLE OF dntab, ls_table TYPE dntab, d_ref TYPE REF TO data, lt_comp TYPE abap_component_tab, lt_alv_cat TYPE TABLE OF lvc_s_fcat, ls_alv_cat LIKE LINE OF lt_alv_cat, gv_noinput TYPE c, gv_modify TYPE c.*----- For Dialog Program Logic flowFIELD-SYMBOLS <gv_screen_no> TYPE any ."VALUE '1000'.DATA ok_code LIKE sy-ucomm.*----- Field SymbolFIELD-SYMBOLS: <dyn_table> TYPE STANDARD TABLE , <dyn_tmp_struc> TYPE any, <dyn_wa> TYPE any , <dyn_tmp_table> TYPE table.*-------- For ALVDATA: g_container TYPE scrfname VALUE 'ALV_P', g_container_1 TYPE scrfname VALUE 'ALV_P2', grid1 TYPE REF TO cl_gui_alv_grid, grid2 TYPE REF TO cl_gui_alv_grid, gs_print TYPE lvc_s_prnt, gs_print_1 TYPE lvc_s_prnt, gs_layout TYPE lvc_s_layo, gs_layout_1 TYPE lvc_s_layo, g_custom_container_ma TYPE REF TO cl_gui_custom_container, g_custom_container TYPE REF TO cl_gui_custom_container, lt_fieldcat TYPE slis_t_fieldcat_alv WITH HEADER LINE, ir_data_changed TYPE REF TO cl_alv_changed_data_protocol.*----Excel openDATA: lv_rc TYPE i.DATA: lt_file_table TYPE filetable.
**SEREEN **
SELECTION-SCREEN BEGIN OF SCREEN 1100 AS SUBSCREEN.PARAMETERS: p_tab_n LIKE tabname .PARAMETERS: p_infile TYPE localfile DEFAULT 'C:\temp\upload.xlsx' . SELECTION-SCREEN BEGIN OF BLOCK lc_2 WITH FRAME TITLE TEXT-002 . PARAMETERS: r_ins TYPE c RADIOBUTTON GROUP g1. PARAMETERS: r_mod TYPE c RADIOBUTTON GROUP g1. SELECTION-SCREEN END OF BLOCK lc_2.SELECTION-SCREEN END OF SCREEN 1100 .CALL SCREEN 1000.AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_infile. CALL METHOD cl_gui_frontend_services=>file_open_dialog EXPORTING window_title = '打开文件' CHANGING file_table = lt_file_table rc = lv_rc. IF sy-subrc = 0. READ TABLE lt_file_table INTO DATA(wa_file_table) INDEX 1. p_infile = wa_file_table-filename. ENDIF.
FROM and MODULE
*&---------------------------------------------------------------------**& Form authorization_check*&---------------------------------------------------------------------**& Begin Date : 2021/02/02*& Author : Kevin Yu*& Description : 权限及输入条件确认及卡控*----------------------------------------------------------------------**& Version :*----------------------------------------------------------------------*FORM authorization_check. " UNASSIGN <dyn_table>. " UNASSIGN <dyn_tmp_struc>. IF p_tab_n IS INITIAL OR p_infile IS INITIAL. MESSAGE 'Table or Path cannot be null!!' TYPE 'I' DISPLAY LIKE 'E'. ELSE. SELECT SINGLE dd02l~tabname FROM dd02l INTO @DATA(lv_tabname) WHERE dd02l~tabname EQ @p_tab_n. IF sy-subrc EQ 0. PERFORM get_dynamic_itab. PERFORM excel_upload TABLES <dyn_table> . "CHECK <dyn_table> IS NOT INITIAL. PERFORM display_data USING <dyn_table> . IF r_ins EQ 'X' AND r_mod EQ ''. ELSEIF r_mod EQ 'X' AND r_ins EQ ''. ENDIF. ELSE. MESSAGE 'Table Not Active, Please check!!' TYPE 'I' DISPLAY LIKE 'E'. ENDIF. ENDIF.ENDFORM.*&---------------------------------------------------------------------**& Form get_dynamic_itab*&---------------------------------------------------------------------**& Begin Date : 2021/02/02*& Author : Kevin Yu*& Description : 依输入 TABLE 名产出对应栏位*----------------------------------------------------------------------**& Version :*----------------------------------------------------------------------*FORM get_dynamic_itab.*取出结构字段目录CALL FUNCTION 'NAMETAB_GET' EXPORTING langu = sy-langu tabname = p_tab_n TABLES nametab = lt_table. IF sy-subrc NE 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF.*依字段目录产出参考目录CLEAR lt_alv_cat.LOOP AT lt_table ASSIGNING FIELD-SYMBOL(<fs_table>). ls_alv_cat-fieldname = ls_alv_cat-ref_field = <fs_table>-fieldname. ls_alv_cat-ref_table = p_tab_n. APPEND ls_alv_cat TO lt_alv_cat. CLEAR: <fs_table>,ls_alv_cat.ENDLOOP.UNASSIGN <fs_table>.CALL METHOD cl_alv_table_create=>create_dynamic_table EXPORTING it_fieldcatalog = lt_alv_cat IMPORTING ep_table = d_ref. IF sy-subrc NE 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF.ASSIGN d_ref->* TO <dyn_table>.ASSIGN d_ref TO <dyn_tmp_struc>.ENDFORM.*&---------------------------------------------------------------------**& Form excel_upload*&---------------------------------------------------------------------**& Begin Date : 2021/02/02*& Author : Kevin Yu*& Description : 将 Excel data 从本地端传至宣告的 Table 中*----------------------------------------------------------------------**& Version :*----------------------------------------------------------------------*FORM excel_upload TABLES table. DATA: lt_data_in_file TYPE TABLE OF zalsmex_tabline, ls_data_in_file TYPE zalsmex_tabline, lv_count TYPE i, lv_count_2 TYPE i.DATA truxs_t_text_data(4096) TYPE c OCCURS 0. "不影响回传资料,仅因 FUNCTION 需求而设"DATA: gt_data TYPE alsmex_tabline OCCURS 0 WITH HEADER LINE."不影响回传资料,仅因 FUNCTION 需求而设CLEAR table.CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP' EXPORTING* I_FIELD_SEPERATOR = i_line_header = 'X' i_tab_raw_data = truxs_t_text_data i_filename = p_infile TABLES i_tab_converted_data = table EXCEPTIONS conversion_failed = 1 OTHERS = 2 . IF sy-subrc NE 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF.ENDFORM.*&---------------------------------------------------------------------**& Form display_data*&---------------------------------------------------------------------**& Begin Date : 2021/02/02*& Author : Kevin Yu*& Description : 呈现 Excel 上传至 table 中的资料 --OO ALV*----------------------------------------------------------------------**& Version :*----------------------------------------------------------------------*FORM display_data USING table."如要再 PAI 做 OO ALV 跳转时,要REFRESH ALV 物件及 GUI" refresh_table_display & SAPGUI_SET_FUNCTIONCODE IF grid1 IS INITIAL. g_custom_container = NEW cl_gui_custom_container( g_container ). grid1 = NEW cl_gui_alv_grid( g_custom_container ). CALL METHOD grid1->set_table_for_first_display EXPORTING i_structure_name = p_tab_n is_print = gs_print is_layout = gs_layout CHANGING it_outtab = table. CALL METHOD grid1->refresh_table_display EXCEPTIONS finished = 1 OTHERS = 2. ELSE. CALL METHOD grid1->set_table_for_first_display EXPORTING i_structure_name = p_tab_n is_print = gs_print is_layout = gs_layout CHANGING it_outtab = table. CALL METHOD grid1->refresh_table_display EXCEPTIONS finished = 1 OTHERS = 2. ENDIF. IF sy-subrc <> 0.* Implement suitable error handling here ENDIF.CALL FUNCTION 'SAPGUI_SET_FUNCTIONCODE' " 人为触发 PBO EXPORTING functioncode = 'REFRESH' EXCEPTIONS function_not_supported = 1 OTHERS = 2.ENDFORM.*&---------------------------------------------------------------------**& Module PBO OUTPUT*&---------------------------------------------------------------------**&*&---------------------------------------------------------------------*MODULE pbo OUTPUT. SET PF-STATUS 'STANDARD'. IF gv_noinput EQ cl_abap_typedescr=>true. ASSIGN '1200' TO <gv_screen_no>. ELSE. ASSIGN '1100' TO <gv_screen_no>. ENDIF. CHECK grid1 IS NOT INITIAL.* IF gv_modify EQ 'X'.* PERFORM alv_modify.* ENDIF. CALL METHOD grid1->refresh_table_display EXCEPTIONS finished = 1 OTHERS = 2.ENDMODULE.*&---------------------------------------------------------------------**& Module PAI INPUT*&---------------------------------------------------------------------** text*----------------------------------------------------------------------*MODULE pai INPUT."CALL METHOD cl_gui_cfw=>dispatch. "人为触发 PAI CLEAR gv_noinput. CASE ok_code. WHEN 'ENDE' OR 'ECAN'. PERFORM exit_program. WHEN 'EXE' OR 'ONLI' . PERFORM authorization_check. WHEN 'GET'. PERFORM exit_program. WHEN 'E'. IF gs_layout-edit EQ cl_abap_typedescr=>true. "'X'. gs_layout-edit = cl_abap_typedescr=>false. PERFORM authorization_check. ENDIF. WHEN 'CHANGE_MODE'. CHECK grid1 IS NOT INITIAL. gv_noinput = cl_abap_typedescr=>true. "X" gv_modify = cl_abap_typedescr=>true. "X" PERFORM alv_modify TABLES <dyn_table>. WHEN 'SPOS'. PERFORM alv_modify TABLES <dyn_table>. WHEN 'ENTRY_DATA'. PERFORM data_entry. ENDCASE. CLEAR ok_code.ENDMODULE.FORM exit_program.* CALL METHOD G_CUSTOM_CONTAINER->FREE.* CALL METHOD CL_GUI_CFW=>FLUSH. LEAVE TO SCREEN 0.ENDFORM.*&---------------------------------------------------------------------**& Form alv_modify*&---------------------------------------------------------------------**& Begin Date : 2021/02/03*& Author : Kevin Yu*& Description :*----------------------------------------------------------------------**& Version :*----------------------------------------------------------------------*FORM alv_modify TABLES pt_list .IF gs_layout-edit = cl_abap_typedescr=>true. gs_layout-edit = cl_abap_typedescr=>false.ELSE. gs_layout-edit = cl_abap_typedescr=>true.ENDIF. CALL METHOD grid1->register_edit_event EXPORTING i_event_id = cl_gui_alv_grid=>mc_evt_enter. CALL METHOD grid1->set_table_for_first_display EXPORTING i_structure_name = p_tab_n is_print = gs_print is_layout = gs_layout CHANGING it_outtab = <dyn_table>. CALL METHOD grid1->refresh_table_display EXCEPTIONS finished = 1 OTHERS = 2.ENDFORM.
首先为了使Selection Screen 与 ALV 呈现在相同介面
必须要先自製自己的 Screen,并将ALV 包入物件中,并使用Custom Control 来呈现 ALV 物件
而为了使介面呈现Selection Screen 的部分,在PBO 及 PAI 皆要调用其作为subscreen,如此便可让两者同时
存在于同一画面中
而接着便是创建 ALV 相关物件
可参照程式TOP做宣告类型 ,运用宣告类型如下
g_container TYPE scrfname VALUE 'ALV_P'grid1 TYPE REF TO cl_gui_alv_gridgs_print TYPE lvc_s_prntgs_layout TYPE lvc_s_layog_custom_container TYPE REF TO cl_gui_custom_container
物件创建如下
g_custom_container = NEW cl_gui_custom_container( g_container ). grid1 = NEW cl_gui_alv_grid( g_custom_container ).
準备好相关参数后接着调用 Method->set_table_for_first_display
便可在所设计的custom control 位置中呈现 alv
CALL METHOD grid1->set_table_for_first_display EXPORTING i_structure_name = p_tab_n is_print = gs_print is_layout = gs_layout CHANGING it_outtab = <dyn_table>.
而其中要注意的便是 alv 刷新问题
通常在刷新 alv 会调用Method->refresh_table_display
CALL METHOD grid1->refresh_table_display EXCEPTIONS finished = 1 OTHERS = 2.
然而因此範例并非再 PBO 处理,故要自行触发PBO 刷新 GUI 介面
CALL FUNCTION 'SAPGUI_SET_FUNCTIONCODE' " 人为触发 PBO EXPORTING functioncode = 'REFRESH' EXCEPTIONS function_not_supported = 1 OTHERS = 2.
至于其他细节就提供给各位看官自行研究啦~