ABAP 中的动态结构与数据引用

举报
雨绸缪 发表于 2023/07/31 17:11:37 2023/07/31
【摘要】 动态结构和数据引用已经被很好地记录和编写了十多年,它是 SAP 开发中最灵活(尽管也是最危险的安全)的组件之一。我不会重新设计车轮,而是在动态结构的不同层面上呈现它。我们将利用动态和数据引用从最简单的结构到更复杂的结构。我会尝试的是向一个刚接触 ABAP 编程的人最好地解释动态编程,因为这是一个巨大的话题,尽早学习它有助于培养良好的框架思维方式。FIELD-SYMBOLS: <lfs_vko...

动态结构和数据引用已经被很好地记录和编写了十多年,它是 SAP 开发中最灵活(尽管也是最危险的安全)的组件之一。我不会重新设计车轮,而是在动态结构的不同层面上呈现它。

我们将利用动态和数据引用从最简单的结构到更复杂的结构。我会尝试的是向一个刚接触 ABAP 编程的人最好地解释动态编程,因为这是一个巨大的话题,尽早学习它有助于培养良好的框架思维方式。

FIELD-SYMBOLS: <lfs_vkorg> TYPE vkorg.
CONSTANTS: lc_curr_vkorg TYPE objectname VALUE '(SAPMV13H)KOMGH-VKORG'.

... Do something ...

ASSIGN (lc_curr_vkorg) TO <lfs_vkorg>.
IF <lfs_vkorg> IS ASSIGNED.
   IF <lfs_vkorg> IS NOT INITIAL.

... Do something ...

   ENDIF.
ENDIF.

动态结构

用法:这通常是与动态表同时进行的,但如果不是的话,它给你一个机会从一个名字或一个引用(如另一个变量)中创建一个结构。有多种方法来创建动态结构,但其中一种方法如下:

PARAMETERS: p_tab   TYPE tabname.
DATA: lo_structure    TYPE REF TO cl_abap_structdescr,
      lr_data         TYPE REF TO data.

lo_structure ?= cl_abap_structdescr=>describe_by_name( p_name = p_tab ).  
CREATE DATA lr_data TYPE HANDLE lo_structure.
ASSIGN lr_data->* TO FIELD-SYMBOL(<lfs_structure>).

IF <lfs_structure> IS ASSIGNED. 
" Do something
ENDIF. 

另一个例子是一个没有 "参考 "的动态生成的结构。在这个例子中,我正在根据参数 p_cnt 生成一个带有若干标准价格字段的结构。它在运行时生成该结构。这在它可以改变输出的程序中非常有用。

一个常见的用例是根据一个时间范围生成 ALV 输出,如月度值,其中月数是根据用户输出而变化的。

PARAMETERS: p_cnt   TYPE i.

TYPES: BEGIN OF ty_material_price,
         matnr    TYPE matnr,
         waers    TYPE waers,
       END   OF ty_material_price.

DATA: go_struc       TYPE REF TO cl_abap_structdescr,
      go_new_struc   TYPE REF TO cl_abap_structdescr,
      gr_structure   TYPE REF TO data,
      go_tabdata     TYPE REF TO data,
      go_descr       TYPE REF TO cl_abap_datadescr,
      gv_price       TYPE STPRS,
      gs_mat_price   TYPE ty_material_price.


go_struc ?= cl_abap_structdescr=>describe_by_data( gs_mat_price ).

DATA(components)  = go_struc->get_components( ).

DO p_cnt TIMES.
  go_descr ?= cl_abap_typedescr=>describe_by_data( gv_price  ).
  APPEND INITIAL LINE TO components
    ASSIGNING FIELD-SYMBOL(<component>).
  <component> = VALUE #( name = |STPRS{ sy-index }| type = go_descr  ).
ENDDO.

TRY.
  DATA(new_struc) = cl_abap_structdescr=>create( p_components = components ).             " Structure Type Object
  CREATE DATA gr_structure TYPE HANDLE new_struc.
  ASSIGN gr_structure->* TO FIELD-SYMBOL(<new_structure>).
  IF <new_structure> IS ASSIGNED. 
    " Do something
  ENDIF. 
CATCH cx_sy_struct_creation. " Exception when creating a structure description
ENDTRY.

动态内表

ABAP 中的大多数动态用法都是围绕着动态表进行的。有无数的用途,特别是在动态程序中,围绕着动态表的创建。事实上,大多数框架程序在编码中都有一些动态表的概念。

与动态结构类似,有多种方法来创建动态表,但只是为了继续动态结构到动态表的创建,下面是一个如何创建动态表的好例子。

 PARAMETERS: p_tab   TYPE tabname.

  DATA: lo_structure    TYPE REF TO cl_abap_structdescr,
        lo_table        TYPE REF TO cl_abap_tabledescr,
        lr_data         TYPE REF TO data,
        lr_table_data   TYPE REF TO data.

  FIELD-SYMBOLS: <lfs_table> TYPE STANDARD TABLE.


  lo_structure ?= cl_abap_structdescr=>describe_by_name( p_name = p_tab ).
  CREATE DATA lr_data TYPE HANDLE lo_structure.

  lo_table ?= cl_abap_tabledescr=>create(
                p_line_type  = lo_structure                   " Line Type
*                p_table_kind = tablekind_std      " Table Category (STANDARD, SORTED, HASHED)
*                p_unique     = abap_false         " Uniqueness of the Key
*                p_key        =                    " Key table
*                p_key_kind   = keydefkind_default " Key category
              ).

  CREATE DATA lr_table_data TYPE HANDLE lo_table.


  ASSIGN lr_data->* TO FIELD-SYMBOL(<lfs_structure>).
  ASSIGN lr_table_data->* TO FIELD-SYMBOL(<lfs_table_data>).

  IF <lfs_table_data> IS ASSIGNED.
    " Do something
  ENDIF.

按照动态结构的例子2,我们也可以用结构来创建一个动态结构的内部表:

PARAMETERS: p_cnt   TYPE i.

TYPES: BEGIN OF ty_material_price,
         matnr    TYPE matnr,
         waers    TYPE waers,
       END   OF ty_material_price.

DATA: go_struc       TYPE REF TO cl_abap_structdescr,
      go_new_struc   TYPE REF TO cl_abap_structdescr,
      gr_structure   TYPE REF TO data,
      gr_table       TYPE REF TO data,
      go_descr       TYPE REF TO cl_abap_datadescr,
      gv_price       TYPE STPRS,
      gs_mat_price   TYPE ty_material_price.

FIELD-SYMBOLS: <new_table> TYPE STANDARD TABLE.

go_struc ?= cl_abap_structdescr=>describe_by_data( gs_mat_price ).

DATA(components)  = go_struc->get_components( ).

DO p_cnt TIMES.
  go_descr ?= cl_abap_typedescr=>describe_by_data( gv_price  ).
  APPEND INITIAL LINE TO components
    ASSIGNING FIELD-SYMBOL(<component>).
  <component> = VALUE #( name = |STPRS{ sy-index }| type = go_descr  ).
ENDDO.

TRY.
  DATA(new_struc) = cl_abap_structdescr=>create( p_components = components ).             " Structure Type Object
  CREATE DATA gr_structure TYPE HANDLE new_struc.
  ASSIGN gr_structure->* TO FIELD-SYMBOL(<new_structure>).
  IF <new_structure> IS ASSIGNED.
    " Do something
  ENDIF.

  DATA(new_table) = cl_abap_tabledescr=>create( p_line_type = new_struc  ).
  CREATE DATA gr_table TYPE HANDLE new_table.
  ASSIGN gr_table->* TO <new_table>.
  IF <new_table> IS ASSIGNED.
    " Do something
  ENDIF.

  CATCH cx_sy_table_creation. " Exception when Creating a Table Type
  CATCH cx_sy_struct_creation. " Exception when creating a structure description
ENDTRY.

访问动态结构中的动态字段

如果你不能访问结构中的字段,整个动态表就没有用。来自动态结构和表的字段在设计时是不明确的,只能在运行时生成。

也就是说,你可以使用 ASSIGN COMPONENT 命令或 ASSIGN 命令访问它们。它将尝试在运行时访问该字段或组件。两者都能达到相同的结果。

CREATE DATA gr_structure TYPE HANDLE new_struc.
    ASSIGN gr_structure->* TO FIELD-SYMBOL(<new_structure>).
    IF <new_structure> IS ASSIGNED.

      gv_field =  |STPRS{ p_cnt }|.

      "Option 1
      ASSIGN <new_structure>-(gv_field) TO FIELD-SYMBOL(<stprs2>).
      IF <stprs2> IS ASSIGNED.
        <stprs2> = 10.  
      ENDIF.

      "Option 2
      ASSIGN COMPONENT gv_field OF STRUCTURE <new_structure> TO FIELD-SYMBOL(<stprs>).
      IF <stprs> IS ASSIGNED.
        <stprs> = 20.
        " Do something

        BREAK-POINT.

      ENDIF.
      UNASSIGN <stprs>.

      " Do something
    ENDIF.
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。