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.
出現了保存布局按鈕