Loading

ABAP杂项

字符串拼接

*cl_abap_char_utilities=>CR_LF 获取换行符
CONCATENATE   L1  cl_abap_char_utilities=>CR_LF L2  INTO L3.
*或者
CONCATENATE   L1   cl_abap_char_utilities=>newline  L2    INTO L3.

ALV布局保存参数

* 布局可以通过调用`REUSE_ALV_VARIANT_ALL_MAINTAIN`这个函数模块进行修改 比如删除掉全局的缺省布局
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      i_callback_program       = sy-repid
      is_layout                = gt_layout
      it_fieldcat              = gt_fieldcat[]
      i_save = 'U'  "SPACE. 布局不能被保存 U 仅自定义的布局可以被保存 
	  "X 仅全局布局可以被保存  A 自定义的布局和全局的布局都可以被保存
      i_callback_user_command  = 'FORM_USER_COMMAND' "客户命令指定子程序
      i_callback_pf_status_set = 'FORM_PF_STATUS_SET'   "GUI指定子程序
      it_events                = gt_events
    TABLES
      t_outtab                 = gt_out[]
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.

动态赋值内表字段的值

data: BEGIN OF student occurs 0,
  name type char5,
  age  type int2,
  school type string,
  END OF student.
  data field type string . "字段名
  FIELD-SYMBOLS <filed> type any.
*  想实现的效果 内表中的字段名
*   student-filed = '张三'.    "name
*   student-filed = '24'. "age
*    student-filed = 'zhangsan小学'."school
*    append student.

*    实现方式
    field = 'student-name'.
    ASSIGN (field) to <filed>.
    <filed> = '张三'.
        field = 'student-age'.
    ASSIGN (field) to <filed>.
    <filed> = 24.
        field = 'student-school'.
    ASSIGN (field) to <filed>.
    <filed> = 'zhangsan小学'.
    append student.

ABAP Sql

sum函数的用法
*销售订单中的退货订单  在进行含税价格求和时 需要将退货的订单的金额置为负数 在进行求和
select sum( vbap~kzwi1 * ( case auart
                                        when 'ZRE' then ( -1 )
                                        else 1
                                end ) ) as kzwi1_sum
                                from vbap  inner join vbak  on vbak~vbeln = vbap~vbeln

遍历结构

  FIELD-SYMBOLS: <F>.
  DO.
    ASSIGN COMPONENT SY-INDEX OF STRUCTURE student TO <F>.
    IF SY-SUBRC NE 0.
      EXIT.
    ELSE.
*      Do something.....
    ENDIF.
  ENDDO.

两个内表不同名称字段赋值的快捷方法

简单结构
* 定义两个工作区 
DATA:
  BEGIN OF struct1,
    a1 TYPE string VALUE 'a1',
    a2 TYPE string VALUE 'a2',
    a3 TYPE string VALUE 'a3',
    a4 TYPE string VALUE 'a4',
    a5 TYPE string VALUE 'a5',
  END OF struct1,
  BEGIN OF struct2,
    b1 TYPE string VALUE 'b1',
    b2 TYPE string VALUE 'b2',
    b3 TYPE string VALUE 'b3',
    a4 TYPE string VALUE 'b4',
    a5 TYPE string VALUE 'b5',
  END OF struct2.
* 创建映射关系    其实字段名称相同的话 可以不用去映射 但是就不能指定kind为3的其他映射关系
*				level 代表层级  有的结构或者内表是嵌套结构 结构中的字段属性可能也是一个结构 
*               kind  代表映射类型  可指定 1 2 3 9 
DATA(mapper) =
  cl_abap_corresponding=>create(
    source            = struct1  
    destination       = struct2
    mapping           = VALUE cl_abap_corresponding=>mapping_table(
      ( level = 0 kind = 1 srcname = 'a1' dstname = 'b3' )    
      ( level = 0 kind = 1 srcname = 'a3' dstname = 'b1' )
      ( level = 0 kind = 3 ) ) ).

*执行
mapper->execute( EXPORTING source      = struct1
                 CHANGING  destination = struct2 ).

cl_demo_output=>display( struct2 ).

官方文档对于kind的解释

  • CL_ABAP_CORRESPONDING=>MAPPING_COMPONENT (1) (The components specified in this row are mapped to each other.)

  • CL_ABAP_CORRESPONDING=>MAPPING_EXCEPT_COMPONENT (2) (The component of the source structure specified in this row is excluded from the mapping of identically named components.)

  • CL_ABAP_CORRESPONDING=>MAPPING_EXCEPT_ALL (3) (All components of the current source structure are excluded from the mapping of identically name components.)

  • CL_ABAP_CORRESPONDING=>MAPPING_DISCARDING_DUPLICATES (9) (In a source table, duplicate rows are ignored as when using [DISCARDING DUPLICATES](javascript:call_link('abencorresponding_constr_dupl.htm')) in a mapping rule of the component operator. The target table must have a unique table key.)

嵌套结构
*定义结构
DATA:
  BEGIN OF struct1,
    a1 TYPE string VALUE 'a1',
    a2 TYPE string VALUE 'a2',
    a3 TYPE string VALUE 'a3',
    a4 TYPE string VALUE 'a4',
    a5 TYPE string VALUE 'a5',
    BEGIN OF asub1,
      s1_a1 TYPE string VALUE 's1_a1',
      s1_a2 TYPE string VALUE 's1_a2',
      s1_a3 TYPE string VALUE 's1_a3',
      BEGIN OF asub2,
        s2_a1 TYPE string VALUE 's2_a1',
        s2_a2 TYPE string VALUE 's2_a2',
        s2_a3 TYPE string VALUE 's2_a3',
      END OF asub2,
    END OF asub1,
  END OF struct1,
  BEGIN OF struct2,
    b1 TYPE string VALUE 'b1',
    b2 TYPE string VALUE 'b2',
    b3 TYPE string VALUE 'b3',
    a4 TYPE string VALUE 'b4',
    a5 TYPE string VALUE 'b5',
    BEGIN OF bsub1,
      s1_b1 TYPE string VALUE 's1_b1',
      s1_b2 TYPE string VALUE 's1_b2',
      s1_b3 TYPE string VALUE 's1_b3',
      BEGIN OF bsub2,
        s2_b1 TYPE string VALUE 's2_b1',
        s2_b2 TYPE string VALUE 's2_b2',
        s2_b3 TYPE string VALUE 's2_b3',
      END OF bsub2,
    END OF bsub1,
  END OF struct2.
*定义映射表
DATA(mapping_tab) = VALUE cl_abap_corresponding=>mapping_table(
( level = 0 kind = 1 srcname = 'a1' dstname = 'b3' )
( level = 0 kind = 1 srcname = 'a3' dstname = 'b1' )
( level = 0 kind = 2 srcname = 'a5' )
( level = 0 kind = 1 srcname = 'asub1' dstname = 'bsub1' )
( level = 1 kind = 1 srcname = 's1_a1' dstname = 's1_b3' )
( level = 1 kind = 1 srcname = 's1_a3' dstname = 's1_b1' )
( level = 1 kind = 1 srcname = 'asub2' dstname = 'bsub2' )
( level = 2 kind = 1 srcname = 's2_a1' dstname = 's2_b3' )
( level = 2 kind = 1 srcname = 's2_a3' dstname = 's2_b1' ) ).
*执行
cl_abap_corresponding=>create(
  source            = struct1
  destination       = struct2
  mapping           = mapping_tab
  )->execute( EXPORTING source      = struct1
              CHANGING  destination = struct2 ).
内表
TYPES: BEGIN OF line1,
         col1 TYPE i,
         col2 TYPE i,
       END OF line1,
       BEGIN OF line2,
         col2 TYPE i,
         col3 TYPE i,
       END OF line2.
*创建两个内表
DATA: itab1 TYPE TABLE OF line1 WITH EMPTY KEY,
      itab2 TYPE TABLE OF line2 WITH EMPTY KEY.

* 添加数据
itab1 = VALUE #(
  ( col1 = 11 col2 = 12 )
  ( col1 = 21 col2 = 22 ) ).

itab2 = VALUE #(
  ( col2 = 212 col3 = 312 )
  ( col2 = 222 col3 = 322 ) ).
* 创建映射表
cl_abap_corresponding=>create(
  source            = itab1
  destination       = itab2
  mapping           = VALUE cl_abap_corresponding=>mapping_table(
   ( level = 0 kind = 1 srcname = 'col1' dstname = 'col2' )
   ( level = 0 kind = 1 srcname = 'col2' dstname = 'col3' ) )
  )->execute( EXPORTING source      = itab1
              CHANGING  destination = itab2 ).

动态声明变量的类型

  FIELD-SYMBOLS: <f>.
  DATA col__typ.
  DATA dec  TYPE i.
  DATA length TYPE i.
  ASSIGN input TO <f>.
*  判断传输参数的类型
  DESCRIBE FIELD <f> TYPE col__typ.
**        判断传入参数的小数位数
  DESCRIBE FIELD <f> DECIMALS dec.
*  获取传入参数的总长度
  DESCRIBE FIELD <f> LENGTH length IN BYTE  MODE.

  DATA:
    dref_i    TYPE REF TO data,
    elem_type TYPE REF TO cl_abap_elemdescr.

  "创建基本类型,cl_abap_elemdesc类中提供了很多静态方法 可以去类中查看
  elem_type ?= cl_abap_elemdescr=>get_p( EXPORTING  p_length = length p_decimals = dec  ).

*创建变量对象
  CREATE DATA dref_i TYPE HANDLE elem_type .

*引用动态创建的变量
  FIELD-SYMBOLS <output> TYPE any.
  IF dref_i IS BOUND.
    ASSIGN dref_i->* TO <output>.
  ENDIF.

ABAP SQL中不同长度字段的关联

 SELECT B~VBELN,
       A~KSCHL
  FROM NAST AS a
 INNER JOIN VBRK AS B ON  LEFT( a~OBJKY,10 ) =  B~VBELN
 WHERE  ( B~VKORG BETWEEN 'A101' AND  'A103' )
   AND  A~KSCHL = 'ZGPB'
  INTO TABLE @DATA(LT_NA).

ABAP SQL中with关键字的用法

感觉这个关键字类似于创建了一张临时表,我们可以在后面的sql中使用这张表,例如下面这个示例,需要按照销售订单和行号以及发票编号分组,由于发票中会有多个批次,体现在发票上就是多个行项目,但是我们并不关心批次,可以使用这种方式进行汇总之后再关联主要SQL获取数据

  WITH +itab AS (
   SELECT vbeln, aubel,aupos,FKDAT_ANA,
    SUM( CASE vbrp~vbtyp_ana WHEN 'M' THEN fkimg ELSE 0 - fkimg END ) AS fkimg ,
    SUM( CASE vbrp~vbtyp_ana WHEN 'M' THEN kzwi1 ELSE 0 - kzwi1 END ) AS zkpje
    FROM vbrp WHERE aubel  IN @s_vbeln AND vbeln IN @s_fp GROUP BY aubel, aupos,vbeln,FKDAT_ANA
    )
    SELECT
       vbak~vbeln,
       vbkd~bstkd,
     vbak~kunnr,
       vbak~vkorg, "组织
     vbak~vtweg,"渠道
     vbak~auart AS ddlx,
     vbak~erdat,
     vbkd~kdgrp,"客户类型
     vbkd~bstdk,
     vbap~posnr,
     vbap~matnr,
     vbap~arktx,
    CASE vbak~auart WHEN 'ZOR' THEN kwmeng ELSE 0 - kwmeng END AS kwmeng,
    CASE vbak~auart WHEN 'ZOR' THEN kbmeng ELSE 0 - kbmeng END AS kbmeng,
     vbap~vrkme , "销售单位
     vbap~umvkz,"销售单位和基本单位的换算因子
     vbap~meins AS jbdw,"基本单位
    CASE vbak~auart WHEN 'ZOR' THEN kzwi1 ELSE 0 - kzwi1 END AS zje,
      vpa1~kunnr AS zywy,
      zsdt0011d~z_dnum AS dm,
      zsdt0011d~z_hnum AS hm,
    zsdt0011d~je AS fpje,
    zsdt0011d~se AS fpse,
    bseg~belnr,
    +itab~vbeln AS fp,
    +itab~fkimg,
    +itab~zkpje,
    +itab~fkdat_ana as kprq
       FROM vbak
       INNER JOIN vbap ON vbap~vbeln = vbak~vbeln
      LEFT JOIN +itab ON vbap~vbeln = +itab~aubel AND vbap~posnr = +itab~aupos
       INNER JOIN vbkd ON vbak~vbeln = vbkd~vbeln AND vbkd~posnr = ''
       LEFT JOIN vbpa AS vpa1 ON vbak~vbeln = vpa1~vbeln AND vpa1~parvw = 'Z1'  "业务员
      LEFT JOIN zsdt0011d ON zsdt0011d~djbh = +itab~vbeln
      LEFT JOIN bseg ON koart = 'D'  AND bseg~vbeln = +itab~vbeln
     WHERE
      vbak~vkorg IN @s_vkorg
     AND  vbak~erdat IN @s_erdat
     AND vbak~vbeln IN @s_vbeln
     AND vbak~kunnr IN @s_kunnr
     AND vpa1~kunnr IN @s_ywy
     AND +itab~aubel IN @s_fp
     AND zsdt0011d~z_dnum IN @s_dm
     AND zsdt0011d~z_hnum IN @s_hm
     AND vbap~abgru = ''
       INTO TABLE @DATA(table).

注意:

  • with后面的表名必须要以+开头
  • 多个临时表使用逗号隔开即可,像下面这样
WITH
    +wo AS ( SELECT aufk~auart,aufk~erdat,afih~iwerk,afih~ingpr,aufk~vaplz,afih~iloan,equnr,aufk~objnr
             FROM aufk INNER JOIN afih
             ON aufk~aufnr = afih~aufnr ),
    +wocounts AS ( SELECT COUNT(*) AS wosum
              FROM +wo ),
    +co AS ( SELECT objnr,wrttp,
             SUM( wtg001 + wtg002 + wtg003 + wtg004 + wtg005 + wtg006 + wtg007 + wtg008 ) AS cost01,
             SUM( wtg009 + wtg010 + wtg011 + wtg012 + wtg013 + wtg014 + wtg015 + wtg016 ) AS cost02
             from v_cosp_view
             GROUP BY objnr,wrttp,versn
             HAVING wrttp IN ('01','04')
                    AND versn = '000' )
    SELECT +wo~auart,+wo~iloan,+wo~equnr,+co~wrttp,SUM( +wocounts~wosum ) AS wonum,
    sum( cost01 ) as cost01,
    sum( cost02 ) as cost02
    FROM +wo CROSS JOIN +wocounts
    INNER JOIN +co
    ON +wo~objnr = +co~objnr
    WHERE +wo~auart IN @s_auart
      AND +wo~erdat IN @s_erdat
      AND +wo~iwerk IN @s_iwerk
      AND +wo~ingpr IN @s_ingpr
      AND +wo~vaplz IN @s_vaplz
      AND +wo~iloan IN (
        SELECT iloan FROM iflot
              INNER JOIN iflos
              ON iflot~tplnr = iflos~tplnr
              WHERE strno IN @s_strno AND actvs = 'X')
      GROUP BY +wo~auart,+wo~iloan,+wo~equnr,wrttp
      INTO TABLE @DATA(lt_basic).

内表转ranges

FOR ALL ENTRIES IN这个关键字是在我们经常需要使用的,但是使用了该关键字之后,ABAP SQL中很多功能就无法使用,例如group by就无法和FOR ALL ENTRIES IN同时使用,那么这个问题我们就可以使用ranges解决,此时就需要将我们内表中的数据转移到ranges中,使用loop的方式感觉不太优雅,我们可以使用下面这个方式,实际上就是在Value中遍历该内表

data r_vbeln type RANGE OF sy-index.
DATA: BEGIN OF vbeln OCCURS 0,
        col LIKE sy-index,
      END OF vbeln.
*向内表添加假数据
DO 10 TIMES.
  vbeln-col = sy-index.
  APPEND vbeln.
ENDDO.

r_vbeln = VALUE #( for wa_vbeln in vbeln  (
sign = 'I' option = 'EQ' low = wa_vbeln-col
 ) ).

range的定义方式有两种,但是通过这种方式给range赋值只适用于第二种定义的方式

ranges:s_vbeln for vbak-vbeln.
data:s_vbeln type range of vbak-vbeln.
posted @ 2021-09-28 11:28  _fun_ny  阅读(173)  评论(0)    收藏  举报