原文:Small Fire · ABAP 7.40 Quick Reference · ABAP 子专栏 · Small Fire 技术笔记
Inline Declarations
注意@DATA(ITAB)语句的强大,有了它,我们在访问数据库的时候,直接写SELECT就好了,不需要构建各式各样的內表和表类型了。注意在使用FOR ALL ENTRIES 语句的时候,管理的內表前面要加上@。
Data statement
// Before 7.40
DATA text TYPE string.
text = ABC.
// With 7.40
DATA(text) = ABC.
Loop at into work area
// Before 7.40
DATA wa like LINE OF itab.
LOOP AT itab INTO wa.
......
ENDLOOP.
// With 7.40
LOOP AT itab INTO DATA(wa).
......
ENDLOOP.
Call method
// Before 7.40
DATA a1 TYPE char10.
DATA a2 TYPE char10.
oref->meth( IMPORTING p1 = a1
IMPORTING p2 = a2 ).
// With 7.40
oref->meth( IMPORTING p1 = DATA(a1)
IMPORTING p2 = DATA(a2) ).
Loop at assigning
// Before 7.40
FIELD-SYMBOLS: <line> type any.
LOOP AT itab ASSIGNING <line>.
......
ENDLOOP.
// With 7.40
LOOP AT itab ASSIGNING FIELD-SYMBOL(<line>).
.......
ENDLOOP.
Read assigning
// Before 7.40
FIELD-SYMBOLS: <line> type any.
READ TABLE itab ASSIGNING <line>.
// With 7.40
READ TABLE itab ASSIGNING FIELD-SYMBOL(<line>).
Select into table
// Before 7.40
DATA itab TYPE TABLE OF dbtab.
DATA lv_fld1 TYPE char20.
SELECT * FROM dbtab INTO TABLE itab WHERE fld1 = lv_fld1.
// With 7.40
SELECT but000~partner,
but000~name_org1,
but000~bu_group,
lfa1~nodel
FROM but000 INNER JOIN lfa1 ON but000~partner = lfa1~lifnr
FOR ALL ENTRIES IN @gt_partner
WHERE but000~partner = @gt_partner-partner
INTO TABLE @DATA(lt_but).
Select single
// Before 7.40
SELECT SINGLE f1 f2 FROM scarr INTO (lv_f1, lv_f2) WHERE carrid = id.
// With 7.40
SELECT SINGLE f1 AS my_f1, F2 AS my_f2
FROM dbtab INTO DATA(ls_structure) WHERE carrid = @id.
WRITE: / ls_structure-my_f1, ls_structure-my_f2.
Table Expressions
itab [ ... ]相当于READ TABLE itab...。
如果对应没找到,会抛出 CX_SY_ITAB_LINE_NOT_FOUND 异常,系统变量 SY-SUBRC 不会记录成功与否。
可使用 line_exists(itab[…]) 。
Read table index
// Before 7.40
READ TABLE itab INDEX idx INTO wa.
// With 7.40
wa = itab[ idx ].
Read table using key
// Before 7.40
READ TABLE itab INDEX idx USING KEY key INTO wa.
// With 7.40
wa = itab[ KEY key INDEX idx ].
Read table with key
// Before 7.40
READ TABLE itab WITH KEY col1 = lv_col1 col2 = lv_col2 INTO wa.
// With 7.40
wa = itab[ col1 = lv_col1 col2 = lv_col2 ].
Read table with key components
// Before 7.40
READ TABLE itab WITH TABLE KEY key COMPONENTS col1 = lv_col1 col2 = lv_col2 INTO wa.
// With 7.40
wa = itab[ KEY key col1 = lv_col1 col2 = lv_col2 ].
Does record exist
// Before 7.40
READ TABLE itab … TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
......
ENDIF.
// With 7.40
IF line_exists( itab[ … ] ).
......
ENDIF.
Get table index
// Before 7.40
DATA idx type sy-tabix.
READ TABLE itab ... TRANSPORTING NO FIELDS.
idx = sy-tabix.
// With 7.40
DATA(idx) = line_index( itab[ ... ] ).
Conversion Operator CONV
Definition
CONV dtype|# ( … )
dtype : Type you want to convert to (explicit)
# : Compiler must use the context to decide the type to convert to (implicit)
Example
Method “cl_abap_codepage=>convert_to” expects a string.
Before 7.40
DATA text TYPE c LENGTH 255.
DATA helper TYPE string.
DATA xstr TYPE xstring.
helper = text.
xstr = cl_abap_codepage=>convert_to( source = helper ).
With 7.40
DATA text TYPE c LENGTH 255.
DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV string( text ) ).
"或则使用"
DATA(xstr) = cl_abap_codepage=>convert_to( source = CONV #( text ) ).
Value Operator Value
Definition
Variables: VALUE dtype|# ( ).
Structures: VALUE dtype|# ( [BASE dobj] compl = a1 comp2 = a2 … )
Tables: VALUE dtype|# ( [BASE itab] ( line1-com1 = dobj1 ) ( line2… ) … ) …)
Example for structures
TYPES:BEGIN OF ty_columns1, “Simple structure"
cols1 TYPE i,
cols2 TYPE i,
END OF ty_columns1.
TYPES: BEGIN OF ty_columnns2, "Nested structure"
coln1 TYPE i,
coln2 TYPE ty_columns1,
END OF ty_columns2.
DATA: struc_simple TYPE ty_columns1,
struc_nest TYPE ty_columns2.
struct_nest = VALUE t_struct(coln1 = 1
coln2-cols1 = 1
coln2-cols2 = 2 ).
"或则使用"
struct_nest = VALUE t_struct(coln1 = 1
coln2 = VALUE #( cols1 = 1 cols2 = 2 ) ).
Example for internal tables
// Elementary line type:
TYPES t_itab TYPE TABLE OF i WITH EMPTY KEY.
DATA itab TYPE t_itab.
itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ).
// 覆盖
itab = VALUE #( ( 4 ) ( 5 ) ( 6 ) ).
// 追加
itab = VALUE #( BASE itab ( 1 ) ( 2 ) ( 3 ) ).
// Structured line type (RANGES table):
DATA itab TYPE RANGE OF i.
itab = VALUE #( sign = 'I'
option = 'BT' ( low = 1 high = 10 )
( low = 21 high = 30 )
( low = 41 high = 50 )
option = 'GE' ( low = 61 ) ).
For operator
Definition
FOR wa|<fs> IN itab [INDEX INTO idx] [COND].
VALUE itab( FOR i = ... [THEN expr] UNTIL|WHERE log_ext ... )
REDUCE type (INIT FOR ... NEXT ...)
Explanation
This effectively causes a loop at itab. For each loop the row read is assigned to a work area (wa) or field-symbol(<fs>).
This wa or <fs> is local to the expression i.e. if declared in a subrourine the variable wa or <fs> is a local variable of that subroutine. Index like SY-TABIX in loop.
TYPES: BEGIN OF ty_ship,
tknum TYPE tknum, “Shipment Number
name TYPE ernam, “Name of Person who Created the Object
city TYPE ort01, “Starting city
route TYPE route, “Shipment route
END OF ty_ship.
TYPES: ty_ships TYPE SORTED TABLE OF ty_ship WITH UNIQUE KEY tknum.
TYPES: ty_citys TYPE STANDARD TABLE OF ort01 WITH EMPTY KEY.
DATA: gt_ships type ty_ships.
Example1
// Before 7.40
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.
// With 7.40
DATA(gt_citys) = VALUE ty_citys( FOR ls_ship IN gt_ships ( ls_ship-city ) ).
注意:ls_ship似乎尚未声明,但已隐式声明。
Example2
// Before 7.40
DATA: gt_citys TYPE ty_citys,
gs_ship TYPE ty_ship,
gs_city TYPE ort01.
LOOP AT gt_ships INTO gs_ship WHERE route = ‘R0001’.
gs_city = gs_ship–city.
APPEND gs_city TO gt_citys.
ENDLOOP.
// With 7.40
DATA(gt_citys) = VALUE ty_citys( FOR ls_ship IN gt_ships WHERE ( route = 'R0001' )
( ls_ship-city ) ).
FOR with THEN and UNTIL|WHILE
FOR i = … [THEN expr] UNTIL|WHILE log_exp
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.
// Before 7.40
DATA: gt_itab TYPE ty_tab,
j TYPE i.
FIELD-SYMBOLS <ls_tab> TYPE ty_line.
j = 1.
DO.
j = j + 10.
IF j > 40. EXIT. ENDIF.
APPEND INITIAL LINE TO gt_itab ASSIGNING <ls_tab>.
<ls_tab>–col1 = j.
<ls_tab>–col2 = j + 1.
<ls_tab>–col3 = j + 2.
ENDDO.
// With 7.40
DATA(gt_itab) = VALUE ty_tab( FOR j = 11 THEN j + 10 UNTIL j > 40
( col1 = j col2 = j + 1 col3 = j + 2 ) ).
Reduction operator REDUCE
Definition
REDUCE type(
INIT result = start_value
FOR for_exp1
FOR for_exp2
......
NEXT …
result = iterated_value
… )
虽然VALUE和NEW表达式可以包含FOR表达式,但REDUCE必须包含至少一个FOR表达式。您可以在REDUCE中使用各种FOR表达式
- With IN for iterating internal tables
- With UNTIL or WHILE for conditional iterations
Example1
// Before 7.40
DATA: lv_lines TYPE i.
LOOP AT gt_itab INTO ls_itab where F1 = ‘XYZ’.
lv_lines = lv_lines + 1.
ENDLOOP.
// With 7.40
DATA(lv_lines) = Reduce i( INIT x = 0 FOR wa IN gt_itab
WHERE( F1 = 'XUZ' ) NEXT x = x + 1 )
Example2
DATA gt_itab TYPE STANDARD TABLE OF i WITH EMPTY KEY.
gt_itab = VALUE #( FOR j = 1 WHILE j <= 10 ( j ) ).
// Before 7.40
DATA: lv_lines TYPE i.
LOOP AT gt_itab INTO ls_itab where F1 = ‘XYZ’.
lv_lines = lv_lines + 1.
ENDLOOP.
// With 7.40
DATA(lv_sum) = REDUCE i( INIT x = 0 FOR wa IN itab NEXT x = x + wa ).
Conditional operators COND and SWITCH
Definition
COND dtype|#( WHEN log_exp1 THEN result1
[ WHEN log_exp2 THEN result2 ]
...
[ ELSE resultn ] ) .
SWITCH dtype|#( operand WHEN const1 THEN result1
[ WHEN const2 THEN result2 ]
...
[ ELSE resultn ] ) .
Example for COND
DATA(time) = COND string(
WHEN sy-timlo < ‘120000’ THEN |{ sy-timlo TIME = ISO } AM|
WHEN sy-timlo > ‘120000’ THEN
|{ CONV t( sy-timlo – 12 * 3600 ) TIME = ISO } PM|
WHEN sy-timlo = ‘120000’ THEN |High Noon|
ELSE
THROW cx_cant_be( )
).
Example for SWITCH
DATA(text) = NEW class( )->meth(
SWITCH #( sy-langu
WHEN 'D' THEN 'DE'
WHEN 'E' THEN 'EN'
ELSE THROW cx_langu_not_supported(
)
)
).
Move Corresponding Operator
Definition
CORRESPONDING type( [BASE ( base )] struct|itab [mapping|except] )
Example Code
// With 7.40
TYPES: BEGIN OF line1,
col1 TYPE i,
col2 TYPE i,
END OF line1.
TYPES: BEGIN OF line2,
col1 TYPE i,
col2 TYPE i,
col3 TYPE i,
END OF line2.
DATA(ls_line1) = VALUE line1( col1 = 1 col2 = 2 ).
WRITE: / ‘ls_line1 =’ ,15 ls_line1–col1, ls_line1–col2.
DATA(ls_line2) = VALUE line2( col1 = 4 col2 = 5 col3 = 6 ).
WRITE: / ‘ls_line2 =’ ,15 ls_line2–col1, ls_line2–col2, ls_line2–col3.
SKIP 2.
ls_line2 = CORRESPONDING #( ls_line1 ).
WRITE: / ‘ls_line2 = CORRESPONDING #( ls_line1 )’,70 ‘Result is ls_line2 = ‘
,ls_line2–col1, ls_line2–col2, ls_line2–col3.
SKIP.
ls_line2 = VALUE line2( col1 = 4 col2 = 5 col3 = 6 ). “Restore ls_line2
ls_line2 = CORRESPONDING #( BASE ( ls_line2 ) ls_line1 ).
WRITE: / ‘ls_line2 = CORRESPONDING #( BASE ( ls_line2 ) ls_line1 )’
, 70 ‘Result is ls_line2 = ‘, ls_line2–col1, ls_line2–col2, ls_line2–col3.
SKIP.
ls_line2 = VALUE line2( col1 = 4 col2 = 5 col3 = 6 ). “Restore ls_line2
DATA(ls_line3) = CORRESPONDING line2( BASE ( ls_line2 ) ls_line1 ).
WRITE: / ‘DATA(ls_line3) = CORRESPONDING line2( BASE ( ls_line2 ) ls_line1 )’
, 70 ‘Result is ls_line3 = ‘ , ls_line3–col1, ls_line3–col2, ls_line3–col3.
Strings
String Templates
字符串模板由两个字符"|“括起来并创建一个字符串。
文字文本由不在大括号”{}“中的所有字符组成。
大括号可以包含:
- 数据对象
- 计算表达式
- 构造函数表达式
- 表表达式
- 预定义功能,或 功能方法和方法链
// Before 7.40
DATA itab TYPE TABLE OF scarr.
DATA wa LIKE LINE OF itab.
DATA output TYPE string.
SELECT * FROM scarr INTO TABLE itab.
READ TABLE itab WITH KEY carrid = ‘LH’ INTO wa.
CONCATENATE ‘Carrier:’ wa-carrname INTO output SEPARATED BY space.
cl_demo_output=>display( output ).
// With 7.40
SELECT * FROM scarr INTO TABLE @DATA(lt_scarr).
cl_demo_output=>display( |Carrier: { lt_scarr[ carrid = ‘LH’ ]–carrname }| ).
Conacatenation
// Before 7.40
DATA lv_output TYPE string.
CONCATENATE ‘Hello’ ‘world’ INTO lv_output SEPARATED BY space.
// With 7.40
DATA(lv_out) = |Hello| & | | & |world|.
Width/Alignment/Padding
// With 7.40
WRITE / |{ 'Left' WIDTH = 20 ALIGN = LEFT PAD = '0' }|.
WRITE / |{ 'Center' WIDTH = 20 ALIGN = CENTER PAD = '0' }|.
WRITE / |{ 'Right' WIDTH = 20 ALIGN = RIGHT PAD = '0' }|.
Case
WRITE / |{ ‘Text’ CASE = (cl_abap_format=>c_raw) }|.
WRITE / |{ ‘Text’ CASE = (cl_abap_format=>c_upper) }|.
WRITE / |{ ‘Text’ CASE = (cl_abap_format=>c_lower) }|.
ALPHA conversion
DATA(lv_vbeln) = ‘0000012345’.
WRITE / |{ lv_vbeln ALPHA = OUT }|.
// OR use "ALPHA = IN" to go in other direction
Date conversion
DATA(pa_date) = sy-datum.
WRITE / |{ pa_date DATE = ISO }|. “Date Format YYYY-MM-DD
WRITE / |{ pa_date DATE = User }|. “As per user settings
WRITE / |{ pa_date DATE = Environment }|. “Formatting setting of language environment
Loop at group by
Definition
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 <group>}]
...
[LOOP AT GROUP group|<group>
...
ENDLOOP.]
...
ENDLOOP.
外循环将对每个键执行一次迭代。 因此,如果 3 个记录与键匹配,则这 3 个记录将只有一个迭代。 结构“ group”不寻常,因为可以使用“LOOP AT GROUP”语句进行循环。 这将遍历该组的 3 个记录(成员)。 结构 “group” 还包含当前键以及组的大小和组的索引(如果已为 GROUP SIZE 和 GROUP INDEX 分配了字段名)。 通过示例可以最好地理解这一点。
Example
TYPES: BEGIN OF ty_employee,
name TYPE char30,
role TYPE char30,
age TYPE i,
END OF ty_employee,
ty_employee_t TYPE STANDARD TABLE OF ty_employee WITH KEY name.
DATA(gt_employee) = VALUE ty_employee_t(
( name = ‘John‘ role = ‘ABAP guru‘ age = 34 )
( name = ‘Alice‘ role = ‘FI Consultant‘ age = 42 )
( name = ‘Barry‘ role = ‘ABAP guru‘ age = 54 )
( name = ‘Mary‘ role = ‘FI Consultant‘ age = 37 )
( name = ‘Arthur‘ role = ‘ABAP guru‘ age = 34 )
( name = ‘Mandy‘ role = ‘SD Consultant‘ age = 64 ) ).
DATA: gv_tot_age TYPE i,gv_avg_age TYPE decfloat34.
“Loop with grouping on Role
LOOP AT gt_employee INTO DATA(ls_employee)
GROUP BY ( role = ls_employee-role
size = GROUP SIZE
index = GROUP INDEX )
ASCENDING ASSIGNING FIELD-SYMBOL(<group>).
CLEAR: gv_tot_age.
“Output info at group level
WRITE: / |Group: { <group>-index } Role: { <group>-role WIDTH = 15 }|
& |Number in this role: { <group>-size }|.
“Loop at members of the group
LOOP AT GROUP <group> ASSIGNING FIELD-SYMBOL(<ls_member>).
gv_tot_age = gv_tot_age + <ls_member>-age.
WRITE: /13 <ls_member>-name.
ENDLOOP.
“Average age
gv_avg_age = gv_tot_age / <group>-size.
WRITE: / |Average age: { gv_avg_age }|.
SKIP.
ENDLOOP.
Output
Group: 1 Role: ABAP guru Number in this role: 3
John
Barry
Arthur
Average age: 40.66666666666666666666666666666667
Group: 2 Role: FI Consultant Number in this role: 2
Alice
Mary
Average age: 39.5
Group: 3 Role: SD Consultant Number in this role: 1
Mandy
Average age: 64
Classes/Methods
Referencing fields within returned structures
// Before 7.40
DATA: ls_lfa1 TYPE lfa1,
lv_name1 TYPE lfa1-name1.
ls_lfa1 = my_class=>get_lfa1( ).
lv_name1 = ls_lfa1-name1.
// With 7.40
DATA(lv_name1) = my_class=>get_lfa1( )-name1.
Methods that return a type BOOLEAN
类型BOOLEAN不是真正的布尔值,而是具有允许值"X”,"-“和"blank"的char1。使用“ FLAG”或“ WDY_BOOLEAN”类型也可以。
// Before 7.40
IF my_class=>return_boolean( ) = abap_true.
...
ENDIF.
// With 7.40
IF my_class=>return_boolean( ).
...
ENDIF.
New Operator
// Before 7.40
DATA: lo_delivs TYPE REF TO zcl_sd_delivs,
lo_deliv TYPE REF TO zcl_sd_deliv.
CREATE OBJECT lo_delivs.
CREATE OBJECT lo_deliv.
lo_deliv = lo_delivs->get_deliv( lv_vbeln ).
// With 7.40
DATA(lo_deliv) = new zcl_sd_delivs->get_deliv( lv_vbeln ).
Filter
基于一个表中的记录过滤另一个表中的记录。
Definition
FILTER ptype|#( itab [EXCEPT] [IN ftab] [USING KEY keyname]
WHERE c1 op f1 [AND c2 op f2 […]] )
Solution
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.