目录
2. 在 CL_SALV_TABLE 输出中增加 GUI 状态
5.1. 方法一:使用列对象的 set_short_text/set_long_text/set_medium_text
6. 在 CL_SALV_TABLE 中控制输出字段(隐藏不需要的字段)
6.2. 方法二:使用 set_technical 隐藏技术字段
1.常见SALV输出中的各种情况
DATA: lr_columns TYPE REF TO cl_salv_columns_table, lr_column TYPE REF TO cl_salv_column_table. IF GT_ZFI027A IS INITIAL. MESSAGE '没有满足条件的数据' TYPE 'S' DISPLAY LIKE 'E'. RETURN. ENDIF. TRY. CL_SALV_TABLE=>FACTORY( IMPORTING R_SALV_TABLE = DATA(LR_SALV) CHANGING T_TABLE = GT_ZFI027A ). " 设置 GUI 状态 SET PF-STATUS 'STANDARD' OF PROGRAM SY-REPID. " 使用自定义状态 SET TITLEBAR 'TITLE1'. " 设置标题栏 " 添加自定义功能 DATA(LR_FUNCTIONS) = LR_SALV->GET_FUNCTIONS( ). LR_FUNCTIONS->SET_ALL( ABAP_TRUE ). " 显示所有标准功能 " 注册事件处理(可选) * DATA(lr_events) = LR_SALV->get_event( ). * SET HANDLER lcl_handler=>on_user_command FOR lr_events. "这里需要定义事件处理类lcl_handler " 可以进一步定制 ALV 显示 DATA(LR_DISPLAY) = LR_SALV->GET_DISPLAY_SETTINGS( ). LR_DISPLAY->SET_STRIPED_PATTERN( ABAP_TRUE ). " 斑马线样式 * lr_display->set_list_header( '我的自定义 ALV 报表' ). " 列优化 LR_SALV->GET_COLUMNS( )->SET_OPTIMIZE( ABAP_TRUE ). " 修改特定列标题 下列情况适用于只有单独几个字段需要修改字段名称时 *TRY. * lr_column ?= lr_columns->get_column( 'MATNR' ). " 物料编号字段 * lr_column->set_short_text( '物料编号' ). " 短文本 * lr_column->set_medium_text( '物料编号' ). " 中等文本 * lr_column->set_long_text( '物料主数据编号' ). " 长文本 * CATCH cx_salv_not_found. * " 处理列不存在的情况 *ENDTRY. " 隐藏不需要的列 " 获取列对象 lr_columns = LR_SALV->get_columns( ). TRY. lr_column ?= lr_columns->get_column( 'TABIX' ). " 要隐藏的字段名 lr_column->set_visible( abap_false ). " 设置为不可见 CATCH cx_salv_not_found. ENDTRY. TRY. lr_column ?= lr_columns->get_column( 'MANDT' ). " 要隐藏的字段名 lr_column->set_visible( abap_false ). " 设置为不可见 CATCH cx_salv_not_found. ENDTRY. * 隐藏不需要的列 方法2 * 获取列对象 *lr_columns = gr_table->get_columns( ). * * 将字段标记为技术字段(会自动隐藏) *TRY. * lr_column ?= lr_columns->get_column( 'TECH_FIELD' ). * lr_column->set_technical( abap_true ). " 设置为技术字段 * CATCH cx_salv_not_found. *ENDTRY. "而如果需要每个都改的话,则可以用下列方式 *" 获取所有列引用 *lt_cols = lr_columns->get( ). * *" 循环设置列标题 *LOOP AT lt_cols INTO ls_col. * CASE ls_col-columnname. * WHEN 'MATNR'. * ls_col-r_column->set_short_text( '物料编号' ). * WHEN 'MAKTX'. * ls_col-r_column->set_short_text( '物料描述' ). * WHEN 'WERKS'. * ls_col-r_column->set_short_text( '工厂' ). * WHEN 'LGORT'. * ls_col-r_column->set_short_text( '库存地点' ). * " 添加更多字段... * ENDCASE. *ENDLOOP. LR_SALV->DISPLAY( ). CATCH CX_ROOT INTO DATA(LX_ERROR). MESSAGE 'Error displaying ALV: ' && LX_ERROR->GET_TEXT( ) TYPE 'E'. ENDTRY.
2. 在 CL_SALV_TABLE 输出中增加 GUI 状态
在使用 CL_SALV_TABLE=>FACTORY
显示 ALV 表格时,可以通过以下方法添加自定义 GUI 状态(菜单栏和工具栏):
2.1. 完整实现步骤
REPORT z_alv_with_gui_status. * 定义数据 DATA: gt_data TYPE TABLE OF spfli. " 示例数据表 DATA: gr_table TYPE REF TO cl_salv_table. * 获取数据 SELECT * FROM spfli INTO TABLE gt_data UP TO 20 ROWS. * 创建 ALV 显示 START-OF-SELECTION. TRY. " 创建 ALV 实例 cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_data ). " 设置 GUI 状态 SET PF-STATUS 'MYSTATUS' OF PROGRAM sy-repid. " 使用自定义状态 SET TITLEBAR 'TITLE1'. " 设置标题栏 " 添加自定义功能 DATA(lr_functions) = gr_table->get_functions( ). lr_functions->set_all( abap_true ). " 显示所有标准功能 " 注册事件处理(可选) DATA(lr_events) = gr_table->get_event( ). SET HANDLER lcl_handler=>on_user_command FOR lr_events. " 显示 ALV gr_table->display( ). CATCH cx_salv_msg INTO DATA(lx_error). MESSAGE lx_error->get_text( ) TYPE 'E'. ENDTRY.
2.2. 创建 GUI 状态的方法
- 在 ABAP 开发工具中创建状态:
-
- 进入程序属性(右键程序 → 属性)
- 转到 "GUI 状态" 选项卡
- 创建新状态(如 'MYSTATUS')
- 添加菜单项和工具栏按钮
-
定义状态代码(通常在程序顶部):
-
*&---------------------------------------------------------------------* *& Module STATUS_0100 OUTPUT *&---------------------------------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'MYSTATUS'. SET TITLEBAR 'TITLE1'. ENDMODULE.
- 事件处理类示例(用于处理用户命令):
CLASS lcl_handler DEFINITION. PUBLIC SECTION. CLASS-METHODS: on_user_command FOR EVENT added_function OF cl_salv_events IMPORTING e_salv_function. ENDCLASS. CLASS lcl_handler IMPLEMENTATION. METHOD on_user_command. CASE e_salv_function. WHEN 'MYFUNCTION1'. MESSAGE '自定义功能1被触发' TYPE 'I'. WHEN 'MYFUNCTION2'. MESSAGE '自定义功能2被触发' TYPE 'I'. WHEN OTHERS. " 处理其他功能 ENDCASE. ENDMETHOD. ENDCLASS.
2.3. 注意事项
- 状态名称:确保
SET PF-STATUS
中使用的状态名与 GUI 状态设计中创建的名称一致 - 程序范围:GUI 状态必须与 ALV 程序在同一个程序中定义
- 功能代码:自定义按钮的功能代码必须唯一,不能与标准 ALV 功能代码冲突
- 权限检查:对于敏感操作,应在事件处理中添加权限检查
3. 高级定制选项
" 可以进一步定制 ALV 显示 DATA(lr_display) = gr_table->get_display_settings( ). lr_display->set_striped_pattern( abap_true ). " 斑马线样式 lr_display->set_list_header( '我的自定义 ALV 报表' ). " 列优化 gr_table->get_columns( )->set_optimize( abap_true ).
4. 解决 lcl_handler
未知类型错误
当在使用 CL_SALV_TABLE
并尝试注册事件处理程序时遇到 "类型 lcl_handler 未知" 的错误,这是因为尚未定义事件处理类 lcl_handler
。
4.1. 完整解决方案
首先定义事件处理类
在程序顶部(START-OF-SELECTION
之前)添加以下类定义:
*---------------------------------------------------------------------* * CLASS lcl_event_handler DEFINITION *---------------------------------------------------------------------* CLASS lcl_handler DEFINITION. PUBLIC SECTION. METHODS: on_user_command FOR EVENT added_function OF cl_salv_events IMPORTING e_salv_function. ENDCLASS. *---------------------------------------------------------------------* * CLASS lcl_event_handler IMPLEMENTATION *---------------------------------------------------------------------* CLASS lcl_handler IMPLEMENTATION. METHOD on_user_command. CASE e_salv_function. WHEN 'MYFUNCTION'. " 替换为您的功能代码 MESSAGE '自定义功能被触发' TYPE 'I'. WHEN OTHERS. " 处理其他功能代码 ENDCASE. ENDMETHOD. ENDCLASS.
4.2. 修改ALV显示代码
START-OF-SELECTION. DATA: lo_handler TYPE REF TO lcl_handler. " 声明处理程序对象 TRY. " 创建ALV实例 cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_data ). " 创建事件处理程序实例 CREATE OBJECT lo_handler. " 获取事件对象并注册处理程序 DATA(lr_events) = gr_table->get_event( ). SET HANDLER lo_handler->on_user_command FOR lr_events. " 显示ALV gr_table->display( ). CATCH cx_salv_msg INTO DATA(lx_error). MESSAGE lx_error->get_text( ) TYPE 'E'. ENDTRY.
4.3. 完整示例程序
REPORT z_alv_with_event_handler. * 数据定义 DATA: gt_data TYPE TABLE OF spfli, gr_table TYPE REF TO cl_salv_table. * 事件处理类定义 CLASS lcl_handler DEFINITION. PUBLIC SECTION. METHODS: on_user_command FOR EVENT added_function OF cl_salv_events IMPORTING e_salv_function. ENDCLASS. CLASS lcl_handler IMPLEMENTATION. METHOD on_user_command. CASE e_salv_function. WHEN 'MYFUNCTION'. MESSAGE '您点击了自定义功能按钮!' TYPE 'I'. WHEN OTHERS. " 可以添加对其他功能代码的处理 ENDCASE. ENDMETHOD. ENDCLASS. START-OF-SELECTION. " 获取数据 SELECT * FROM spfli INTO TABLE gt_data UP TO 20 ROWS. " 创建ALV显示 DATA: lo_handler TYPE REF TO lcl_handler. TRY. cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_data ). " 创建处理程序实例 CREATE OBJECT lo_handler. " 注册事件 DATA(lr_events) = gr_table->get_event( ). SET HANDLER lo_handler->on_user_command FOR lr_events. " 添加自定义功能到工具栏 DATA(lr_functions) = gr_table->get_functions( ). lr_functions->add_function( name = 'MYFUNCTION' icon = '@5D@' " 使用SAP图标代码 text = '自定义功能' tooltip = '这是我的自定义功能' position = if_salv_c_function_position=>right_of_salv_functions ). " 显示ALV gr_table->display( ). CATCH cx_salv_msg INTO DATA(lx_error). MESSAGE lx_error->get_text( ) TYPE 'E'. ENDTRY.
4.4. 关键点说明
- 类定义位置:必须在程序顶部定义
lcl_handler
类,然后才能在后面的代码中使用 - 处理程序实例化:必须使用
CREATE OBJECT
创建处理程序实例后才能注册 - 功能代码匹配:确保
CASE
语句中的功能代码与您添加到工具栏的代码一致 - 图标代码:
@5D@
是SAP内部图标代码,可以在SE38中执行程序SHOWICON
查看所有可用图标
这样修改后,您的程序就能正确识别 lcl_handler
类并处理ALV表格的事件了。
5. 在 CL_SALV_TABLE 中修改输出列名称
当使用 CL_SALV_TABLE=>FACTORY
输出数据时,可以通过以下方法修改显示的列名称(列标题),使其不显示底表字段名:
5.1. 方法一:使用列对象的 set_short_text/set_long_text/set_medium_text
DATA: lr_columns TYPE REF TO cl_salv_columns_table, lr_column TYPE REF TO cl_salv_column_table. " 获取列对象 lr_columns = gr_table->get_columns( ). " 设置所有列优化显示 lr_columns->set_optimize( abap_true ). " 修改特定列标题 TRY. lr_column ?= lr_columns->get_column( 'MATNR' ). " 物料编号字段 lr_column->set_short_text( '物料编号' ). " 短文本 lr_column->set_medium_text( '物料编号' ). " 中等文本 lr_column->set_long_text( '物料主数据编号' ). " 长文本 CATCH cx_salv_not_found. " 处理列不存在的情况 ENDTRY. " 修改另一列 TRY. lr_column ?= lr_columns->get_column( 'WERKS' ). " 工厂字段 lr_column->set_short_text( '工厂' ). lr_column->set_long_text( '生产工厂' ). CATCH cx_salv_not_found. ENDTRY.
5.2. 方法二:批量设置列标题
DATA: lt_cols TYPE salv_t_column_ref, ls_col LIKE LINE OF lt_cols. " 获取所有列引用 lt_cols = lr_columns->get( ). " 循环设置列标题 LOOP AT lt_cols INTO ls_col. CASE ls_col-columnname. WHEN 'MATNR'. ls_col-r_column->set_short_text( '物料编号' ). WHEN 'MAKTX'. ls_col-r_column->set_short_text( '物料描述' ). WHEN 'WERKS'. ls_col-r_column->set_short_text( '工厂' ). WHEN 'LGORT'. ls_col-r_column->set_short_text( '库存地点' ). " 添加更多字段... ENDCASE. ENDLOOP.
5.3. 方法三:使用字典结构的文本标识
如果内表基于DDIC结构,可以使用字段的文本标识:
" 首先确保列对象已获取 lr_columns = gr_table->get_columns( ). " 设置使用字段文本作为列标题 lr_columns->set_use_key_as_header( abap_false ). " 不使用技术名称 lr_columns->set_key_fixation( abap_false ).
5.4. 完整示例
REPORT z_change_column_headers. DATA: gt_data TYPE TABLE OF makt, " 物料描述表 gr_table TYPE REF TO cl_salv_table. START-OF-SELECTION. " 获取示例数据 SELECT * FROM makt INTO TABLE gt_data UP TO 20 ROWS WHERE spras = sy-langu. TRY. " 创建ALV表 cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_data ). " 获取列对象 DATA(lr_columns) = gr_table->get_columns( ). " 设置列优化 lr_columns->set_optimize( abap_true ). " 修改特定列标题 DATA(lr_column) TYPE REF TO cl_salv_column_table. TRY. lr_column ?= lr_columns->get_column( 'MATNR' ). lr_column->set_short_text( '物料号' ). lr_column->set_long_text( '物料主编号' ). CATCH cx_salv_not_found. ENDTRY. TRY. lr_column ?= lr_columns->get_column( 'MAKTX' ). lr_column->set_short_text( '描述' ). lr_column->set_long_text( '物料描述文本' ). CATCH cx_salv_not_found. ENDTRY. " 显示ALV表 gr_table->display( ). CATCH cx_salv_msg INTO DATA(lx_error). MESSAGE lx_error->get_text( ) TYPE 'E'. ENDTRY.
5.5. 注意事项
- 字段名大小写:SALV中字段名通常是大写的,确保使用大写字段名
- 错误处理:使用TRY-CATCH处理可能不存在的字段
- 文本长度:短文本(short_text)通常限制在10个字符内,中等文本(medium_text)约20个字符,长文本(long_text)可更长
- 性能考虑:对于大量列,使用方法二的批量处理更高效
通过这些方法,可以轻松地将ALV表格中的技术字段名替换为更有业务意义的描述性标题。
用这个 cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_data ).输出gt_data的数据时如果不想要输出gt_data中的全部字段 ,该怎么处理
6. 在 CL_SALV_TABLE 中控制输出字段(隐藏不需要的字段)
当使用 CL_SALV_TABLE=>FACTORY
输出数据时,可以通过以下几种方法控制显示的字段,隐藏不需要的列:
6.1. 方法一:使用 set_visible 隐藏特定列
DATA: lr_columns TYPE REF TO cl_salv_columns_table, lr_column TYPE REF TO cl_salv_column_table. " 获取列对象 lr_columns = gr_table->get_columns( ). " 隐藏不需要的列 TRY. lr_column ?= lr_columns->get_column( 'FIELD_TO_HIDE1' ). " 要隐藏的字段名 lr_column->set_visible( abap_false ). " 设置为不可见 CATCH cx_salv_not_found. ENDTRY. TRY. lr_column ?= lr_columns->get_column( 'FIELD_TO_HIDE2' ). lr_column->set_visible( abap_false ). CATCH cx_salv_not_found. ENDTRY.
6.2. 方法二:使用 set_technical 隐藏技术字段
" 获取列对象 lr_columns = gr_table->get_columns( ). " 将字段标记为技术字段(会自动隐藏) TRY. lr_column ?= lr_columns->get_column( 'TECH_FIELD' ). lr_column->set_technical( abap_true ). " 设置为技术字段 CATCH cx_salv_not_found. ENDTRY.
6.3. 方法三:预先处理数据(推荐)
最彻底的方法是只选择需要的字段到工作区中:
" 1. 定义只包含所需字段的结构 TYPES: BEGIN OF ty_output, matnr TYPE matnr, " 物料编号 maktx TYPE maktx, " 物料描述 meins TYPE meins, " 单位 " 只添加需要的字段... END OF ty_output. " 2. 定义内表 DATA: gt_output TYPE TABLE OF ty_output. " 3. 从原始数据中只选择需要的字段 LOOP AT gt_data ASSIGNING FIELD-SYMBOL(<fs_data>). APPEND VALUE #( matnr = <fs_data>-matnr maktx = <fs_data>-maktx meins = <fs_data>-meins " 只赋值需要的字段... ) TO gt_output. ENDLOOP. " 4. 使用处理后的数据输出ALV cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_output " 使用只包含需要字段的内表 ).
6.4. 方法四:使用字段目录控制显示
DATA: lt_fieldcat TYPE salv_t_fieldcat, ls_fieldcat LIKE LINE OF lt_fieldcat. " 获取字段目录 lt_fieldcat = cl_salv_controller_metadata=>get_lvc_fieldcatalog( r_columns = gr_table->get_columns( ) r_aggregations = gr_table->get_aggregations( ) ). " 修改字段属性 LOOP AT lt_fieldcat INTO ls_fieldcat. CASE ls_fieldcat-fieldname. WHEN 'FIELD_TO_HIDE1' OR 'FIELD_TO_HIDE2'. ls_fieldcat-no_out = abap_true. " 设置为不输出 ENDCASE. MODIFY lt_fieldcat FROM ls_fieldcat. ENDLOOP. " 应用修改后的字段目录 cl_salv_controller_metadata=>set_lvc_fieldcatalog( r_columns = gr_table->get_columns( ) t_fieldcatalog = lt_fieldcat ).
6.5. 完整示例
REPORT z_selective_alv_columns. DATA: gt_mara TYPE TABLE OF mara, " 原始数据(包含所有字段) gt_output TYPE TABLE OF ty_output, gr_table TYPE REF TO cl_salv_table. " 定义输出结构 TYPES: BEGIN OF ty_output, matnr TYPE mara-matnr, " 物料编号 mtart TYPE mara-mtart, " 物料类型 meins TYPE mara-meins, " 基本单位 END OF ty_output. START-OF-SELECTION. " 获取原始数据 SELECT * FROM mara INTO TABLE gt_mara UP TO 20 ROWS. " 方法三:预先处理数据(推荐) LOOP AT gt_mara ASSIGNING FIELD-SYMBOL(<fs_mara>). APPEND VALUE #( matnr = <fs_mara>-matnr mtart = <fs_mara>-mtart meins = <fs_mara>-meins ) TO gt_output. ENDLOOP. TRY. " 创建ALV表 cl_salv_table=>factory( IMPORTING r_salv_table = gr_table CHANGING t_table = gt_output ). " 方法一:额外隐藏不需要的列(如果需要) DATA(lr_columns) = gr_table->get_columns( ). TRY. lr_column ?= lr_columns->get_column( 'MEINS' ). " 假设还要隐藏单位字段 lr_column->set_visible( abap_false ). CATCH cx_salv_not_found. ENDTRY. " 设置列优化 lr_columns->set_optimize( abap_true ). " 显示ALV表 gr_table->display( ). CATCH cx_salv_msg INTO DATA(lx_error). MESSAGE lx_error->get_text( ) TYPE 'E'. ENDTRY.
6.6. 方法比较
方法 | 优点 | 缺点 |
set_visible | 简单直接 | 数据仍然存在于内表中 |
set_technical | 自动隐藏技术字段 | 仅适用于真正技术字段 |
预先处理数据 | 最干净,减少内存使用 | 需要额外编码 |
字段目录 | 最灵活 | 最复杂 |
推荐做法:对于简单情况使用方法一,对于复杂报表推荐使用方法三(预先处理数据),这样不仅控制显示,还能提高性能减少内存使用。