使用背景:在很多报表中都会取值长文本,一般我们都是使用 read text函数取值,或者 通过ID取值
使用比较简单,但是效率低下,因为在每一循环中都是要取值长文本。
今天来介绍一种复杂一些,但是效率大大提升的方法。
一、源代码
TYPES: BEGIN OF ty_stxl_raw, "压缩的文本
clustr TYPE stxl-clustr,
clustd TYPE stxl-clustd,
END OF ty_stxl_raw.
TYPES:BEGIN OF ty_text, "解压的文本
tdobject TYPE stxl-tdobject,
tdid TYPE stxl-tdid,
tdname TYPE stxl-tdname,
tdline TYPE string,
END OF ty_text.
TYPES: BEGIN OF ty_stxl, "直接查询stxl的数据格式
tdobject TYPE stxl-tdobject,
tdid TYPE stxl-tdid,
tdname TYPE stxl-tdname,
clustr TYPE stxl-clustr,
clustd TYPE stxl-clustd,
END OF ty_stxl.
DATA: lt_stxl TYPE TABLE OF ty_stxl WITH HEADER LINE. "
DATA: lt_stxl_raw TYPE TABLE OF ty_stxl_raw WITH HEADER LINE,
ls_stxl_raw TYPE ty_stxl_raw.
DATA lt_tline TYPE STANDARD TABLE OF tline WITH HEADER LINE.
DATA lt_text TYPE TABLE OF ty_text .
DATA ls_text TYPE ty_text.
"查询销售订单以及订单行
SELECT vbak~vbeln,
vbap~posnr,
vbak~ernam,
CAST( vbak~ernam AS CHAR( 200 ) ) AS longtexth,"抬头长文本
CAST( vbak~ernam AS CHAR( 200 ) ) AS longtext, "定义一个200长度的字段,里面的内容后面直接清空掉
concat( vbak~vbeln ,vbap~posnr ) AS tdname "订单 + 订单行 = TDNAME
FROM vbak
INNER JOIN vbap ON vbak~vbeln EQ vbap~vbeln
WHERE vbak~vbeln = '0000013856' "指定的销售订单号,作为测试
INTO TABLE @DATA(lt_vbak).
"查询抬头文本
"先给我销售订单去重,一个销售订单一行
DATA(lt_vbak_h) = lt_vbak[].
SORT lt_vbak_h BY vbeln .
DELETE ADJACENT DUPLICATES FROM lt_vbak_h COMPARING vbeln .
SELECT stxl~tdobject,
stxl~tdid,
stxl~tdname,
stxl~clustr,
stxl~clustd
FROM stxl
INNER JOIN @lt_vbak_h AS l ON l~vbeln EQ stxl~tdname
WHERE stxl~tdobject = 'VBBK'
AND stxl~tdid = 'Z003'
AND stxl~tdspras = @sy-langu
INTO CORRESPONDING FIELDS OF TABLE @lt_stxl.
CLEAR:lt_vbak_h[]."后续使用不到就清空
"查询销售行的长文本
SELECT stxl~tdobject,
stxl~tdid,
stxl~tdname,
stxl~clustr,
stxl~clustd
FROM stxl
INNER JOIN @lt_vbak AS l ON l~tdname EQ stxl~tdname "之所以没有使用FOR ALL 是因为@DATA(LT_VBAK) 产生的TDNAME字段与 STXL~TDNAME 字段长度不一致
WHERE stxl~tdobject = 'VBBP'
AND stxl~tdid = 'Z007'
AND stxl~tdspras = @sy-langu
APPENDING CORRESPONDING FIELDS OF TABLE @lt_stxl.
"解压文本
LOOP AT lt_stxl.
CLEAR:lt_stxl_raw,lt_stxl_raw[], lt_tline,lt_tline[].
lt_stxl_raw-clustr = lt_stxl-clustr.
lt_stxl_raw-clustd = lt_stxl-clustd.
APPEND lt_stxl_raw.
IMPORT tline = lt_tline FROM INTERNAL TABLE lt_stxl_raw.
LOOP AT lt_tline.
ls_text-tdline = ls_text-tdline && lt_tline-tdline.
ENDLOOP.
ls_text-tdobject = lt_stxl-tdobject.
ls_text-tdid = lt_stxl-tdid.
ls_text-tdname = lt_stxl-tdname.
IF ls_text-tdline NE ''.
INSERT ls_text INTO TABLE lt_text.
ENDIF.
CLEAR ls_text.
ENDLOOP.
SORT lt_text BY tdobject tdid tdname ."排序为二分法做准备
DELETE ADJACENT DUPLICATES FROM lt_text COMPARING tdobject tdid tdname.
"匹配到ALV内表中
LOOP AT lt_vbak INTO DATA(ls_vbak).
CLEAR: ls_vbak-longtext ,ls_vbak-longtexth."先清空长文本
"取值销售订单抬头长文本
READ TABLE lt_text INTO ls_text WITH KEY tdobject = 'VBBK' tdid = 'Z003' tdname = ls_vbak-vbeln BINARY SEARCH.
IF sy-subrc = 0.
ls_vbak-longtexth = ls_text-tdline.
ENDIF.
CLEAR ls_text.
"销售行文本
READ TABLE lt_text INTO ls_text WITH KEY tdobject = 'VBBP' tdid = 'Z007' tdname = ls_vbak-tdname BINARY SEARCH.
IF sy-subrc = 0.
ls_vbak-longtext = ls_text-tdline.
ENDIF.
CLEAR ls_text .
MODIFY lt_vbak FROM ls_vbak.
CLEAR:ls_vbak.
ENDLOOP.
cl_demo_output=>display_data( lt_vbak ).
二、结果展示
本例子中,只要改改销售订单,以及长文本id就能直接使用了,测试起来蛮方便的,而且上述例子中有取值抬头和长文本的两种示范,方便你复制使用。
三、效率提升点
1.没有长文本的数据不再SQL,减少数据量。
2.二分法匹配。
3.避免在循环中取数匹配。
四、应用场景
当你取值多个长文本,并且数据量大时候就可以考虑这个方法了。