OOALV總結


1.1ALV屏幕

1.1.1定義無CONTAINER屏幕

1、屏幕中可以不使用定制控制控件畫范圍,直接定義一個屏幕即可。

g_grid_9000      TYPE REF TO cl_gui_alv_grid, "容器的實例
g_container_9000 TYPE REF TO cl_gui_docking_container, "容器 不用畫屏幕容器

2、創建容器

CREATE OBJECT g_container_9000
  EXPORTING
    repid  = sy-repid
    dynnr = '9000'
*     side = cl_gui_docking_container=>dock_at_right”ALV貼屏幕右邊,從屏幕右邊開始算寬度
    side = cl_gui_docking_container=>dock_at_top"ALV貼屏幕左邊,從左邊算屏幕寬度,
    extension = 1000 "屏幕寬度
*     ratio = 95  "屏幕比例 小於5大於95會報cntl_error異常
    style = cl_gui_control=>ws_child "可選參數,設置ALV是否可拖動大小
  EXCEPTIONS
    cntl_error                  = 1
    cntl_system_error           = 2
    create_error                = 3
    lifetime_error              = 4
    lifetime_dynpro_dynpro_link = 5
    OTHERS                      = 6.

3、創建容器實例

*  創建容器實例
  CREATE OBJECT g_grid_9000
  EXPORTING
    i_parent          = g_container_9000
  EXCEPTIONS
    error_cntl_create = 1
    error_cntl_init   = 2
    error_cntl_link   = 3
    error_dp_create   = 4
    OTHERS            = 5.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

4、排序匯總

在業務中,需要根據提貨單號,將相同提貨單號的行的提貨單數量匯總。

首先設置排序

FORM frm_alv_sort_9000.
  CLEAR:gs_sort.
  gs_sort-fieldname = 'THDXH'.
  gs_sort-UP = 'X'.
  gs_sort-subtot = 'X'.
  APPEND gs_sort TO gt_sort.
ENDFORM.

設置匯總

gs_fieldcat-do_sum  = &3.
init_fill_fcat 'ZBCJHSL' '提貨單數量' 'X' '' '' '' '' '' ''.

5、事件注冊

FORM frm_alv_event_9001.
  DATA: lr_event_handler TYPE REF TO alv_event_9001.
  DATA: lt_f4 TYPE lvc_t_f4,
        ls_f4 TYPE lvc_s_f4.

  CLEAR:ls_f4.
  ls_f4-fieldname  = 'Z_ZFBZ'."作廢標記
  ls_f4-register   = 'X'.
  ls_f4-chngeafter = 'X'.
  INSERT ls_f4 INTO TABLE lt_f4.

  CALL METHOD g_grid_9001->register_edit_event  "注冊回車事件
  EXPORTING
    i_event_id = cl_gui_alv_grid=>mc_evt_enter.

  CALL METHOD g_grid_9001->register_edit_event  "注冊失去鼠標事件
  EXPORTING
    i_event_id = cl_gui_alv_grid=>mc_evt_modified.

  CALL METHOD g_grid_9001->register_f4_for_fields "注冊搜索幫助事件
  EXPORTING
    it_f4 = lt_f4.


  IF lr_event_handler IS INITIAL.
    CREATE OBJECT lr_event_handler.
  ENDIF.
  SET HANDLER lr_event_handler->handle_data_changed FOR g_grid_9001. "數據改動事件
  SET HANDLER lr_event_handler->handle_double_click FOR g_grid_9001.
  SET HANDLER lr_event_handler->handle_on_f4 FOR g_grid_9001.
  SET HANDLER lr_event_handler->handle_hotspot_click FOR g_grid_9001 .
  SET HANDLER lr_event_handler->handle_toolbar FOR g_grid_9001.      "工具欄事件
  SET HANDLER lr_event_handler->handle_user_command FOR g_grid_9001. "用戶命令事件

ENDFORM.

6、展示ALV

CALL METHOD g_grid_9000->set_table_for_first_display
    EXPORTING
      is_variant                    = gs_variant_9000
*       i_save                        = 'A'
      is_layout                     = gs_layout_9000
      it_toolbar_excluding          = gt_exclude_9000
    CHANGING
      it_outtab                     = gt_selalv      "輸出數據的內表
      it_fieldcatalog               = gt_fieldcat_9000  "
      it_sort                       = gt_sort"排序
      it_filter                     = gt_filt
    EXCEPTIONS
      invalid_parameter_combination = 1
      program_error                 = 2
      too_many_lines                = 3
      OTHERS                        = 4.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

7、屏幕刷新

FORM frm_refresh_alv_9000 .
  DATA: lt_celltab TYPE lvc_t_styl,
        ls_celltab TYPE lvc_s_styl,
        ls_stable  TYPE lvc_s_stbl.

  ls_stable-row = 'X'.  "固定行
  ls_stable-col = 'X'.  "固定列

  CHECK g_grid_9000 IS NOT INITIAL.

  CALL METHOD g_grid_9000->refresh_table_display
  EXPORTING
    is_stable = ls_stable
*     I_SOFT_REFRESH = 'X'
  EXCEPTIONS
    finished  = 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.
  CALL METHOD cl_gui_cfw=>flush.
ENDFORM.

1.1.2定義有CONTAINER屏幕

1、首先在屏幕中使用空間畫一個框

 

2、如果使用定制控制在控件中畫范圍,則需要使用另一個類。

g_container_9000 TYPE REF TO  cl_gui_custom_container"ALV container容器 需要畫屏幕容器

並且為屏幕中的控件定義名字,在程序中使用

gv_9000 TYPE scrfname VALUE 'Z9000_ITEM', "GV_TABLE 是屏幕中定義的控件

3、創建容器

*  創建 容器
  CREATE OBJECT g_container_9000
    EXPORTING
      container_name = gv_9000.

  CREATE OBJECT g_grid_9000
    EXPORTING
      i_parent = g_container_9000.

4、創建容器實例

*  創建容器實例
  CREATE OBJECT g_grid_9000
  EXPORTING
    i_parent          = g_container_9000
  EXCEPTIONS
    error_cntl_create = 1
    error_cntl_init   = 2
    error_cntl_link   = 3
    error_dp_create   = 4
    OTHERS            = 5.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

其他的部分都與無CONTAINER的創建方法一致。

1.2事件處理

1.2.1定義事件類

1、初始化事件類

INITIALIZATION.
  CLASS alv_event_9000 DEFINITION DEFERRED.

2、定義事件類的方法

CLASS alv_event_9000 DEFINITION.
  PUBLIC SECTION.
    METHODS handle_data_changed FOR EVENT data_changed OF cl_gui_alv_grid"數據改動事件
      IMPORTING er_data_changed e_onf4 e_onf4_before e_onf4_after e_ucomm.
    METHODS handle_double_click FOR EVENT double_click  OF cl_gui_alv_grid"雙擊事件
      IMPORTING e_row e_column es_row_no.
    METHODS handle_on_f4 FOR EVENT onf4 OF cl_gui_alv_grid"F4
      IMPORTING e_fieldname e_fieldvalue es_row_no er_event_data et_bad_cells e_display.
    METHODS handle_user_command FOR EVENT user_command OF cl_gui_alv_grid"用戶按鈕事件
      IMPORTING e_ucomm.
    METHODS handle_hotspot_click FOR EVENT hotspot_click OF cl_gui_alv_grid"熱區單擊事件
      IMPORTING e_row_id e_column_id es_row_no.
    METHODS handle_toolbar FOR EVENT toolbar OF cl_gui_alv_grid"工具條事件
      IMPORTING e_object e_interactive.
ENDCLASS. 

3、實現類的方法

CLASS alv_event_9000 IMPLEMENTATION.
  METHOD handle_data_changed.        "數據改動事件
    PERFORM frm_handle_data_changed USING er_data_changed.
  ENDMETHOD.
  METHOD handle_double_click .      "雙擊事件
    PERFORM frm_double_click USING e_row e_column es_row_no.
  ENDMETHOD.                    "HANDLE_USER_COMMAND
  METHOD handle_on_f4 .              "F4
    PERFORM frm_alv_on_f4 USING  e_fieldname e_fieldvalue es_row_no er_event_data e_display.
    er_event_data->m_event_handled = 'X' .
  ENDMETHOD.
  METHOD handle_user_command.       "用戶按鈕事件
    PERFORM frm_handle_user_command9000 USING e_ucomm.
  ENDMETHOD.
  METHOD handle_hotspot_click.       "熱區單擊事件
    PERFORM handle_hotspot_click USING e_row_id e_column_id es_row_no.
  ENDMETHOD.                    "handle_hotspot_click
  METHOD  handle_toolbar.            "工具條事件
    PERFORM frm_handle_toolbar9000 USING e_object e_interactive."設置工具條圖標
  ENDMETHOD.                    "HANDLE_DOUBLE_CLICK
ENDCLASS.

1.2.2搜索幫助事件

1、定義響應F4的字段

DATA: lr_event_handler TYPE REF TO alv_event_9001.
DATA: lt_f4 TYPE lvc_t_f4,
         ls_f4 TYPE lvc_s_f4.  

CLEAR:ls_f4.
  ls_f4-fieldname  = 'Z_ZFBZ'."作廢標記
  ls_f4-register   = 'X'.
  ls_f4-chngeafter = 'X'.
  INSERT ls_f4 INTO TABLE lt_f4.

2、將F4內表注冊到搜索幫助

  CALL METHOD g_grid_9001->register_f4_for_fields "注冊搜索幫助事件
    EXPORTING
      it_f4 = lt_f4.

3、將搜索幫助注冊到屏幕

IF lr_event_handler IS INITIAL.
    CREATE OBJECT lr_event_handler.
  ENDIF.

 SET HANDLER lr_event_handler->handle_on_f4 FOR g_grid_9001.

4、定義字段為F4屬性

gs_fieldcat-f4availabl = &5.

init_fill_fcat 'Z_ZFBZ' '作廢標記' '' '' 'X' '' 'X' '' ''.

5、定義F4響應邏輯

FORM frm_alv_on_f4 USING pv_fieldname pv_fieldvalue pv_row_no TYPE lvc_s_roid
      pv_event_data TYPE REF TO cl_alv_event_data
      pv_display.

  DATA:lv_fieldname1 TYPE dfies-fieldname,
        lv_fieldname2 TYPE help_info-dynprofld.

  DATA:rs_selfield TYPE slis_selfield.
  DATA:ref_grid TYPE REF TO cl_gui_alv_grid.

  DATA:lt_return TYPE STANDARD TABLE OF ddshretval,
        ls_return TYPE ddshretval.

  DATA:BEGIN OF lt_zf OCCURS 0,
    z_zfbz TYPE ztthdvk-z_zfbz, "作廢標志
  END OF lt_zf.

  DATA:ls_zf LIKE lt_zf.

 

REFRESH:lt_zf.
    CLEAR:ls_zf.
    ls_zf-z_zfbz = 'X'.
    APPEND ls_zf TO lt_zf. "作廢標記不可逆,一旦打上X,則不可能再更改過來

  lv_fieldname1 = pv_fieldname ."搜索幫助的字段名
  lv_fieldname2 = pv_fieldname ."搜索幫助的字段名
  CONDENSE lv_fieldname1 NO-GAPS.
  CONDENSE lv_fieldname2 NO-GAPS.
  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
  IMPORTING
    e_grid = ref_grid.  "獲取全局變量
*  PERFORM frm_refresh_alv.
  REFRESH:lt_return.

CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
    EXPORTING
      retfield        = pv_fieldname1
      dynpprog        = sy-repid
      dynpnr          = sy-dynnr
      dynprofield     = pv_fieldname2
      value_org       = 'S'
      display         = 'F'
    TABLES
      value_tab       = lt_zf
      return_tab      = lt_return
    EXCEPTIONS
      parameter_error = 1
      no_values_found = 2
      OTHERS          = 3.

    CLEAR:gs_head.
    READ TABLE gt_head INTO gs_head INDEX pv_row_no-row_id.
        IF sy-subrc =  0.
       READ TABLE lt_return INTO ls_return INDEX 1.
       IF sy-subrc = 0.
                gs_head-z_zfbz = ls_return-fieldval.
       ENDIF.
      MODIFY gt_head FROM gs_head INDEX pv_row_no-row_id."更新ALV內表
    ENDIF. 

 PERFORM frm_refresh_alv_9001.
ENDFORM.

6、當出現多列的搜索幫助時,需要在點擊某一行時,返回多列的值。例如點擊承運商搜索幫助,點擊承運商后,也需要返回承運商代碼,則需要特殊處理。

 

搜索幫助內表需要定義為兩列

 TYPES:BEGIN OF ty_cys,
    zcysdm TYPE ztthdvk-zcysdm, "承運商編碼
    zcys   TYPE ztthdvk-zcys, "承運商名稱
  END OF ty_cys.

ls_cys-zcysdm = gs_zttlifnrc-lifnr.
ls_cys-zcys = gs_zttlifnrc-ztext.
APPEND ls_cys TO lt_cys.
CLEAR:ls_cys.

 

CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
      EXPORTING
        retfield         = pv_fieldname1
        dynpprog         = sy-repid
        dynpnr           = sy-dynnr
        dynprofield      = pv_fieldname2
        value_org        = 'S'
        display          = 'F'
*        可以返回兩個返回值-begin
        callback_program = sy-repid
        callback_form    = 'USER_F4_FORM'
*          --end
      TABLES
        value_tab        = lt_cys
        return_tab       = pt_return
      EXCEPTIONS
        parameter_error  = 1
        no_values_found  = 2
        OTHERS           = 3.

*---------------------------------------------------------------------*
*       F4搜索幫助的回調函數,除了F4IF_INT_TABLE_VALUE_REQUEST
*       中定義的字段,還可以返回其他列的字段值
*----------------------------------------------------------------------*
FORM user_f4_form TABLES record_tab STRUCTURE seahlpres CHANGING shlp TYPE shlp_descr_t   callcontrol LIKE ddshf4ctrl .
  DATA: interface LIKE LINE OF shlp-interface.
  READ TABLE shlp-interface INTO interface INDEX 1.

  CLEAR interface.
  interface-shlpfield = 'F0001'. "調試可知,承運商代碼列名為F0001
  interface-valfield = 'ZCYSDM'. "字段名稱
  APPEND interface TO shlp-interface.
ENDFORM.   

1.2.3數據改變事件

1、回車事件和失去鼠標焦點事件都稱為數據改變事件

CALL METHOD g_grid_9000->register_edit_event  "注冊回車事件
  EXPORTING
    i_event_id = cl_gui_alv_grid=>mc_evt_enter.

CALL METHOD g_grid_9000->register_edit_event  "注冊失去鼠標事件
  EXPORTING
    i_event_id = cl_gui_alv_grid=>mc_evt_modified.

SET HANDLER lr_event_handler->handle_data_changed FOR g_grid_9000. "數據改動事件

2、數據改變事件處理

FORM frm_handle_data_changed  USING pv_data_changed TYPE REF TO cl_alv_changed_data_protocol.
  DATA:lt_data TYPE  lvc_t_modi,
        ls_data LIKE LINE OF lt_data.

  DATA:lv_zbcjhsl TYPE ztthdvb-zbcjhsl, "本次交貨數量
        lv_jiansh  TYPE ztthdvb-jiansh, "件數
        lv_value   TYPE char100.

  CLEAR:gv_stop."流程控制標識

  lt_data = pv_data_changed->mt_mod_cells.

LOOP AT lt_data INTO ls_data.
      IF ls_data-fieldname = 'ZBCJHSL'.
        CLEAR:lv_zbcjhsl.
        CALL METHOD pv_data_changed->get_cell_value "獲取單元格中的值
        EXPORTING
          i_row_id    = ls_data-row_id "行號
          i_fieldname = 'ZBCJHSL' "要獲取的列的列名
        IMPORTING
          e_value     = lv_zbcjhsl. "獲取到的單元格中的值

       ...處理邏輯

       ENDIF.

ENDLOOP.
PERFORM frm_refresh_alv_9001.

ENDFORM.

 3、關於數據改變的驗證

業務中需要對數據改變之后的有效性做校驗,判斷改變后的數據是否符合業務要求,在合適位置加上校驗邏輯即可,報響應的消息。

IF lv_zbcjhsl <= 0.
        gv_stop = 'X'."當需要中斷程序時打上標識
        REFRESH:pv_data_changed->mt_mod_cells."清掉編輯框中的數據,恢復至內表中的正確數據 此處如果不清理,展示的字段內容仍然是編輯后的錯誤數據
        MESSAGE s024(zsd) WITH ls_data-row_id DISPLAY LIKE 'E'.
        PERFORM frm_refresh_alv_9000.
        RETURN.
ENDIF.

后來發現,因為消息並不是E類型,直接終止程序。所以,如果對於數據改變之后,一不敲回車,二直接點擊創建等操作按鈕后,雖然也會報消息,但是RETURN只是推出了數據改變事件這一流程塊,但是仍然進入創建按鈕的邏輯。因此,我們可以在報錯時,加入流程控制標識:gv_stop = 'X'."當需要中斷程序時打上標識,這樣在執行創建邏輯時加入判斷:CHECK gv_stop <> 'X'."流程控制,判斷事件處理是否有誤,並在執行完之后清除流程控制符。

 

3.2.4工具條事件

1、因OOALV定義的狀態欄的標准按鈕時無法使用的,所以應使用OOALV屏幕中自帶的工具欄,定義的GUI狀態欄只負責定義返回按鈕即可。

2、自定義的工具欄按鈕,可以添加到OOALV屏幕自帶的工具欄

 

3、當自定義的GUI狀態欄只有返回按鈕沒有應用程序工具欄按鈕時,會在標准的屏幕工具欄上邊出現一條空白,影響美觀,我們可以在屏幕中做設置。

 

這樣就可以只使用GUI狀態欄的返回退出按鈕,而不必出現空白。

4、定義屏幕工具欄的自定義按鈕

FORM frm_handle_toolbar9000 USING p_object p_interactive.
    PERFORM frm_handle_toolbar_pro USING p_object 'CREATE_THD'  '@5Y@' '生成提貨單'.

ENDFORM.



FORM frm_handle_toolbar_pro USING p_object TYPE REF TO cl_alv_event_toolbar_set
      p_function TYPE stb_button-FUNCTION
      p_icon TYPE stb_button-ICON
      p_text TYPE stb_button-TEXT.
  DATA: ls_toolbar   TYPE stb_button,
        lv_quickinfo TYPE stb_button-quickinfo.

  CLEAR ls_toolbar.
  MOVE 3 TO ls_toolbar-butn_type. " 分隔符
  APPEND ls_toolbar TO p_object->mt_toolbar.

  CLEAR ls_toolbar.
  MOVE 0 TO ls_toolbar-butn_type.   " 按鈕(正常)
  MOVE p_function TO ls_toolbar-FUNCTION. "功能碼
  MOVE p_icon TO ls_toolbar-ICON.   "圖標
  MOVE p_text TO ls_toolbar-TEXT.   "顯示文本
  lv_quickinfo = p_text.
  MOVE lv_quickinfo  TO ls_toolbar-quickinfo.
  APPEND ls_toolbar TO p_object->mt_toolbar.
ENDFORM.

5、自定義的屏幕工具欄按鈕響應

 

6、GUI狀態的按鈕響應,需要在屏幕的PAI中定義

 

1.3細節處理

1.3.1選擇屏幕設置

當選擇屏幕需要切換時,如果輸入框有必輸字段則需要輸入值才能切換到另一個界面

 

一般的處理方法是,去掉必輸標識,用程序控制是否必輸,報消息提醒,但是這種方法畢竟沒法給用戶直觀的必輸體驗,因此可以采用下面的方法:

銷售組織不設置必輸

 

此處只打上勾,但是卻不自動校驗是否輸值,只是一個外觀效果

AT SELECTION-SCREEN OUTPUT.

  LOOP AT SCREEN.
    IF screen-name = 'S_VKORG-LOW'.
      screen-required = '2'."外觀上打鈎必輸,但不自動校驗
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.

FORM frm_check_srceen.
  IF s_vkorg-low IS INITIAL.
    MESSAGE e016(zsd).
  ENDIF.
ENDFORM.

1.3.2選擇框

在OOALV中,定義側邊欄BOX選擇框是不起作用的,但是勾選的選擇框對於大量的數據實在比較不方便,因此我們需要使用側邊欄BOX,並做特殊處理。

在調用創建等操作按鈕之前,使用get_selected_rows獲取選中的行,先將上一次選中的行的BOX標記去掉,之后將選中行的BOX字段打上標記。

CALL METHOD g_grid_9000->get_selected_rows
  IMPORTING
    et_index_rows = lt_row
    et_row_no     = lt_roid.

*  因為OOALV中側邊欄選擇框不起作用,但是需要使用,就將選中的行的側邊欄的值修改一下
    gs_item-box = ''.
    MODIFY gt_item FROM gs_item TRANSPORTING box WHERE box = 'X'.
    LOOP AT lt_row INTO ls_row.
      READ TABLE gt_item INTO gs_item INDEX ls_row-INDEX.
      IF sy-subrc EQ 0.
        gs_item-box = 'X'.
        MODIFY gt_item FROM gs_item INDEX ls_row-INDEX TRANSPORTING box .
      ENDIF.
      CLEAR:ls_row,gs_item.
    ENDLOOP.

1.3.3動態列

在OOALV中需要實現不同條件下,顯示不同列。

1、DATA: G_GRID TYPE REF TO CL_GUI_ALV_GRID.

使用G_GRID->GET_FRONTEND_FIELDCATALOG ,獲取當前的列信息,之后修改為需要顯示的列,或者直接清空,用PERFORM INIT_FIELDCAT1.重新賦值。之后使用G_GRID->SET_FRONTEND_FIELDCATALOG,傳入新賦值的列內表即可。

 

1.3.4獲取雙擊單元格的值

*&---------------------------------------------------------------------*
*&      Form  FRM_DOUBLE_CLICK
*&---------------------------------------------------------------------*
FORM frm_double_click_9001 USING p_e_row_id TYPE lvc_s_row
      p_e_column_id TYPE lvc_s_col
      p_es_row_no TYPE lvc_s_roid.

  "獲取當前單元格的內容
  DATA:e_value TYPE char255.
  CALL METHOD g_grid_9001->get_current_cell
    IMPORTING
      e_value = e_value.

  CASE p_e_column_id-fieldname.
    WHEN 'MATNR'.
      SET PARAMETER ID 'MAT' FIELD e_value.
      CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN.
    WHEN 'PLNUM'."計划訂單
      SET PARAMETER ID 'PAF' FIELD e_value.
      CALL TRANSACTION 'MD13' AND SKIP FIRST SCREEN.
  ENDCASE.

ENDFORM.

1.3.5沒有保存布局按鈕

OOALV中只有更改布局按鈕,沒有保存布局按鈕

 插入代碼

gs_variant_9000-report = sy-repid && sy-dynnr.

出現了保存布局按鈕


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM