ABAP学习(4):内表

ABAP内表

    ABAP内表类似于一个结构体,可以用来保存从数据库表中查出来的数据。内表只是在内存中作为操作表数据载体,在java等语言中使用对象保存一条数据库记录,对象列表保存多条记录。ABAP中使用内表保存数据库表中的一条或多条记录。

1内表定义

    方式1:

    使用types定义结构类型:定义内表行结构

  Types:begin of <结构名>,

            <变量名> type|like <类型>,

            …………

            end of <结构名>.

    定义内表:

    Data:<内表名> type ( table| sorted table | hashed table ) of <结构名>

    [with non-unique default key]

    [initial size <记录数>]

    [with header line]

示例:

*"定义linetype

TYPES: BEGIN OF firstLine,

      id(8) type C,

      name(20) type C,

      age type I,

      addr(30) type C,

      end of firstLine.

"定义内表(不指定talbe类型默认标准table,标准表只能使用  with NON-UNIQUE DEFAULT KEY
Data: firstTab TYPE TABLE OF firstLine

      with NON-UNIQUE DEFAULT KEY

      INITIAL SIZE 20

      WITH HEADER LINE

"定义sorted table  WITH UNIQUE KEY,或with non-unique default key 指定是否使用重复key field
Data: firstTab1 type SORTED TABLE OF firstLine

      INITIAL SIZE 20

      WITH HEADER LINE

      WITH NON-UNIQUE DEFAULT KEY.

"定义hash table 必须指定 WITH UNIQUE key,key field不重复
Data: firstTab2 TYPE HASHED TABLE OF firstLine

      WITH UNIQUE KEY id.

      INITIAL SIZE 20

      WITH HEADER LINE.

    方式2:

    使用data定义结构体:定义行结构

    Data:begin of <结构体名>,

            <变量名> type|like <数据类型>,

            …………

         end of <结构体名>.

  定义内表:语法类似,只是将type关键字换成like关键字

示例:

"使用data定义结构体

DATA: BEGIN OF firstLine1,

      id(8) type C,

      name(20) type C,

      age type I,

      addr(30) type C,

      end of firstLine1.

"定义内表必须使用like table of 
DATA:firstTab3 LIKE TABLE OF firstLine1.

DATA:firstTab4 LIKE SORTED TABLE OF firstLine1 WITH NON-UNIQUE DEFAULT KEY.

DATA:firstTab5 LIKE HASHED TABLE OF firstLine1 WITH UNIQUE KEY id.

 

   方式3:直接使用data定义内表

    Data:begin of <内表名> occurs <数字>,

            <变量名> type|like <数据类型>,

            …………

         end of <内表名>.

示例:

"直接定义内表,带header line

DATA:BEGIN OF t_people OCCURS 0,

    name type string,

    age type I,

    END OF t_people.

   

方式4:定义数据库表,结构体类型的内表:

    Data:<内表名> ( type | like ) [<类型>] table of  ( 数据库表名 | 结构体名 )

    [with header line]

示例:

"type:ABAP中使用types定义类型需使用type;ABAP提供的基本类型,结构体,数据库表,感觉和like区别不大

"like : 程序员定义类型,数据库表名

"根据数据库表定义内表

DATA:t_spfli LIKE TABLE OF spfli.

DATA:t_spfli1 TYPE TABLE OF spfli.

"有表头行

DATA:t_spfli2 LIKE TABLE OF spfli WITH HEADER LINE.

DATA:t_spfli3 TYPE TABLE OF spfli WITH HEADER LINE.

"可以是自己定义的数据库表,结构体,z_spfli 为自定义数据库表,结构体

DATA:t_test LIKE  TABLE OF Z_SPFLI.

DATA:t_test TYPE  TABLE OF Z_SPFLI.

2内表表头行

    根据内表是否具有表头行,我们的操作也不同。判断内表是否具有表头行我们一般判断定义内表时,是否有with header line 关键词,occurs定义的内表,具有表头行。

    带表头行内表插入操作:直接使用append <内表>语句插入

    不带表头行内表插入操作:需要先定义一个结构体类型的工作区,然后将工作区赋值,通过append <工作区数据> to <内表>

   内表初始化:使用refresh <内表>

   内表和其他类型变量:

   内表使用clear <内表>[];

   clear <内表> 工作区初始化

   clear <变量名>

   释放内存空间:free <变量>

示例:

"内表初始化赋值
FORM f_itab1.
  "带表头行赋值
  "直接定义内表,带header line
  DATA:BEGIN OF t_people OCCURS 0,
      name type string,
      age type I,
      END OF t_people.
  "带headline的内表赋值
  t_people-name = 'tang'.
  t_people-age  = 11.
  "添加记录到t_people
  APPEND t_people.

  "没有表头行内表赋值
  DATA:BEGIN OF l_people,
      name TYPE string,
      age TYPE I,
       END OF l_people.
  "如果上面是使用types定义type,还需要定义一个工作区
*  DATA:wa_people LIKE LINE OF l_people.
  DATA:lt_people LIKE TABLE OF l_people.
  "内表赋值
  l_people-name = 'tang'.
  l_people-age = 10.
  APPEND l_people to t_people.

  "初始化内表
  "清空内表,不能用于其他类型变量初始化
  refresh t_people.
  "clear可以用于其他类型变量初始化
  "如果内表有表头行,仅清空表头工作区。
  CLEAR t_people.
  "refresh功能,清空内表
  CLEAR t_people[].
  "clear,refresh不会释放内存,free释放内表所占内存
  FREE t_people.
ENDFORM.

3内表赋值

两个内表之间赋值,需要在循环中逐条赋值:

将内表表头行A赋值给B内表表头行

语法:move-corresponding <内表A表头行> to <内表B表头行>

语法:append <内表B表头行>

这个也可以用于两个工作区之间赋值

"****内表之间直接赋值
FORM f_itab2.
  "不带表头行
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:lt_spfli_1 TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  "带表头行
  DATA:lt_spfli_head TYPE TABLE OF spfli WITH HEADER LINE.
  DATA:lt_spfli_head1 TYPE TABLE OF spfli WITH HEADER LINE.
  SELECT * FROM spfli INTO TABLE lt_spfli.

  "循环赋值
  "不带表头和带表头内表可以互相赋值
  LOOP AT lt_spfli INTO ls_spfli.
    "方式1:
*    MOVE-CORRESPONDING ls_spfli TO lt_spfli_head.
*    APPEND lt_spfli_head.
    "方式2:
    APPEND ls_spfli TO lt_spfli_head.
  ENDLOOP.
  LOOP AT lt_spfli_head WHERE carrid = 'AZ'.
    WRITE:/ '0',lt_spfli_head-carrid.
  ENDLOOP.

  "直接赋值
  CLEAR lt_spfli_head[].
  "不带表头赋值给带表头内表,不能赋值
  "lt_spfli_head = lt_spfli. "报错
  "lt_spfli_head = lt_spfli[]. "报错
  "带表头行内表直接赋值
  "lt_spfli_head1 = lt_spfli_head. "赋值失败
  "lt_spfli_head1[] = lt_spfli_head[]. "赋值失败
  "将带表头行的内表赋值给不带表头内表
  "lt_spfli = lt_spfli_head[]. "赋值失败

  "不带表头行内表互相赋值
  "方式1:
  lt_spfli_1 = lt_spfli.
  "方式2:
  MOVE lt_spfli TO lt_spfli_1.
ENDFORM.

内表插入数据:

    根据前面示例,可以使用append语句,标准表中使用append,hash和sorted表不能使用append,默认都是标准表。

    语法:insert <工作区> into table <内表>

    insert <内表名> into table <内表>,带表头行的内表,可以直接使用内表赋值插入数据。

示例:

"*******************************************内表中添加数据
FORM f_itab_add.
  "append语句
  "hash和sorted表不能使用append
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  DATA:lt_spfli_head TYPE TABLE OF spfli WITH HEADER LINE.

  lt_spfli_head-carrid = 'ZZ'.
  "带表头行可以直接append
  "APPEND lt_spfli_head.
  "APPEND lt_spfli_head TO lt_spfli_head.
  "使用insert
  INSERT lt_spfli_head INTO TABLE lt_spfli_head.
  LOOP AT lt_spfli_head.
    WRITE:/ lt_spfli_head-carrid.
  ENDLOOP.

  "不带表头行,使用工作区插入内表
  ls_spfli-carrid = 'ZT'.
  INSERT ls_spfli INTO TABLE lt_spfli.
  "APPEND ls_spfli TO lt_spfli.

  "多条数据插入
  DATA:lt_itab3 TYPE TABLE OF spfli.
  DATA:lt_itab4 TYPE TABLE OF spfli.
  SELECT * FROM spfli INTO TABLE lt_itab3.
  "将1到2条数据插入testTab2,内表行号从1开始,index指定插入位置
*  INSERT LINES OF lt_itab3 from 1 to 2 into lt_itab4 INDEX 1.
  "index值范围1到内表数据条数+1
  INSERT LINES OF lt_itab3 INTO lt_itab4 INDEX 3.
ENDFORM

Collect语句

    语法:collect <内表名>,这是带表头行的内表。内表名代表表头行。

    语法:collect <工作区> into <内表>,不带表头行的内表操作

示例:

"Collect语句

"collect也是将元素加入内表,但是他会将非数字字符相同的行合并,并且数字列相加。

Data:BEGIN OF testTable OCCURS 20,

      col2 type I,

      col1(20) type C,

    END OF testTable.

 

testTable-col1 = 'a'.

testTable-col2 = 20.

COLLECT testTable.

 

testTable-col1 = 'b'.

testTable-col2 = 39.

COLLECT testTable.

 

testTable-col1 = 'a'.

testTable-col2 = 19.

COLLECT testTable.

 

"不带表头行的内表,collect操作

Data:BEGIN OF wa_testTable,

      col2 type I,

      col1(20) type C,

    END OF wa_testTable.

DATA:testTable1  LIKE TABLE OF wa_testTable.

 

wa_testTable-col2 = 1.

wa_testTable-col1 = 'he'.

COLLECT wa_testTable INTO testTable1.

 

wa_testTable-col2 = 12.

wa_testTable-col1 = 'he'.

COLLECT wa_testTable INTO testTable1.

 

wa_testTable-col2 = 1.

wa_testTable-col1 = 'ha'.

COLLECT wa_testTable INTO testTable1.

 

LOOP AT testTable1 INTO wa_testTable.

  WRITE:/ wa_testTable-col2,wa_testTable-col1.

ENDLOOP.

4内表循环遍历

    一般内表数据访问需要循环内表。

    语法:loop at <内表> [into wa].

            <访问内表属性>

          endloop.

    没有表头行的内表需要使用into,将内表循环到工作区,通过工作区访问对应属性。

    读取内表符合条件的记录

    语法:read table <内表> with key <列名>=<值>

          read table <内表> index <数字>

    查找符合条件的记录,只查找一条。Index是内部记录对应行,行号从1开始。

示例:

**********************************
"read读取内表数据
**********************************
FORM f_itab_read.
  "带表头行内表
  DATA:lt_spfli_head TYPE TABLE OF spfli WITH HEADER LINE.
  "不带表头行内表
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  SELECT * FROM spfli INTO TABLE lt_spfli_head.
  lt_spfli = lt_spfli_head[].
  READ TABLE lt_spfli_head WITH KEY carrid = 'AA'."找到一个就结束查找
  WRITE:/ lt_spfli_head-carrid.
  "读取对应行的记录,行号从1开始
  READ TABLE lt_spfli_head INDEX 3.
  WRITE:/ lt_spfli_head-carrid.

  "不带表头行
  READ TABLE lt_spfli INTO ls_spfli WITH KEY carrid = 'AA'."找到一个就结束查找
  WRITE:/ ls_spfli-carrid.
  READ TABLE lt_spfli INTO ls_spfli INDEX 4.
  WRITE:/ ls_spfli-carrid.
ENDFORM.

5删除内表记录

    语法:delete table <内表> from <工作区>

    删除工作区对应的那一条内表记录。删除成功sy-subrc = 0,删除失败sy-subrc = 4。

    语法:delete <内表> where <列名> = <值> [and | or <列名> = <值>].

示例:

FORM f_itab_delete.
  "使用工作区删除记录
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  SELECT * FROM spfli INTO TABLE lt_spfli.
  "使用工作区
  ls_spfli-carrid = 'AA'.
  "删除的记录每个字段值必须和内表对应字段值相等
  DELETE TABLE lt_spfli FROM ls_spfli.

  "直接条件删除记录,对应符合条件多条记录删除
  DELETE lt_spfli where carrid = 'AA'.
  "loop循环删除记录
  LOOP AT lt_spfli INTO ls_spfli.
    IF ls_spfli-carrid = 'AZ'.
      DELETE lt_spfli.
    ENDIF.
  ENDLOOP.
  LOOP AT lt_spfli INTO ls_spfli.
    WRITE:/ ls_spfli-carrid.
  ENDLOOP.

  "排序,默认所有字段升序
  SORT lt_spfli.
  "根据指定字段排序
  SORT lt_spfli BY carrid ASCENDING connid DESCENDING.
  "删除所有栏位都相同的记录
  DELETE ADJACENT DUPLICATES FROM lt_spfli.
  "删除所有栏位都相同的记录
  DELETE ADJACENT DUPLICATES FROM lt_spfli COMPARING ALL FIELDS.
ENDFORM

6修改内表记录

    更新内表记录。

    语法:modify <内表> transporting  <列名> [列名……] where <列名> = <值> [ and | or <列名> = <值>].

    语法:modefy <内表>

    如果内表有表头行,直接在循环中更新内表属性值。

    语法:modefy <内表> from <wa>

    如果内表没有表头行,需要使用工作区,将要更新内容写入。

示例:

*********************************
"modify修改内表数据
*********************************
FORM f_itab_modify.
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  SELECT * FROM spfli INTO TABLE lt_spfli.
  ls_spfli-carrid = 'ZA'.
  ls_spfli-connid = '0017'.
  "使用transporting指定修改列,where条件筛选列
  MODIFY lt_spfli FROM ls_spfli TRANSPORTING carrid connid WHERE carrid = 'ZA' .

  "循环中更新记录modify
  LOOP AT lt_spfli INTO ls_spfli.
    clear ls_spfli.
    ls_spfli-cityfrom = 'GG'.
    MODIFY lt_spfli FROM ls_spfli TRANSPORTING cityfrom.
  ENDLOOP.

  LOOP AT lt_spfli INTO ls_spfli.
    WRITE:/ ls_spfli-carrid,ls_spfli-cityfrom.
  ENDLOOP.
ENDFORM

7Range Table

ABAP的Range Table:

    Range Table相当于一个内表,由 sign,option,low,high四个字段组成。

seltab结构:

DATA: BEGIN OF <seltab>,

         SIGN(1),

         OPTION(2)

         LOW  LIKE <f>,

         HIGH LIKE <f>,

      END OF <seltab>.

定义Range Table:

    语法:<变量名> ( type|like ) range of <数据类型>

      [INITIAL SIZE n]

      [WITH HEADER LINE]

      [VALUE IS INITIAL]

      [READ-ONLY].

    语法:ranges: <变量名> for <数据类型>

      [OCCURS n].

Sign取值:

‘I’表示在区间内;

‘E’表示在区间外;

Option取值:

‘EQ’:等于,单值;

‘NE’:不等于,单值;

‘GT’:大于,单值;

‘LT’:小于,单值;

‘GE’:大于等于,单值;

‘LE’:小于等于,单值;

‘CP’: 包含,当字符串使用了*和+字符,*代替字符串,+代替单个字符;

‘NP’:不包含

‘BT’:位于,high有值,在范围中;

‘NB’:不位于,hight有值,不在范围中;

示例:

"定义一个range类型

DATA:t_range LIKE RANGE OF spfli-carrid WITH HEADER LINE.

"定义range类型

RANGES: t_range1 FOR spfli-carrid OCCURS 0.

 

设置值Range Table:

示例:

* 宏定义

DEFINE set_range.

  wa_range-sign   = 'I'.

  wa_range-option = 'EQ'.

  wa_range-low    = &1.

  append wa_range to t_range.

END-OF-DEFINITION.

 

set_range 'DL'.

8内表记录排序

使用Sort关键字,将内表记录进行排序。

语法:SORT <内表名> BY <栏位> [ASCENDING|DESCENDING]

[<栏位> [ASCENDING|DESCENDING]…………].

示例:

"内表定义

DATA:test_spfli LIKE TABLE OF spfli WITH HEADER LINE.

"查询数据

SELECT * FROM spfli INTO CORRESPONDING FIELDS OF TABLE test_spfli.

 

"排序,指定按照connid升序

SORT test_spfli BY connid ASCENDING.

"排序,指定按照某栏位升序,某栏位降序,从左到右依次匹配

SORT test_spfli BY connid ASCENDING FLTIME DESCENDING.

9内表去除重复记录

一般将内表记录进行排序,然后按照指定栏位去除重复记录,不指定栏位那么就是比较全部栏位相同的去掉重复内容。

示例:

"删除所有栏位都相同的记录

*DELETE ADJACENT DUPLICATES FROM test_spfli.

"删除所有栏位都相同的记录

*DELETE ADJACENT DUPLICATES FROM test_spfli COMPARING ALL FIELDS.

"去重指定栏位相同记录

DELETE ADJACENT DUPLICATES FROM test_spfli COMPARING connid .

"去重指定栏位相同的记录,只保留一笔比较栏位相同的记录

DELETE ADJACENT DUPLICATES FROM test_spfli COMPARING carrid connid .

10动态内表

    创建动态内表,我们需要在程序执行过程中获取内表或结构体的字段属性。

类CL_ABAP_TYPEDESCR和它的子类的结构图:

CL_ABAP_TYPEDESCR

  |--CL_ABAP_DATADESCR

  |     |--CL_ABAP_ELEMDESCR

  |     |--CL_ABAP_REFDESCR

  |     |--CL_ABAP_COMPLEXDESCR

  |         |

  |         |--CL_ABAP_STRUCTDESCR

  |         |--CL_ABAP_TABLEDESCR

  |--CL_ABAP_OBJECTDESCR

        |--CL_ABAP_CLASSDESCR

        |--CL_ABAP_INTFDESCR

通过CL_ABAP_TABLEDESCR类可以获取到内表的结构字段,

通过CL_ABAP_TYPEDESCR类可以获取结构体工作区结构字段,

通过CL_ABAP_STRUCTDESCR类可以保存获取的结构字段。

示例1

获取程序定义中内表字段结构

FORM get_struct.
  "sflight内表
  DATA:t_sflight like sflight OCCURS 0 .
  "cl_abap_tabledescr类获取内表结构
  DATA:l_tabledescr_ref TYPE REF TO cl_abap_tabledescr,
       l_descr_ref      TYPE REF TO cl_abap_structdescr.
  "字段结构
  DATA:wa_struct TYPE ABAP_COMPDESCR.
  "cl_abap_typedescr程序运行的时候取得某个内表或者某个结构它的属性或者它的字段的属性
  "获取sflight内表结构
  l_tabledescr_ref ?= cl_abap_typedescr=>describe_by_data( t_sflight ).
  "cl_abap_tabledescr获取表头结构
  l_descr_ref ?= l_tabledescr_ref->get_table_line_type( ).
  LOOP AT l_descr_ref->components INTO wa_struct .
    WRITE:/ wa_struct-name .
  ENDLOOP.

   "people结构
  TYPES:BEGIN OF s_people,
        name TYPE String,
        age TYPE I,
        addr TYPE String,
        END OF s_people.
  "people类型工作区
  DATA:wa_people TYPE s_people.
  FIELD-SYMBOLS:<wa_struct> TYPE ABAP_COMPDESCR.
  "cl_abap_typedescr获取工作区结构
  l_descr_ref  ?=  cl_abap_typedescr=>describe_by_data( wa_people ).
  "使用指针方式
  LOOP AT l_descr_ref->components ASSIGNING <wa_struct> .
    WRITE:/ <wa_struct>-name .
  ENDLOOP.
ENDFORM.

示例2

根据数据库表,获取对应动态内表结构,创建动态内表

PARAMETERS p_name TYPE tabname.  "数据库表名
"*************************************************
"TYPE REF TO 和 Field Symbol 都可以指定指针类型
"      定义
"       Type Ref To 有两种初始化的方法:
"          第一种是用 CREATE DATA 动态开辟内存;
"          第二种是用 GET REFERENCE OF 指向已经存在的内存变量.
"      Field Symbol 的初始化,则只能指向已经存在的内存变量。
*        CREATE DATA ref TYPE ty_ym.        "指定类型
*        CREATE DATA ref LIKE LINE OFit_ym.  "指定结构,like line
*        CREATE DATA ref LIKE wa_ym.
*        CREATE DATA ref LIKE ym.
*        GET REFERENCE OF wa_ym INTO ref. "TypeRef To的初始化,效果相当于指向 wa_ym
*        GET REFERENCE OF v_ym INTO ref.  "Type Ref To的初始化,效果相当于指向 v_ym
*

*       "定义指针类型
*       FIELD-SYMBOLS :
*         <dyn_table> TYPE table,  "指定类型table
*         <dyn_wa> TYPE ANY,       "不指定类型
*       Field Symbol初始化
*       ASSIGN wa_ym TO < fs >."Field Symbol的初始化,效果相当于指向wa_ym
*       ASSIGN v_ym TO < fs >.  "Field Symbol的初始化,效果相当于指向v_ym

"*****************************************************

DATA: d_ref TYPE REF TO data,    "不指定特定类型和结构, 保存表字段结构
lt_alv_cat TYPE TABLE OF lvc_s_fcat,
ls_alv_cat LIKE LINE OF lt_alv_cat.

DATA: lt_table LIKE TABLE OF dntab.  "获取表的natab,表的结构表
DATA: ls_table TYPE dntab.

DATA: dyn_table TYPE REF TO data.
DATA: dyn_wa TYPE REF TO data.

"定义指针类型
FIELD-SYMBOLS :
  <dyn_table> TYPE table,  "指定类型
  <dyn_wa> TYPE ANY,       "不指定类型
  <dyn_field> TYPE ANY,
  <fs_str> TYPE ANY.

*取出表结构的字段目录
CALL FUNCTION 'NAMETAB_GET'
     EXPORTING
          langu          = sy-langu
          tabname        = p_name
     TABLES
          nametab        = lt_table
     EXCEPTIONS
          no_texts_found = 1.

*根据取出的字段目录生成参考字段目录
LOOP AT lt_table INTO ls_table.
  ls_alv_cat-fieldname = ls_table-fieldname.
  ls_alv_cat-ref_table = p_name.
  ls_alv_cat-ref_field = ls_table-fieldname.
  APPEND ls_alv_cat TO lt_alv_cat.
  CLEAR ls_alv_cat.
ENDLOOP.

*动态内表创建
CALL METHOD cl_alv_table_create=>create_dynamic_table
  EXPORTING
    it_fieldcatalog = lt_alv_cat
  IMPORTING
    ep_table = d_ref.   "生成内表

*指定生成的内表到指针
ASSIGN d_ref->* TO <dyn_table>.
*创建动态工作区结构
CREATE DATA dyn_wa LIKE LINE OF <dyn_table>.
*创建动态工作区
ASSIGN dyn_wa->* TO <dyn_wa>.

*从动态表中取数到动态内表中
SELECT * INTO CORRESPONDING FIELDS OF TABLE <dyn_table> UP TO 10 ROWS FROM (p_name).

*******************动态编辑数据********************************新增行
  IF P_NAME = 'T001'."这里以公司代码表为例
    ASSIGN COMPONENT 'BUKRS' OF STRUCTURE <dyn_wa> TO <fs_str>.
    <fs_str> = '9998'.
    append <dyn_wa> to <dyn_table>.
    <fs_str> = <fs_str> + 1.
    append <dyn_wa> to <dyn_table>.
  ENDIF.

*显示内表中的数据
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
     EXPORTING
          i_structure_name = p_name
     TABLES
          t_outtab         = <dyn_table>
     EXCEPTIONS
          program_error    = 1
          OTHERS           = 2.

IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
  WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

示例3

完全自定义创建动态内表,自己自定义内表数据类型,栏位名

"create dynamic table with any fields
DATA:lt_comp TYPE cl_abap_structdescr=>component_table.
DATA:ls_comp LIKE LINE OF lt_comp.
DATA:new_type TYPE REF TO cl_abap_structdescr.
DATA:new_table TYPE REF TO cl_abap_tabledescr.
DATA:t_data TYPE REF TO data.
"alv fieldcat
DATA:lt_fieldcat TYPE SLIS_T_FIELDCAT_ALV.
DATA:ls_fieldcat LIKE LINE OF lt_fieldcat.
DATA:col_pos TYPE I.

FIELD-SYMBOLS:
         <lt_dyntable> TYPE STANDARD TABLE,
         <ls_newline> TYPE ANY,
         <filed> TYPE ANY.

define d_filed_add.
" Field name
  ls_comp-name = &1.

**   Element Description
*        lo_element ?= cl_abap_elemdescr=>describe_by_name( &2 ).

*   Field type
  case &2.
    when 'P'."包装类型

      ls_comp-type = cl_abap_elemdescr=>get_p(
                        p_length   = &3
                        p_decimals = &4 ).
    when 'C'."字符型

      ls_comp-type = cl_abap_elemdescr=>get_c(
                        p_length   = &3 ).
    when 'I'."整型 4字节

      ls_comp-type = cl_abap_elemdescr=>get_i( ).

    when 'D'."日期类型,8个字符

      ls_comp-type = cl_abap_elemdescr=>get_d( ).

    when 'T'."时间类型,6个字符

      ls_comp-type = cl_abap_elemdescr=>get_t( ).

    when 'N'."数字字符串

      ls_comp-type = cl_abap_elemdescr=>get_n(
                        p_length   = &3 ).

    when 'S'.  "String类型

      ls_comp-type = cl_abap_elemdescr=>get_string( ).

  endcase.

  append ls_comp to lt_comp.
  clear: ls_comp.
end-OF-DEFINITION.

DEFINE d_fieldcat.
  clear ls_fieldcat.
  add 1 to col_pos.
  clear ls_fieldcat.
  ls_fieldcat-col_pos      = col_pos.        "column position
  ls_fieldcat-fieldname    = &1.             "显示的字段
  ls_fieldcat-reptext_ddic = &2.             "显示栏目名

  append ls_fieldcat to lt_fieldcat.
END-OF-DEFINITION.

"creat dynamic table with any fields
"初始化表
CLEAR lt_comp[].
"构建内表字段结构
d_filed_add 'NAME' 'C' 10 space.
d_filed_add 'AGE' 'I' space space.
d_filed_add 'ADDR' 'S' space space.
d_filed_add 'TEL' 'C' 15 space.
d_filed_add 'REJIST_DATE' 'D' space space.

"根据结构创建Type
new_type = cl_abap_structdescr=>create( lt_comp ).

"根据Type创建table type
new_table = cl_abap_tabledescr=>create(
                  p_line_type  = new_type
                  p_table_kind = cl_abap_tabledescr=>tablekind_std
                  p_unique     = abap_false ).

"根据table type 创建内表
CREATE DATA t_data TYPE HANDLE new_table.
"将内表赋给指针
ASSIGN t_data->* to <lt_dyntable>.

"创建内表相应工作区
DATA:ls_newline TYPE REF TO data.
CREATE DATA ls_newline LIKE LINE OF <lt_dyntable>.
ASSIGN ls_newline->* to <ls_newline>.

"动态添加数据
ASSIGN COMPONENT 'NAME' OF STRUCTURE <ls_newline> to <filed>.
IF sy-subrc = 0.
  <filed> = '张三'.
ENDIF.

ASSIGN COMPONENT 'AGE' OF STRUCTURE <ls_newline> to <filed>.
IF sy-subrc = 0.
  <filed> = 12.
ENDIF.

ASSIGN COMPONENT 'ADDR' OF STRUCTURE <ls_newline> to <filed>.
IF sy-subrc = 0.
  <filed> = '四川'.
ENDIF.


ASSIGN COMPONENT 'TEL' OF STRUCTURE <ls_newline> to <filed>.
IF sy-subrc = 0.
  <filed> = '18938893339'.
ENDIF.

ASSIGN COMPONENT 'REJIST_DATE' OF STRUCTURE <ls_newline> to <filed>.
IF sy-subrc = 0.
  <filed> = '20180902'.
ENDIF.

APPEND <ls_newline> to <lt_dyntable>.
CLEAR <ls_newline>.

"alv 字段
d_fieldcat 'NAME' '姓名'.
d_fieldcat 'AGE' '年龄'.
d_fieldcat 'ADDR' '地址'.
d_fieldcat 'TEL' '电话'.
d_fieldcat 'REJIST_DATE' '注册时间' .

*显示内表中的数据
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
     EXPORTING
          it_fieldcat      = lt_fieldcat[]
     TABLES
          t_outtab         = <lt_dyntable>
     EXCEPTIONS
          program_error    = 1
          OTHERS           = 2.

IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
  WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.


"动态创建结构 create dynamic structure
form create_dynamic_structure.
"创建动态structure
DATA:lt_comp1 TYPE cl_abap_structdescr=>component_table.
DATA:lwa_comp1 TYPE abap_componentdescr.
DATA:lo_strucdesc TYPE REF TO cl_abap_structdescr.
DATA:lo_struc TYPE REF TO data.
FIELD-SYMBOLS: <fs_struc> TYPE ANY.

CLEAR lt_comp1[].
lwa_comp1-name = 'NAME'.
lwa_comp1-type = cl_abap_elemdescr=>get_c( 10 ).
APPEND lwa_comp1 to lt_comp1.
CLEAR lwa_comp1.

lwa_comp1-name = 'AGE'.
lwa_comp1-type = cl_abap_elemdescr=>get_i( ).
APPEND lwa_comp1 to lt_comp1.
clear lwa_comp1.

"创建动态结构
 lo_strucdesc  = CL_ABAP_STRUCTDESCR=>create( P_COMPONENTS = lt_comp1 ).
 CREATE DATA lo_struc TYPE HANDLE lo_strucdesc.
 ASSIGN lo_struc->* to <fs_struc>.

ENDFORM.

示例4

FORM method3.
  DATA:t_spfli LIKE TABLE OF spfli WITH HEADER LINE.
  SELECT * INTO CORRESPONDING FIELDS OF TABLE t_spfli FROM spfli WHERE CARRID = 'AA'.

  LOOP AT t_spfli.
    WRITE:/ t_spfli-carrid,t_spfli-connid,t_spfli-countryfr,t_spfli-cityfrom.
  ENDLOOP.

  "指针变量
  DATA: dyn_wa TYPE REF TO data.
  "定义指针类型
  FIELD-SYMBOLS :
  <dyn_wa> TYPE ANY,       "不指定类型
  <dyn_field> TYPE ANY.

  "创建动态工作区,分配内存
  CREATE DATA dyn_wa LIKE LINE OF t_spfli.
  "将指针变量赋给field symbol
  ASSIGN dyn_wa->* TO <dyn_wa>.
  "填充数据
  LOOP AT t_spfli INTO <dyn_wa>.
     ASSIGN COMPONENT 'CONNID' OF STRUCTURE <dyn_wa> TO <dyn_field>.
     WRITE:/ <dyn_field>.
  ENDLOOP.
ENDFORM.

11内表前后内容变更比较

    使用Function, CTVB_COMPARE_TABLES可以比较前后两个内表记录变更情况。

输入参数:

    TABLE_OLD:传入修改之前记录内表;

    TABLE_NEW: 传入修改之后记录内表;

    KEY_LENGTH:关键字栏位数,前面多少栏位是关键字栏位;

    IF_SORTED:是否比较内表排好序

输出参数:

    NO_CHANGES:是否有改变;

    TABLE_DEL:被删除记录;

    TABLE_ADD:新增记录;

    TABLE_MOD:被修改记录;

注意:传入table类型参数必须加[]。

示例:

"比较两个内表记录差异
FORM f_itab_dis.
  DATA:old_tab LIKE TABLE OF spfli WITH HEADER LINE.
  DATA:new_tab LIKE TABLE OF spfli WITH HEADER LINE.
  DATA:chg_tab LIKE TABLE OF spfli WITH HEADER LINE.
  DATA:add_tab LIKE TABLE OF spfli WITH HEADER LINE.
  DATA:del_tab LIKE TABLE OF spfli WITH HEADER LINE.
  DATA:NO_CHANGES TYPE  FLAG.
  SELECT * INTO CORRESPONDING FIELDS OF TABLE old_tab FROM spfli WHERE CARRID = 'AA'.

  LOOP AT old_tab.
    MOVE-CORRESPONDING old_tab to new_tab.
    IF old_tab-connid = '17'.
      new_tab-connid = '18'.
    ENDIF.
    APPEND new_tab.
  ENDLOOP.

  DELETE old_tab WHERE carrid = 'AA' AND connid = '0300'.

  new_tab-carrid = 'BB'.
  new_tab-connid = '33'.
  APPEND new_tab.

  "比较两个内表
  CALL FUNCTION 'CTVB_COMPARE_TABLES'
    EXPORTING
      TABLE_OLD        = old_tab[]
      TABLE_NEW        = new_tab[]
      KEY_LENGTH       = 2
      IF_SORTED        = 'X'
    IMPORTING
      TABLE_DEL        = del_tab[]
      TABLE_ADD        = add_tab[]
      TABLE_MOD        = chg_tab[]
      NO_CHANGES       = NO_CHANGES.
  IF NO_CHANGES = 'X'.
    WRITE:/ 'no change'.
  ELSE.
    WRITE:/ 'some change'.
    LOOP AT old_tab.
      WRITE:/ 'old',old_tab-carrid,old_tab-connid,old_tab-countryfr.
    ENDLOOP.

    LOOP AT new_tab.
      WRITE:/ 'new',new_tab-carrid,new_tab-connid,new_tab-countryfr.
    ENDLOOP.

    LOOP AT chg_tab.
      WRITE:/ '改变',chg_tab-carrid,chg_tab-connid,chg_tab-countryfr.
    ENDLOOP.

    LOOP AT add_tab.
      WRITE:/ '增加',add_tab-carrid,add_tab-connid,add_tab-countryfr.
    ENDLOOP.

    LOOP AT del_tab.
      WRITE:/ '减少',del_tab-carrid,del_tab-connid,del_tab-countryfr.
    ENDLOOP.
  ENDIF.
ENDFORM.

12内表相关系统变量

示例:

"测试sy-index sy-tabix
FORM f_itab_sys.
"sy-index 和sy-tabix记录内表循环次数
  "不带表头行的内表
  DATA:lt_spfli LIKE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF  lt_spfli.
  "创建带表头行的内表
  DATA:lt_spfli_head LIKE TABLE OF spfli WITH HEADER LINE.
  DATA:lv_lines TYPE I.

  SELECT * FROM spfli INTO TABLE lt_spfli_head.
  lt_spfli = lt_spfli_head[].
  "sy-index只在do循环中有效
  DO 2 TIMES.
    WRITE:/ sy-index,sy-tabix.
  ENDDO.
  "sy-tabix只在loop循环中有效
  LOOP AT lt_spfli INTO ls_spfli.
    WRITE:/ sy-index,sy-tabix.
  ENDLOOP.

  "返回当前处理内表记录数
  WRITE:/ sy-tfill.
  "sy-dbcnt记录查询到的记录数
  WRITE:/ sy-dbcnt.

  "返回当前内表记录数
  DESCRIBE TABLE lt_spfli LINES lv_lines.
  lv_lines = lines( lt_spfli ).
  WRITE:/ lv_lines.
ENDFORM.

 

"****内表之间直接赋值
FORM f_itab2.
  "不带表头行
  DATA:lt_spfli TYPE TABLE OF spfli.
  DATA:lt_spfli_1 TYPE TABLE OF spfli.
  DATA:ls_spfli LIKE LINE OF lt_spfli.
  "带表头行
  DATA:lt_spfli_head TYPE TABLE OF spfli WITH HEADER LINE.
  DATA:lt_spfli_head1 TYPE TABLE OF spfli WITH HEADER LINE.
  SELECT FROM spfli INTO TABLE lt_spfli.

  "循环赋值
  "不带表头和带表头内表可以互相赋值
  LOOP AT lt_spfli INTO ls_spfli.
    "方式1
*    MOVE-CORRESPONDING ls_spfli TO lt_spfli_head.
*    APPEND lt_spfli_head.
    "方式2
    APPEND ls_spfli TO lt_spfli_head.
  ENDLOOP.
  LOOP AT lt_spfli_head WHERE carrid 'AZ'.
    WRITE:'0',lt_spfli_head-carrid.
  ENDLOOP.

  "直接赋值
  CLEAR lt_spfli_head[].
  "不带表头赋值给带表头内表,不能赋值
  "lt_spfli_head = lt_spfli. "报错
  "lt_spfli_head = lt_spfli[]. "报错
  "带表头行内表直接赋值
  "lt_spfli_head1 = lt_spfli_head. "赋值失败
  "lt_spfli_head1[] = lt_spfli_head[]. "赋值失败
  "将带表头行的内表赋值给不带表头内表
  "lt_spfli = lt_spfli_head[]. "赋值失败

  "不带表头行内表互相赋值
  "方式1
  lt_spfli_1 lt_spfli.
  "方式2
  MOVE lt_spfli TO lt_spfli_1.
ENDFORM.

原文地址:https://www.cnblogs.com/tangToms/p/11794091.html