matinal:SAP ABAP 7.40及以上新语法VALUE&REDUCE&FILTER的用法实战

2023-10-14 15:44:41 浏览数 (2)

直接在功能中使用这些关键字

代码语言:javascript复制
*&---------------------------------------------------------------------*
*& Report ZQC_NEW_STATEMENT
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zqc_new_statement.
*--------------------------------------------------------------------*   "实例一
"在VALUE子句中,字段可以分开赋值,也可以使用结构整体赋值,为内表赋值时,需要用小括号将一行的数据包在一起
TYPES:BEGIN OF lty_data,
        matnr TYPE mara-matnr,
        mtart TYPE mara-mtart,
        matkl TYPE mara-matkl,
        text1 TYPE char50,
      END OF lty_data.
 
 
DATA: lt_data  TYPE TABLE OF lty_data.
*DATA: lwa_data TYPE TABLE OF lty_data.
 
DATA(lwa_data) = VALUE lty_data( matnr = 'MATERIAL-001'
                                 mtart = 'FOOD'
                                 matkl = '1020'
                                 text1 = 'FIRST material' ).
 
lwa_data = VALUE #( BASE lwa_data
                    matnr = 'MATERIAL-001'
                    mtart = '数据已改'
                    matkl = '1020'
                    text1 = 'FIRST material' ).
*注意:使用 BASE 语句时,尽量保持前后结构一致,在使用不同的结构时,可能不报错但数据会错位
 
*lwa_data = VALUE #( ( matnr = 'MATERIAL-001'
*                                 mtart = 'FOOD'
*                                 matkl = '1020'
*                                 text1 = 'FIRST material' ) ).
 
lt_data = VALUE #( ( lwa_data ) " 预定义的数据类型可以用#代替
                   ( matnr = 'MATERIAL-002'
                     mtart = 'BAGA'
                     matkl = '1010'
                     text1 = 'SECOND material' ) ).
lt_data = VALUE #( BASE lt_data
                   ( matnr = 'MATERIAL-003'
                     mtart = 'FOOD'
                     matkl = '1030'
                     text1 = '数据追加' ) ).
CALL METHOD cl_demo_output=>display( lt_data ).
*--------------------------------------------------------------------*
*--------------------------------------------------------------------*  实例二
"此外,VALUE语句作为结构时,可以直接在特定语句中使用
APPEND VALUE #( matnr = 'TEST1'  text1 = '110') TO lt_data.
APPEND VALUE #( matnr = 'TEST2' ) TO lt_data.
APPEND VALUE #( matnr = 'TEST3' ) TO lt_data.
APPEND VALUE #( matnr = 'TEST4'  text1 = '120') TO lt_data.
 
MODIFY lt_data FROM VALUE #( text1 = 'X' ) TRANSPORTING text1 WHERE text1 IS INITIAL.
 
CALL METHOD cl_demo_output=>display( lt_data ).
*--------------------------------------------------------------------*
 
 
*--------------------------------------------------------------------*  实例三
*数据类型的转换可以用 CONV 实现,部分类型不再需要通过中间变量来转换
 
DATA(lv_string) = '001001.001'.
DATA(lv_int) = CONV i( lv_string ).
DATA(lv_float) = CONV f( lv_string ).
 
 
DATA(lv_division) = 1 / 3.                "浮点类型无法直接定义,可以通过类似的方法转化
DATA(lv_div) = CONV decfloat34( 1 / 3 ).  "
*p          1~ 6 byte 压缩数类型,可存储小数,自定义长度和小数点位数 (尽量用decfloat16和decfloat34替代)
*decfloat16 8 byte  十进制浮点数,可最长有16位小数位(推荐使用)
*decfloat34	16 byte	十进制浮点数,可最长有34位小数位(推荐使用)
 
*--------------------------------------------------------------------*
 
 
*--------------------------------------------------------------------*  实例四
*动态赋值语句,通常根据同一变量的不同数据来动态处理,用法类似于 CASE 语句
DATA(lv_indicator1) = 1.
DATA(lv_day1) = SWITCH char10( lv_indicator1
                              WHEN 1 THEN 'Monday'
                              WHEN 2 THEN 'Tuesday'
                              WHEN 3 THEN 'Wednesday'
                              WHEN 4 THEN 'Thursday'
                              WHEN 5 THEN 'Friday'
                              WHEN 6 THEN 'Saturday'
                              WHEN 7 THEN 'Sunday'
                              ELSE '404' && '-Error' ).
CALL METHOD cl_demo_output=>display( lv_day1 ).
*--------------------------------------------------------------------*
 
 
 
*--------------------------------------------------------------------*  实例五
*COND语句中允许使用较为复杂的判断条件,因此VALUE语句中动态赋值通常会使用COND
DATA(lv_indicator2) = 7.
DATA(lv_day2) = COND char10( WHEN lv_indicator2 = 1 THEN 'Monday'
                            WHEN lv_indicator2 = 2 THEN 'Tuesday'
                            WHEN lv_indicator2 = 3 THEN 'Wednesday'
                            WHEN lv_indicator2 = 4 THEN 'Thursday'
                            WHEN lv_indicator2 = 5 THEN 'Friday'
                            WHEN lv_indicator2 = 6 THEN 'Saturday'
                            WHEN lv_indicator2 = 7 AND sy-langu EQ 'E'  THEN 'Sunday'
                            WHEN lv_indicator2 = 7 AND sy-langu EQ 'F'  THEN 'Dimanche'
                            ELSE '404' && '-Error' ).
*--------------------------------------------------------------------*
 
*--------------------------------------------------------------------*  实例六
*REDUCE语句返回值为结构时,常用来汇总字段或作其他处理(例如取最大值/最小值/平均值等)
TYPES:BEGIN OF lty_result,
        sum   TYPE netwr,
        count TYPE i,
        max   TYPE netwr,
        min   TYPE netwr,
      END OF lty_result.
TYPES: lty_table TYPE TABLE OF lty_result WITH DEFAULT KEY.  "WITH DEFAULT KEY只要是CHAR类型的全是键值
SELECT netwr FROM ekpo INTO TABLE @DATA(lt_table) UP TO 8 ROWS WHERE netwr > 0.
SORT lt_table by netwr.
DELETE ADJACENT DUPLICATES FROM lt_table COMPARING ALL FIELDS.
CALL METHOD cl_demo_output=>display( lt_table ).
"初始化lwa_tmp参考lty_result 再根据 lt_table 定义 lwa_table 并且循环
"并通过nmax nmin返回值 再通过REDUCE计算获得最大最小值
DATA(lwa_result) = REDUCE #( INIT lwa_tmp = VALUE lty_result( )
                             FOR lwa_table IN lt_table
                             INDEX INTO lv_index
                             NEXT lwa_tmp = VALUE #( BASE lwa_tmp
                             sum   = lwa_tmp-sum   lwa_table-netwr
                             count = lwa_tmp-count   1
                             max   = nmax( val1 = lwa_tmp-max val2 = lwa_table-netwr )
                             min   = COND #( WHEN lv_index = 1 THEN lwa_table-netwr
                                             ELSE nmin( val1 = lwa_tmp-min val2 = lwa_table-netwr
                                             ) ) ) ).
CALL METHOD cl_demo_output=>display( lwa_result ).
*ABS:取绝对值
*SIGN( N ):N>0 时返回 1;N<0 时返回 -1;N=0 时返回 0 CEIL:向上取整
*FLOOR:向下取整
*TRUNC:取整数位
*FRAC:取小数位
*IPOW:计算幂值,可以用来代替 ** 使用,避免部分数据丢失精度
*NMAX/NMIN:返回参数中的最大值/最小值,参数最多传入 9 个
*ROUND:计算舍入值,DEC 指定舍入位置,可以使用 MODE指定舍入规则
*RESCALE:与 ROUND 用法一致,但是当需要保留的位数大于实际位数时,RESCALE 会在尾部填充 0,而 ROUND不会
*DATA(lv_sign) = sign( lv_num ).
*DATA(lv_ceil) = ceil( lv_num ).
*DATA(lv_floor) = floor( lv_num ).
*DATA(lv_trunc) = trunc( lv_num ).
*DATA(lv_frac) = frac( lv_num ).
*DATA(lv_ipow) = |{ ipow( base = '1.2' exp = 2 ) } , { ( '1.2' ** 2 ) }|.
*DATA(lv_nmax) = nmax( val1 = lv_ceil val2 = lv_floor ).
*DATA(lv_nmin) = nmin( val1 = lv_ceil val2 = lv_floor ).
*DATA(lv_round) = round( val = lv_num dec = 3 ).
*DATA(lv_rescale) = rescale( val = lv_num dec = 8 ).
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例七
*使用 FILTER 时,待过滤的内表结构至少需要有一个用于访问的 SORTED KEY 或 HASHED KEY,否则不
*能通过语法检查,另外,在 WHERE 条件中运算符两边的字段类型需要完全兼容,否则也不能通过语法检查;4
*在 FILTER 语句中可以通过 EXCEPT 关键字来指定是需要过滤数据还是保留数据;
DATA:lt_data2 TYPE TABLE OF lty_data WITH KEY matnr WITH NON-UNIQUE SORTED KEY matkl COMPONENTS matkl. "NON-UNIQUE非唯一
 
lt_data2 = VALUE #( ( matnr = 'Material-001'
                     matkl = '1020'
                     text1 = 100 )
                   ( matnr = 'Material-002'
                     matkl = '1030'
                     text1 = 200 )
                   ( matnr = 'Material-003'
                     matkl = '1020'
                     text1 = 300 )
                   ( matnr = 'Material-004'
                     matkl = '1040'
                     text1 = 300 )
                   ( matnr = 'Material-005'
                     matkl = '1050'
                     text1 = 300 ) ).
"保留数据
DATA(lt_filter) = FILTER #( lt_data2 USING KEY matkl WHERE matkl = CONV matkl( '1020' ) ).
"过滤数据
lt_filter = FILTER #( lt_data2 EXCEPT USING KEY matkl WHERE matkl = CONV matkl( '1050' ) ).
 
*--------------------------------------------------------------------*
 
 
 
 
*--------------------------------------------------------------------* 实例八
 
*在 SELECT 语句中使用 CASE 作为条件语句,与一般条件判断使用的 CASE 类似,但有所区别
*该语句不仅可以用于单值判断,也可以根据复杂条件进行判断;此外,WHEN OTHERS 不再适用,
*需要使用 ELSE 代替,语句结束时使用 END,而不是 ENDCASE,且需要定义别名
 
*CARRID    航线ID
*CARRNAME  航线名称
*CURRCODE  航线货币
*URL       URL
 
SELECT CASE currcode
       WHEN 'EUR' THEN carrname
       ELSE url
       END AS case_simple,
 
       CASE
       WHEN currcode = 'EUR' THEN url
       WHEN carrname <> ' '  THEN carrname
       ELSE carrid && '@' && currcode
       END AS case_complex
  FROM scarr
  INTO TABLE @DATA(lt_data3)
    UP TO 5 ROWS.
CALL METHOD cl_demo_output=>display( lt_data3 ).
 
 
*--------------------------------------------------------------------*
 
 
 
*--------------------------------------------------------------------* 实例九
DATA:lv_dec(16) TYPE p DECIMALS 2.
 
CALL FUNCTION 'UNITS_STRING_CONVERT'
  EXPORTING
    units_string = '123,456.78'
    dcpfm        = 'X' "这个是根据tcode:su01里的数字格式来设置,sap标准的格式有三种:空,X,Y
*   MLLN         = 'M'
*   TSND         = 'T'
  IMPORTING
    units        = lv_dec " UNITS  时参照你输入的l_p来定义的
  EXCEPTIONS
    invalid_type = 1
    OTHERS       = 2.
 
 
*CURRENCY 根据指定货币 cur 调整数值的小数位,参考表 TCURX 【 CURRENCY = cur 】
DATA(lv_currency) =  |{ lv_dec  CURRENCY = 'AU5' }|.  "五位小数,输出123.45678
DATA(lv_currency1) = |{ lv_dec  CURRENCY = 'BHD' }|. "三位小数,输出12345.678
 
 
*当数值为浮点数时,将不会调整小数点位置,而是在浮点数后增加0
DATA(lv_string1) = '123456.78'.
DATA(lv_dec1) = CONV  f( lv_string ).
DATA(lv_currency2) = |{ lv_dec1 CURRENCY = 'BHD' }|. "三位小数,输出123456.780
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十
*默认不做变更(RAW)【 ALPHA = [ IN | OUT | RAW ]  】
DATA(lv_alpha) = |{  CONV char4( '1' ) ALPHA = IN }|.         "移除前导0
DATA(lv_alpha1) = |{  '0001' ALPHA = OUT }|.         "移除前导0
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十一
*TIMEZONE 将时间戳转换成指定时区的时间戳,参考表 TTZZ 【 TIMEZONE = tz 】
DATA(lv_stamp) = CONV timestamp( '20190601181609' ).
DATA(lv_timezone) = |{ lv_stamp TIMEZONE = 'CET' }|.
DATA(lv_timezone1) = |{ lv_stamp TIMEZONE = 'JAPAN' }|.
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十二
*ALIGN 定义字符串对齐方式,适用于使用了 WIDTH 选项且预定义长度超出实际长度的情况
*【 ALIGN = [ LEFT | CENTER | RIGHT ] 】
*PAD 使用指定字符串中的第一位字符填充剩余的位置,适用于使用了 WIDTH 选项且预定义
*长度超出实际长度的情况,默认会使用空格填充 【 PAD = c 】
*CASE 将字符串进行大小写转换,默认为 RAW,该选项不会更改大小写格式,
*[CASE = [ RAW | LOWER | UPPER ] ]
DATA(lv_width) = |"{ 'A' WIDTH = 5 }BCD"|. "以A为起始为计算 A也为占位 5 - 1 = 4 输出结果 "A    BCD"
DATA(lv_align) = |"{ 'A' WIDTH = 2 ALIGN = RIGHT }BCD"|. "以字段首位为起始位向右偏移   2 - 1 = 1 输出结果 " ABCD"
DATA(lv_pad) = |"{ 'A' WIDTH = 2 ALIGN = RIGHT PAD = '@' }BCD"|."同上,空格用@填充
DATA(lv_case) = |"{ 'A' CASE = LOWER }BCD"|. "LOWER转换为小写a UPPER 反之
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十三
*SIGN
*用来调整数值类型符号的显示
*LEFT/RIGHT:不显示正号,将符号放置在数值左侧/右侧
*LEFTPLUS/RIGHTPLUS:显示正号,并将符号放置在数值左侧/右侧
*LEFTSPACE/RIGHTSPACE:用空格代替正号显示,并将符号放置在数值左侧/右侧
DATA(lv_sign_default) = |"{ -1 }"|.    "输出默认值
DATA(lv_sign_left) = |"{  1 SIGN = LEFT }"|.  "不显示正号,数值放置在左侧
DATA(lv_sign_leftplus) = |"{ 1 SIGN = LEFTPLUS }"|.  "显示正号,数值放置在左侧
DATA(lv_sign_leftspace) = |"{ 1 SIGN = LEFTSPACE }"|.   "用空格代替正号,将符号放置在左侧
DATA(lv_sign_right) = |"{ -1 SIGN = RIGHT }"|.    "符号放置在右侧
DATA(lv_sign_rightplus) = |"{ -1 SIGN = RIGHTPLUS }"|. "符号放置在右侧
DATA(lv_sign_rightspace) = |"{ -1 SIGN = RIGHTSPACE }"|. "符号放置在右侧
 
 
"负号前置
DATA VALUE TYPE char20 VALUE '5-'.
CALL FUNCTION 'CLOI_PUT_SIGN_IN_FRONT'
  CHANGING
    value         = value.
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十四
*REVERSE 字符串反转
DATA(lv_reverse) = reverse( 'DEMO' ).
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十五
*SEGMENT
*根据分隔符获取指定位置的字符串,可以用来拆分字符串,INDEX 用来指定位置,指定位置不存在时,
*会抛出异常 CX_SY_STRG_PAR_VAL
*通过 SEP 指定的分隔符会被当做一个整体进行操作,当分隔符连续出现时,该位置会返回空字符串;
DO.
  TRY.
      DATA(lv_sep) = segment( val   = 'AB;CD ;EF ; ;GH'
                        index = sy-index
                        sep = ' ;' ).
    CATCH cx_sy_strg_par_val.
      EXIT.
  ENDTRY.
 IF sy-subrc = 0.
 DATA:lt_sep LIKE TABLE OF lv_sep.
 APPEND lv_sep to lt_sep.
 ENDIF.
ENDDO.
CALL METHOD cl_demo_output=>display( lt_sep ).
*而通过 SPACE 指定的分隔符中,每个字符都会被视作单独的分隔符,且在分隔符连续出现时也不会单独返回空串
DO.
  TRY.
      DATA(lv_space) = segment( val   = '2.12584261'
                          index = sy-index
                          space = '.' ).
    CATCH cx_sy_strg_par_val.
      EXIT.
  ENDTRY.
 IF sy-subrc = 0.
 DATA:lt_space LIKE TABLE OF lv_space.
 APPEND lv_space to lt_space.
 READ TABLE lt_space INTO lv_space INDEX LINES( lt_space ).
* DATA(lv_fl) = lv_space
 ENDIF.
ENDDO.
CALL METHOD cl_demo_output=>display( lt_space ).
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十六
*TYPES:BEGIN OF comm2,
*      free TYPE bkpf-blart,
*END OF comm2.
*
*TYPES: BEGIN OF t_day,
*         work TYPE c LENGTH 8,
*         free TYPE c LENGTH 16.
*         INCLUDE TYPE comm2.
*TYPES:END OF t_day.
*结构复用
*RENAMING WITH SUFFIX suffix:如果include进来的结构类型(或结构变量)的组件字段与现有的重复,
*则可以使用此选项重命名include进来的结构类型(或结构变量)的各组件字段名,具体做法只是在原
*来组件名后加上了指定的后缀suffix
TYPES: BEGIN OF t_day,
         work TYPE c LENGTH 8,
         free TYPE c LENGTH 16,
       END OF t_day.
TYPES: BEGIN OF week,
         work TYPE c LENGTH 8,
         free TYPE c LENGTH 16.
        INCLUDE TYPE t_day AS monday    RENAMING WITH SUFFIX _01.
TYPES: END OF week.
DATA:lv_week TYPE week.
*--------------------------------------------------------------------*
*--------------------------------------------------------------------* 实例十七
*FIND ALL OCCURRENCES 用法
DATA: lv_str TYPE string.
DATA: LV_len1 TYPE i.
DATA: LV_len2 TYPE i.
DATA: lv_LONGTXT1 TYPE string.
DATA: lv_LONGTXT2  TYPE string.
lv_str = '微af老王df五十asdf今天asdf肯sdf德基d疯狂adF星期df四adf'.
DATA: lv_arktx TYPE string.
DATA: lt_result_tab TYPE match_result_tab,
      lt_wa         LIKE LINE OF lt_result_tab.
*https://blog.csdn.net/zhongguomao/article/details/83186939
*匹配双字节字符(包括汉字在内):[^x00-xff]
FIND ALL OCCURRENCES OF REGEX '[^x00-xff]*' IN lv_str
    RESULTS lt_result_tab.
LOOP AT lt_result_tab INTO lt_wa WHERE length <> 0.
   CONCATENATE lv_LONGTXT1 lv_str lt_wa-offset(lt_wa-length) INTO lv_LONGTXT1.
ENDLOOP.
lv_len1 = cl_abap_list_utilities=>dynamic_output_length( lv_LONGTXT1 ).
CLear lt_result_tab.
FIND ALL OCCURRENCES OF REGEX '[x00-xff]*' IN lv_str
    RESULTS lt_result_tab.
LOOP AT lt_result_tab INTO lt_wa WHERE length <> 0.
  CONCATENATE lv_LONGTXT2 lv_str lt_wa-offset(lt_wa-length) INTO lv_LONGTXT2.
ENDLOOP.
lv_len2 = cl_abap_list_utilities=>dynamic_output_length( lv_LONGTXT2 ).
WRITE:lv_LONGTXT1 , lv_len1.
WRITE:/ lv_LONGTXT2 , lv_len2.
*--------------------------------------------------------------------*

0 人点赞