文章目录
前言
练习本实例所需要具备的ABAP知识:
-
FUNCTION ALV (FM_ALV) 程序的熟练编写:字段目录、布局样式、事件处理
-
ABAP 面向对象编程的基本知识,了解类的定义,实施方式,事件的处理。
-
OOALV 除事件处理外,可自己独立实现OOALV的展示……
在此知识基础上,练习本实例才有可能比较容易的顺利理解……否则,建议先打好基础知识的底子,以提高学习的效率……
一、效果图
实例用表:SPFLI 航班计划 SAPLANE 飞机 . 以SPFLI 部分字段为基础,字段PLANETYPE (飞机类型) 去除参照数据元素,直接TYPE 基本数据类型。作飞机类型的自定义搜索帮助(数据源:SAPLANE)。
二、程序思路:
在ALV中实现指定字段的搜索帮助:
- 一种方法是:在ABAP字典定义搜索帮助。然后在FIELDCATALGO 中设置三个参数:
REF_TABLE (参照表) REF_FIELD (参照字段) F4AVAILABL = ‘X’ (字段有搜索帮助)。
- 第二种方法:自定义代码来实现ALV的搜索帮助。
对于FM_ALV 来说,要走这种“自定义搜索帮助”的思路, 其实就是给自己“套”个 OOALV的“壳”后,利用类:CL_GUI_ALV_GRIDR 一些特性, 主要是 ONF4 事件来实现自定义搜索帮助。 F4AVAILABL = ‘X’ (字段有搜索帮助) 也是要有的。
三、程序文件
如下为全部代码,为方便大家一步复制到自己的系统上,直接执行,查看运行效果,我去除了 INCLUDE 文件。但是建议希望大家,验证效果后,自己再归整为如图下方式,便于调试与理解。
如下代码,直接复制后,粘贴到自己系统直接就好……
*&---------------------------------------------------------------------*
*& Report ZRAY_FM_ALV_F4
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZRAY_FM_ALV_F4C.
***声明变量部
TYPE-POOLS: slis.
TABLES: spfli.
TYPES: BEGIN OF ty_spfli,
carrid TYPE char3 , "航线代码
connid TYPE numc4 , "航班连接编号
countryfr TYPE char3 , "国家/地区代码
cityfrom TYPE char20 , "起飞城市
airpfrom TYPE char3 , "始发机场
countryto TYPE char3 , "国家/地区代码
cityto TYPE char20 , "到达城市
airpto TYPE char3 , "目标机场
plane TYPE char10 , "飞机类型
seatsmax TYPE int4 , "经济舱的最大容量
END OF ty_spfli.
TYPES:BEGIN OF ty_help, "自定义搜索帮助表类型
planetype TYPE s_planetye , "飞机类型
seatsmax TYPE s_seatsmax , "经济舱的最大容量
seatsmax_b TYPE s_smax_b , "商务舱的最大容量
seatsmax_f TYPE s_smax_f , "头等舱的最大容量
END OF ty_help.
DATA:
gt_alv TYPE STANDARD TABLE OF ty_spfli, "定义内表 及工作区
gs_alv TYPE ty_spfli.
DATA: gt_f4_help TYPE STANDARD TABLE OF ty_help.
DATA: gs_layout TYPE lvc_s_layo, " 设置布局样式 参数结构
gt_fieldcat TYPE lvc_t_fcat, "设置字段目录参数表
gs_fieldcat TYPE lvc_s_fcat, "设置字段目录参数表的工作区
gT_events TYPE slis_t_event. " 设置ALV 的事件参数表
DATA:
go_grid TYPE REF TO cl_gui_alv_grid.
***---------------------------------------------------
*&---------------------------------------------------------------------*
*& 包含 ZRAY_FM_ALV_F4_CLASS
*&---------------------------------------------------------------------*
***"类自定义部分及类方法相关子例
CLASS lcl_event_receiver DEFINITION.
PUBLIC SECTION.
METHODS: handle_f4
FOR EVENT ONF4 OF cl_gui_alv_grid
IMPORTING e_fieldname "字段名称
es_row_no "行号,注意这是个结构
er_event_data . "事件数据
ENDCLASS.
CLASS: lcl_event_receiver IMPLEMENTATION.
METHOD HANDLE_F4.
DATA: LS_STABLE TYPE LVC_S_STBL. "定义基于稳定的刷新 所需要参数。
LS_STABLE-ROW = 'X'. "行固定
LS_STABLE-COL = 'X'. "列固定
IF e_fieldname = 'PLANE'. "又是小写的问题,一定要注意
PERFORM f4_help_plane USING e_fieldname "字段名称
es_row_no "行号,注意这是个结构
er_event_data . "事件数据
ENDIF.
CALL METHOD go_grid->refresh_table_display " 使用类:CL_GUI_ALV_GRID的实例的方法,稳定刷新
EXPORTING
is_stable = LS_STABLE.
ENDMETHOD.
ENDCLASS.
**------------------------------------------
*&---------------------------------------------------------------------*
*& 包含 ZRAY_FM_ALV_F4_FM01
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form FM01_GET_DATAL
*&---------------------------------------------------------------------*
*& 获取数据到ALV 内表
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM fm01_get_data .
SELECT * FROM spfli
INTO CORRESPONDING FIELDS OF TABLE gt_alv.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FM02_SET_LAYOUT_FIELDCAT
*&---------------------------------------------------------------------*
*& 设置字段目录与布局样式
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM fm02_set_layout_fieldcat .
DATA: lv_index TYPE sy-index VALUE 0.
gs_layout-zebra = 'X'. "斑马线
gs_layout-cwidth_opt = 'X'. "优化列宽
DEFINE: fill_fieLd.
lv_index = lv_index + 1. "自累加列号
CLEAR: gs_fieldcat.
gs_fieldcat-col_pos = lv_index.
gs_fieldcat-fieldname = &1. "字段
gs_fieldcat-just = &2. "对齐
gs_fieldcat-ref_field = &3. "参数字段
gs_fieldcat-ref_table = &4. "参数表
gs_fieldcat-coltext = &5. "列字段名
CASE &1.
WHEN 'PLANE'.
gs_fieldcat-edit = 'X'. "设置可编辑
gs_fieldcat-f4availabl = 'X'. "设置有搜索帮助
ENDCASE.
APPEND gs_fieldcat TO gt_fieldcat.
END-OF-DEFINITION.
* &1 &2 &3 &4 &5
fill_field: 'CARRID' 'C' 'CARRID' 'SPFLI' '航线代码' .
fill_field: 'CONNID' 'C' 'CONNID' 'SPFLI' '航班连接编号' .
fill_field: 'COUNTRYFR' 'C' 'COUNTRYFR' 'SPFLI' '国家/地区代码' .
fill_field: 'CITYFROM' 'R' 'CITYFROM' 'SPFLI' '起飞城市' .
fill_field: 'AIRPFROM' 'C' 'AIRPFROM' 'SPFLI' '始发机场' .
fill_field: 'COUNTRYTO' 'C' 'COUNTRYTO' 'SPFLI' '国家/地区代码' .
fill_field: 'CITYTO' 'R' 'CITYTO' 'SPFLI' '到达城市' .
fill_field: 'AIRPTO' 'C' 'AIRPTO' 'SPFLI' '目标机场' .
fill_field: 'PLANE' 'C' '' '' '选择飞机类型' .
fill_field: 'SEATSMAX' 'C' '' '' '经济舱容量 ' .
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FM06_CALL_ALV
*&---------------------------------------------------------------------*
*& 展示FM ALV
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM fm06_call_alv .
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = sy-repid
is_layout_lvc = gs_layout
it_fieldcat_lvc = gt_fieldcat
it_events = gt_events[]
TABLES
t_outtab = gt_alv
EXCEPTIONS
program_error = 1
OTHERS = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FM03_CREATE_F4_PLANE_TABLE
*&---------------------------------------------------------------------*
*& 获取搜索帮助表
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM fm03_create_f4_plane_table .
SELECT * FROM saplane
INTO CORRESPONDING FIELDS OF TABLE gt_f4_help
UP TO 10 ROWS.
SORT gt_f4_help BY planetype.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FM04_SET_FM_ALV_EVENT
*&---------------------------------------------------------------------*
*& 设置FM_ALV 的CALLER_EXIT 事件
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM fm04_set_fm_alv_event .
DATA: ls_events TYPE slis_alv_event.
ls_events-name = 'CALLER_EXIT' .
ls_events-form = 'FRM_CALLER_EXIT'.
APPEND ls_events TO gt_events.
ENDFORM.
FORM FRM_CALLER_EXIT USING e_grid TYPE slis_data_caller_exit.
DATA:
lo_event_receiver TYPE REF TO lcl_event_receiver.
DATA: "定义的变量为类的方法:REGISTER_F4_FOR_FIELDS 用参数
lt_f4 TYPE lvc_t_f4 WITH HEADER LINE.
IF go_grid IS INITIAL.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = go_grid.
ENDIF.
* 设置事件-回车
CALL METHOD go_grid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter
EXCEPTIONS
error = 1
OTHERS = 2.
**指定OOALV 中F4字段
lT_f4-fieldname = 'PLANE'. "指定字段'PLANE'有搜索帮助
lT_f4-register = 'X'.
lT_f4-getbefore = 'X'.
lT_f4-chngeafter = 'X'.
APPEND lt_f4.
CALL METHOD go_grid->register_f4_for_fields
EXPORTING
IT_F4 = LT_F4[].
**** 注册F4 搜索帮助处理方法
CREATE OBJECT LO_EVENT_RECEIVER.
SET HANDLER lO_event_receiver->HANDLE_F4 FOR go_grid.
ENDFORM.
**-------------------------------------------------------
*&---------------------------------------------------------------------*
*& 包含 ZRAY_FM_ALV_F4_FM02
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form f4_help_plane
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> E_FIELDNAME
*& --> ES_ROW_NO
*& --> ER_EVENT_DATA
*&---------------------------------------------------------------------*
FORM f4_help_plane USING p_e_fieldname TYPE lvc_fname "输入的: 列名称
p_es_row_no TYPE lvc_s_roid "输入的: 行号
p_er_event_data TYPE REF TO cl_alv_event_data.
DATA: lt_return_tab TYPE STANDARD TABLE OF ddshretval,
ls_return_tab TYPE ddshretval.
* SELECT * FROM saplane
* INTO CORRESPONDING FIELDS OF TABLE gt_f4_help
* UP TO 5 ROWS.
* SORT gt_f4_help BY planetype.
IF p_e_fieldname = 'PLANE' .
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'PLANETYPE' "搜索帮助表:GT_F4_HELP 里的字段:PLANETYPE
dynpprog = sy-repid " 当前程序
dynpnr = sy-dynnr "当前屏幕号
value_org = 'S' "默认为C但是此处不用S不行
callback_program = sy-repid "回诘程序,也为当前程序
TABLES
value_tab = gt_f4_help " F4 搜索帮助表 (说明:函数对这个表参照类型并未做规定,但返回表的类型是定死的为:DDSHRETVAL
return_tab = lt_return_tab "选择后,返回表值:已经选的值。准备用来回写到ALV表对应字段上
EXCEPTIONS
parameter_error = 1
no_values_found = 2
OTHERS = 3.
IF sy-subrc = 0.
*** 将选定的值填入ALV字段中: 这步回填,是在FM_ALV层次上操作。
CLEAR: gs_alv. " 先清空一下工作区,下步好用
READ TABLE gt_alv INTO gs_alv INDEX p_es_row_no-row_id. "根据传入的参数,当前行号,读取选择操作对应的字段行记录
IF sy-subrc = 0. "如果读取成功,说明有这条记录
READ TABLE lt_return_tab INTO ls_return_tab INDEX 1 . "从返回值表中,读取选择定后值记录
IF ls_return_tab-fieldval IS NOT INITIAL . " 如果读取成功
gs_alv-plane = ls_return_tab-fieldval.
ENDIF.
MODIFY gt_alv FROM gs_alv INDEX p_es_row_no-row_id TRANSPORTING plane. "注意工作区内唯一发生改变的是PLANETYPE 字段
ENDIF.
"X表示事件已经处理,不会去调取系统标准搜索帮助
p_er_event_data->m_event_handled = 'X'.
ENDIF.
ENDIF.
ENDFORM.
**主程序开始
START-OF-SELECTION.
PERFORM FM01_GET_DATA. "获取数据,到 GT_ALV 内表
PERFORM FM02_SET_LAYOUT_FIELDCAT. " 生成ALV 的字段目录及布局样式等参数表 结构
PERFORM FM03_CREATE_F4_PLANE_TABLE.
PERFORM FM04_SET_FM_ALV_EVENT. "设置FM_ALV 的EVENTS 事件: CALLER_EXIT.
PERFORM FM06_CALL_ALV. " 展示FM ALV
四、重要知识点说明
4.1 关于 SAP 标准类中的事件,所对应的参数
本文涉及SAP标准类:CL_GUI_ALV_GRID. 我们想针对某一特定的类所对应的事情,写处理方法,就必须提前了解这个事件(例如:ONF4 事件)有哪些所对应的参数可以被我们使用,同时还要心中有数这些参数所参照的数据类型:表、结构 等。对这些事件参数的清楚了解,是我们动手编写程序的前提。当然,要看完全看懂如上第三部分主程序,这也是前提。
SE24:CL_GUI_ALV_GRID 选择”事件“标签 ->选择”ONF4"事件–> 点“参数”。
- e_fieldname "字段名称
- es_row_no "行号,注意这是个结构 (ROW_ID ,SUB_ROW_ID)
- er_event_data "事件数据
- et_bad_cells. "错误行
我们的理解是:当触发“ONF4”事件时,如上的参数可以被我们引用。我们可以在写对应处理方法时,按需要引入全部或部分参数进来。 如下就是本程序中一段代码 : 写这个处理方法:我需要拿到 ”当前字段名称,当前的行号 ,事件数据 (这个参数我还不太明白)
CLASS lcl_event_receiver DEFINITION.
PUBLIC SECTION.
METHODS: handle_f4
FOR EVENT onf4 OF cl_gui_alv_grid
IMPORTING e_fieldname "字段名称
es_row_no "行号,注意这是个结构
er_event_data "事件数据
ENDCLASS.
4.2 函数:F4IF_INT_TABLE_VALUE_REQUEST 的部分参数
此函数支持自定义内表搜索帮助,但是不能通过指定search help的方式打开对话框。可以理解为,通过这个函数,为OOALV 表中的字段(这是是:‘PLANE’,注意大写),指定一个自定义的搜索帮助内表。
SE37: F4IF_INT_TABLE_VALUE_REQUEST 打开看一下“导入”参数说明,还有“表 ”。图上边说的比我全面
重要的参数,我的代码中也有注释:
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'PLANE' "搜索帮助表:GT_F4_HELP 里的字段:PLANETYPE
DYNPPROG = SY-REPID " 当前程序
DYNPNR = SY-DYNNR "当前屏幕号
* WINDOW_TITLE =
* VALUE = ' '
VALUE_ORG = 'S' "默认为C但是此处不用S不行
* MULTIPLE_CHOICE = ' '
* DISPLAY = ' '
CALLBACK_PROGRAM = SY-REPID "回调程序,也为当前程序
* CALLBACK_FORM = ' '
* CALLBACK_METHOD =
* MARK_TAB =
* IMPORTING
* USER_RESET =
tables
value_tab = GT_F4_HELP " F4 搜索帮助表 (说明:函数对这个表参照类型并未做规定,但返回表的类型是定死的为:DDSHRETVAL
* FIELD_TAB =
RETURN_TAB = LT_RETURN_TAB "选择后,返回表值:已经选的值。准备用来回写到ALV表对应字段上
EXCEPTIONS
PARAMETER_ERROR = 1
NO_VALUES_FOUND = 2
OTHERS = 3 .
4.3 OOALV 中 指定F4字段的方法
类:CL_GUI_ALV_GRID 的标准定义的方法:register_f4_for_fields
**指定OOALV 中F4字段
lT_f4-fieldname = 'PLANE'.
lT_f4-register = 'X'.
lT_f4-getbefore = 'X'.
lT_f4-chngeafter = 'X'.
APPEND lt_f4.
CALL METHOD go_grid->register_f4_for_fields
EXPORTING
IT_F4 = LT_F4[].
4.4 OOALV 中注意编辑事件
类:CL_GUI_ALV_GRID 的标准定义的方法:register_edit_event
* 设置事件-回车
CALL METHOD go_grid->register_edit_event
EXPORTING
i_event_id = cl_gui_alv_grid=>mc_evt_enter
EXCEPTIONS
error = 1
OTHERS = 2.
4.5 函数 GET_GLOBALS_FROM_SLVC_FULLSCR
我的理解是:获取当前ALV的全局参数。这里是把FM_ALV的全局参数赋值给一个OOALV ,相当于把FM_ALV 装载到 OOALV中。然后当作OOALV 来进行操作。
以后,有更深刻的了解,我再做详细补充……
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = go_grid.
4.6 基于稳定的回刷。
类:CL_GUI_ALV_GRID 的标准定义的实例方法:refresh_table_display。
所谓稳定,就是滚动条,上下不滚动,左右不滚动。 LS_STABLE-ROW = ‘X’. LS_STABLE-COL = ‘X’. 记住就好 ,没什么好解释的。代码如下:
DATA: LS_STABLE TYPE LVC_S_STBL. "定义基于稳定的刷新 所需要参数。
LS_STABLE-ROW = 'X'. "行固定
LS_STABLE-COL = 'X'. "列固定
CALL METHOD go_grid->refresh_table_display " 使用类:CL_GUI_ALV_GRID的实例的方法,稳定刷新
EXPORTING
is_stable = LS_STABLE.
五、学习心得几点。
- 本文是在学习CSDN 作者:寒武青锋 的博文 《ABAP ALV中自定义搜索帮助》基础上汇总,形成自己的学习笔记,感谢原创作者的分享。
- 作为新手,一定,一定记得,编写ABAP程序时,单引号内的字符务必全部大写,我是有血的教训了。
- 常常见ABAP高手,把现成的代码,贴贴就好……对于新手来说,不建议。因为新手还没有这个资格,初期学习一定老老实实的自己敲代码,印象深,进步会更快~~