透過 ALV 修改資料的好處是可以減少 Screen 的控制,直接讓 User 像是直接在 Excel 上編輯,程式只需要將畫面上新的值寫回 Internal Table 並且將 Internal Table 再顯示在 ALV 中。
STEP1 : Create Sample Code
REPORT Z_ABAP_19_ALV_MODIFY.
TYPE-POOLS SLIS.
DATA: BEGIN OF IT_SPFLI OCCURS 0.
DATA: MARK TYPE C,
CARRID LIKE SPFLI-CARRID,
CONNID LIKE SPFLI-CONNID,
CITYFROM LIKE SPFLI-CITYFROM,
AIRPFROM LIKE SPFLI-AIRPFROM.
DATA: END OF IT_SPFLI.
DATA: gt_fieldcat TYPE slis_t_fieldcat_alv,
gt_events TYPE slis_t_event,
layout TYPE slis_layout_alv.
DATA: GT_SORTINFO TYPE SLIS_T_SORTINFO_ALV.
PARAMETERS : R_G1 RADIOBUTTON GROUP G1,
R_G2 RADIOBUTTON GROUP G1.
START-OF-SELECTION.
SELECT * UP TO 10 ROWS INTO CORRESPONDING FIELDS OF TABLE IT_SPFLI
FROM SPFLI.
PERFORM fieldcat_init USING gt_fieldcat[]. "設定欄位
PERFORM sortinfo_init USING gt_sortinfo[]. "設定排序
PERFORM events_init USING gt_events[]. "設定 Event top of page, User Command
PERFORM build_layout USING layout. "設定 ALV 顯示的內容
PERFORM reuse_alv_list_display.
END-OF-SELECTION.
*&---------------------------------------------------------------------*
*& Form FIELDCAT_INIT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM FIELDCAT_INIT USING it_fieldcat TYPE slis_t_fieldcat_alv.
DATA : st_fieldcat TYPE slis_fieldcat_alv.
DEFINE st_fieldcat.
clear st_fieldcat.
st_fieldcat-fieldname = &1.
st_fieldcat-seltext_l = &2.
st_fieldcat-tabname = 'SPFLI'.
st_fieldcat-outputlen = &3.
st_fieldcat-key = &4.
st_fieldcat-input = &5.
st_fieldcat-lowercase = 'X'.
st_fieldcat-cfieldname = &6.
st_fieldcat-edit = &7.
append st_fieldcat to gt_fieldcat.
clear st_fieldcat.
END-OF-DEFINITION.
st_fieldcat 'CARRID' 'CARRID' 10 ' ' ' ' ' ' ' '.
st_fieldcat 'CONNID' 'CONNID' 10 ' ' ' ' ' ' ' '.
st_fieldcat 'CITYFROM' 'CITYFROM' 30 ' ' 'X' ' ' 'X'.
st_fieldcat 'AIRPFROM' 'AIRPFROM' 18 ' ' ' ' ' ' ' '.
ENDFORM. " FIELDCAT_INIT
*&---------------------------------------------------------------------*
*& Form SORTINFO_INIT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM sortinfo_init USING it_sortinfo TYPE slis_t_sortinfo_alv.
DATA : st_sort TYPE slis_sortinfo_alv.
DEFINE st_sort.
clear st_sort.
st_sort-spos = &1.
st_sort-fieldname = &2.
st_sort-tabname = 'SPFLI'.
st_sort-up = &3.
append st_sort to it_sortinfo.
clear st_sort.
END-OF-DEFINITION.
st_sort : '01' 'CARRID' 'X',
'02' 'CONNID' 'X',
'03' 'CITYFROM' 'X'.
ENDFORM. " SORTINFO_INIT
*&---------------------------------------------------------------------*
*& Form EVENTS_INIT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM events_init USING rt_events TYPE slis_t_event.
DATA : ls_event TYPE slis_alv_event.
CONSTANTS : c_form_top_of_page TYPE slis_formname VALUE 'TOP_OF_PAGE'.
"捉取 ALV Event
CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
EXPORTING
i_list_type = 0
IMPORTING
et_events = rt_events.
READ TABLE rt_events WITH KEY name = slis_ev_top_of_page
INTO ls_event.
IF sy-subrc = 0.
MOVE c_form_top_of_page TO ls_event-form.
MODIFY rt_events FROM ls_event INDEX sy-tabix.
ENDIF.
READ TABLE gt_events WITH KEY name = slis_ev_user_command
INTO ls_event.
IF sy-subrc = 0.
MOVE 'USER_COMMAND' TO ls_event-form.
MODIFY gt_events FROM ls_event INDEX sy-tabix.
ENDIF.
ENDFORM. " EVENTS_INIT
*&---------------------------------------------------------------------*
*& Form top_of_page
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM top_of_page.
data: t_header type slis_t_listheader,
wa_header type slis_listheader,
t_line like wa_header-info,
ld_lines type i,
ld_linesc(10) type c.
wa_header-typ = 'H'.
wa_header-info = 'SPFLI Table Report'.
append wa_header to t_header.
clear wa_header.
call function 'REUSE_ALV_COMMENTARY_WRITE'
exporting
it_list_commentary = t_header.
ENDFORM. "TOP_OF_PGAE
*&---------------------------------------------------------------------*
*& Form BUILD_LAYOUT
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM user_command USING ucom LIKE sy-ucomm
selfd TYPE slis_selfield.
DATA: gd_repid LIKE sy-repid,
ref_grid TYPE REF TO cl_gui_alv_grid.
"把目前正在編輯的資料寫回 ALV GRID_DISPLAY 才要
IF R_G2 = 'X'.
IF ref_grid IS INITIAL.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = ref_grid.
ENDIF.
IF NOT ref_grid IS INITIAL.
CALL METHOD ref_grid->check_changed_data .
ENDIF.
ENDIF.
CASE UCOM.
WHEN 'DELE'.
DELETE IT_SPFLI WHERE MARK = 'X'.
WHEN 'SAVE'.
LEAVE TO SCREEN 0.
WHEN 'BACK_U' OR 'CANC_U' OR 'EXIT_U'.
LEAVE TO SCREEN 0.
ENDCASE.
selfd-refresh = 'X'.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form BUILD_LAYOUT
*&---------------------------------------------------------------------*
* ALV Layout
*----------------------------------------------------------------------*
FORM build_layout USING rt_layout TYPE slis_layout_alv.
rt_layout-zebra = 'X'. "Each row display difference color
" rt_layout-detail_popup = 'X'.
rt_layout-box_fieldname = 'MARK'. "勾選欄位
"rt_layout-detail_initial_lines = 'X'.
ENDFORM. " BUILD_LAYOUT
*&---------------------------------------------------------------------*
*& Form REUSE_ALV_LIST_DISPLAY
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM REUSE_ALV_LIST_DISPLAY .
DATA: LC_GLAY TYPE LVC_S_GLAY.
DATA : L_FUNAME TYPE RS38L_FNAM.
"DATA: ls_exit TYPE slis_exit_by_user.
LC_GLAY-EDT_CLL_CB = 'X'.
IF R_G1 = 'X'.
L_FUNAME = 'REUSE_ALV_LIST_DISPLAY' .
ELSE.
L_FUNAME = 'REUSE_ALV_GRID_DISPLAY'.
ENDIF.
CALL FUNCTION L_FUNAME
EXPORTING
i_callback_program = sy-repid
i_callback_pf_status_set = 'SET_PF_STATUS'
is_layout = layout
it_fieldcat = gt_fieldcat[]
it_sort = gt_sortinfo[]
it_events = gt_events
"for REUSE_ALV_GRID_DISPLAY 更新 ALV 值到 Internal Table (但正在編輯欄不會寫入)
I_GRID_SETTINGS = LC_GLAY
"IMPORTING
" es_exit_caused_by_user = ls_exit "捉取 User 按的是 Back/Exit/Cancel
TABLES
t_outtab = IT_SPFLI
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
LOOP AT IT_SPFLI.
WRITE:/ IT_SPFLI-CITYFROM.
ENDLOOP.
ENDFORM. " REUSE_ALV_LIST_DISPLAY
*&---------------------------------------------------------------------*
*& Form 設定 ALV STATUS
*&---------------------------------------------------------------------*
FORM set_pf_status USING tab TYPE slis_t_extab.
APPEND 'POST' TO TAB. "不顯示 ALV_MENU 哪個按鈕
APPEND 'SAVE' TO TAB. "不顯示 ALV_MENU 哪個按鈕
SET PF-STATUS 'ALV_MENU' EXCLUDING tab.
ENDFORM. "set_pf_status
STEP2 : Create GUI Status
並且建立一個自行程式要使用的 STATUS,BACK / EXIT / CANC 要加上 "_U" 的原因是為了要讓 User 按下這三個按鈕後仍能進入 User Command,不會直接被 ALV 本身處理 BACK / EXIT / CANC 功能,直接離開程式未進入 User Command (因為在 User Command 還要做變動值寫回 Internal Table 的程式)
程式執行時,提供 User 能夠選擇執行哪個 ALV 的 FM
以下功能主要是用來設定 ALV 要顯示的欄位,並設定哪些欄位能夠編輯,如果使用的是 FM P REUSE_ALV_GRID_DISPLAY 時,則 input / edit 都要設定為 X,如果是 REUSE_AV_LIST_DISPLAY 則只需要 input = 'X'
PERFORM fieldcat_init USING gt_fieldcat[].
主要影響是否能夠編輯來自下面兩行
st_fieldcat-input = &5.
st_fieldcat-edit = &7.
以下功能則用來設定 ALV 預設排序的欄位
PERFORM sortinfo_init USING gt_sortinfo[]. "設定排序
而要設定 TOP OF PAGE (即第一張圖中的 SPFLI Table Report) 以及 User Command 則要在 events_init 中設定
PERFORM events_init USING gt_events[].
先由 CALL FUNCTION 'REUSE_ALV_EVENTS_GET' 取得所有 ALV Event
再跟據 Event 的名稱把 Event 寫入傳入的參數 gt_events, E.G.:TOP_OF_PAGE, USER_COMMAND
這邊只是設定 ALV 要使用的 Event,並且要用 Event 的名稱建立 FORM TOP_OF_PAGE & FORM USER_COMMAND
再來即設定 ALV 的樣式
PERFORM build_layout USING layout.
rt_layout-zebra 影響的是畫面每一筆資料是否有不同顏色
rt_layout-mark 則是否要顯示最左邊的選項
最後則是透過 reuse_alv_list_display 執行上敘顯示 ALV 的 FM
而影響 User 變動的資料寫回 Internal Table 則來自下面兩段程,第一段是在呼叫 ALV FM 時,要設定 I_GRID_SETTINGS,這功能影響的是當 User 輸入完後有按 Enter 後,會把值變動到 Internal Table
FORM REUSE_ALV_LIST_DISPLAY .
DATA: LC_GLAY TYPE LVC_S_GLAY.
LC_GLAY-EDT_CLL_CB = 'X'.
"L_FUNAME 為 REUSE_ALV_LIST_DISPLAY or REUSE_ALV_GRID_DISPLAY
CALL FUNCTION L_FUNAME
EXPORTING
.....
I_GRID_SETTINGS = LC_GLAY
.....
但有一種可能 User 打完後鼠標沒有移開,此時不會透過上面功能進行更新,則需要透過下面的程式進行編輯,此程式則需寫在 USER_COMMAND 中的語法 CALL METHOD ref_grid->check_changed_data.,此變動只有在使用 FM REUSE_ALV_GRID_DISPLAY 才需要使用,如果是 REUSE_ALV_LIST_DISPLAY 則填入後即會更新,最後的 selfd-refresh = 'X'. 則不管用哪一個 FM 都要使用
FORM user_command USING ucom LIKE sy-ucomm
selfd TYPE slis_selfield.
IF R_G2 = 'X'.
IF ref_grid IS INITIAL.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = ref_grid.
ENDIF.
IF NOT ref_grid IS INITIAL.
CALL METHOD ref_grid->check_changed_data .
ENDIF.
ENDIF.
selfd-refresh = 'X'.
之後當執行時,在 ALV 進行資料的變動後,按下 BACK/EXIT/CANC 後執行 LOOP 把 CITYFROM 值寫在畫面上
謝謝你的分享
回覆刪除