news 2026/4/15 15:07:56

被SAP分类视图拖垮的报表:一招让取数爽到飞起

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
被SAP分类视图拖垮的报表:一招让取数爽到飞起

干ABAP的老兄弟们,估计都被 “物料分类视图” 这玩意儿坑过 —— 本来跑得顺顺的报表,只要加上分类视图的数据,直接从火箭速度掉到龟爬模式,鼠标转转转就是出不来结果,真让人火大啊!

我们前阵子碰到的情况,报表里加了物料的分类视图信息,结果性能大幅度减低,本就不富裕的运行时间更是雪上加霜,几个小时都跑不出来,查了下进程信息(如下图),整个瓶颈全卡在取分类视图数据这一步。明明其他逻辑都优化到极致了,偏偏栽在这一个环节上,别提多闹心了。

为啥分类视图取数这么磨人?分类视图一般有两个取数方法

青铜玩法:用 BAPI_OBJCL_GETDETAIL

这方法的优点是简单,不用啥技术门槛,但架不住每个物料得调一次啊!要是遇上几百上千个物料,那就是几百上千次接口调用,服务器都得累得喘粗气,速度慢到想砸键盘,直接 PASS。

白银玩法:JOIN表批量查

稍微进阶点的会去连INOB、AUSP、CABN这些表批量取数,性能是能提不少,但架不住表关联逻辑复杂,数据量大的时候还是慢,而且写SQL得小心翼翼,非CHAR类型的字段还需要自己转换,心累。

那有没有能让分类视图取数 “像查普通字段一样丝滑” 的招?

你来看!要是有下面这样一张表,是不是取数就爽多了?

直接在透明表取数了,这哪儿仅仅是是提升性能啊,简直是把分类视图取数从地狱难度改成了新手模式——下次报表里要分类视图数据,直接查这张表,效率拉满还不费脑,甚至还可以做JOIN,在主SQL就把问题解决了。

下面介绍一下这个表的数据更新是怎么通过增强做到实时更新的。

1、创建表ZMKSSK、ZMAUSP

MANDT MANDTMATNR MATNRKLART KLASSENARTATINN ATINNATZHL WZAEHLADZHL ADZHLATZHW ATZHLATFOR ATFORATNAM ATNAMATBEZ ATBEZATWRT ATWRTATWTB ATWTBATWRO ATWRTAEDAT AEDATAEZET AEZETAENAM AENAM
MANDT MANDTMATNR MATNRKLART KLASSENARTCLASS KLASSE_DKSCHL KLSBEZ

2、SMOD:CLFM0002

ZXCLFU02代码为:

DATA lt_zmausp TYPE TABLE OF zmausp WITH HEADER LINE.DATA ls_zmkssk TYPE zmkssk.DATA: BEGIN OF ls_cabn, atfor TYPE cabn-atfor, atnam TYPE cabn-atnam, atsch TYPE cabn-atsch, msehi TYPE cabn-msehi, atdim TYPE cabn-atdim, atdex TYPE cabn-atdex, anzdz TYPE cabn-anzdz, atbez TYPE cabnt-atbez, END OF ls_cabn.DATA: ls_tcabn TYPE cabn, ls_tcawn TYPE cawn. LOOP AT t_allkssk WHERE obtab = 'MARA' AND vbkz = 'D'. ls_zmkssk-matnr = t_allkssk-objek. ls_zmkssk-klart = t_allkssk-klart. ls_zmkssk-class = t_allkssk-class. DELETE zmkssk FROM ls_zmkssk.ENDLOOP. LOOP AT t_allkssk WHERE obtab = 'MARA' AND vbkz NE 'D'. ls_zmkssk-matnr = t_allkssk-objek. ls_zmkssk-klart = t_allkssk-klart. ls_zmkssk-class = t_allkssk-class. ls_zmkssk-kschl = t_allkssk-kschl. MODIFY zmkssk FROM ls_zmkssk.ENDLOOP. LOOP AT t_allausp WHERE obtab = 'MARA' AND statu = 'L'. lt_zmausp-matnr = t_allausp-objek. lt_zmausp-klart = t_allausp-klart. lt_zmausp-atinn = t_allausp-atinn. lt_zmausp-atzhl = t_allausp-atzhl. DELETE zmausp FROM lt_zmausp.ENDLOOP. LOOP AT t_allausp WHERE obtab = 'MARA' AND statu = 'H'. SELECT SINGLE cabn~atfor cabn~atnam cabn~atsch cabn~msehi cabn~atdim cabn~atdex cabn~anzdz cabnt~atbez INTO CORRESPONDING FIELDS OF ls_cabn FROM cabn LEFT JOIN cabnt ON cabnt~atinn = cabn~atinn AND cabnt~adzhl = cabn~adzhl AND cabnt~spras = '1' WHERE cabn~atinn = t_allausp-atinn. lt_zmausp-matnr = t_allausp-objek. lt_zmausp-klart = t_allausp-klart. lt_zmausp-atinn = t_allausp-atinn. lt_zmausp-atzhl = t_allausp-atzhl. lt_zmausp-atfor = ls_cabn-atfor. lt_zmausp-atnam = ls_cabn-atnam. lt_zmausp-atbez = ls_cabn-atbez. lt_zmausp-aedat = sy-datum. lt_zmausp-aezet = sy-uzeit. lt_zmausp-aenam = sy-uname. IF lt_zmausp-atfor = 'CHAR'. lt_zmausp-atwrt = t_allausp-atwrt. SELECT SINGLE cawn~atzhl cawnt~atwtb INTO (lt_zmausp-atzhw,lt_zmausp-atwtb) FROM cawn LEFT JOIN cawnt ON cawnt~atinn = cawn~atinn AND cawnt~atzhl = cawn~atzhl AND cawnt~spras = '1' WHERE cawn~atinn = t_allausp-atinn AND cawn~atwrt = t_allausp-atwrt. IF lt_zmausp-atwtb IS NOT INITIAL. lt_zmausp-atwro = lt_zmausp-atwtb. ELSE. lt_zmausp-atwro = lt_zmausp-atwrt. ENDIF. ELSE. ls_tcabn-atfor = ls_cabn-atfor. ls_tcabn-atsch = ls_cabn-atsch. ls_tcabn-msehi = ls_cabn-msehi. ls_tcabn-atdex = ls_cabn-atdex. ls_tcabn-atdim = ls_cabn-atdim. ls_tcabn-anzdz = ls_cabn-anzdz. ls_tcawn-atwrt = t_allausp-atwrt. ls_tcawn-atflv = t_allausp-atflv. ls_tcawn-atflb = t_allausp-atflb. ls_tcawn-atcod = t_allausp-atcod. ls_tcawn-atawe = t_allausp-atawe. ls_tcawn-ataw1 = t_allausp-ataw1. CALL FUNCTION 'CTCV_PREPARE_VALUES_TO_DISPLAY' EXPORTING structure_cabn = ls_tcabn structure_cawn = ls_tcawn string_with_baseunit = 'YES' IMPORTING string = lt_zmausp-atwro EXCEPTIONS OTHERS = 5. ENDIF. APPEND lt_zmausp. CLEAR lt_zmausp.ENDLOOP.INSERT zmausp FROM TABLE lt_zmausp ACCEPTING DUPLICATE KEYS.

注意激活SMOD哦(或者使用CMOD,虽然我不建议使用)。另外,更新表应该使用更新函数,懒,不想写这么复杂了,各位自行修改。

最后,这种优化方式一般还会有一个初始化的程序,把历史数据都更新到自定义表,如下:

*&---------------------------------------------------------------------**& Report ZMATAUSP*&---------------------------------------------------------------------**& 物料分类视图特征值初始化*& Baitianzh*&---------------------------------------------------------------------*REPORT zmatausp NO STANDARD PAGE HEADING. TYPE-POOLS slis.TABLES mara.DATA: gt_fldct TYPE lvc_t_fcat, gt_style TYPE lvc_t_styl, gs_slayt TYPE lvc_s_layo, gs_varnt TYPE disvariant.DATA: BEGIN OF gs_out, objek TYPE kssk-objek, klart TYPE kssk-klart, class TYPE klah-class, kschl TYPE swor-kschl, atinn TYPE char10, "ksml-imerk, posnr TYPE ksml-posnr, atnam TYPE cabn-atnam, atfor TYPE cabn-atfor, anzdz TYPE cabn-anzdz, atkla TYPE cabn-atkla, adzhl TYPE cabn-adzhl, atsch TYPE cabn-atsch, msehi TYPE cabn-msehi, atdex TYPE cabn-atdex, atdim TYPE cabn-atdim, atzhl TYPE ausp-atzhl, atwrt TYPE ausp-atwrt, atflv TYPE ausp-atflv, atflb TYPE ausp-atflb, atcod TYPE ausp-atcod, atawe TYPE ausp-atawe, ataw1 TYPE ausp-ataw1, atbez TYPE cabnt-atbez, atzhw TYPE cawnt-atzhl, atwtb TYPE cawnt-atwtb, atwro TYPE ausp-atwrt, END OF gs_out.DATA: gt_out LIKE TABLE OF gs_out.DATA: BEGIN OF gt_cawn OCCURS 0, atinn TYPE cawn-atinn, atwrt TYPE cawn-atwrt, atzhl TYPE cawn-atzhl, atwtb TYPE cawnt-atwtb, END OF gt_cawn. SELECT-OPTIONS: s_matnr FOR mara-matnr, s_klart FOR gs_out-klart, s_class FOR gs_out-class, s_atnam FOR gs_out-atnam, s_atbez FOR gs_out-atbez. AT SELECTION-SCREEN OUTPUT. %_s_matnr_%_app_%-text = '物料'. %_s_klart_%_app_%-text = '类别种类'. %_s_class_%_app_%-text = '分类'. %_s_atnam_%_app_%-text = '特征'. %_s_atbez_%_app_%-text = '特征描述'. START-OF-SELECTION. PERFORM getdata. IF sy-batch = 'X'. PERFORM save_zmausp. ELSE. PERFORM outdata. ENDIF. *&---------------------------------------------------------------------**& getdata*&---------------------------------------------------------------------*FORM getdata. IF '001' IN s_klart. SELECT kssk~objek kssk~klart klah~class ksml~imerk AS atinn ksml~posnr cabn~atnam cabn~atnam cabn~atfor cabn~anzdz cabn~atkla cabn~adzhl cabn~atsch cabn~msehi cabn~atdex cabn~atdim ausp~atzhl ausp~atwrt ausp~atflv ausp~atflb ausp~atcod ausp~atawe ausp~ataw1 cabnt~atbez swor~kschl INTO CORRESPONDING FIELDS OF TABLE gt_out FROM kssk INNER JOIN ksml ON ksml~clint = kssk~clint INNER JOIN klah ON klah~clint = kssk~clint INNER JOIN cabn ON cabn~atinn = ksml~imerk INNER JOIN cabnt ON cabnt~atinn = ksml~imerk AND cabnt~spras = sy-langu AND cabnt~adzhl = ksml~adzhl INNER JOIN ausp ON ausp~objek = kssk~objek AND ausp~atinn = ksml~imerk AND ausp~mafid = kssk~mafid AND ausp~klart = kssk~klart LEFT JOIN swor ON swor~clint = kssk~clint AND swor~spras = sy-langu AND swor~klpos = 1 WHERE kssk~klart EQ '001' AND kssk~objek IN s_matnr AND klah~class IN s_class AND cabn~atnam IN s_atnam AND cabnt~atbez IN s_atbez. ENDIF. SELECT inob~objek kssk~klart klah~class ksml~imerk AS atinn ksml~posnr cabn~atnam cabn~atnam cabn~atfor cabn~anzdz cabn~atkla cabn~adzhl cabn~atsch cabn~msehi cabn~atdex cabn~atdim ausp~atzhl ausp~atwrt ausp~atflv ausp~atflb ausp~atcod ausp~atawe ausp~ataw1 cabnt~atbez swor~kschl APPENDING CORRESPONDING FIELDS OF TABLE gt_out FROM inob INNER JOIN kssk ON kssk~klart = inob~klart AND kssk~objek = inob~cuobj INNER JOIN ksml ON ksml~clint = kssk~clint INNER JOIN klah ON klah~clint = kssk~clint INNER JOIN cabn ON cabn~atinn = ksml~imerk INNER JOIN cabnt ON cabnt~atinn = ksml~imerk AND cabnt~spras = sy-langu AND cabnt~adzhl = ksml~adzhl INNER JOIN ausp ON ausp~objek = kssk~objek AND ausp~atinn = ksml~imerk AND ausp~mafid = kssk~mafid AND ausp~klart = kssk~klart LEFT JOIN swor ON swor~clint = kssk~clint AND swor~spras = sy-langu AND swor~klpos = 1 WHERE inob~obtab EQ 'MARA' AND inob~objek IN s_matnr AND kssk~klart IN s_klart AND klah~class IN s_class AND cabn~atnam IN s_atnam AND cabnt~atbez IN s_atbez. SORT gt_out BY objek klart posnr. LOOP AT gt_out INTO gs_out WHERE atfor = 'CHAR'. gt_cawn-atinn = gs_out-atinn. gt_cawn-atwrt = gs_out-atwrt. COLLECT gt_cawn. ENDLOOP. IF gt_cawn[] IS NOT INITIAL. SELECT cawn~atinn cawn~atwrt cawn~atzhl cawnt~atwtb INTO CORRESPONDING FIELDS OF TABLE gt_cawn FROM cawn INNER JOIN cawnt ON cawnt~atinn = cawn~atinn AND cawnt~atzhl = cawn~atzhl AND cawnt~spras = sy-langu FOR ALL ENTRIES IN gt_cawn WHERE cawn~atinn = gt_cawn-atinn AND cawn~atwrt = gt_cawn-atwrt. SORT gt_cawn BY atinn atwrt. ENDIF. LOOP AT gt_out INTO gs_out. IF gs_out-atfor = 'CHAR'. READ TABLE gt_cawn WITH KEY atinn = gs_out-atinn atwrt = gs_out-atwrt BINARY SEARCH. IF sy-subrc = 0. gs_out-atzhw = gt_cawn-atzhl. gs_out-atwtb = gt_cawn-atwtb. gs_out-atwro = gt_cawn-atwtb. ELSE. gs_out-atwro = gs_out-atwrt. ENDIF. ELSE. PERFORM prepare_values USING gs_out-atfor gs_out-atsch gs_out-msehi gs_out-atdex gs_out-atdim gs_out-anzdz gs_out-atwrt gs_out-atflv gs_out-atflb gs_out-atcod gs_out-atawe gs_out-ataw1 CHANGING gs_out-atwro. ENDIF. MODIFY gt_out FROM gs_out. ENDLOOP.ENDFORM. "getdata *&---------------------------------------------------------------------**&*&---------------------------------------------------------------------*FORM prepare_values USING pv_atfor pv_atsch pv_msehi pv_atdex pv_atdim pv_anzdz pv_atwrt pv_atflv pv_atflb pv_atcod pv_atawe pv_ataw1 CHANGING cv_atwrt. DATA: ls_cabn TYPE cabn, ls_cawn TYPE cawn. ls_cabn-atfor = pv_atfor. ls_cabn-atsch = pv_atsch. ls_cabn-msehi = pv_msehi. ls_cabn-atdex = pv_atdex. ls_cabn-atdim = pv_atdim. ls_cabn-anzdz = pv_anzdz. ls_cawn-atwrt = pv_atwrt. ls_cawn-atflv = pv_atflv. ls_cawn-atflb = pv_atflb. ls_cawn-atcod = pv_atcod. ls_cawn-atawe = pv_atawe. ls_cawn-ataw1 = pv_ataw1. CALL FUNCTION 'CTCV_PREPARE_VALUES_TO_DISPLAY' EXPORTING structure_cabn = ls_cabn structure_cawn = ls_cawn string_with_baseunit = 'YES' IMPORTING string = cv_atwrt EXCEPTIONS OTHERS = 5.ENDFORM. "convert *&---------------------------------------------------------------------**& Form save_zmausp*&---------------------------------------------------------------------*FORM save_zmausp. DATA lt_save1 TYPE TABLE OF zmausp WITH HEADER LINE. DATA lt_save2 TYPE TABLE OF zmkssk WITH HEADER LINE. DATA lt_matnr TYPE TABLE OF matnr WITH HEADER LINE. DATA: BEGIN OF lt_swor OCCURS 0, klart TYPE klah-klart, class TYPE klah-class, kschl TYPE swor-kschl, END OF lt_swor. SELECT klah~klart klah~class swor~kschl INTO CORRESPONDING FIELDS OF TABLE lt_swor FROM klah LEFT JOIN swor ON swor~clint = klah~clint AND swor~klpos = '01' AND swor~spras = '1'. SORT lt_swor BY klart class. LOOP AT gt_out INTO gs_out. lt_matnr = gs_out-objek. COLLECT lt_matnr. lt_save1-matnr = gs_out-objek. lt_save1-klart = gs_out-klart. lt_save1-atinn = gs_out-atinn. lt_save1-atzhl = gs_out-atzhl. lt_save1-atzhw = gs_out-atzhw. lt_save1-atnam = gs_out-atnam. lt_save1-atbez = gs_out-atbez. lt_save1-atfor = gs_out-atfor. lt_save1-atwrt = gs_out-atwrt. lt_save1-atwtb = gs_out-atwtb. lt_save1-atwro = gs_out-atwro. lt_save1-aedat = sy-datum. lt_save1-aezet = sy-uzeit. lt_save1-aenam = sy-uname. APPEND lt_save1. CLEAR lt_save1. lt_save2-matnr = gs_out-objek. lt_save2-klart = gs_out-klart. lt_save2-class = gs_out-class. lt_save2-kschl = gs_out-kschl. COLLECT lt_save2. CLEAR lt_save2. ENDLOOP. LOOP AT lt_save2. READ TABLE lt_swor WITH KEY klart = lt_save2-klart class = lt_save2-class BINARY SEARCH. IF sy-subrc = 0. lt_save2-kschl = lt_swor-kschl. ENDIF. MODIFY lt_save2. ENDLOOP. LOOP AT lt_matnr. DELETE FROM zmausp WHERE matnr = lt_matnr. DELETE FROM zmkssk WHERE matnr = lt_matnr. ENDLOOP. MESSAGE s000(oo) WITH '删除完毕'. COMMIT WORK. INSERT zmausp FROM TABLE lt_save1 ACCEPTING DUPLICATE KEYS. INSERT zmkssk FROM TABLE lt_save2. MESSAGE s000(oo) WITH '保存完毕'. COMMIT WORK.ENDFORM. "save_zmausp *&---------------------------------------------------------------------**& outdata*&---------------------------------------------------------------------*FORM outdata. gs_slayt-zebra = 'X'. gs_varnt-report = sy-repid. gs_varnt-handle = 1. PERFORM catset TABLES gt_fldct USING: 'OBJEK' 'MARA ' 'MATNR' '物料', 'KLART' 'KSSK ' 'KLART' '类别种类', 'CLASS' 'KLAH ' 'CLASS' '分类', 'KSCHL' 'SWOR ' 'KSCHL' '类别描述', 'ATINN' ' ' ' ' '内部特性', 'ATZHL' 'AUSP ' 'ATZHL' '计数器', 'ATFOR' 'CABN ' 'ATFOR' '格式', 'ATNAM' 'CABN ' 'ATNAM' '特征', 'ATBEZ' 'CABNT' 'ATBEZ' '特征描述', 'ATWRT' 'AUSP ' 'ATWRT' '特征值', 'ATWTB' 'CAWNT' 'ATWTB' '特征值描述', 'ATWRO' 'AUSP ' 'ATWRT' '输出值'. CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC' EXPORTING it_fieldcat_lvc = gt_fldct i_save = 'A' is_variant = gs_varnt is_layout_lvc = gs_slayt i_callback_program = sy-repid i_callback_user_command = 'USER_COMMAND' i_callback_pf_status_set = 'SET_STATUS' TABLES t_outtab = gt_out.ENDFORM. "outdata *&---------------------------------------------------------------------**& SET_STATUS*&---------------------------------------------------------------------*FORM set_status USING t_extab TYPE slis_t_extab. IF s_klart[] IS NOT INITIAL OR s_class[] IS NOT INITIAL OR s_atnam[] IS NOT INITIAL OR s_atbez[] IS NOT INITIAL. APPEND 'POST' TO t_extab. ENDIF. SET PF-STATUS 'STD_FULL' EXCLUDING t_extab.ENDFORM. "SET_PF_STATUS *&--------------------------------------------------------------------**& Form user_command*&--------------------------------------------------------------------*FORM user_command USING pv_ucomm TYPE sy-ucomm pv_field TYPE slis_selfield. READ TABLE gt_out INTO gs_out INDEX pv_field-tabindex. CASE pv_ucomm. WHEN '&IC1'. "双击或者HOTSPOT SET PARAMETER ID 'MXX' FIELD 'C'. SET PARAMETER ID 'MAT' FIELD gs_out-objek. CALL TRANSACTION 'MM03' AND SKIP FIRST SCREEN. WHEN 'POST'. PERFORM save_zmausp. ENDCASE.ENDFORM. "user_command *&---------------------------------------------------------------------**& Form catset*&---------------------------------------------------------------------*FORM catset TABLES t_fldcat USING pv_field pv_reftab pv_reffld pv_text. DATA: ls_fldcat TYPE lvc_s_fcat. ls_fldcat-fieldname = pv_field. ls_fldcat-scrtext_l = pv_text. ls_fldcat-coltext = pv_text. ls_fldcat-ref_table = pv_reftab. ls_fldcat-ref_field = pv_reffld. ls_fldcat-col_opt = 'A'. APPEND ls_fldcat TO t_fldcat. CLEAR ls_fldcat.ENDFORM. "catset

祝你成功!

公众号有ABAP交流群,可以加我微信拉你入群

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 6:04:13

打造‘盲人电子书’无障碍阅读服务基于IndexTTS生成

打造“盲人电子书”无障碍阅读服务:基于IndexTTS生成 在数字内容爆炸式增长的今天,视障群体却依然面临严峻的信息鸿沟。尽管屏幕朗读器和语音助手早已普及,但大多数系统提供的“机器音”仍难以支撑长时间、高专注度的阅读体验——语调单调、节…

作者头像 李华
网站建设 2026/4/16 5:59:32

Zotero文献去重神器:终极智能合并插件完整指南

还在为文献库中大量重复条目而烦恼吗?当您从不同数据库导入文献时,经常会发现同一篇文章被重复收录多次,这不仅浪费存储空间,还严重影响文献管理的效率。Zotero Duplicates Merger插件就是专门为解决这一问题而生的智能工具&#…

作者头像 李华
网站建设 2026/4/16 5:58:00

三步提取视频中的PPT!高效实用的幻灯片导出工具新手教程

三步提取视频中的PPT!高效实用的幻灯片导出工具新手教程 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt extract-video-ppt是一款专注于从视频中提取演示文稿内容的实用工…

作者头像 李华
网站建设 2026/4/16 5:56:31

OBS多平台推流完整配置教程:新手也能快速上手

OBS多平台推流完整配置教程:新手也能快速上手 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 还在为每次直播都要重复配置多个平台而烦恼吗?想要一键实现B站、抖…

作者头像 李华
网站建设 2026/4/15 15:02:45

结构方程模型不会做?lavaan一行代码解决复杂因果关系分析

第一章:结构方程模型与lavaan简介结构方程模型(Structural Equation Modeling, SEM)是一种强大的多变量统计分析方法,广泛应用于心理学、社会学、管理学和教育研究等领域。它能够同时估计测量关系(通过验证性因子分析&…

作者头像 李华