隨著產業日漸成熟,客戶對於需求也越來困難,ABAPER 為了生存不可避免也必須不斷精進自我,而這篇文章也是自己在學習路上的一份積累。
報表程式是 ABAP 中最常開發的功能之一,其中 ALV 報表必是ABAPER 無法避免的課題,在使用者沒有要求時,大多會CALL Function 來呈現,下方列出部分常用 ALV fcnction:
然而在部分需求中,如:搜尋條件要與 ALV 報表在相同介面時,此時便須要ALV-OO 才能達成目的
實現介面如下
在開始介紹範例程式時,會運用到下方觀念
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 flow
FIELD-SYMBOLS <gv_screen_no> TYPE any ."VALUE '1000'.
DATA ok_code LIKE sy-ucomm.
*----- Field Symbol
FIELD-SYMBOLS: <dyn_table> TYPE STANDARD TABLE ,
<dyn_tmp_struc> TYPE any,
<dyn_wa> TYPE any ,
<dyn_tmp_table> TYPE table.
*-------- For ALV
DATA: 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 open
DATA: 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_grid
gs_print TYPE lvc_s_prnt
gs_layout TYPE lvc_s_layo
g_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.
至於其他細節就提供給各位看官自行研究啦~