本文以如下财务的收款认领平台为例,来展示一个常规的ALV两栏式报表程序的开发,案例图如下:
实现的大概逻辑是:首先定制一个屏幕容器,然后在定制屏幕中存放子容器来分别显示两栏ALV报表。最终实现了一个上栏是主数据,下栏可以通过点击热键显示某条主数据的详情数据。
一、首先是程序代码,准备数据和最重要的新建屏幕
二、新建一个通常屏幕内容如下:
全局定义参数:
DATA: go_toolbar TYPE REF TO cl_gui_toolbar,
go_dragdrop_alv TYPE REF TO cl_dragdrop,
go_container TYPE REF TO cl_gui_custom_container,
go_container_d TYPE REF TO cl_gui_docking_container,
go_container_s TYPE REF TO cl_gui_docking_container,
gs_layo_detial TYPE lvc_s_layo,
gs_layo_data TYPE lvc_s_layo,
gs_layo_data_dis TYPE lvc_s_layo,
gs_fcat_detial TYPE lvc_s_fcat,
gt_fcat_detial TYPE lvc_t_fcat,
gs_fcat_data TYPE lvc_s_fcat,
gt_fcat_data TYPE lvc_t_fcat,
gs_fcat_data_dis TYPE lvc_s_fcat,
gt_fcat_data_dis TYPE lvc_t_fcat,
go_grid_detial TYPE REF TO cl_gui_alv_grid,
go_grid_data_dis TYPE REF TO cl_gui_alv_grid,
go_grid_data TYPE REF TO cl_gui_alv_grid.
2.1 状态栏和返回退出功能
(1)GUI STATUS
MODULE status_9000 OUTPUT.
SET PF-STATUS 'STATUS2'.
SET TITLEBAR 'ZTIT'.
ENDMODULE.
(2)exit 注意要设置功能类型为E才能生效,如下图
MODULE exit_0100 INPUT.
LEAVE TO SCREEN 0.
ENDMODULE.
(3)创建容器
FORM create_container .
IF go_container IS INITIAL.
CREATE OBJECT go_container
EXPORTING
container_name = 'CTRL_CONTAINER'."定制屏幕名
ENDIF.
ENDFORM.
(4)user_command
FORM user_command_9000 .
CLEAR: gv_code.
gv_code = ok_code.
CLEAR: ok_code.
go_grid_detial->check_changed_data( ).
go_grid_data->check_changed_data( ).
CASE gv_code.
WHEN '&IC1'."双击
WHEN '&DATA_SAVE'."保存数据存底表
PERFORM frm_save_data.
WHEN 'CONFIRM'."确认收款
PERFORM frm_confirm_data.
WHEN 'DISCON'."拆行
PERFORM frm_disconnect_data.
WHEN 'YSFL'. "确认预收并返利
PERFORM frm_ysfl_data.
WHEN 'CHARGE'."冲销收款认领
PERFORM frm_charge_data.
WHEN 'SAVE'."明细确认
PERFORM frm_detail_data_confirm.
ENDCASE.
CLEAR: gv_code.
ENDFORM.
2.2主数据界面逻辑
FORM display_data .
IF go_grid_data IS INITIAL.
CREATE OBJECT go_grid_data
EXPORTING
i_parent = go_container.
PERFORM set_alv_drag_data. "设置GRAG
PERFORM set_layo_data. "格式设置
PERFORM set_fcat_data. "设置列属性
PERFORM register_event_data. "注册事件
PERFORM alv_first_display_data. "ALV显示
ELSE.
PERFORM refresh_table_display USING go_grid_data.
ENDIF.
ENDFORM.
FORM set_alv_drag_data .
DATA lv_effect TYPE i .
lv_effect = cl_dragdrop=>move + cl_dragdrop=>copy .
CREATE OBJECT go_dragdrop_alv.
CALL METHOD go_dragdrop_alv->add
EXPORTING
flavor = 'LINE'
dragsrc = 'X'
droptarget = ''
effect = lv_effect.
go_dragdrop_alv->get_handle( IMPORTING handle = gv_node_dragdropid_d ).
ENDFORM.
FORM set_layo_data .
CLEAR: gs_layo_data.
gs_layo_data-zebra = 'X'.
gs_layo_data-cwidth_opt = 'X'.
gs_layo_data-sel_mode = 'D'.
gs_layo_data-s_dragdrop-row_ddid = gv_node_dragdropid_d.
ENDFORM.
FORM set_fcat_data .
DEFINE set_fieldcat2.
CLEAR gs_fcat_data.
gs_fcat_data-fieldname = &1.
gs_fcat_data-scrtext_l = &2.
gs_fcat_data-ref_field = &3.
gs_fcat_data-ref_table = &4.
gs_fcat_data-key = &5.
gs_fcat_data-edit = &6.
gs_fcat_data-hotspot = &7.
gs_fcat_data-datatype = &8.
gs_fcat_data-outputlen = &9.
APPEND gs_fcat_data TO gt_fcat_data.
END-OF-DEFINITION.
REFRESH: gt_fcat_data.
set_fieldcat2 'ID' '检查状态' '' '' '' '' '' '' 18.
set_fieldcat2 'MSG' '错误信息' '' '' '' '' '' '' 18.
set_fieldcat2 'ZLSM' '银行流水编码' '' '' '' '' '' '' 18.
set_fieldcat2 'ZCHXM' '拆分行项目' '' '' '' '' '' '' 18.
ENDFORM.
FORM register_event_data .
IF go_event_handler IS INITIAL.
CREATE OBJECT go_event_handler.
ENDIF.
CALL METHOD go_grid_data->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_modified.
CALL METHOD go_grid_data->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter.
SET HANDLER go_event_handler->handle_data_changed FOR go_grid_data.
SET HANDLER go_event_handler->handle_toolbar FOR go_grid_data.
SET HANDLER go_event_handler->handle_hotspot FOR go_grid_data.
SET HANDLER go_event_handler->handle_user_command FOR go_grid_data.
SET HANDLER go_event_handler->handle_after_user_command FOR go_grid_data.
ENDFORM.
FORM alv_first_display_data .
DATA: ls_variant TYPE disvariant.
ls_variant-report = sy-repid.
ls_variant-username = sy-uname.
ls_variant-handle = '1'.
CALL METHOD go_grid_data->set_table_for_first_display
EXPORTING
is_variant = ls_variant
i_save = 'A'
i_default = 'X'
is_layout = gs_layo_data
CHANGING
it_fieldcatalog = gt_fcat_data
it_outtab = gt_main_data.
ENDFORM.
FORM refresh_table_display USING po_grid TYPE REF TO cl_gui_alv_grid.
DATA: ls_stbl TYPE lvc_s_stbl .
ls_stbl-row = 'X' .
ls_stbl-col = 'X' .
CHECK NOT po_grid IS INITIAL.
"刷新LAYOUT,优化列宽
gs_layout-cwidth_opt = 'X'.
CALL METHOD po_grid->set_frontend_layout
EXPORTING
is_layout = gs_layout.
CALL METHOD po_grid->refresh_table_display
EXPORTING
is_stable = ls_stbl
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.
ENDFORM.
注册事件:
CLASS lcl_event_handler DEFINITION.
PUBLIC SECTION.
METHODS:
handle_data_changed FOR EVENT data_changed_finished OF cl_gui_alv_grid
IMPORTING e_modified et_good_cells,
handle_toolbar
FOR EVENT toolbar OF cl_gui_alv_grid
IMPORTING sender e_object,
handle_after_user_command
FOR EVENT after_user_command OF cl_gui_alv_grid
IMPORTING sender e_ucomm,
handle_user_command
FOR EVENT after_user_command OF cl_gui_alv_grid
IMPORTING sender e_ucomm,
handle_hotspot
FOR EVENT hotspot_click OF cl_gui_alv_grid
IMPORTING sender e_row_id e_column_id.
ENDCLASS.
CLASS lcl_event_handler IMPLEMENTATION.
METHOD handle_data_changed.
PERFORM handle_data_changed ."回车事件
ENDMETHOD.
METHOD handle_toolbar.
PERFORM handle_toolbar USING sender e_object. "容器工具栏事件
ENDMETHOD. "handle_toolbar
METHOD handle_hotspot.
PERFORM hotspot_click USING sender e_row_id e_column_id."热键事件
ENDMETHOD. "HANDLE_HOTSPOT
METHOD handle_after_user_command.
PERFORM handle_after_user_command USING sender e_ucomm.
ENDMETHOD. "handle_after_user_command
METHOD handle_user_command.
PERFORM after_user_command USING sender e_ucomm.
ENDMETHOD. "HANDLE_USER_COMMAND
ENDCLASS.
DATA: go_event_handler TYPE REF TO lcl_event_handler.
FORM handle_after_user_command USING po_sender
pa_ucomm TYPE sy-ucomm.
cl_gui_cfw=>set_new_ok_code( pa_ucomm ).
ENDFORM. " HANDLE_AFTER_USER_COMMAND
FORM after_user_command USING po_sender
pa_ucomm TYPE sy-ucomm.
cl_gui_cfw=>set_new_ok_code( pa_ucomm ).
ENDFORM.
2.3 详情数据
FORM display_detail .
IF go_grid_detial IS INITIAL.
IF go_container_d IS INITIAL.
CREATE OBJECT go_container_d
EXPORTING
side = cl_gui_docking_container=>dock_at_bottom "位于下方
extension = 50
EXCEPTIONS
cntl_error = 1
cntl_system_error = 2
create_error = 3
lifetime_error = 4
lifetime_dynpro_dynpro_link = 5
OTHERS = 6.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDIF.
CREATE OBJECT go_grid_detial
EXPORTING
i_parent = go_container_d.
PERFORM set_alv_drag_detial. "设置GRAG
PERFORM set_layo_detial. "格式设置
PERFORM set_fcat_detial. "设置列属性
PERFORM register_event_detial. "注册事件
PERFORM alv_first_display_detial. "ALV显示
ELSE.
PERFORM refresh_table_display USING go_grid_detial.
ENDIF.
IF r1 = 'X'.
CALL METHOD go_container_d->set_visible "容器显示与否
EXPORTING
visible = ''.
ELSE.
CALL METHOD go_container_d->set_visible
EXPORTING
visible = 'X'.
ENDIF.
ENDFORM.
其余逻辑通主数据界面逻辑,注意grid参数和容器参数的不同
2.4 穿透
至于说穿透到另外一个ALV界面的话可以用FUNCTION ALV来实现。就例如本案例的拆行功能。点击按钮后跳转到新的界面,form如下,详细代码省略,读者可以按照function alv的逻辑去写,模板可用笔者的另外一篇文章SAP ABAP常规报表开发模板_sap文档模版-CSDN博客。
FORM frm_disconnect_data .
DATA:lv_flag TYPE c1.
DATA:lt_row TYPE lvc_t_roid.
"获取选中行
CALL METHOD go_grid_data->get_selected_rows(
IMPORTING
et_row_no = lt_row ).
CLEAR:gs_main_data_dis,gt_main_data_dis.
LOOP AT gt_main_data INTO gs_main_data.
READ TABLE lt_row INTO DATA(ls_row) WITH KEY row_id = sy-tabix.
IF sy-subrc <> 0.
CONTINUE.
ENDIF.
IF gs_main_data-belnr IS NOT INITIAL AND gs_main_data-belnr1 IS INITIAL.
MESSAGE '已认领过的数据不能拆行!' TYPE 'S' DISPLAY LIKE 'E'.
lv_flag = 'X'.
ENDIF.
MOVE-CORRESPONDING gs_main_data TO gs_main_data_dis.
APPEND gs_main_data_dis TO gt_main_data_dis.
EXIT.
ENDLOOP.
CHECK lv_flag IS INITIAL.
"添加二十条空白行
DO 20 TIMES.
APPEND INITIAL LINE TO gt_main_data_dis.
ENDDO.
CLEAR:gt_fieldcat.
PERFORM frm_set_layout.
PERFORM frm_set_fieldcat.
PERFORM frm_display_alv.
ENDFORM.