)
SAP顾问实战手把手教你给MB51报表加自定义字段附完整代码在SAP项目实施过程中业务部门经常会提出为什么报表里看不到这个字段的灵魂拷问。最近就遇到一个典型场景物料管理团队需要在MB51报表中直接查看供应商名称和原因代码而不是每次都要点进凭证详情。这种需求看似简单但标准SAP并未提供直接配置选项需要开发介入。作为从业多年的SAP技术顾问我处理过数十个类似的报表增强需求。与常见的用户出口增强不同MB51这类标准报表往往需要采用隐式增强技术。本文将完整呈现从分析程序结构到最终字段显示的全流程特别针对RM07DOCS_GENERATED这个关键包含程序给出可直接复用的代码方案。1. 环境准备与程序定位1.1 确定增强对象首先需要通过事务码SE93查询MB51报表对应的主程序。输入事务代码MB51后我们发现其主程序为RM07DOCS。但实际开发中大部分数据处理逻辑都封装在其包含程序RM07DOCS_GENERATED中。关键检查点使用SE80打开程序RM07DOCS在菜单栏选择包含查看关联程序确认RM07DOCS_GENERATED为数据处理的包含程序提示SAP标准程序中命名包含_GENERATED的程序通常由系统自动生成但正是这类程序往往包含可增强的关键逻辑1.2 隐式增强点定位不同于常规的用户出口隐式增强需要在源代码中直接插入修改。在RM07DOCS_GENERATED中我们需要关注三个关键位置内表结构定义通常在程序开头部分数据获取逻辑搜索DATA_SELECTION相关子程序ALV字段目录查找build_fieldcatalog或类似名称的方法 示例查找内表定义位置 DATA: BEGIN OF itab OCCURS 0. INCLUDE STRUCTURE bapi2017_gm_head_ret. 这里将添加自定义字段 DATA: name2 TYPE lfa1-name1, 供应商名称 reason1 TYPE ztmm017-reason1, 原因代码1 reason1_desc TYPE ztmm00-zvalue2, 原因描述 reason2 TYPE ztmm017-reason2, 原因代码2 END OF itab.2. 内表结构扩展实战2.1 添加自定义字段在包含程序中找到内表itab的定义位置通常在程序开头部分添加业务需要的字段。根据需求我们需要添加供应商名称从LFA1获取原因代码及描述从自定义表ZTMM017获取 完整字段添加示例 DATA: BEGIN OF itab OCCURS 0. INCLUDE STRUCTURE bapi2017_gm_head_ret. DATA: lifnr TYPE mseg-lifnr, 供应商编号原内表可能已有 name2 TYPE lfa1-name1, 新增供应商名称 reason1 TYPE ztmm017-reason1, 新增原因代码1 reason1_desc TYPE ztmm00-zvalue2, 新增原因描述 reason2 TYPE ztmm017-reason2, 新增原因代码2 END OF itab.2.2 数据结构验证添加字段后建议在增强点附近添加临时调试代码验证结构是否生效 临时调试代码完成后删除 BREAK-POINT. FIELD-SYMBOLS: fs_field TYPE any. ASSIGN COMPONENT NAME2 OF STRUCTURE itab TO fs_field. IF sy-subrc 0. WRITE: / 字段添加成功. ENDIF.3. 数据获取逻辑实现3.1 主数据获取逻辑在DATA_SELECTION_NEW等子程序中添加供应商和原因代码的获取逻辑。关键是要找到合适的位置插入代码通常是在内表itab填充完成后 在DATA_SELECTION_NEW末尾添加 LOOP AT itab ASSIGNING fs_itab. 获取供应商名称 IF fs_itab-lifnr IS NOT INITIAL. SELECT SINGLE name1 INTO fs_itab-name2 FROM lfa1 WHERE lifnr fs_itab-lifnr. ENDIF. 获取原因代码及描述 SELECT SINGLE reason1 reason2 INTO (fs_itab-reason1, fs_itab-reason2) FROM ztmm017 WHERE mblnr fs_itab-mblnr AND mjahr fs_itab-mjahr. 获取原因描述 IF fs_itab-reason1 IS NOT INITIAL. SELECT SINGLE zvalue2 INTO fs_itab-reason1_desc FROM ztmm00 WHERE zid MM0006 AND zvalue1 fs_itab-reason1. ENDIF. ENDLOOP.3.2 性能优化建议对于大数据量情况建议改用批量读取优化性能 批量读取优化版本 DATA: lt_lifnr TYPE RANGE OF lifnr, lt_lfa1 TYPE TABLE OF lfa1, lt_mseg_key TYPE TABLE OF mseg_key. 收集所有供应商编号 LOOP AT itab ASSIGNING fs_itab. IF fs_itab-lifnr IS NOT INITIAL. APPEND VALUE #( sign I option EQ low fs_itab-lifnr ) TO lt_lifnr. APPEND VALUE mseg_key( mblnr fs_itab-mblnr mjahr fs_itab-mjahr ) TO lt_mseg_key. ENDIF. ENDLOOP. 批量获取供应商名称 IF lt_lifnr IS NOT INITIAL. SELECT lifnr name1 INTO TABLE lt_lfa1 FROM lfa1 WHERE lifnr IN lt_lifnr. ENDIF. 批量获取原因代码 DATA: lt_reason TYPE TABLE OF ztmm017. IF lt_mseg_key IS NOT INITIAL. SELECT mblnr mjahr reason1 reason2 INTO TABLE lt_reason FROM ztmm017 FOR ALL ENTRIES IN lt_mseg_key WHERE mblnr lt_mseg_key-mblnr AND mjahr lt_mseg_key-mjahr. ENDIF. 更新内表 LOOP AT itab ASSIGNING fs_itab. 更新供应商名称 READ TABLE lt_lfa1 INTO DATA(ls_lfa1) WITH KEY lifnr fs_itab-lifnr BINARY SEARCH. IF sy-subrc 0. fs_itab-name2 ls_lfa1-name1. ENDIF. 更新原因代码 READ TABLE lt_reason INTO DATA(ls_reason) WITH KEY mblnr fs_itab-mblnr mjahr fs_itab-mjahr BINARY SEARCH. IF sy-subrc 0. fs_itab-reason1 ls_reason-reason1. fs_itab-reason2 ls_reason-reason2. 获取原因描述 IF ls_reason-reason1 IS NOT INITIAL. SELECT SINGLE zvalue2 INTO fs_itab-reason1_desc FROM ztmm00 WHERE zid MM0006 AND zvalue1 ls_reason-reason1. ENDIF. ENDIF. ENDLOOP.4. ALV字段显示配置4.1 标准字段添加在build_runtimetable子程序中添加标准表字段的显示配置 添加供应商名称字段来自标准表LFA1 CLEAR ls_fieldcat. ls_fieldcat-fieldname NAME2. ls_fieldcat-tabname ITAB. ls_fieldcat-seltext_m 供应商名称. ls_fieldcat-outputlen 35. APPEND ls_fieldcat TO pt_fieldcat.4.2 自定义字段添加对于来自自定义表的字段应在build_fieldcatalog中添加 添加原因代码相关字段 DATA: lt_fieldcat TYPE lvc_t_fcat. CLEAR ls_fieldcat. ls_fieldcat-fieldname REASON1. ls_fieldcat-tabname ITAB. ls_fieldcat-seltext_m 原因代码1. ls_fieldcat-outputlen 10. APPEND ls_fieldcat TO lt_fieldcat. CLEAR ls_fieldcat. ls_fieldcat-fieldname REASON1_DESC. ls_fieldcat-tabname ITAB. ls_fieldcat-seltext_m 原因描述. ls_fieldcat-outputlen 20. APPEND ls_fieldcat TO lt_fieldcat. CLEAR ls_fieldcat. ls_fieldcat-fieldname REASON2. ls_fieldcat-tabname ITAB. ls_fieldcat-seltext_m 原因代码2. ls_fieldcat-outputlen 10. APPEND ls_fieldcat TO lt_fieldcat. 合并字段目录 APPEND LINES OF lt_fieldcat TO pt_fieldcat.4.3 字段显示优化可以进一步优化字段显示属性 设置字段显示属性 LOOP AT pt_fieldcat ASSIGNING fs_fcat. CASE fs_fcat-fieldname. WHEN NAME2. fs_fcat-hotspot X. 可点击 fs_fcat-fix_column X. 固定列 WHEN REASON1_DESC. fs_fcat-emphasize C300. 高亮颜色 ENDCASE. ENDLOOP.5. 常见问题排查5.1 字段不显示问题排查现象可能原因解决方案新增字段完全不可见1. 字段未添加到ALV字段目录2. 内表结构修改未生效1. 检查build_fieldcatalog代码2. 使用调试确认内表结构字段显示为空白1. 数据获取逻辑未执行2. 字段名拼写错误1. 检查DATA_SELECTION代码2. 核对字段名大小写字段显示为技术名称未设置seltext_m属性在fieldcat中完善字段描述5.2 性能问题优化对于大数据量报表建议添加索引支持 确保ZTMM017表有MBLNRMJAHR索引 SELECT * FROM ztmm017 WHERE mblnr lv_mblnr AND mjahr lv_mjahr INTO TABLE DATA(lt_data) BYPASSING BUFFER. 绕过缓冲区获取最新数据使用内存缓存 使用共享内存缓存供应商名称 DATA: lv_cache_key TYPE string. lv_cache_key |LFA1_{ fs_itab-lifnr }|. TRY. fs_itab-name2 cl_shm_areaget_value( lv_cache_key ). CATCH cx_shm_error. 缓存不存在则从数据库获取 SELECT SINGLE name1 INTO fs_itab-name2 FROM lfa1 WHERE lifnr fs_itab-lifnr. cl_shm_areaset_value( iv_key lv_cache_key iv_value fs_itab-name2 ). ENDTRY.分页处理建议 在GET_DATA方法中添加分页逻辑 DATA: lv_offset TYPE i VALUE 0, lv_pagesize TYPE i VALUE 500. WHILE lv_offset lv_total. SELECT * FROM mseg INTO TABLE lt_mseg WHERE matnr IN lt_matnr ORDER BY mblnr mjahr zeile OFFSET lv_offset UP TO lv_pagesize ROWS. lv_offset lv_offset lv_pagesize. 处理当前页数据... ENDWHILE.6. 增强方案扩展6.1 动态字段控制可以通过参数控制字段显示 在程序顶部添加参数 PARAMETERS: p_show_sup AS CHECKBOX DEFAULT X, p_show_rsn AS CHECKBOX DEFAULT X. 修改build_fieldcatalog IF p_show_sup X. 添加供应商名称字段 CLEAR ls_fieldcat. ls_fieldcat-fieldname NAME2. APPEND ls_fieldcat TO pt_fieldcat. ENDIF. IF p_show_rsn X. 添加原因代码字段 CLEAR ls_fieldcat. ls_fieldcat-fieldname REASON1. APPEND ls_fieldcat TO pt_fieldcat. ENDIF.6.2 导出功能增强扩展ALV工具栏添加导出按钮 在INITIALIZE_ALV方法中添加 DATA: lt_toolbar TYPE ttb_button. CLEAR ls_toolbar. ls_toolbar-function EXPORT. ls_toolbar-icon 5C. Excel图标 ls_toolbar-quickinfo 导出到Excel. ls_toolbar-butn_type 0. APPEND ls_toolbar TO lt_toolbar. 在handle_user_command方法处理事件 CASE iv_ucomm. WHEN EXPORT. PERFORM export_to_excel USING it_data. ENDCASE.6.3 字段搜索增强为新增字段添加搜索功能 修改fieldcat属性 LOOP AT pt_fieldcat ASSIGNING fs_fcat. CASE fs_fcat-fieldname. WHEN NAME2 OR REASON1_DESC. fs_fcat-no_out space. 显示字段 fs_fcat-no_search space. 允许搜索 ENDCASE. ENDLOOP. 在ALV显示前设置 CALL METHOD go_grid-set_table_for_first_display EXPORTING is_layout ls_layout CHANGING it_fieldcatalog pt_fieldcat it_outtab it_data.