精华内容
下载资源
问答
  • ABAP新语法.txt

    2020-04-22 14:23:20
    SAP HANA系统的查询语法有了许多更新,使用新语法能提高查询速度,特别是大数据的。本文档里面的内容放了大量的新语法,欢迎各位下载。
  • ABAP 新语法记录(一)

    千次阅读 2019-10-28 13:25:50
    原文链接:... 主要内容 内联声明 构造表达式 ...本文列出了ABAP新语法的一些使用方式,供大家学习参考。 内联声明 代码实现: *&---------------------------...

    原文链接:https://www.cnblogs.com/learnning/p/10647174.html

    主要内容

    • 内联声明

    • 构造表达式

    • 内表操作

    • Open SQL

    • 其他


     

     

    本文列出了ABAP新语法的一些使用方式,供大家学习参考。

     

    内联声明

    代码实现:

    *&----------------------------------------------------------------------
    * 主题一:内联声明
    * 语法:DATA(...) ,FILED-SYMBOL(…)
    * 1. 定义变量
    * 2. 定义结构
    * 3. 定义内表
    * 4. 定义指针
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                          记录人: YALUOO
    *&---------------------------------------------------------------------*
    *&*********取数
      "客户的标签信息表
      SELECT *
        FROM ztcust_tag
        INTO TABLE @DATA(gt_data)
          UP TO 5 ROWS.
        cl_demo_output=>write( gt_data ).
    
    *&*********定义变量
      DATA(lv_card_no) = '1000023312'.     "会员号
      cl_demo_output=>write( lv_card_no ).
    
    *&*********定义结构
      READ TABLE gt_data INTO DATA(gs_data) INDEX 1.
      IF sy-subrc EQ 0.
        DATA(ls_data) = gs_data.
        cl_demo_output=>write( ls_data ).
      ENDIF.
    
    *&*********定义内表
      DATA(lt_data) = gt_data.
      cl_demo_output=>write( lt_data ).
    
    *&*********定义指针
      LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs_data>) WHERE card_no EQ lv_card_no.
        <fs_data>-create_user = 'YALUOO'. "修改创建人
      ENDLOOP.
      cl_demo_output=>write( lt_data ).
      cl_demo_output=>display(  ).

    运行结果:

     

    构造表达式

    代码实现:

     

    *&----------------------------------------------------------------------
    * 主题二:构造表达式
    * 1. 实现构造: NWE -创建数据对象或类的实现
    *     1.1 构造单值
    *     1.2 构造结构
    *     1.3 构造内表
    *     1.4 构造类
    * 2. 值构造:  VALUE - 创建一个类型为dypee的数据
    *     2.1 构造结构
    *         语法: ... VALUE dtype | #(  [BASE dobj] comp1 = dobj1 comp2 = dobj2 ... ) ...
    *     2.2 构造内表 :
    *         语法: ... VALUE dtype | #( [BASE itab] (  (line1-com1 = dobj1) ( line2 ..) ... ) ...
    *     note: dytpe可接具体类型或者# ,接#数据类型必须确定
    *           可以嵌套使用;
    *           内表赋值不能带表头;
    * 3. 组件构造: CORRESPONDING
    *         语法:... CORRESPONDING dtype | #(  [BASE dobj] comp1 = dobj1 comp2 = dobj2 ... ) ...
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                          记录人: YALUOO
    *&---------------------------------------------------------------------*
    " 自定义类型
    TYPES: BEGIN OF ty_man,
             name   TYPE char10,    " 姓名
             sex    TYPE char1,       " 性别
             age    TYPE p DECIMALS 2," 年龄
             school TYPE char20,      " 学校
           END OF ty_man.
    DATA: gt_man TYPE TABLE OF ty_man.
    *&*********结构赋值
    DATA(gs_man) = VALUE ty_man( name = 'Tom' sex = 'B' ).
    cl_demo_output=>write( gs_man ).
    
    "附加年龄信息
    gs_man = VALUE #( name = 'Tom' sex = 'B' age = 18 ).
    *DATA(gs_man_02) = VALUE #( name = 'Tom' sex = 'B' age = 18 ) . "错误,未明确类型
    cl_demo_output=>write( gs_man ).
    
    "附加学校信息
    gs_man = VALUE ty_man( BASE gs_man school = 'A SCHOOL' ).
    cl_demo_output=>write( gs_man ).
    
    "调整学校信息
    gs_man = VALUE #( BASE gs_man school = 'B SCHOOL' ).
    cl_demo_output=>write( gs_man ).
    
    *&*********内表赋值
    gt_man = VALUE #( ( name = 'Anna' sex = 'G' age = 17 ) ( name = 'Ann' sex = 'G' age = 16 ) ).
    cl_demo_output=>write( gt_man ).
    
    "内表基础上附加额外数据
    gt_man = VALUE #( BASE gt_man ( name = 'Xiaohong' sex = 'G' age = 20 school = 'C SCHOOL' )
                                  ( name = 'Xiaoming' sex = 'B' age = 21  school = 'D SCHOOL' ) ).
    cl_demo_output=>write( gt_man ).
    cl_demo_output=>display(  ).
    
    &*********Range 表赋值
    DATA:   r_data    TYPE RANGE OF ztcust_tag-data_type. "内表不带表头
    RANGES: r_data_01 FOR ztcust_tag-data_type.           "内表带表头-不支持
    
    "逐步往下填充内表数据
    r_data  = VALUE #( sign = 'I' option = 'BT'  ( low = 10 high = 20 )
                                             ( low = 100 high = 150 )
                               option = 'GT'  ( low  = 180 )
                               option = 'LT'  ( low = 200 )
                               option = 'EQ'  ( low = 8 )
                     sign = 'E' option = 'BT'  ( low = 15 high = 18 )
                    ).
    cl_demo_output=>write( r_data ).
    cl_demo_output=>display(  ).

     

    运行结果:

     

     

    代码实现:

    TYPES: BEGIN OF ty_data.
           INCLUDE TYPE ztcust_tag.
    TYPES: flag TYPE char1,
           END OF ty_data.
    
    TYPES: BEGIN OF ty_data_t.
           INCLUDE TYPE ztcust_tag.
    TYPES: flag_t TYPE char1,
           END OF ty_data_t.
    
    DATA: gs_data_02 TYPE ty_data,
          gs_data_03 TYPE ty_data_t.
    
    *&*********取数
      SELECT SINGLE *
        FROM ztcust_tag
        INTO @DATA(gs_data).
    
    *&*********对应字段赋值
      gs_data_02 = CORRESPONDING #( gs_data ).
      cl_demo_output=>write( gs_data_02 ).
    
      gs_data_03-flag_t = abap_true.
      gs_data_03 = CORRESPONDING #( BASE ( gs_data_03 ) gs_data_02 )."不指定BASE 初始值会丢失
       cl_demo_output=>write( gs_data_03 ).
    
      gs_data_03 = CORRESPONDING #( gs_data_02 )."初始值丢失
      cl_demo_output=>write( gs_data_03 ).
      cl_demo_output=>display(  ).

    运行结果:

    内表操作

    代码实现:

     

    *&----------------------------------------------------------------------
    * 主题三:内表操作
    * 1. 内表表达式- 相当于READ TABLE
    *    语法:… itab[ … ] …
    *     note: 如果未找到对应的记录就会抛出CX_SY_ITAB_LINE_NOT_FOUND异常,SY-SUBRC不会记录
    *           可以通过line_exists预定义函数改进
    * 2. 內表预定义函数
    *     2.1 line_exists( ) - 判断记录是否存在
    *     2.2 line_index( )  - 获取符合记录的索引值
    * 3. 內表推导 - FOR 理解为LOOP,是对实现操作符 NEW 和值操作符VALUE的一种增强,作用是构造內表内容
    *     语法1 : …FOR i = ... [THEN expr]  UNTIL | WHILE  log_exp ...
    *     语法2 : …FOR wa|<fs> IN itab [INDEX INTO idx][cond][let_exp]...
    * 4. 內表筛选-FILTER -筛选内表中的数据
    *     语法:  FILTER  type(  itab   [EXCEPT]   [IN ftab]   [USING KEY keyname ]
    *                            WHERE c1 op f1  [AND c2 op f2  [...] ]  ) ...
    *      note: WHERE对应过滤的条件,是必须要指定的,注意有些操作符是不能在WHERE中使用的,如:OR , NOT 等
    *            EXCEPT如果不指定则表示满足条件的找出来,如果指定则表示不满足条件的找出来
    * 5. 內表缩减
    *      语法: ... REDUCE type(
    *                              [let_exp]
    *                              INIT {x1 = rhs1}|{<x1> = wrexpr1}|{x1|<x1> TYPE dtype1}
    *                                   {x2 = rhs2}|{<x2> = wrexpr2}|{x2|<x2> TYPE dtype2}
    *                                   ...
    *                              FOR for_exp1
    *                              FOR for_exp2
    *                              ...
    *                              NEXT ...
    *                                   {x1 = rhs1}|{<x1> = wrexpr1}
    *                                   {x2 = rhs2}|{<x2> = wrexpr2}
    *                                   ... ) ...
    * 6. 内表分组
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                           记录人: YALUOO
    *&---------------------------------------------------------------------*
    
    *&*********取数
      SELECT *
        FROM ztcust_tag
        INTO TABLE @DATA(gt_data)
          UP TO 5 ROWS.
    
    *&*********定义变量
      DATA(lv_card_no) = '1000023312'.  "会员号
      cl_demo_output=>write( gt_data ).
    
      "通过索引值判断某一行记录是否存在,也可通过条件判断
      IF line_exists( gt_data[ 4 ] ).
       "获取第4行记录
        DATA(ls_data) = gt_data[ 4 ].
       "获取第4行记录中的标签类型
        DATA(lv_classify) = gt_data[ 4 ]-classify."标签类型
        cl_demo_output=>write( ls_data ).
        cl_demo_output=>write( lv_classify ).
      ENDIF.
    
      "获取符合条件的索引值,未找到LV_INDEX为0
        DATA(lv_index) = line_index( gt_data[ card_no = lv_card_no classify = lv_classify ] ).
        IF lv_index NE 0 AND line_exists( gt_data[ lv_index + 1 ] ) .
           CLEAR ls_data.
           "获取下一行记录
           ls_data = gt_data[ lv_index + 1 ].
           cl_demo_output=>write( ls_data ).
        ENDIF.
    
      cl_demo_output=>display(  ).

     

    运行结果:

    代码实现:

      TYPES: BEGIN OF ty_line,
               col1 TYPE i,
               col2 TYPE i,
               col3 TYPE i,
             END OF ty_line,      "结构体
             ty_tab TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.
    
    *&*********通过语法1给新內表赋值 - 类似于JAVA中的FOR循环
      "for每次遍历一次都将结果,通过value赋值给内表gt_itab
      DATA(gt_itab) = VALUE ty_tab( FOR j = 11 THEN j + 10 UNTIL j > 40  "初始值,递增量,结束条件
                                  " 结构中的字段赋值-参考类型ty_tab
                                  ( col1 = j col2 = j + 1 col3 = j + 2  )
                                "11    12    13   - value 到 gt_itab
                                   "21    22    23   - value 到 gt_itab
                                   "31    32    33   - value 到 gt_itab
                                   "41               - 结束循环
                                   ).
      cl_demo_output=>display( gt_itab ).

     

    运行结果:

    代码实现:

     

    *&*********同过语法2给新內表赋值
    *&*********取数
        "客户标签信息
         SELECT *
           FROM ztcust_tag
           INTO TABLE @DATA(gt_data)
             UP TO 5 ROWS.
    
        IF gt_data IS NOT INITIAL.
          "标签日期日志表
          SELECT *
            FROM ztcust_tag_log
            INTO TABLE @DATA(gt_data_t)
             FOR ALL ENTRIES IN @gt_data
           WHERE tag_id = @gt_data-tag_id.
    
           SORT gt_data_t BY tag_id.
           DELETE ADJACENT DUPLICATES FROM gt_data_t COMPARING tag_id.
        ENDIF.
    
         cl_demo_output=>write( gt_data ).
         cl_demo_output=>write( gt_data_t ).
    
        TYPES: BEGIN OF ty_tag_line,
              "标签表
               tag_id        TYPE ztcust_tag-tag_id,          "标签ID
               card_no       TYPE ztcust_tag-card_no,         "会员号
               tag_name      TYPE ztcust_tag-tag_name,        "标签值
               "日志表
               sernumber     TYPE ztcust_tag_log-sernumber,   "流水号
               uname         TYPE ztcust_tag_log-uname,       "用户名
               log_date      TYPE ztcust_tag_log-log_date,    "备份日期
               log_time      TYPE ztcust_tag_log-log_time,    "备份时间
               message_type  TYPE ztcust_tag_log-message_type,"消息类型
               message       TYPE ztcust_tag_log-message,     "消息文本
             END OF ty_tag_line,
             ty_tag_tab TYPE STANDARD TABLE OF ty_tag_line WITH EMPTY KEY.
    
    *&*********将标签表和日志表的数据整合在一起,构建新的内表
    DATA(gt_itab) = VALUE ty_tag_tab( FOR ls_itab IN gt_data WHERE ( classify = 'brands' )"遍历标签类型为brands; ls_itab 为隐形声明或者<fs>
                                      (
                                      tag_id    = ls_itab-tag_id
                                      card_no   = ls_itab-card_no
                                      tag_name  = ls_itab-tag_name
                                      sernumber = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-sernumber ) "通过VALUE语句和内表表达式赋值
                                          uname      = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-uname )
                                      log_date  = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-log_date )
                                      log_time  = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-log_time )
                                      message_type = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-message_type )
                                      message   = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-message )
                                      )
                                    ).
    cl_demo_output=>write( gt_itab ).
    
    *&*********使用操作符FILTER过滤
    DATA: gt_filter TYPE HASHED TABLE OF ty_tag_line
                      WITH UNIQUE KEY uname.
    
    ***INitialize filter Table
    gt_filter = VALUE #( ( uname = 'XUWENPAN' ) ).
    
    "找出满足条件的数据
    DATA(gt_out) = FILTER #( gt_itab IN gt_filter WHERE uname = uname ) .
    cl_demo_output=>write( gt_out ).
    
    "找出不满足条件的数据
    DATA(gt_out_t) = FILTER #( gt_itab EXCEPT IN gt_filter WHERE uname = uname ) .
    cl_demo_output=>write( gt_out_t ).
    
    cl_demo_output=>display(  ).
    

     

    运行结果:

    代码实现:

    *&*********取数
    TYPES: BEGIN OF ty_man,
             name   TYPE char10,    " 姓名
             sex    TYPE char1,       " 性别
             age    TYPE p DECIMALS 2," 年龄
             school TYPE char20,      " 学校
           END OF ty_man.
    DATA: gt_man TYPE TABLE OF ty_man.
    
     gt_man = VALUE #( ( name = 'Anna' sex = 'G' age = 17 )
                      ( name = 'Ann'  sex = 'G' age = 16 ) ).
     cl_demo_output=>write( gt_man ).
    
    "内表基础上附加额外数据
     gt_man = VALUE #( BASE gt_man ( name = 'Xiaohong' sex = 'G' age = 20 school = 'C SCHOOL' )
                                  ( name = 'Xiaoming' sex = 'B' age = 21  school = 'D SCHOOL' ) ).
     cl_demo_output=>write( gt_man ).
    
     "内表行数
     DATA(lv_lines) = lines( gt_man ).
      "内表中符合条件的数据有几条
     DATA(lv_lines_g) = REDUCE i( INIT x = 0
                                  FOR  ls_man IN gt_man WHERE ( sex = 'G' )
                               NEXT x = x + 1 ).
     cl_demo_output=>write( lv_lines ).
     cl_demo_output=>write( lv_lines_g ).
    
      "累计内表中符合条件的年龄之和
     TYPES: ty_age TYPE p DECIMALS 2.
     DATA(lv_sum_age) = REDUCE ty_age( INIT dage = VALUE ty_age( )
                                    FOR wa IN gt_man WHERE ( sex = 'G' )
                                    NEXT dage = dage + wa-age ).
     cl_demo_output=>write( lv_sum_age ).
    
    "综合例子
    TYPES:BEGIN OF ty_result,
             sum  TYPE p DECIMALS 2, "总和
              max  TYPE p DECIMALS 2, "最大值
              avg  TYPE p DECIMALS 2, "平均
              cunt TYPE i,            "记录数
            END OF ty_result.
    
      DATA(ls_result) = REDUCE ty_result( INIT res = VALUE ty_result( )  "可以默认值:ty_result( min = 0 max = 0 )
                                           FOR <fs_man> IN gt_man WHERE ( sex = 'G' ) "性别为G
                                          NEXT res-sum = res-sum + <fs_man>-age       "年龄总和
                                               res-max = nmax( val1 = res-max val2 = <fs_man>-age )"最大年龄
                                               res-cunt = res-cunt + 1                "满足条件的条目数
                                         ).
    
    
      ls_result-avg = ls_result-sum / ls_result-cunt.  "平均值
      cl_demo_output=>write( ls_result ).
    
     cl_demo_output=>display(  ).
    

    运行结果:

     

    Open SQL

    代码实现:

    *&----------------------------------------------------------------------
    * 主题四:Open SQL
    *
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                          记录人: YALUOO
    *&---------------------------------------------------------------------*
        DATA(lv_card_no) = '1000023083'.
    
        SELECT a~tag_id,     "标签ID
               card_no,       "会员号
               tag_name,      "会员值
               sernumber,     "流水号
               uname,         "用户名
               log_date,      "备份日期
               log_time,      "备份时间
               message_type,  "消息类型
               message        "消息文本
          FROM ztcust_tag AS a
          INNER JOIN ztcust_tag_log AS b
            ON a~tag_id = b~tag_id
          INTO TABLE @DATA(gt_tag)
         WHERE a~card_no = '1000023312' OR a~card_no = @lv_card_no
           AND classify  = 'brands' .
    
       cl_demo_output=>display( gt_tag ).
    

    运行结果:

     

    展开全文
  • ABAP 新语法-实例讲解

    2019-04-03 10:25:00
    主要内容 内联声明 ...本文列出了ABAP新语法的一些使用方式,供大家学习参考。 内联声明 代码实现: *&----------------------------------------------------------------------...

    主要内容

    • 内联声明

    • 构造表达式

    • 内表操作

    • Open SQL

    • 其他


     

     

    本文列出了ABAP新语法的一些使用方式,供大家学习参考。

     

    内联声明

    代码实现:

    *&----------------------------------------------------------------------
    * 主题一:内联声明
    * 语法:DATA(...) ,FILED-SYMBOL(…)
    * 1. 定义变量
    * 2. 定义结构
    * 3. 定义内表
    * 4. 定义指针
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                          记录人: YALUOO
    *&---------------------------------------------------------------------*
    *&*********取数
      "客户的标签信息表
      SELECT *
        FROM ztcust_tag
        INTO TABLE @DATA(gt_data)
          UP TO 5 ROWS.
        cl_demo_output=>write( gt_data ).
    
    *&*********定义变量
      DATA(lv_card_no) = '1000023312'.     "会员号
      cl_demo_output=>write( lv_card_no ).
    
    *&*********定义结构
      READ TABLE gt_data INTO DATA(gs_data) INDEX 1.
      IF sy-subrc EQ 0.
        DATA(ls_data) = gs_data.
        cl_demo_output=>write( ls_data ).
      ENDIF.
    
    *&*********定义内表
      DATA(lt_data) = gt_data.
      cl_demo_output=>write( lt_data ).
    
    *&*********定义指针
      LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs_data>) WHERE card_no EQ lv_card_no.
        <fs_data>-create_user = 'YALUOO'. "修改创建人
      ENDLOOP.
      cl_demo_output=>write( lt_data ).
      cl_demo_output=>display(  ).

    运行结果:

     

    构造表达式

    代码实现:

    *&----------------------------------------------------------------------
    * 主题二:构造表达式
    * 1. 实现构造: NWE -创建数据对象或类的实现
    *     1.1 构造单值
    *     1.2 构造结构
    *     1.3 构造内表
    *     1.4 构造类
    * 2. 值构造:  VALUE - 创建一个类型为dypee的数据
    *     2.1 构造结构
    *         语法: ... VALUE dtype | #(  [BASE dobj] comp1 = dobj1 comp2 = dobj2 ... ) ...
    *     2.2 构造内表 :
    *         语法: ... VALUE dtype | #( [BASE itab] (  (line1-com1 = dobj1) ( line2 ..) ... ) ...
    *     note: dytpe可接具体类型或者# ,接#数据类型必须确定
    *           可以嵌套使用;
    *           内表赋值不能带表头;
    * 3. 组件构造: CORRESPONDING
    *         语法:... CORRESPONDING dtype | #(  [BASE dobj] comp1 = dobj1 comp2 = dobj2 ... ) ...
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                          记录人: YALUOO
    *&---------------------------------------------------------------------*
    " 自定义类型
    TYPES: BEGIN OF ty_man,
             name   TYPE char10,    " 姓名
             sex    TYPE char1,       " 性别
             age    TYPE p DECIMALS 2," 年龄
             school TYPE char20,      " 学校
           END OF ty_man.
    DATA: gt_man TYPE TABLE OF ty_man.
    *&*********结构赋值
    DATA(gs_man) = VALUE ty_man( name = 'Tom' sex = 'B' ).
    cl_demo_output=>write( gs_man ).
    
    "附加年龄信息
    gs_man = VALUE #( name = 'Tom' sex = 'B' age = 18 ).
    *DATA(gs_man_02) = VALUE #( name = 'Tom' sex = 'B' age = 18 ) . "错误,未明确类型
    cl_demo_output=>write( gs_man ).
    
    "附加学校信息
    gs_man = VALUE ty_man( BASE gs_man school = 'A SCHOOL' ).
    cl_demo_output=>write( gs_man ).
    
    "调整学校信息
    gs_man = VALUE #( BASE gs_man school = 'B SCHOOL' ).
    cl_demo_output=>write( gs_man ).
    
    *&*********内表赋值
    gt_man = VALUE #( ( name = 'Anna' sex = 'G' age = 17 ) ( name = 'Ann' sex = 'G' age = 16 ) ).
    cl_demo_output=>write( gt_man ).
    
    "内表基础上附加额外数据
    gt_man = VALUE #( BASE gt_man ( name = 'Xiaohong' sex = 'G' age = 20 school = 'C SCHOOL' )
                                  ( name = 'Xiaoming' sex = 'B' age = 21  school = 'D SCHOOL' ) ).
    cl_demo_output=>write( gt_man ).
    cl_demo_output=>display(  ).
    
    &*********Range 表赋值
    DATA:   r_data    TYPE RANGE OF ztcust_tag-data_type. "内表不带表头
    RANGES: r_data_01 FOR ztcust_tag-data_type.           "内表带表头-不支持
    
    "逐步往下填充内表数据
    r_data  = VALUE #( sign = 'I' option = 'BT'  ( low = 10 high = 20 )
                                             ( low = 100 high = 150 )
                               option = 'GT'  ( low  = 180 )
                               option = 'LT'  ( low = 200 )
                               option = 'EQ'  ( low = 8 )
                     sign = 'E' option = 'BT'  ( low = 15 high = 18 )
                    ).
    cl_demo_output=>write( r_data ).
    cl_demo_output=>display(  ).

    运行结果:

     

     

    代码实现:

    TYPES: BEGIN OF ty_data.
           INCLUDE TYPE ztcust_tag.
    TYPES: flag TYPE char1,
           END OF ty_data.
    
    TYPES: BEGIN OF ty_data_t.
           INCLUDE TYPE ztcust_tag.
    TYPES: flag_t TYPE char1,
           END OF ty_data_t.
    
    DATA: gs_data_02 TYPE ty_data,
          gs_data_03 TYPE ty_data_t.
    
    *&*********取数
      SELECT SINGLE *
        FROM ztcust_tag
        INTO @DATA(gs_data).
    
    *&*********对应字段赋值
      gs_data_02 = CORRESPONDING #( gs_data ).
      cl_demo_output=>write( gs_data_02 ).
    
      gs_data_03-flag_t = abap_true.
      gs_data_03 = CORRESPONDING #( BASE ( gs_data_03 ) gs_data_02 )."不指定BASE 初始值会丢失
       cl_demo_output=>write( gs_data_03 ).
    
      gs_data_03 = CORRESPONDING #( gs_data_02 )."初始值丢失
      cl_demo_output=>write( gs_data_03 ).
      cl_demo_output=>display(  ).

    运行结果:

    内表操作

    代码实现:

    *&----------------------------------------------------------------------
    * 主题三:内表操作
    * 1. 内表表达式- 相当于READ TABLE
    *    语法:… itab[ … ] …
    *     note: 如果未找到对应的记录就会抛出CX_SY_ITAB_LINE_NOT_FOUND异常,SY-SUBRC不会记录
    *           可以通过line_exists预定义函数改进
    * 2. 內表预定义函数
    *     2.1 line_exists( ) - 判断记录是否存在
    *     2.2 line_index( )  - 获取符合记录的索引值
    * 3. 內表推导 - FOR 理解为LOOP,是对实现操作符 NEW 和值操作符VALUE的一种增强,作用是构造內表内容
    *     语法1 : …FOR i = ... [THEN expr]  UNTIL | WHILE  log_exp ...
    *     语法2 : …FOR wa|<fs> IN itab [INDEX INTO idx][cond][let_exp]...
    * 4. 內表筛选-FILTER -筛选内表中的数据
    *     语法:  FILTER  type(  itab   [EXCEPT]   [IN ftab]   [USING KEY keyname ]
    *                            WHERE c1 op f1  [AND c2 op f2  [...] ]  ) ...
    *      note: WHERE对应过滤的条件,是必须要指定的,注意有些操作符是不能在WHERE中使用的,如:OR , NOT 等
    *            EXCEPT如果不指定则表示满足条件的找出来,如果指定则表示不满足条件的找出来
    * 5. 內表缩减
    *      语法: ... REDUCE type(
    *                              [let_exp]
    *                              INIT {x1 = rhs1}|{<x1> = wrexpr1}|{x1|<x1> TYPE dtype1}
    *                                   {x2 = rhs2}|{<x2> = wrexpr2}|{x2|<x2> TYPE dtype2}
    *                                   ...
    *                              FOR for_exp1
    *                              FOR for_exp2
    *                              ...
    *                              NEXT ...
    *                                   {x1 = rhs1}|{<x1> = wrexpr1}
    *                                   {x2 = rhs2}|{<x2> = wrexpr2}
    *                                   ... ) ...
    * 6. 内表分组
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                           记录人: YALUOO
    *&---------------------------------------------------------------------*
    
    *&*********取数
      SELECT *
        FROM ztcust_tag
        INTO TABLE @DATA(gt_data)
          UP TO 5 ROWS.
    
    *&*********定义变量
      DATA(lv_card_no) = '1000023312'.  "会员号
      cl_demo_output=>write( gt_data ).
    
      "通过索引值判断某一行记录是否存在,也可通过条件判断
      IF line_exists( gt_data[ 4 ] ).
       "获取第4行记录
        DATA(ls_data) = gt_data[ 4 ].
       "获取第4行记录中的标签类型
        DATA(lv_classify) = gt_data[ 4 ]-classify."标签类型
        cl_demo_output=>write( ls_data ).
        cl_demo_output=>write( lv_classify ).
      ENDIF.
    
      "获取符合条件的索引值,未找到LV_INDEX为0
        DATA(lv_index) = line_index( gt_data[ card_no = lv_card_no classify = lv_classify ] ).
        IF lv_index NE 0 AND line_exists( gt_data[ lv_index + 1 ] ) .
           CLEAR ls_data.
           "获取下一行记录
           ls_data = gt_data[ lv_index + 1 ].
           cl_demo_output=>write( ls_data ).
        ENDIF.
    
      cl_demo_output=>display(  ).

    运行结果:

    代码实现:

      TYPES: BEGIN OF ty_line,
               col1 TYPE i,
               col2 TYPE i,
               col3 TYPE i,
             END OF ty_line,      "结构体
             ty_tab TYPE STANDARD TABLE OF ty_line WITH EMPTY KEY.
    
    *&*********通过语法1给新內表赋值 - 类似于JAVA中的FOR循环
      "for每次遍历一次都将结果,通过value赋值给内表gt_itab
      DATA(gt_itab) = VALUE ty_tab( FOR j = 11 THEN j + 10 UNTIL j > 40  "初始值,递增量,结束条件
                                  " 结构中的字段赋值-参考类型ty_tab
                                  ( col1 = j col2 = j + 1 col3 = j + 2  )
                                "11    12    13   - value 到 gt_itab
                                   "21    22    23   - value 到 gt_itab
                                   "31    32    33   - value 到 gt_itab
                                   "41               - 结束循环
                                   ).
      cl_demo_output=>display( gt_itab ).

    运行结果:

    代码实现:

    *&*********同过语法2给新內表赋值
    *&*********取数
        "客户标签信息
         SELECT *
           FROM ztcust_tag
           INTO TABLE @DATA(gt_data)
             UP TO 5 ROWS.
    
        IF gt_data IS NOT INITIAL.
          "标签日期日志表
          SELECT *
            FROM ztcust_tag_log
            INTO TABLE @DATA(gt_data_t)
             FOR ALL ENTRIES IN @gt_data
           WHERE tag_id = @gt_data-tag_id.
    
           SORT gt_data_t BY tag_id.
           DELETE ADJACENT DUPLICATES FROM gt_data_t COMPARING tag_id.
        ENDIF.
    
         cl_demo_output=>write( gt_data ).
         cl_demo_output=>write( gt_data_t ).
    
        TYPES: BEGIN OF ty_tag_line,
              "标签表
               tag_id        TYPE ztcust_tag-tag_id,          "标签ID
               card_no       TYPE ztcust_tag-card_no,         "会员号
               tag_name      TYPE ztcust_tag-tag_name,        "标签值
               "日志表
               sernumber     TYPE ztcust_tag_log-sernumber,   "流水号
               uname         TYPE ztcust_tag_log-uname,       "用户名
               log_date      TYPE ztcust_tag_log-log_date,    "备份日期
               log_time      TYPE ztcust_tag_log-log_time,    "备份时间
               message_type  TYPE ztcust_tag_log-message_type,"消息类型
               message       TYPE ztcust_tag_log-message,     "消息文本
             END OF ty_tag_line,
             ty_tag_tab TYPE STANDARD TABLE OF ty_tag_line WITH EMPTY KEY.
    
    *&*********将标签表和日志表的数据整合在一起,构建新的内表
    DATA(gt_itab) = VALUE ty_tag_tab( FOR ls_itab IN gt_data WHERE ( classify = 'brands' )"遍历标签类型为brands; ls_itab 为隐形声明或者<fs>
                                      (
                                      tag_id    = ls_itab-tag_id
                                      card_no   = ls_itab-card_no
                                      tag_name  = ls_itab-tag_name
                                      sernumber = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-sernumber ) "通过VALUE语句和内表表达式赋值
                                          uname      = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-uname )
                                      log_date  = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-log_date )
                                      log_time  = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-log_time )
                                      message_type = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-message_type )
                                      message   = VALUE #( gt_data_t[ tag_id = ls_itab-tag_id ]-message )
                                      )
                                    ).
    cl_demo_output=>write( gt_itab ).
    
    *&*********使用操作符FILTER过滤
    DATA: gt_filter TYPE HASHED TABLE OF ty_tag_line
                      WITH UNIQUE KEY uname.
    
    ***INitialize filter Table
    gt_filter = VALUE #( ( uname = 'XUWENPAN' ) ).
    
    "找出满足条件的数据
    DATA(gt_out) = FILTER #( gt_itab IN gt_filter WHERE uname = uname ) .
    cl_demo_output=>write( gt_out ).
    
    "找出不满足条件的数据
    DATA(gt_out_t) = FILTER #( gt_itab EXCEPT IN gt_filter WHERE uname = uname ) .
    cl_demo_output=>write( gt_out_t ).
    
    cl_demo_output=>display(  ).

     

    运行结果:

    代码实现:

    *&*********取数
    TYPES: BEGIN OF ty_man,
             name   TYPE char10,    " 姓名
             sex    TYPE char1,       " 性别
             age    TYPE p DECIMALS 2," 年龄
             school TYPE char20,      " 学校
           END OF ty_man.
    DATA: gt_man TYPE TABLE OF ty_man.
    
     gt_man = VALUE #( ( name = 'Anna' sex = 'G' age = 17 )
                      ( name = 'Ann'  sex = 'G' age = 16 ) ).
     cl_demo_output=>write( gt_man ).
    
    "内表基础上附加额外数据
     gt_man = VALUE #( BASE gt_man ( name = 'Xiaohong' sex = 'G' age = 20 school = 'C SCHOOL' )
                                  ( name = 'Xiaoming' sex = 'B' age = 21  school = 'D SCHOOL' ) ).
     cl_demo_output=>write( gt_man ).
    
     "内表行数
     DATA(lv_lines) = lines( gt_man ).
      "内表中符合条件的数据有几条
     DATA(lv_lines_g) = REDUCE i( INIT x = 0
                                  FOR  ls_man IN gt_man WHERE ( sex = 'G' )
                               NEXT x = x + 1 ).
     cl_demo_output=>write( lv_lines ).
     cl_demo_output=>write( lv_lines_g ).
    
      "累计内表中符合条件的年龄之和
     TYPES: ty_age TYPE p DECIMALS 2.
     DATA(lv_sum_age) = REDUCE ty_age( INIT dage = VALUE ty_age( )
                                    FOR wa IN gt_man WHERE ( sex = 'G' )
                                    NEXT dage = dage + wa-age ).
     cl_demo_output=>write( lv_sum_age ).
    
    "综合例子
    TYPES:BEGIN OF ty_result,
             sum  TYPE p DECIMALS 2, "总和
              max  TYPE p DECIMALS 2, "最大值
              avg  TYPE p DECIMALS 2, "平均
              cunt TYPE i,            "记录数
            END OF ty_result.
    
      DATA(ls_result) = REDUCE ty_result( INIT res = VALUE ty_result( )  "可以默认值:ty_result( min = 0 max = 0 )
                                           FOR <fs_man> IN gt_man WHERE ( sex = 'G' ) "性别为G
                                          NEXT res-sum = res-sum + <fs_man>-age       "年龄总和
                                               res-max = nmax( val1 = res-max val2 = <fs_man>-age )"最大年龄
                                               res-cunt = res-cunt + 1                "满足条件的条目数
                                         ).
    
    
      ls_result-avg = ls_result-sum / ls_result-cunt.  "平均值
      cl_demo_output=>write( ls_result ).
    
     cl_demo_output=>display(  ).

     

    运行结果:

     

    Open SQL

    代码实现:

     

    *&----------------------------------------------------------------------
    * 主题四:Open SQL
    *
    *&---------------------------------------------------------------------*
    * 记录时间:23.03.2019                          记录人: YALUOO
    *&---------------------------------------------------------------------*
        DATA(lv_card_no) = '1000023083'.
    
        SELECT a~tag_id,     "标签ID
               card_no,       "会员号
               tag_name,      "会员值
               sernumber,     "流水号
               uname,         "用户名
               log_date,      "备份日期
               log_time,      "备份时间
               message_type,  "消息类型
               message        "消息文本
          FROM ztcust_tag AS a
          INNER JOIN ztcust_tag_log AS b
            ON a~tag_id = b~tag_id
          INTO TABLE @DATA(gt_tag)
         WHERE a~card_no = '1000023312' OR a~card_no = @lv_card_no
           AND classify  = 'brands' .
    
       cl_demo_output=>display( gt_tag ).

     

    运行结果:

     

    其他

     待补充。。。

     

     

     说明:1. 以上为个人总结,如有纰漏请留言,谢谢。

        2. 本文部分内容参考 http://www.cnblogs.com/mingdashu/p/6744637.html

      

     

    转载于:https://www.cnblogs.com/learnning/p/10647174.html

    展开全文
  • SAP ABAP新语法

    2020-05-15 17:08:14
    其他语法 4.1 FILTER 语法定义: FILTER type( itab [EXCEPT] [IN ftab] [USING KEY keyname] WHERE c1 op f1 [AND c2 op f2 […]] ). 实例: TYPES: BEGIN OF ty_filter, cityfrom TYPE spfli–cityfrom, cityto ...

    变量及对象声明

    1.1 变量声明

    Before:

    DATA text TYPE string.

    text = ....

    After:

    DATA(text) = ....

    1.2 使用工作区

    Before:

    DATA wa like LINE OF itab.

    LOOP AT itab INTO wa.

    ENDLOOP.

    After:

    LOOP AT itab INTO DATA(wa).

    ENDLOOP.

    1.3 返回参数

    Before:

    DATA xml TYPE xstring.

    CALL TRANSFORMATION … RESULT XML xml.

    After:

    CALL TRANSFORMATION … RESULT XML DATA(xml).

    1.4 引用声明

    Before:

    DATA ixml TYPE REF TO if_ixml.

    DATA stream_factory TYPE REF TO if_ixml_stream_factory.

    DATA document TYPE REF TO if_ixml_document.

    ixml = cl_ixml=>create( ).

    stream_factory = ixml->create_stream_factory( ).

    document = ixml->create_document( ).

    After:

    DATA(ixml) = cl_ixml=>create( ).

    DATA(stream_factory) = ixml->create_stream_factory( ).

    DATA(document) = ixml->create_document( ).

    1.5 对象实例化

    Before:

    DATA lo_human TYPE REF TO class_human.

    CREATE OBJECT lo_human EXPORTING NAME = ‘TONY’.

    After:

    lo_human = NEW class_human( name = ‘TONY’ ).

    内表操作

    2.1 READ TABLE

    2.1.1 Read Table with key

    Before:

    READ TABLE flight_schedules INTO DATA(flight_schedule)

    WITH KEY carrid = ‘AA’

    connid = ‘0017’.

    After:

    DATA(flight_schedule) = flight_schedules[ carrid = ‘AA’ connid = ‘0017’ ].

    2.1.2 Read Table index

    Before:

    READ TABLE itab INDEX idx

    INTO wa.

    After:
    wa = itab[ idx ].

    2.1.3 Read Table using key

    Before:

    READ TABLE itab INDEX idx

    USING KEY key
    INTO wa.
    After:
    wa = itab[ KEY key INDEX idx ].

    2.1.4 Read Table index

    Before:

    DATA idx type sy-tabix.

    READ TABLE …

    TRANSPORTING NO FIELDS.

    idx = sy-tabix.

    After:

    DATA(idx) = line_index( itab[ … ] ).

    2.1 READ TABLE ASSIGNING

    Before:

    FIELD-SYMBOLS: type …

    READ TABLE itab

    ASSIGNING .

    After:

    READ TABLE itab

    ASSIGNING FIELD-SYMBOL( ).

    2.2 获得内表行数

    Before:

    DATA: lv_rows TYPE i.

    LV_ROWS = LINES( ITAB)

    After:

    DATA(lv_rows) = LINES( itab ).

    2.3 填充内表的值到目标内表中

    Before:

    DATA: gt_citys TYPE ty_citys,

    gs_ship TYPE ty_ship,

    gs_city TYPE ort01.

    LOOP AT gt_ships INTO gs_ship.

    gs_city = gs_ship-city.
    APPEND gs_city TO gt_citys.

    ENDLOOP.

    After:

    DATA(gt_citys) = VALUE ty_citys( FOR ls_ship IN gt_ships ( ls_ship-city ) ).

    Open SQL

    3.1 取数到内表

    Before:

    DATA itab TYPE TABLE OF dbtab.

    SELECT * FROM dbtab

    INTO TABLE itab

    WHERE fld1 = lv_fld1.

    After:

    SELECT * FROM dbta

    INTO TABLE DATA(itab)

    WHERE fld1 = @lv_fld1

    3.2 宿主变量

    在ABAP 7.40之前,OPEN SQL 中我们通常会添加一些变量,用来作为取数的限制条件,这种方式下,Open SQL parser将open SQL语句进行解析成与底层数据可相对应SQL时,可能会出现误差,为了能清晰的区分算符两端的东西到底是ABAP变量、还是数据库内容,从而发送相应的内容给数据库。为了完成这一任务,Open SQL中的ABAP变量因此成为了完全的宿主变量(host variables)。

    宿主变量用”@ ”来标记。

    3.3 宿主表达式

    Before:

    没有宿主变量之前,书写SQL时,可能会出现下面的错误。并且不容易察觉。
    1)SELECT carrid connid fldate seatsocc seatsmax
    FROM sflight INTO TABLE sflight_tab
    WHERE seatsmax < sflight-seatsocc.

    2)SELECT carrid, connid, fldate, seatsocc, seatsmax
    FROM sflight

    WHERE seatsmax < sflight~seatsocc

    INTO TABLE sflight_tab.

    第一种情况 sflight-seatsocc表示的是变量,而第二种sflight~seatsocc则表示的是数据库字段

    他们的执行结果是不同的。
    After:

    3)SELECT carrid, connid, fldate, seatsocc, seatsmax

    FROM sflight

    WHERE seatsmax < @sflight-seatsocc
    INTO TABLE @sflight_tab.

    引入宿主变量之后,通过@符号,我们能准确区分@sflight-seatsocc

    是宿主变量,也就是程序中的变量,执行结果不会出现误差。

    其他语法

    4.1 FILTER

    语法定义:

    FILTER type( itab [EXCEPT] [IN ftab] [USING KEY keyname]

    WHERE c1 op f1 [AND c2 op f2 […]] ).

    实例:

    TYPES: BEGIN OF ty_filter,

    cityfrom TYPE spfli–cityfrom,

    cityto TYPE spfli–cityto,

    f3 TYPE i,

    END OF ty_filter,

    ty_filter_tab TYPE HASHED TABLE OF ty_filter

    WITH UNIQUE KEY cityfrom cityto.

    DATA: lt_splfi TYPE STANDARD TABLE OF spfli.

    SELECT * FROM spfli APPENDING TABLE lt_splfi.

    DATA(lt_filter) = VALUE ty_filter_tab( f3 = 2

    ( cityfrom = ‘NEW YORK’ cityto = ‘SAN FRANCISCO’ )
    ( cityfrom = ‘FRANKFURT’ cityto = ‘NEW YORK’ ) ).

    DATA(lt_myrecs) = FILTER #( lt_splfi IN lt_filter

    WHERE cityfrom = cityfrom

    AND cityto = cityto ).

    “Output filtered records

    LOOP AT lt_myrecs ASSIGNING FIELD–SYMBOL(<ls_rec>).

    WRITE: / <ls_rec>–carrid,8 <ls_rec>–cityfrom,30

    <ls_rec>–cityto,45 <ls_rec>–deptime.

    ENDLOOP.

    4.2 REDUCE

    语法定义:

    … REDUCE type(
    [let_exp]
    INIT {x1 = rhs1}|{ = wrexpr1}|{x1| TYPE dtype1}
    {x2 = rhs2}|{ = wrexpr2}|{x2| TYPE dtype2}

    FOR for_exp1
    FOR for_exp2

    NEXT …
    {x1 = rhs1}|{ = wrexpr1}
    {x2 = rhs2}|{ = wrexpr2}
    … ) …

    实例:

    DATA itab TYPE STANDARD TABLE OF i WITH EMPTY KEY.
    itab = VALUE #( FOR j = 1 WHILE j <= 10 ( j ) ).

    DATA(sum) = REDUCE i( INIT x = 0 FOR wa IN itab NEXT x = x + wa ).

    4.3 使用类转换字符串 conv

    Before:

    DATA text TYPE c LENGTH 255.

    DATA helper TYPE string.

    DATA xstr TYPE xstring.

    helper = text.

    xstr = cl_abap_codepage=>convert_to( source = helper ).

    After:

    DATA text TYPE c LENGTH 255.

    DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV string( text ) ).

    OR

    DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV #( text ) ).

    展开全文
  • 接触abap新语法有一段时间了,看起来新语法吸收了很多java的特性,使代码更加简练,易读(某些也不是那么易读)。 众所周知,abap是典型的面向对象语言,但是在我们的应用中,除了badi,oo=alv我们似乎很少使用到...

    接触abap新语法有一段时间了,看起来新语法吸收了很多java的特性,使代码更加简练,易读(某些也不是那么易读)。

    众所周知,abap是典型的面向对象语言,但是在我们的应用中,除了badi,oo=alv我们似乎很少使用到class等,但是就目前来看,oo肯定会成为abap的主流(如果abap能活下去)。

    废话不多说,RT所示,如何使用ABAP新语法+OO之300行代码搞定AI五子棋,abap不是为了写应用而生的语言,所以此篇只为练习所用,并非不务正业。

    首先是设计,思路大概为:抽象出五子棋的方法,封装成五子棋的class,利用salv模拟棋盘,内表模拟数组,图标模拟棋子,选取估值算法为AI(这个好写点,abap对算法支持没那么好,我又比较菜)

    其次是方法:落子(双向)+判负+估值+棋盘绘制+初始化游戏

    为大量节省代码,还封装了取棋盘任意位置的棋子类型的方法,大概看起来和数组一样。

    以下为class的设计。

    "类定义
    CLASS cl_gobang DEFINITION.
      PUBLIC SECTION.
        "SALV对象
        DATA: mo_qp TYPE REF TO cl_salv_table.
        "常量:边界,以及两种棋子的图标
        CONSTANTS:border_ins TYPE c4 VALUE icon_border_inside."border
        CONSTANTS:player_wht TYPE c4 VALUE icon_incomplete.
        CONSTANTS:player_bak TYPE c4 VALUE icon_dummy.
        "步数,当前设定人先落子,所以步数为单数,轮到AI (可动态设定)
        DATA:step TYPE p VALUE 0.
        "核心表,存储当前棋盘
        "核心表设计思路:
        "需要模拟数组进行读取操作,所以对于行列敏感,除去边界,1-15行以及1-15列为棋盘,X为内表行,Y为列,列递增寻址,所以要基于列名的可拼接
        " 如C101,即为棋盘内表的第2列,棋盘的第一列,所以读取方式为 it_qp[ X ]-|C {Y + 99}|  => C {Y + 99}即为列名
        " 以下当传入参数为行列的i类型时,Y坐标为列的数字-99
        DATA :BEGIN OF wa_qp,
                c100 TYPE c4, "border
                c101 TYPE c4,c102 TYPE c4,c103 TYPE c4,c104 TYPE c4,c105 TYPE c4,
                c106 TYPE c4,c107 TYPE c4,c108 TYPE c4,c109 TYPE c4,c110 TYPE c4,
                c111 TYPE c4,c112 TYPE c4,c113 TYPE c4,c114 TYPE c4,c115 TYPE c4,
                c116 TYPE c4, "border
                "该列为TYPE列,设定该列支持link事件,详见初始化函数实现
                ctyp TYPE salv_t_int4_column,
              END OF wa_qp.
        DATA:it_qp LIKE TABLE OF wa_qp.
        "初始化棋盘,17*17的内表 其中最外围为边界,所以棋盘大小为15*15
        METHODS: ini_gobang.
        "棋盘绘制,调用SALV模拟棋盘
        METHODS: dis_gobang.
        "落子算法,绑定SALV的link click事件
        METHODS: set_gobang FOR EVENT link_click OF cl_salv_events_table IMPORTING row column.
        "AI核心算法,人落子之后,循环棋盘上所有未落子的点,调用估值算法估值,选择估值最高的点落子(基于博弈树的估值算法)
        METHODS: ai1_gobang."
        "模拟数组,并基于偏移方向以及偏移量的内表读取,分8个方向
        "偏移方向以及偏移量是可选的,当不传入的时候,返回当前坐标的值
        "返回值为基于偏移方向以及偏移量的内表字段值
        METHODS: get_gobang IMPORTING row TYPE i col TYPE i off TYPE i OPTIONAL set TYPE i OPTIONAL "偏移量
                                                                           RETURNING VALUE(value) TYPE c4.
        "AI核心估值算法,传入该点坐标以及需要估值的玩家,返回该点的估值
        METHODS: env_gobang IMPORTING row TYPE i col TYPE i player TYPE c4 RETURNING VALUE(value) TYPE i.
        "判负算法,通过对该点8个方向的延伸探索,判断四条线的同类棋子数目
        "返回值为以该点为原点,一条线上连续棋子的数量
        METHODS: win_gobang IMPORTING row TYPE i off TYPE i column TYPE c4 RETURNING VALUE(score) TYPE i."判负算法
        "消息
        METHODS: mes_gobang IMPORTING mes TYPE string.
    ENDCLASS.

    这部分是核心代码,实现部分我将会之后附上。

    首先棋子图标的选取凭自己喜欢,以能分清为好,可以用icon事务码或者showicon程序查看所有图标代码选择自己喜欢的。

    为了优化程序,我设计了17*17的数组(内表),最外一层为边界,这样可以不必担心越界问题,读到边界图标停止。

    命名采用c1**的形式,所以读取的时候格式统一,不会出问题。

    一个很有意思的方法是基于偏移量的内表读取,这其实是数组的概念,我们可以知道某位置的周边棋子分布,用来估值计算AI以及判负使用。

    至于每个方法的用处,代码中注释已经说明了一切,是的,即使要300行实现五子棋,我也没有就省略注释,注释是一个很好的行为(虽然我也不喜欢写)

     

    以下为实现,有点长

    "类的实现部分
    CLASS cl_gobang IMPLEMENTATION.
    
      "判负算法
      METHOD: win_gobang.
        score = 1.
        DATA(col_cur)  = CONV i( column+1(3) - 99 ).
        ASSIGN COMPONENT column OF STRUCTURE it_qp[ row ] TO FIELD-SYMBOL(<pawn>) ."获取当前棋子类型
        "以下两次循环,通过判断方向以及偏移量判定同种棋子的类型,
        "当偏移量为正负时,8个方向可以看成四条线,所以调用时判断四次即可,
        DO 4 TIMES.
          IF <pawn> NE get_gobang( row = row col = col_cur off = off set =  sy-index  ).EXIT.ENDIF."若该方向遇见不同棋子,直接结束循环,下同
          score = score + 1.
        ENDDO.
        "一条线的另一方向
        DO 4 TIMES.
          IF <pawn> NE get_gobang( row = row col = col_cur off = off set = - sy-index ).EXIT.ENDIF.
          score = score + 1.
        ENDDO.
    
      ENDMETHOD.
    
    * 基于偏移向量以及偏移量的读取
      METHOD: get_gobang.
    
        DATA(row_now) = row.
        DATA(col_now) = col.
        CASE off.
          WHEN 1.row_now = row_now + set.                               "  方向图示 0为初始点
          WHEN 2.col_now = col_now + set.                               "                   7      2      8
          WHEN 3.row_now = row_now - set.                               "
          WHEN 4.col_now = col_now - set.                               "
          WHEN 5.row_now = row_now + set.col_now = col_now + set.       "                   4      0      3
          WHEN 6.row_now = row_now + set.col_now = col_now - set.       "
          WHEN 7.row_now = row_now - set.col_now = col_now - set.       "
          WHEN 8.row_now = row_now - set.col_now = col_now + set.       "                   6      1      5
          WHEN OTHERS.
        ENDCASE.
    
    *    IF col_now < 1 OR col_now > 16 OR row_now < 1 OR row_now > 17.
    *      value = border_ins.RETURN.
    *    ENDIF.
        "返回基于方向以及偏移量的值,如果assign失败,那么为设定该值为边界
        ASSIGN COMPONENT col_now OF STRUCTURE it_qp[ row_now ] TO FIELD-SYMBOL(<pawn_cur>).
        value = COND #( WHEN <pawn_cur> IS ASSIGNED THEN <pawn_cur> ELSE border_ins ).
    
      ENDMETHOD.
      "初始化棋盘 为带边界的17*17内表,其中内部15*15位空。详情可调试并观察结果
      METHOD: ini_gobang.
        "双层循环得到2-16行
        it_qp = VALUE #( FOR j = 1 UNTIL j > 15 (
                           c100 = border_ins
                           c116 = border_ins
                           "该循环得到Ctyp列,该列为表结构,存储设置为link事件的所有列
                           ctyp = VALUE #( FOR i = 1 UNTIL i > 15 (
                              columnname = |C{ i + 100 }|
                              value = if_salv_c_cell_type=>hotspot ) ) ) ).
        "循环得到一个边界工作区
        DO 17 TIMES.
          ASSIGN COMPONENT sy-index  OF STRUCTURE wa_qp TO FIELD-SYMBOL(<value>).
          <value> = border_ins.
        ENDDO.
        "将上下边界放入内表,初始化完毕
        INSERT wa_qp INTO it_qp INDEX 1.
        APPEND wa_qp TO it_qp.
    
      ENDMETHOD.
      "弹出消息,通常为获胜或者平局时,初始化棋盘重新开始
      METHOD: mes_gobang.
        MESSAGE mes TYPE 'I'.
        ini_gobang( ).
        dis_gobang( ).
      ENDMETHOD.
      "主显示方法
      METHOD: dis_gobang.
        "如果SALV对象不存在(第一次绘制)
        IF mo_qp IS NOT BOUND.
          ini_gobang( )."初始化棋盘
          "通过内表获取SALV对象
          cl_salv_table=>factory( IMPORTING r_salv_table = mo_qp CHANGING t_table = it_qp ).
    
    *      mo_qp->get_functions( )->set_all( )."act all functions
    *      mo_qp->get_functions( )->add_function( "附加按钮只能用于可控模式,所以会dump
    *      name = 'NEWGAME' "icon = l_icon
    *      text = 'New Game'
    *      tooltip = 'New Game'
    *      position = if_salv_c_function_position=>right_of_salv_functions ).
          "分配set_bang方法绑定到alv对象的事件 事件获取:mo_qp->get_event( )
          SET HANDLER me->set_gobang FOR mo_qp->get_event( ).
          "获取所有列对象
          DATA(gr_columns) = mo_qp->get_columns( ).
          "设定CTYP列为格式列(该列存储link事件,所以值被设定为Hotspot,详情见初始化)
          gr_columns->set_cell_type_column( 'CTYP' ).
          "循环获取所有的列,设置输出长度为2,并且居中显示,以便看上去像个棋盘
          DO 17 TIMES.
            DATA(gr_column) = gr_columns->get_column( CONV lvc_fname( |C{ sy-index + 99 }| ) )."通过列合集获取单列对象,输入参数为列明名称
            gr_column->set_output_length( 2 )."输出长度
            gr_column->set_alignment( 3 )."居中显示
          ENDDO.
          "设定表头以及其他信息,因刷新问题取消(需要重新设定)
          DATA(lo_header) = NEW cl_salv_form_layout_grid( ).
          DATA: lo_h_label TYPE REF TO cl_salv_form_label,
                lo_h_flow  TYPE REF TO cl_salv_form_layout_flow.
          lo_h_label = lo_header->create_label( row = 1 column = 1 ).
          lo_h_label->set_text( 'GoBang!' ).
          "绘制表头
          mo_qp->set_top_of_list( lo_header ).
          "绘制ALV
          mo_qp->display( ).
        ELSE.
          "如果不是第一次显示(刷新) 重新设定标题栏以及TYP列(不知为何refresh方法会把这些信息弄丢,官方文档解释refresh为rebuild)
          lo_header = NEW cl_salv_form_layout_grid( ).
          lo_h_label = lo_header->create_label( row = 1 column = 1 ).
          lo_h_label->set_text( 'GoBang!' ).
          mo_qp->get_columns( )->set_cell_type_column( 'CTYP' ).
          mo_qp->set_top_of_list( lo_header ).
          "基于行列的稳定刷新
          mo_qp->refresh( s_stable = VALUE lvc_s_stbl( row = 'X' col = 'X') refresh_mode = 2 ).
        ENDIF.
    
      ENDMETHOD.
      "set方法, 落子
      METHOD: set_gobang.
        "分配落子位置的值给指针,如果分配成功并且该处为空,即可落子
        ASSIGN COMPONENT column OF STRUCTURE it_qp[ row ] TO FIELD-SYMBOL(<pawn>).
        CHECK <pawn> IS INITIAL AND <pawn> IS ASSIGNED.
        "通过setp的奇偶性判断落子的值
        <pawn> = COND #( WHEN step MOD 2 EQ 1 THEN player_wht ELSE player_bak ).
        "停顿一秒 避免不必要的麻烦
        WAIT UP TO 1 SECONDS.
        step = step + 1."步数累加
        dis_gobang( ).  "刷新棋盘
        "每走一步,传入当前落子点进行胜负判断 分别基于1236四条线,方向设定见get_gobang注释。
        IF win_gobang( row = row column = CONV #( column ) off = 1 ) >= 5
        OR win_gobang( row = row column = CONV #( column ) off = 2 ) >= 5
        OR win_gobang( row = row column = CONV #( column ) off = 5 ) >= 5
        OR win_gobang( row = row column = CONV #( column ) off = 6 ) >= 5.
          "如果某条线的连续棋子总数大于5,弹出获胜消息并初始化棋盘
          mes_gobang( COND #( WHEN step MOD 2 EQ 1 THEN |You Win!| ELSE |You Lost!| ) ).
          EXIT.
        ENDIF.
        "如果步数step = 15*15,说明双方落子已经满了,并且没有分胜负,平局提示并退出
        IF step = 15 * 15.
          mes_gobang( |No Win!|  ).
          EXIT.
        ENDIF.
        "如果setp为奇数,那么刚刚落子的是玩家,此时调用AI算法落子
        CHECK step MOD 2 EQ 1.
        ai1_gobang( ).
      ENDMETHOD.
      "核心算法之AI
      "算法思路:循环棋盘上未落子的所有点进行估值,并且返回得分最高的点,调用set方法落子
      "算法分进攻和防守,可以通过微调分数设定AI智力以及走棋方式
      "可以加随机数算法使AI看起来多样化一些
      METHOD: ai1_gobang.
        "best x y为最佳落子位置
        DATA:best_x TYPE i,
             best_y TYPE i.
        "max为最高分数 因为不需要排序,只取最高,所以冒泡即可
        DATA:max TYPE i VALUE 0.
    
        LOOP AT it_qp INTO wa_qp.
          DATA(x1) = sy-tabix."临时变量存储内表序列(调用其他方法会改变该值)
          "只循环中间的15*15即可
          DO 16 TIMES.
            DATA(y1) = sy-index."临时变量存储do序列(不知道会不会变,保险起见用了临时变量)
            IF get_gobang( row = x1 col = y1 ) IS NOT INITIAL."如果该点已被落子,跳出循环继续
              CONTINUE.
            ENDIF.
            "进攻:对白色棋子进行估值,如果分数大约此前的分数,那么替换掉该分数,并存储当前点为best
            IF max < env_gobang( row = x1 col = y1 player = player_wht ).
              max = env_gobang( row = x1 col = y1 player = player_wht ).
              best_x = x1.
              best_y = y1.
            ENDIF.
            "防守:对黑色棋子进行估值,如果分数大约此前的分数,那么替换掉该分数,并存储当前点为best
            IF max <= env_gobang( row = x1 col = y1 player = player_bak ).
              max = env_gobang( row = x1 col = y1 player = player_bak ).
              best_x = x1.
              best_y = y1.
            ENDIF.
    
          ENDDO.
        ENDLOOP.
        "获取到best落子点后,调用set函数落子,
        set_gobang( row = CONV #( best_x ) column = CONV #( |C{ best_y + 99 }| ) ).
    
      ENDMETHOD.
      "AI核心之估值算法
      "估值算法一般来说取决于条件的齐备,但是即使条件都没问题,AI的智商看起来也不怎么高,
      "这是因为深度不够,如果估值的深度延伸到周围偏移3,就会比较厉害,但是执行慢,并且很麻烦写,
      "以下对估值算法做了一些适度优化,虽然看起来没什么用
      "传入需要估值点的坐标,需要估值的棋子类型
      METHOD: env_gobang."X Y PLAYER
        "定义对手
        DATA(opsite) = COND #( WHEN player = player_wht THEN player_bak ELSE player_wht ).
        "中心点的估值可以适当增加,这是对估值算法的优化1
        value = 16 - abs( row - 8 ) - abs( col - 8 ).
        "对8个方向的棋子循环,通过某方向的棋子数量进行相关估值
        "棋盘类型大致为活四,死四,活三,死三,活二,死二
        DO 8 TIMES.
          DATA(i) = sy-index.
    *      // *11110 ("活四" 必胜 设定为最高分数)
          IF ( get_gobang( row = row col = col off = i set = 1 ) = player
           AND get_gobang( row = row col = col off = i set = 2 ) = player
           AND get_gobang( row = row col = col off = i set = 3 ) = player
           AND get_gobang( row = row col = col off = i set = 4 ) = player
           AND get_gobang( row = row col = col off = i set = 5 ) IS INITIAL ).
            value = value + 4500000.
            "优化2,测试BUG,当双方都有活四时,AI进攻会赢,却选择防守,所以输掉,所以轮到AI时要增加该点估值
            IF player EQ player_wht.value = value + 100000.ENDIF.
          ENDIF.
    *         死四A 21111*
          IF ( get_gobang( row = row col = col off = i set = 1 ) = player
           AND get_gobang( row = row col = col off = i set = 2 ) = player
           AND get_gobang( row = row col = col off = i set = 3 ) = player
           AND get_gobang( row = row col = col off = i set = 4 ) = player
           AND
             ( get_gobang( row = row col = col off = i set = 5 ) = opsite
            OR get_gobang( row = row col = col off = i set = 5 ) = border_ins ) ).
            value = value + 300000.
          ENDIF.
    *          死四B 111*1
          IF ( get_gobang( row = row col = col off = i set = -1 ) = player
           AND get_gobang( row = row col = col off = i set =  1 ) = player
           AND get_gobang( row = row col = col off = i set =  2 ) = player
           AND get_gobang( row = row col = col off = i set =  3 ) = player
           AND
             ( get_gobang( row = row col = col off = i set =  4 ) = opsite
            OR get_gobang( row = row col = col off = i set =  4 ) = border_ins ) ).
            value = value + 300000.
          ENDIF.
    *          死四C 11*11
          IF ( get_gobang( row = row col = col off = i set = -1 ) = player
           AND get_gobang( row = row col = col off = i set = -2 ) = player
           AND get_gobang( row = row col = col off = i set =  1 ) = player
           AND get_gobang( row = row col = col off = i set =  2 ) = player
           AND
             ( get_gobang( row = row col = col off = i set =  3 ) = opsite
            OR get_gobang( row = row col = col off = i set =  3 ) = border_ins ) ).
            value = value + 300000.
          ENDIF.
    *         //  2111* (活三)
          IF ( get_gobang( row = row col = col off = i set =  1 ) = player
           AND get_gobang( row = row col = col off = i set =  2 ) = player
           AND get_gobang( row = row col = col off = i set =  3 ) = player
           AND get_gobang( row = row col = col off = i set =  4 ) IS INITIAL ).
            value = value + 200000.
          ENDIF.
    *         //  211* (活2)
          IF ( get_gobang( row = row col = col off = i set =  1 ) = player
           AND get_gobang( row = row col = col off = i set =  2 ) = player
           AND get_gobang( row = row col = col off = i set =  3 ) IS INITIAL ).
            value = value + 100000.
          ENDIF.
    *         // 死三 11*1 2111*
          IF ( get_gobang( row = row col = col off = i set = -1 ) = player
           AND get_gobang( row = row col = col off = i set = -2 ) = player
           AND get_gobang( row = row col = col off = i set =  1 ) = opsite )
           OR
             ( get_gobang( row = row col = col off = i set =  1 ) = player
           AND get_gobang( row = row col = col off = i set =  2 ) = player
           AND get_gobang( row = row col = col off = i set = -1 ) = opsite ).
            value = value + 80000.
          ENDIF.
    *// 判断是否存在 1*001(死二)
          IF ( get_gobang( row = row col = col off = i set =  1 ) = player
           AND get_gobang( row = row col = col off = i set =  2 ) IS INITIAL
           AND get_gobang( row = row col = col off = i set =  3 ) IS INITIAL ).
            value = value + 100.
          ENDIF.
    *     优化3 附近点比较多的时候适当增加权重
          IF  ( get_gobang( row = row col = col off = i set = -1 ) IS NOT INITIAL
           AND  get_gobang( row = row col = col off = i set = -1 ) <> border_ins )
           OR ( get_gobang( row = row col = col off = i set =  1 ) IS NOT INITIAL
            AND get_gobang( row = row col = col off = i set =  1 ) <> border_ins ).
            value = value + 25.
          ENDIF.
    
        ENDDO.
        "增加随机数,适当改变攻防分数,获取不同玩法(微调)
        "可能会变得更智障
        DATA ran TYPE i.
        CALL FUNCTION 'QF05_RANDOM_INTEGER'
          EXPORTING
            ran_int_max = 2
            ran_int_min = 1
          IMPORTING
            ran_int     = ran.
        value = COND #( WHEN ran EQ 1 THEN value * 99 / 100 ELSE value * 101 / 100 ).
      ENDMETHOD.
    ENDCLASS.

     

    大家都是成熟的abap了,实现部分的代码贴上来大家都能看懂,我就不多解释了(相信注释已经解释了一切)

    嘻嘻我对估值算法做了一些优化哦~~,这是AI的核心,但是大家不必非要搞懂这个。

    最后调用即可:

    "主进程 实例化类并调用显示即可
    DATA(gobang) = NEW cl_gobang( ).
    gobang->dis_gobang( ).

    so,代码就写完了,以上代码直接全复制到se38里可以直接执行哦,我确定没有遗漏什么东西,如果有,那就是TYPES c4(4) TYPE c.的定义了。

    如果还有,别让代码覆盖了你的report头。

    也许我该附上游戏截图,如果有时间的话再改吧。

     

    转载于:https://www.cnblogs.com/yibing-jia/p/10923645.html

    展开全文
  • 何喜同学之前给我说,新语法新语法新语法。。。 今天开发一个ABAP报表用上了,很方便啊,节省了很多工作量。 就是这个: SELECT DISTINCT T0~AUFNR,T0~GSTRI, T0~GLTRI, T0~FTRMI, T0~PLNBEZ, T2~MAKTX, T0...
  • abap新语法(一)

    2021-05-18 17:20:14
    VALUE VALUE作为赋值语句 新语法中,可以使用 VALUE 作为赋值语句,主要用来为内表、结构、变量等对象赋值 在VALUE子句中,字段可以分开赋值,也可以使用结构整体赋值,为内表赋值时,需要用小括号将一行的数据包在...
  • ABAP 新语法 截取字符串

    千次阅读 2020-06-18 20:38:35
     必须放在最后面 2 replace ,但是B不能为空白 语法和1一样 REPLACE( bseg~zuonr , 'A','B' ) 替换成B 3 取掉字符(其他语言是去空格,这个可以去掉去空格,去a都可以) where LTRIM( RTRIM( bseg~zuonr,'...
  • 注意: ltrim rtrim 在其他语言是去空,...另外 replace(bseg~zuonr ,'a','b') 语法也可用,把A替换成B ,问题是 B不能用空白 SELECTbseg~sgtxt,"票据号ztfi005~zpjdh,ztfi005~zpjfl,ztfi005~zbb,"币别ztfi005~zpjlx...
  • ABAP 新语法 substring 截取字符串

    千次阅读 2020-11-10 17:45:15
    IF cb_01 EQ 'X' . LOOP AT gt_out INTO gs_out . SELECT SINGLE belnr FROM bkpf AS t1 WHERE substring( t1~awkey , 1, 10 ) = @gs_out-mblnr AND substring( t1~awkey , 11, 4 ) = @gs_out-mjahr ...
  • SAP ABAP新语法之LOOP GROUP BY

    千次阅读 2020-05-18 18:51:37
    通过下面2个实例代码来理解 LOOP GROUP BY 效果测试代码如下: REPORT ZENG_T06. TYPES: BEGIN OF struct, key1 TYPE string, key2 TYPE string, col TYPE i, END OF struct, itab TYPE STANDARD TABLE OF ...
  • ABAP新语法之LOOP GROUP BY

    千次阅读 2018-07-26 11:23:21
    TYPES: BEGIN OF ty_customer, customer TYPE char10, NAME TYPE char30, city TYPE char30, route TYPE char10, END OF ty_customer. TYPES: tt_customers TYPE SORTED TABLE OF...
  • *LOOP AT itab result [cond] GROUP BY key ( key1 = dobj1 key2 = dobj2 … * [gs = GROUP SIZE] [gi = GROUP INDEX] ) * [ASCENDING|DESCENDING [AS TEXT]] * [WITHOUT MEMBERS] * [{INTO group}|{ASSIGNING <...
  • 例子如下: SELECT FROM vbkd INNER JOIN @lt_temp AS t ON t~zcontractnum EQ vbkd~vbeln FIELDS vbkd~vbeln, "---合同编号 vbkd~bstkd_m ...
  • S/4HANA版本的NetWeaver平台上,ABAP已经进化的和现代编程语言很类似了。ABAP可以支持很多“函数式”调用的写法,这种写法让ABAP的写法更简短,也更容易被现代程序员所接受。 本文列举了最常见的几种“函数式”调用...
  • (1) 直接批量生成数据到ABAP内表里: 2017-05-14 7:17PM in Xun’s house, Wiesloch INSERT demo_join1 FROM TABLE @( VALUE #( ( a = 'a1' b = 'b1' c = 'c1' d = 'uu' ) ( a = 'a2' b = 'b2' c = 'c2' d = 'uu...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,206
精华内容 1,282
关键字:

abap新语法