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 <内表>
示例:
"直接定义内表,带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:t_people LIKE TABLE OF l_people.
"内表赋值
l_people-name = 'tang'.
l_people-age = 10.
APPEND l_people to t_people.
3内表赋值
内表初始化:使用refresh <内表>
内表和其他类型变量:
内表使用clear <内表>[];
clear <内表> 工作区初始化
clear <变量名>
释放内存空间:free <变量>
"初始化内表 "清空内表,不能用于其他类型变量初始化 refresh firstTab. "clear可以用于其他类型变量初始化 "如果内表有表头行,清空表头工作区。 CLEAR firstTab. "refresh功能,清空内表 CLEAR firstTab[]. "clear,refresh不会释放内存,free释放内表所占内存 FREE firstTab.
两个内表之间赋值,需要在循环中逐条赋值:
将内表表头行A赋值给B内表表头行
语法:move-corresponding <内表A表头行> to <内表B表头行>
语法:append <内表B表头行>
这个也可以用于两个工作区之间赋值
DATA:firstTab TYPE TABLE OF firstLine WITH HEADER LINE.
DATA:firstTab1 TYPE TABLE OF firstLine WITH HEADER LINE.
firstTab-id = 1.
firstTab-name = '113'.
APPEND firstTab.
firstTab-id = 2.
firstTab-name = '114'.
APPEND firstTab.
"table之间赋值,这个语句必须两个都是具有表头行内表
LOOP AT firstTab.
"这句只是将工作区值加入目标内表工作区,三种写法都可
MOVE-CORRESPONDING firstTab to firstTab1.
* firstTab1[] = firstTab[].
* MOVE firstTab[] to firstTab1[].
* firstTab1 = firstTab[]. "这种写法只有firstTab1是不带表头行的内表才有效
* MOVE firstTab to firstTab1[]."这句报错
"将工作区保存到内表
APPEND firstTab1.
ENDLOOP.
DATA:wa_line LIKE LINE OF firstTab1.
LOOP AT firstTab1 INTO wa_line.
WRITE:/ wa_line-id,wa_line-name.
ENDLOOP.
内表插入数据:
根据前面示例,可以使用append语句,标准表中使用append,hash和sorted表不能使用append,默认都是标准表。
语法:insert <工作区> into table <内表>
insert <内表名> into table <内表>,带表头行的内表,可以直接使用内表赋值插入数据。
示例:
DATA:BEGIN OF firstTab1 OCCURS 0,
id TYPE I,
name TYPE String,
age TYPE I,
addr TYPE String,
END OF firstTab1.
"insert语句
firstTab1-id = '001'.
firstTab1-name = 'li'.
firstTab1-age = 30.
firstTab1-addr = 'gudong'.
insert firstTab1 into table firstTab1.
TYPES:BEGIN OF firstTab2,
id TYPE I,
name TYPE String,
END OF firstTab2.
DATA:wa_firstTab2 LIKE LINE OF firstTab2.
DATA:t_firstTab2 LIKE TABLE OF firstTab2.
"不带表头行,使用工作区插入内表
wa_firstTab2-id = 1.
wa_firstTab2-name = 'tang'.
INSERT wa_firstTab2 INTO TABLE t_firstTab2.
"多条数据插入
data:testTab01 TYPE TABLE OF firstLine WITH HEADER LINE.
DATA:testTab02 TYPE TABLE OF firstLine WITH HEADER LINE.
testTab01-id = '001'.
testTab01-name = 'li1'.
testTab01-age = 32.
testTab01-addr = 'gudong1'.
append testTab01.
testTab01-id = '002'.
testTab01-name = 'li2'.
testTab01-age = 33.
testTab01-addr = 'gudong2'.
append testTab01.
testTab01-id = '003'.
testTab01-name = 'li2'.
testTab01-age = 33.
testTab01-addr = 'gudong2'.
append testTab01.
testTab02-id = '00223'.
testTab02-name = 'li3'.
testTab02-age = 35.
testTab02-addr = 'gudong3'.
append testTab02.
testTab02-id = '00224'.
testTab02-name = 'li3'.
testTab02-age = 35.
testTab02-addr = 'gudong3'.
append testTab02.
"将1到2条数据插入testTab2,内表行号从1开始,index指定插入位置
*INSERT LINES OF testTab01 from 1 to 2 into testTab02 INDEX 1.
"index值范围1到内表数据条数+1
INSERT LINES OF testTab01 INTO testTab02 INDEX 3.
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开始。
示例:
"带表头行直接使用内表名可以直接访问属性 LOOP AT testTable. WRITE:/ testTable-col1,testTable-col2. ENDLOOP. "不带表头行的内表,使用工作区 DATA:wa_testTable LIKE LINE OF testTable. LOOP AT testTable INTO wa_testTable. WRITE:/ wa_testTable-col1,testTable-col2. ENDLOOP. "循环出符合条件记录 loop AT testTable WHERE col2 = 39. WRITE :/ 'col1=',testTable-col1,'col2=',testTable-col2. ENDLOOP. **read读取内表数据 "查找符合条件记录 READ TABLE testTable WITH KEY col2 = 19."找到一个就结束查找 "读取对应行的记录,行号从1开始 READ TABLE testTable INDEX 3.
5删除内表记录
语法:delete table <内表> from <工作区>
删除工作区对应的那一条内表记录。删除成功sy-subrc = 0,删除失败sy-subrc = 4。
语法:delete <内表> where <列名> = <值> [and | or <列名> = <值>].
示例:
"使用工作区删除记录 DATA:wa_testTable LIKE LINE OF testTable. wa_testTable-col1 = 'a'. wa_testTable-col2 = 20. wa_testTable-col3 = 'cd'. "删除的记录每个域值必须和内表对应域值相等 DELETE TABLE testTable FROM wa_testTable. "直接条件删除记录,对应符合条件多条记录删除 DELETE testTable where col1 = 'a'. "直接条件删除记录,对应符合条件多条记录删除 DELETE testTable where col1 = 'a' AND col2 = 20 OR col2 = 39.
6修改内表记录
更新内表记录。
语法:modify <内表> transporting <列名> [列名……] where <列名> = <值> [ and | or <列名> = <值>].
语法:modefy <内表>
如果内表有表头行,直接在循环中更新内表属性值。
语法:modefy <内表> from <wa>
如果内表没有表头行,需要使用工作区,将要更新内容写入。
示例:
testTable-col1 = 'd'.
testTable-col2 = 40.
testTable-col3 = 'hello'.
"使用transporting指定修改列,where条件筛选列
modify testTable TRANSPORTING col1 col2 col3 WHERE col1 = 'a'.
"测试循环 modify
Data:BEGIN OF testTable OCCURS 0,
name TYPE String,
desc TYPE String,
END OF testTable.
testTable-name = 'tang'.
APPEND testTable.
LOOP AT testTable.
testTable-desc = sy-uname.
MODIFY testTable.
ENDLOOP.
"没有表头行操作
Data:BEGIN OF testTable,
name TYPE String,
desc TYPE String,
END OF testTable.
DATA:t_testTable LIKE TABLE OF testTable.
testTable-name = 'hello'.
APPEND testTable TO t_testTable.
testTable-name = 'hello1'.
APPEND testTable TO t_testTable.
LOOP AT t_testTable INTO testTable.
testTable-desc = sy-uname.
MODIFY t_testTable FROM testTable.
ENDLOOP.
"所有字段重新赋值
LOOP AT t_testTable INTO testTable.
testTable-strs = 'hello'.
testTable-desc = sy-uname.
testTable-name = 'tang'.
MODIFY t_testTable FROM testTable.
ENDLOOP.
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.
11内表前后内容变更比较
使用Function, CTVB_COMPARE_TABLES可以比较前后两个内表记录变更情况。
输入参数:
TABLE_OLD:传入修改之前记录内表;
TABLE_NEW: 传入修改之后记录内表;
KEY_LENGTH:关键字栏位数,前面多少栏位是关键字栏位;
IF_SORTED:是否比较内表排好序
输出参数:
NO_CHANGES:是否有改变;
TABLE_DEL:被删除记录;
TABLE_ADD:新增记录;
TABLE_MOD:被修改记录;
注意:传入table类型参数必须加[]。
示例:
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: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 = '55'.
new_tab-connid = '66'.
ENDIF.
APPEND new_tab.
ENDLOOP.
"比较两个内表
CALL FUNCTION 'CTVB_COMPARE_TABLES'
EXPORTING
TABLE_OLD = old_tab[]
TABLE_NEW = new_tab[]
KEY_LENGTH = 2
IF_SORTED = 'X'
IMPORTING
* TABLE_DEL =
* TABLE_ADD =
TABLE_MOD = chg_tab[]
NO_CHANGES = NO_CHANGES.
