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
如果内表没有表头行,需要使用工作区,将要更新内容写入。
示例:
********************************* "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
SIGN(1),
OPTION(2)
LOW LIKE
HIGH LIKE
END OF
定义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:TYPE ABAP_COMPDESCR. "cl_abap_typedescr获取工作区结构 l_descr_ref ?= cl_abap_typedescr=>describe_by_data( wa_people ). "使用指针方式 LOOP AT l_descr_ref->components ASSIGNING . WRITE:/ -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 : *TYPE table, "指定类型table *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 :TYPE table, "指定类型 TYPE ANY, "不指定类型 TYPE ANY, 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 . *创建动态工作区结构 CREATE DATA dyn_wa LIKE LINE OF . *创建动态工作区 ASSIGN dyn_wa->* TO . *从动态表中取数到动态内表中 SELECT * INTO CORRESPONDING FIELDS OF TABLE UP TO 10 ROWS FROM (p_name). *******************动态编辑数据********************************新增行 IF P_NAME = 'T001'."这里以公司代码表为例 ASSIGN COMPONENT 'BUKRS' OF STRUCTURE TO . = '9998'. append to . = + 1. append to . ENDIF. *显示内表中的数据 CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY' EXPORTING i_structure_name = p_name TABLES t_outtab = 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:TYPE STANDARD TABLE, TYPE ANY, 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 . "创建内表相应工作区 DATA:ls_newline TYPE REF TO data. CREATE DATA ls_newline LIKE LINE OF . ASSIGN ls_newline->* to . "动态添加数据 ASSIGN COMPONENT 'NAME' OF STRUCTURE to . IF sy-subrc = 0. = '张三'. ENDIF. ASSIGN COMPONENT 'AGE' OF STRUCTURE to . IF sy-subrc = 0. = 12. ENDIF. ASSIGN COMPONENT 'ADDR' OF STRUCTURE to . IF sy-subrc = 0. = '四川'. ENDIF. ASSIGN COMPONENT 'TEL' OF STRUCTURE to . IF sy-subrc = 0. = '18938893339'. ENDIF. ASSIGN COMPONENT 'REJIST_DATE' OF STRUCTURE to . IF sy-subrc = 0. = '20180902'. ENDIF. APPEND to . CLEAR . "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 = 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: 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 . 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 :TYPE ANY, "不指定类型 TYPE ANY. "创建动态工作区,分配内存 CREATE DATA dyn_wa LIKE LINE OF t_spfli. "将指针变量赋给field symbol ASSIGN dyn_wa->* TO . "填充数据 LOOP AT t_spfli INTO . ASSIGN COMPONENT 'CONNID' OF STRUCTURE TO . WRITE:/ . 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.