主要通过CL_GUI_ALV_GRID这个类来控制alv的显示,ALV显示需要屏幕容器,容器对应类:
1、cl_gui_custom_container,默认容器alv自动占满整个容器;
2、cl_gui_docking_container,docking容器alv宽度可以直接调整;
3、cl_gui_splitter_contianer,splitter容器,可以将屏幕划分区域显示多个alv;
在ALV的工具条上增加一些按钮来增加我们自定义的功能,当然也可以在GUI状态中增加,2种的处理方式是不一样的.
这里通过toolbar事件来增加按钮,然后通过user_command事件来实现我们自定义的功能.
在TOOLBAR事件里,我们把自定义的按钮加到参数"e_object"的表属性"mt_toolbar"中可以了.
*---------------------------------------------------------------------*
* 定义对象
*---------------------------------------------------------------------*
DATA: oo_field TYPE lvc_t_fcat, "字段目录
oo_layout TYPE lvc_s_layo, "布局
oo_toolbar TYPE stb_button,
oo_cont_on_9001 TYPE scrfname VALUE 'TOOLBAR_9001', "定义子屏幕区域
oo_grid TYPE REF TO cl_gui_alv_grid,
oo_container TYPE REF TO cl_gui_custom_container. "默认容器alv自动占满整个容器
DATA: wa_stbl TYPE lvc_s_stbl.
wa_stbl-row = 'X'." 基于行的稳定刷新
wa_stbl-col = 'X'." 基于列稳定刷新
*---------------------------------------------------------------------*
* OO ALV FIELDCAT 字段定义
*---------------------------------------------------------------------*
CLASS lcl_event_receiver DEFINITION DEFERRED.
DATA: event_receiver TYPE REF TO lcl_event_receiver.
PERFORM frm_create_fieldcat TABLES oo_field USING 'CHECK' '选择' 'L' 'X' '' '' '' 'IT_9001' 0 '' 'X'.
PERFORM frm_create_fieldcat TABLES oo_field USING 'KUNNR' '客户号' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'NAME1' '客户名称' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'VBELN_VF' '发票号' 'L' '' '' '' '' 'IT_9001' 0 'X' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'POSNR_VF' '行项目' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'MATNR' '物料号' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'ARKTX' '物料描述' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'FKLMG' '发票数量' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'KBETR' '含税发票单价' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'VLB_FKLMG' '可数量' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'KPEIN' '单位' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'FKLMG_JS' '总数量' 'L' 'X' 'X' '' '' 'IT_9001' 3 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'VBELN_SO' '销售订单' 'L' '' '' '' '' 'IT_9001' 0 'X' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'POSNR_SO' '行项目' 'L' '' '' '' '' 'IT_9001' 0 '' ''.
PERFORM frm_create_fieldcat TABLES oo_field USING 'ZREMARK' '行备注' 'L' 'X' 'X' '' '' 'IT_9001' 0 '' ''.
oo_layout-smalltitle = 'X'.
oo_layout-zebra = 'X'.
oo_layout-sel_mode = '1'.
oo_layout-cwidth_opt = 'X'.
*---------------------------------------------------------------------*
* 定义 类
*---------------------------------------------------------------------*
CLASS lcl_event_receiver DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
handle_toolbar "自定义工具栏
FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING e_object e_interactive,
handle_menu_button "自定义菜单
FOR EVENT menu_button OF cl_gui_alv_grid
IMPORTING e_object e_ucomm,
handle_user_command "自定义按钮
FOR EVENT user_command OF cl_gui_alv_grid
IMPORTING e_ucomm,
handle_hotspot_click1 "单击事件
FOR EVENT hotspot_click OF cl_gui_alv_grid
IMPORTING e_row_id e_column_id,
handle_data_changed "数据改变触发
FOR EVENT data_changed OF cl_gui_alv_grid
IMPORTING er_data_changed.
PRIVATE SECTION.
ENDCLASS.
*---------------------------------------------------------------------*
* 实现类
*---------------------------------------------------------------------*
CLASS lcl_event_receiver IMPLEMENTATION.
METHOD handle_toolbar.
DATA: ls_toolbar TYPE stb_button.
MOVE '' TO ls_toolbar-function.
MOVE '' TO ls_toolbar-icon.
MOVE '3' TO ls_toolbar-butn_type.
APPEND ls_toolbar TO e_object->mt_toolbar.
CLEAR ls_toolbar.
MOVE 'SELA' TO ls_toolbar-function.
MOVE icon_select_all TO ls_toolbar-icon.
MOVE '全选' TO ls_toolbar-quickinfo.
MOVE ''(112) TO ls_toolbar-text.
APPEND ls_toolbar TO e_object->mt_toolbar.
CLEAR ls_toolbar.
MOVE 'DSEL' TO ls_toolbar-function.
MOVE icon_deselect_all TO ls_toolbar-icon.
MOVE '取消全选' TO ls_toolbar-quickinfo.
MOVE ''(112) TO ls_toolbar-text.
APPEND ls_toolbar TO e_object->mt_toolbar.
CLEAR ls_toolbar.
MOVE 'B_LIST' TO ls_toolbar-function.
MOVE 1 TO ls_toolbar-butn_type.
MOVE icon_calculation TO ls_toolbar-icon.
MOVE '自定义下拉菜单按钮'(202) TO ls_toolbar-quickinfo.
MOVE '下拉菜单按钮' TO ls_toolbar-text.
"MOVE '' TO ls_toolbar-disabled.
APPEND ls_toolbar TO e_object->mt_toolbar.
ENDMETHOD. "handle_toolbar
*--------------------------------------------------------------------
METHOD handle_menu_button . "自定义菜单实现方法
IF e_ucomm = 'B_LIST'."给下拉菜单按钮增加选项,可以多次调用该方法以增加多行
CALL METHOD e_object->add_function
EXPORTING
icon = ICON_OKAY
fcode = 'B_SUM' "字菜单按钮的FunCode
text = '显示ALV总行数'.
CALL METHOD e_object->add_function
EXPORTING
icon = ICON_CANCEL
fcode = 'C_SUM' "字菜单按钮的FunCode
text = '测试'.
ENDIF.
ENDMETHOD. "handle_menu_button
*---------------------------------------------------------------------
METHOD handle_user_command. "自定义按钮实现方法
DATA: sum TYPE i .
CASE e_ucomm.
WHEN 'SELA'.
LOOP AT it_9001 INTO wa_9001.
wa_9001-check = 'X'.
MODIFY it_9001 INDEX sy-tabix FROM wa_9001 TRANSPORTING check.
ENDLOOP.
CALL METHOD oo_grid->refresh_table_display"这句话一定要写,否则界面没刷新,不生效
EXPORTING
is_stable = wa_stbl.
WHEN 'DSEL'.
LOOP AT it_9001 INTO wa_9001.
wa_9001-check = ''.
MODIFY it_9001 INDEX sy-tabix FROM wa_9001 TRANSPORTING check.
ENDLOOP.
CALL METHOD oo_grid->refresh_table_display
EXPORTING
is_stable = wa_stbl.
WHEN 'B_SUM'.
DESCRIBE TABLE it_9001[] LINES sum.
MESSAGE i001(00) WITH '当前ALV表格中的数据总行数为:' sum.
WHEN 'C_SUM'.
MESSAGE i001(00) WITH '测试为:' sum.
ENDCASE.
ENDMETHOD.
METHOD handle_data_changed. "数据变化实现方法
PERFORM handle_data_changed USING er_data_changed.
ENDMETHOD.
METHOD handle_hotspot_click1. "单击事件实现方法
READ TABLE it_9001 INTO wa_9001 INDEX e_row_id-index.
CASE e_column_id-fieldname.
WHEN 'VBELN_VF'.
SET PARAMETER ID 'VF' FIELD wa_9001-vbeln_vf.
CALL TRANSACTION 'VF03' AND SKIP FIRST SCREEN.
WHEN 'VBELN_SO'.
SET PARAMETER ID 'AUN' FIELD wa_9001-vbeln_so.
CALL TRANSACTION 'VA03' AND SKIP FIRST SCREEN.
ENDCASE.
ENDMETHOD. "HANDLE_HOTSPOT_CLICK1
ENDCLASS.
*---------------------------------------------------------------------*
* FRM_CREATE_FIELDCAT
* 9001 ALV 定义
*---------------------------------------------------------------------*
FORM frm_create_fieldcat TABLES t_fcat TYPE lvc_t_fcat
USING u_fieldname TYPE lvc_fname
u_scrtext TYPE any
u_just TYPE lvc_just
u_edit TYPE lvc_edit
u_no_zero TYPE lvc_nozero
u_dosum TYPE lvc_dosum
u_outputlen TYPE any
u_table TYPE string
u_decimals TYPE decimals
u_hotspot TYPE lvc_hotspt
u_checkbox TYPE lvc_checkb
.
DATA:lwa_fcat TYPE lvc_s_fcat.
lwa_fcat-fieldname = u_fieldname.
lwa_fcat-scrtext_s = u_scrtext.
lwa_fcat-just = u_just.
lwa_fcat-edit = u_edit.
lwa_fcat-no_zero = u_no_zero.
lwa_fcat-do_sum = u_dosum.
lwa_fcat-outputlen = u_outputlen.
lwa_fcat-tabname = u_table.
lwa_fcat-decimals = u_decimals.
lwa_fcat-hotspot = u_hotspot.
lwa_fcat-checkbox = u_checkbox.
APPEND lwa_fcat TO t_fcat.
CLEAR lwa_fcat.
ENDFORM.
按理说,实现类中方法,应该统一调用函数PERFORM来实现,这样程序维护起来很容易。前面类实现中,部分方法已经实现,这里是数据发生变化方法的实现。具体业务场景根据自己需要更改代码
*---------------------------------------------------------------------*
* 处理数据的函数
* 当界面的数据发生变化
*---------------------------------------------------------------------*
FORM handle_data_changed USING data_changed TYPE REF TO cl_alv_changed_data_protocol.
DATA: x_change TYPE lvc_s_modi.
LOOP AT data_changed->mt_good_cells INTO x_change.
"结算数量发生变化
IF x_change-fieldname = 'FKLMG_JS'.
READ TABLE it_9001 INTO wa_9001 INDEX x_change-row_id.
wa_9001-fklmg_js = x_change-value.
wa_9001-kbetr_tmp = wa_9001-kbetr_js * wa_9001-fklmg_js / wa_9001-kpein / '1.13'.
MODIFY it_9001 FROM wa_9001 INDEX x_change-row_id.
ENDIF.
"行备注内容发生变化
IF x_change-fieldname = 'ZREMARK'.
READ TABLE it_9001 INTO wa_9001 INDEX x_change-row_id.
wa_9001-zremark = x_change-value.
MODIFY it_9001 FROM wa_9001 INDEX x_change-row_id.
ENDIF.
CALL METHOD oo_grid->refresh_table_display
EXCEPTIONS
finished = 1
OTHERS = 2.
ENDLOOP.
ENDFORM.
这里我创建屏幕是9001,当然你可以是100,1001。
"调用9001屏幕前,需要把显示的数据拼接好,这里就不演示了
CALL SCREEN 9001.
"这里是9001屏幕
PROCESS BEFORE OUTPUT.
MODULE STATUS_9001.
PROCESS AFTER INPUT.
MODULE USER_COMMAND_9001.
"屏幕输出前
MODULE status_9001 OUTPUT.
"设置GUI状态
SET PF-STATUS '9001_PF'.
"设置界面标题
SET TITLEBAR '9001_BAR'.
"控制结算单字段显示
* IF check_js = 'X'.
* LOOP AT SCREEN.
* IF screen-group1 = 'ZC1'.
* screen-input = 0.
* screen-output = 1.
* screen-active = 1.
* MODIFY SCREEN.
* ENDIF.
* ENDLOOP.
* ENDIF.
IF oo_container IS INITIAL.
* 建立一个容器控件作为ALV的容器
CREATE OBJECT oo_container
EXPORTING
container_name = oo_cont_on_9001.
* 建立一个ALV的实例
CREATE OBJECT oo_grid
EXPORTING
i_parent = oo_container.
* 显示表格
CALL METHOD oo_grid->set_table_for_first_display
EXPORTING
is_layout = oo_layout
CHANGING
it_outtab = it_9001[]
it_fieldcatalog = oo_field.
* 注册ALV的事件
CREATE OBJECT event_receiver.
SET HANDLER event_receiver->handle_toolbar FOR oo_grid. "注册工具栏
SET HANDLER event_receiver->handle_menu_button FOR oo_grid. "注册工具栏菜单
SET HANDLER event_receiver->handle_user_command FOR oo_grid. "注册用户自定义命令
SET HANDLER event_receiver->handle_data_changed FOR oo_grid."单元格数据更改时触发
SET HANDLER event_receiver->handle_hotspot_click1 FOR oo_grid."单击事件
"调用此方法才能激活工具栏上增加的自定义按钮
CALL METHOD oo_grid->set_toolbar_interactive.
CALL METHOD oo_grid->register_edit_event "注册事件
EXPORTING
* I_EVENT_ID = CL_GUI_ALV_GRID=>MC_EVT_ENTER. "回车时触发
i_event_id = cl_gui_alv_grid=>mc_evt_modified. "单元格更改触发
ENDIF.
CALL METHOD oo_grid->refresh_table_display.
ENDMODULE.
MODULE user_command_9001 INPUT.
DATA: tmp_code LIKE sy-ucomm.
DATA wl_answer TYPE char01.
tmp_code = ok_code.
CLEAR: ok_code.
CASE tmp_code.
WHEN 'EXIT'.
LEAVE TO SCREEN 0.
WHEN 'BACK'.
LEAVE TO SCREEN 0.
WHEN 'BTN_CREAT'.
CALL METHOD cl_gui_cfw=>flush.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
text_question = '是否保存单据!!'
icon_button_1 = '是'
icon_button_2 = '否'
default_button = '2'
display_cancel_button = 'X'
start_column = 25
start_row = 6
IMPORTING
answer = wl_answer
EXCEPTIONS
text_not_found = 1
OTHERS = 2.
IF wl_answer = '1'.
"结算单界面数据的校验
* PERFORM data_chaeck.
*
* IF check_flag = 'Y'.
* "结算单按钮
* PERFORM command_btn_creat.
* "刷新界面
* CALL METHOD oo_grid->refresh_table_display.
* ELSE.
*
* MESSAGE check_msg TYPE 'S' DISPLAY LIKE 'E'.
*
* ENDIF.
ENDIF.
"打印
WHEN 'PRINT'.
"PERFORM check_print.
"作废
WHEN 'BTN_DEL'.
CALL METHOD cl_gui_cfw=>flush.
CALL FUNCTION 'POPUP_TO_CONFIRM'
EXPORTING
text_question = '是否作废结算单!!'
icon_button_1 = '是'
icon_button_2 = '否'
default_button = '2'
display_cancel_button = 'X'
start_column = 25
start_row = 6
IMPORTING
answer = wl_answer
EXCEPTIONS
text_not_found = 1
OTHERS = 2.
IF wl_answer = '1'.
"结算单界面数据的校验
* PERFORM check_jsdata.
*
* IF check_flag = 'Y'.
* "作废按钮
* PERFORM command_btn_del.
*
* ELSE.
*
* MESSAGE check_msg TYPE 'S' DISPLAY LIKE 'E'.
*
* ENDIF.
"刷新界面
CALL METHOD oo_grid->refresh_table_display.
ENDIF.
WHEN OTHERS.
ENDCASE.
CLEAR ok_code.
ENDMODULE.