2015年6月4日 星期四

ABAP4 - How to use alv to change the value of internal table

ABAP4 - How to use alv to change the value of internal table

透過 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 值寫在畫面上

1 則留言:

How to install & specified python version or distreibtuion package version in google colab

在買了 RTX 3080 要來 挖礦...  嗯~是跑機器學習後,結果發現了 GOOGLE COLAB,其實之前在「GAN 對抗式生成網路」一書就有看到,但資訊人就是什麼都想自己安裝,在本機用 Anaconda + pyCharm 弄了 GPU 環境,結果有天從新竹回家發現家裡沒...