雅思考试模拟题:SAP ABAP语言编程手册2
来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 13:18:46
第一章程序调试
编译任何程序最基本的技能就是对程序的调试(debugging). 所以让我们先熟悉一下SAP ABAP程序的调试手段。
如何调试ABAP程序?
在这本书中,我假设你使用的是ABAP编辑器(事务代码 SE38)开发ABAP程序。 但是,如果你使用的是Object Navigator (事务代码 SE80)做开发工作,过程也是相同的。
在ABAP编辑器屏幕,采取以下步骤设置你的调试断点:
选择你要开始调试的代码行。
按“Session断点“钮。
如果要删除断点, 只要双电击程序行上的Session断点图标(icone)即可删除断点。
提示:
如果你的SAP版本较老,点击断点图标后,会有一个画面弹出, 让你选择是“Session断点“还是”External断点“。
如果你要管理程序里设置的所有断点, 你可以去菜单:实用程序 (Utilities)> 断点。
如何调试Web应用程序?
如果你需要调试一个Web应用程序,设置断点的步骤和你设置ABAP程序断点完全相同,只是你设置的不是Session断点,而是外部断点(External Breakpoint)。
假设你在ABAP编辑器里编辑Web应用程序, 请按照下面的步骤设置断点:
1.在Web应用程序里,选择你想要调试的代码行。
2.点击“External断点”按钮。
3.如果要删除断点,只要双电击程序行上的External断点图标(icone)即可删除断点
提示:
在较老版本上,点击断点图标后,会有一个画面弹出, 让你选择是“Session断点“还是”External断点“。
你也可以去菜单:“实用程序 (Utilities)> External 断点“,去管理所有External断点。
如何在程序里手动设置断点?
你可以在你的程序里设置断点语句,让程序在运行时只会为预先设定的用户停在断点。 这样,其他用户可以自自如地运行程序,而你可以自由地调试程序。
语法
Break.
如果你代码中的登录ID和用户的登录ID相匹配的话, 该程序运行到断点时会停止。
如何调试一个SAP事务(Transaction)?
你可以在事务命令代码框里使用“/H”命令,让后运行SAP事务。事务会停在最开始的程序行。
如何调试弹出屏幕?
前面提到,你可以在事务代码框里使用“/H”来调试事务。不过,如果你想调试在程序运行中弹出的屏幕,你就不能使用命令“/H”了。
这里给你个技巧提示,如何在屏幕弹出时进行调试:
在你的计算机上,用下面的代码创建一个文本文件, 然后将其保存起来。
在SAPGUI窗口弹出时,把文本文件从Windows资源管理器的窗口里拖拉到SAPGUI弹出窗口。 这时,SAPGUI就进入调试模式了。 (在屏幕下,你可以看到”调试被激活“的信息。)
代码 范例
[FUNCTION]
Command=/H
Title=Debugger
Type=SystemCommand
如何调试在背景工作的程序?
如果你有权限可以更改程序,你可以使用这个小技巧调试在背景工作的程序。
在程序中你要调试的地方,加一个无限循环的逻辑。 在这个无限循环的逻辑里,添加一个检查条件以便退出循环。 例如,检查一个变量的值是否被更改。
· 开始在背景里运行程序。
· 运行事务SM50,等到你的程序显示在列表中。
· 到菜单: 处理》程序》调试。 (菜单路径可能在不同的版本中略有不同)
· 现在你的程序正在无限循环逻辑中。 你可以改变变量的值 , 以便退出循环。
第二章 程序基础
2.1数据处理
如何从一个文本字符串中删除尾随或前置的'0'或空格?
代码 范例
SHIFT c RIGHT DELETING TRAILING c1.
SHIFT c LEFT DELETING LEADING c1.
在上面代码中的“C1”变量可以被定义为“空格”或“0”。
如何转移负号?
在SAP的世界里,负号标志是在数字的右侧,如“123.45-”。然而,在某些情况下,用户通常会要求把负号转移到左侧。 例如,如果你的报表列表要下载到个人电脑上的Excel文件,用户将要求你重新安排负号。下面是转移负号的代码 范例。
代码 范例
Data: p_amt(18).
P_amt = ' 12345.67-'.
shift p_amt right deleting trailing '-'.
shift p_amt left deleting leading space.
concatenate '-' p_amt into p_amt.
如何替换字符串?
你可以使用“TRANSLATE”语句来代替字符串中的字符。 下面的代码范例可以把字符串里的‘X' 替换成”Y“。
代码 范例
translate using 'XY'.
如何分割一个被tab分隔(tab-delimited)的字符串?
你可以方便地使用“SPLIT”命令,分裂一个被分隔符分隔的字符串。 在大多数情况下,分隔符是一个或多个字符,如“|”,"||",或','等,但是,” tab-delimited “分隔符是不同的。它必须定义为值是“09”的'×'类型。
下面的代码范例显示了如何分割tab分隔(tab-delimited)的字符串。请注意” tab-delimited “分隔符变量是如何定义的。
代码 范例
Data: tab_del type x value '09'.
SPLIT at tab_del into ….
如何删除字符串中的分隔符?
你可以先把分隔符除掉 , 然后再把所有分割后的子字符串串联在一起。
代码 范例
DATA: tab_del TYPE C VALUE '|'.
DATA: field1, field2, ……, fieldn, final_str TYPE string.
SPLIT AT tab_del INTO: field1 field2 … fieldn.
CONCATENATE field1 field2 … fieldn INTO final_str.
2.2条件运算符和循环
如何调用在另一个程序中的子程序?
语法
PERFORM() using …
如何在程序之间传输数据?
为了在不同的程序之间传输数据,你可以先将数据保存到global ABAP内存,然后在另一个程序中读取它。
注意 :数据传输完成后, 一定要清干净global ABAP内存。
代码 范例
Program 1
EXPORT obj1 ... objn TO MEMORY ID ‘m_id’.
Program 2
IMPORT obj1 ... objn FROM MEMORY. ID ‘m_id’.
… …
FREE MEMORY ID ‘m_id’.
如何使用“MOVE-CORRESPONDING”在两个结构之间复制数据?
如果你有两个结构 , 你想把同一字段类型(field type)的值从一个结构拷贝到另一个结构, 你只要使用语句“MOVE-CORRESPONDING”来实现这一目标。 只要一行代码即可。
然而,尽管这个命令非常方便 , 但对于CPU来说是非常昂贵的, 因为“MOVE-CORRESPONDING”语句会逐一检查每一个字段的类型。因此,如果程序的运行速度要求很高,你可能需要一个字段一个字段地拷贝。
另外请注意 ,因为 “MOVE-CORRESPONDING”语句会逐一检查每一个字段的类型, 如果你有两个相同类型的字段,你将会得到重复的数据。所以请先弄清楚两个结构的内容, 然后再应用此命令。
语法 。
MOVE-CORRESPONDING struc1 TO struc2.
如何把程序分配到不同的包(package)?
在事务SE38或者SE80窗口里,用右键单击Repository Browser窗口里的程序名。然后 选择“更多功能“ à “更改包(Change package assignment)。
如何在循环(Loop),子程序(Subroutine)或报表程序(Report)里使用“EXIT”?
1。“EXIT”在循环(LOOP)结构里。
EXIT命令可以用来跳出循环结构 , 并终止循环的过程。
注意,在这里所说的“循环”结构不仅是指循环结构本身(Loop),而且还包括诸如DO, WHILE, SELECT等结构,
2。“EXIT”在一个子程序中(Subroutine)。
如果“EXIT”命令用在一个子程序或其它模块里,它是用来离开子程序或模块的。
“子程序”在这里指的是”FORM“结构 , 而“模块”是指 如MODULE, FUNCTION, TOP-OF-PAGE, and END-OF-PAGE等结构。
请注意 ,
如果EXIT是在子程序或其他模块内的循环结构里,它只能让你跳出循环,但不能跳出子程序或模块。
3。“EXIT”在报表程序中(Report)。
如果EXIT既不在一个子程序或模块里,也不在循环结构里,那么它就会终止报表程序或者启动最后的清单显示。
如何使用“CHECK”语句 , 而不是”IF“语句?
1。“CHECK”语句用在循环(LOOP)中。
如果检查结果为负,当前循环进程终止 , 然后开始下一个循环。
2。“CHECK”在一个子程序(Subroutine)或报表程序(Report)里
如果检查结果为负,程序停止运行并退出当前的子程序或报表程序。
语法
CHECK.
和需要若干行的“IF”结构比较,CHECK”语句干净简洁。 往往若干行的“IF”代码可以被只有一行的“CHECK“语句取代。
如何在循环结构中使用“AT…ENDAT”结构?
语法
Loop at itab.
At FIRST.
… … ... ...
ENDAT.
At LAST.
… … ... ...
ENDAT
ENDLOOP
2.3文件输入/输出
如何打开一个文件?
你可以使用下面的语句来打开文件。 但请注意,如果你不使用任何附加值,打开的文件只能进行读取而不能更改。而且是二进制模式。
如果你没有指定目录,系统将使用配置参数DIR_HOME定义的目录作为默认目录。 因此 , 我建议你在文件名变量里使用完整的文件路径 , 以避免混乱。
语法
OPEN DATASET.
SY-SUBRC = 0. “文件打开.
SY-SUBRC = 8. “文件无法打开。
如何从文件中读取数据?
如果你想从文件中读取数据,可以使用”OPEN DATASET“ 和”READ DATASET 语句. 只要用户有更改权限, 这个语句就能以“读取/更新”模式打开文件。
如果用户没有更改权限,文件只以'读取'模式打开。 如果这仍然不能打开文件,错误信息就会出现。
下面的代码范例显示如何打开一个文件,一行行读出数据,并保存数据到一个内部表中。
代码 范例
DATA: input_file(40) TYPE c,
itab(94) OCCURS 0 WITH HEADER LINE,
msg(100).
OPEN DATASET input_file FOR INPUT IN TEXT MODE
ENCODING DEFAULT MESSAGE msg.
IF sy-subrc NE 0.
WRITE:/ 'ERROR opening file', input_file, 'with message',
ELSE.
DO.
READ DATASET input_file INTO itab.
IF sy-subrc = 0.
APPEND itab.
ENDIF.
ENDDO.
CLOSE DATASET input_file.
ENDIF.
如何到一个文件中填写数据?
如果你需要保存数据到一个文件中,你可以使用“OPEN DATASET”
对于OUTPUT的语句, 只要用户有文件读取的授权, 此语句试图以'写/更新'模式打开文件。 如果用户没有授权,系统中打开'写'模式文件。
如果该文件已存在,其现有的内容被删除。
如果该文件不存在,系统会创建一个新文件。
代码范例通过循环(LOOP)从 内表中读取数据, 然后一行行地转移到文件中。
代码 范例
DATA: output_file(40) TYPE c,
itab(94) OCCURS 0 WITH HEADER LINE,
msg(100).
OPEN DATASET output_file FOR OUTPUT IN TEXT MODE
ENCODING DEFAULT MESSAGE msg.
IF sy-subrc EQ 0.
LOOP AT itab.
TRANSFER itab TO output_file.
ENDLOOP.
CLOSE DATASET output_file.
ELSE.
WRITE:/ 'ERROR: Writing file with message', msg.
ENDIF.
如何将数据加到一个文件的尾部?
前面的范例是把数据加到一个文件中。
如果文件在系统中存在,旧的内容会被删除然后加进新的数据。 但在很多情况下,你不想清除现有的内容。
你只是想追加新的内容到文件的末尾。
要做到这一点,你可以使用“OPEN DATASET... FOR APPENDING“语句. 这个语句会试图打开文件成”追加'模式, 然后你可以把新的数据加到文件的末尾。
?????? 代码 范例??????
如何使你的文件I / O程序可以在不同的操作系统下运行?
正如你在下面的例子中看到,你需要提供一个逻辑文件名和所属操作系统的名称,从而获得实时的物理文件名。
If you don't specify the operating system, the function module will use system defined operating system name, sy-opsys, by default. 如果你不指定操作系统,功能模块将使用系统定义的默认操作系统的名(SY - opsys)。
代码 范例
DATA: lv_filenam TYPE string.
CALL FUNCTION 'FILE_GET_NAME'
EXPORTING
* CLIENT = SY-MANDT
logical_filename = ''
* OPERATING_SYSTEM = SY-OPSYS
* PARAMETER_1 = ' '
* PARAMETER_2 = ' '
* PARAMETER_3 = ' '
* USE_PRESENTATION_SERVER = ' '
* WITH_FILE_EXTENSION = ' '
* USE_BUFFER = ' '
* ELEMINATE_BLANKS = 'X'
* IMPORTING *进口
* EMERGENCY_FLAG =
* FILE_FORMAT =
file_name = lv_filenam
EXCEPTIONS
file_not_found = 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.
如何在ABAP程序里运行Windows /Unix命令?
如果你是一个Unix或Windows操作系统,下面的代码范例显示如何在该操作系统上运行命令。
该机制其实就是打开一个文件 , 运行命令。 然后将运行结果写入一个文件。
代码范例显示了如何运行的Unix命令。
如果你在Windows系统上,你只需把文件的路径和命令更改成Windows格式。
代码 范例
DATA: result_file(50) VALUE '/tmp/test',
msg_text(50),
command(255) VALUE 'ls'.
OPEN DATASET result_file FOR OUTPUT IN TEXT MODE ENCODING DEFAULT
FILTER command MESSAGE msg_text.
CLOSE DATASET result_file.
DELETE DATASET result_file.
如何从应用服务器(Application Server)上检索到文件列表?
使用功能模块“RZL_READ_DIR_LOCAL”, 你可以从应用服务器上得到给定的文件目录中的文件列表。
下面的代码范例显示了如何从当前目录检索文件列表。
代码范例:
DATA: lv_fdir TYPE pfeflnamel VALUE '.',
it_files LIKE salfldir OCCURS 0 WITH HEADER LINE.
CALL FUNCTION 'RZL_READ_DIR_LOCAL'
EXPORTING
name = lv_fdir
TABLES
file_tbl = it_files.
LOOP AT it_files.
WRITE: / it_files-name.
ENDLOOP.
2.4其他有用的建议
如何转换不同的时区的日期和时间?
日期和时间的转换可以通过先转换日期和时间到格林尼治标准时区(GMT), 然后从格林尼治时区的日期和时间转换到所需时区的日期和时间。
首先,你可以使用功能模块“IB_CONVERT_INTO_TIMESTAMP”转换日期和时间到GMT时区。 输入参数是日期,时间和时区。 输出参数就是格林尼治时间。
然后,你使用功能模块“IB_CONVERT_FROM_TIMESTAMP”再转换日期和时间到你所需的时区。
输入参数是从上面的功能模块获得时间和所需转换的时区。 输出参数是需要的时区的日期和时间。
Please note some related system fields here.
请注意一些相关的系统域值。
域值SY -DATUM和SY - UZEIT分别是系统的日期和时间。
如果你需要得到本地日期,时间,而所在时区,你可以分别使用域值SY - DATLO,SY - TIMLO与SY - ZONLO。
代码 范例
DATA :
timestamp LIKE tzonref-tstamps,
time LIKE sy-uzeit,
date LIKE sy-datum.
time = sy-uzeit.
date = sy-datum.
WRITE :/ 'Current system Date and Time is ',date, time.
WRITE :/ 'Current system located at Time Zone is ', sy-zonlo.
CALL FUNCTION 'IB_CONVERT_INTO_TIMESTAMP'
EXPORTING
i_datlo = date
i_timlo = time
i_tzone = sy-zonlo
IMPORTING
e_timestamp = timestamp.
CALL FUNCTION 'IB_CONVERT_FROM_TIMESTAMP'
EXPORTING
i_timestamp = timestamp
i_tzone = 'PST'
IMPORTING
e_datlo = date
e_timlo = time.
WRITE :/ 'Current Date and Time at PST zone is ',date, time.
如何使用Field Symbols?
在ABAP里,Field symbol就像是C语言里的指针。 它有一个参考值指向内部表记录或一个变量。 它的本身不包含任何数据。
Field Symbol的最大优点就是灵活性。 它不关心指向数据是什么类型。当然它的不利之处也是由于这种灵活性。编译器不检查field symbol的类型。由于没有类型检查,编译器几乎不可能在运行前检测到错误。
field symbol的语法是它总是由尖括号括起来。ASSIGN命令用于把变量或内部表记录分配给field symbol。
语法
FIELD-SYMBOLS.
代码 范例
DATA: itab TYPE TABLE OF spfli,
wa LIKE LINE OF itab.
* 传统的方法更新内部表的记录。
* 1. 把记录读入工作区
* 2. 在工作区里改值。
* 3. 从工作区修改内部表的记录。
READ TABLE itab INTO wa INDEX 3.
wa-carrid = 'AA'.
MODIFY itab FROM wa INDEX 3.
*使用field symbol修改内部表的记录。
FIELD-SYMBOLS.
READ TABLE itab ASSIGNING.
-carrid= 'AA'.
什么是系统域值(System Field)?
系统域值提供了极其有用的系统运行时的数据。 系统域值的语法是SY -《名称》, 如SY - SUBRC。
系统域值的总数超过170,其中包括曾经一些现在已经过时系统域值。 为了你的方便,我在这里给出一个常常在我们的日常工作中使用的系统域值列表。
? SY-SYSID – 正在使用的R / 3系统的名字。
? SY-DYNNR – 屏幕数字。在对话程序中,你可以使用此系统域值来确定你需要的屏幕。 语法是“ LEAVE TO SCREEN SY-DYNNR.”。
? SY-LANGU - 用户的登录语言(一个字节) , 例如英语是E和德语是D。
? SY-MANDT – 你所在的系统客户端号。
? SY-UNAME – 你的系统用户名。
? SY-DATLO – 用户的本地日期。
? SY-DATUM – 当前服务器的日期。
? SY-TIMLO – 用户的本地时间。
? SY-TCODE – 目前的交易(Transaction)代码。
? SY-ULINE/VLINE – 水平/垂直的屏幕输出线。
? SY-INDEX - 在DO或WHILE循环,SY-INDEX给出目前通过循环数
? SY-TABIX – 当前内部表行号。
? SY-DBCNT – 当前“select … from …”语句读到的行数。
? SY-TFILL - 当运行完“DESCRIBE TABLE“或”LOOP AT“或”READ TABLE”后, SY - TFILL给出内部表的总行数目
? SY-UCOMM – 用户命令。 你可以到菜单 “系统》状态...“去查找SY_UCOMM值。
如果我只能在运行期间得到数据库表名,我该如何在运行时动态地指定数据库表名?
下面的代码范例显示了如何在SELECT语句中使用数据库表名变量。
在运行时,程序先获取数据库表的名称- SFLIGHT,并把该数据库表的名称赋予一个变量-。
在稍后的SELECT语句中,使用这个数据库表名称的变量。
请注意 , 在SQL语句里, 变量必须放在括号里。
代码 范例
DATA: tablename TYPE tabname16,
rows TYPE i.
tablename = 'SFLIGHT'.
SELECT COUNT(*) FROM (tablename) INTO rows.
WRITE: rows.
如何在多个程序中搜索特定的字符串?
在某些情况下,你需要在某些程序里寻找特定的字符串。这里几个搜索的办法。
1.使用程序“RPR_ABAP_SOURCE_SCAN”。然而,在4.6C及更高版本, 这一程序不再适用。
2.如果你找不到上面的程序,试试程序RSRSCAN1。 不幸的是,这一程序在新的NetWeaver 6.20平台上也过时了。
3.还有另一种方便的方法可以在某些程序字符串搜索。在transaction SE38的第一个屏幕,进入菜单 “实用程序”》 在源代码中查找“。
如何解开压缩域值(packed field)?
下面的代码范例显示了如何解开压缩域值,并包在域值前置零。压缩域值“p_field”打印出“123”。解压缩后的域值“unp_field”打印出“00000123”。
代码 范例
DATA: p_field(2) TYPE p VALUE 123,
unp_field(8) TYPE c.
WRITE: 'packed filed: ', p_field.
UNPACK p_field TO unp_field.
WRITE: / 'unpacked field: ', unp_field.
打印结果
packed filed: 123
unpacked field: 00000123
如何显示Domain Fixed Value的简短文字?
你可以通过运行transaction SE16来打开表视图(Table View)DD07V。 然后根据Domain (DOMNAME), 固定值(DOMVALUE_L)和语言(DDLANGUAGE)来搜索简短文字(DDTEXT)。
第三章数据库表
如何数据库表选择数据?
select a b into (l_a, l_b) from where c = 'XXX'.
If sy-subrc = 0. 如果型号:SY - subrc = 0。
it_tab_wa-a = l_a. it_tab_wa - 1 = l_a。
it_tab_wa-b = l_b. it_tab_wa -乙= l_b。
append it_tab_wa to it_tab. 追加it_tab_wa的it_tab。
clear it_tab_wa. 明确it_tab_wa。
Else. 其他的。
Exit. 退出。
Endif. Endif。
endselect. endselect。
Sy-dbcnt gives number of lines read from “select” 翟思dbcnt提出了一些“行数选择阅读”
Where [not] between and 如果 [不]和之间
Where [not] like ('_' a single char. '%' any char. string including empty. 如果 [不]喜欢('_'一个单一的字符。'%'的任何字符。串包括空。
[not] in (, …, ) [不]在(,...,)
is [not] NULL 是[不]空
* name and field type in match *名和字段类型比赛
Select a b Into (appending) corresponding fields of table it_tab
from 从
where c = 'XXX'. 其中c ='三十'。
Select ab 选择抗体
into (appending) table it_tab 成(附加)表it_tab
from 从
for all entries in it_tab2 在it_tab2所有条目
where c = it_tab2-c 其中c = it_tab2 - ?
and d = it_tab2-d. 和d = it_tab2三维。
Select A~a B~b 选择A?1乙?b
into corresponding fields of table it_tab 到相应的字段表it_tab
from as A inner join as B 从为A内加入乙
on A~id = B~id 对阿??= B的身份证号
where A~id = '12345' 其中A?编号= '12345'
and A~date between param_open and param_close. 和A之间param_open和param_close?日期。
Data: condition_str(100) type c, 数据:condition_str(100)C型,
I_condition like condition_str occurs 0 with header line. 像condition_str I_condition发生与标题行0。
Concatenate 'Y =' y into condition_str separated by space. 串联'? ='Y到用空格分隔condition_str。
Append condition_str to I_condition. 追加condition_str的I_condition。
If NOT z is initial. 如果没有Z是最初的。
Concatenate 'Z =' z into condition_str separated by space. 串联的'Z ='?进入空间分隔condition_str。
Append condition_str to I_condition. 追加condition_str的I_condition。
Endif. Endif。
Select x into y from db_tble X到辎请从db_tble
Where x = a 其中x = 1
And ( I_condition ). 和(I_condition)。
当用“FOR ALL ENTIRES IN”语句作选择时的最佳方式。
Beware when using 'FOR ALL ENTRIES' in select statement. 小心使用为所有参赛作品的'在选择语句。 Although this addition to the select statement is an efficient way to fetch distinct records from DB table, follow the below steps to ensure data consistency and efficiency. 虽然这对选择语句除了是一种有效的方法 , 从数据库表中提取不同的记录,请按照下列步骤 , 以确保数据的一致性和效率。
1. 1。 Sort the Internal table used in the 'FOR ALL ENTRIES IN' clause. 排序表使用内部的所有参赛作品'中'的条款。
2. 2。 make sure they do not contain duplicates. 确保它们不包含重复。
3. 3。 last and most importantly include a primary key field(Unique entry) 最后 , 也是最重要的是包括一个主键字段(唯一项)
in the select list. 在选择列表中。 The reason, the system gets unique field records based 究其原因,该系统获得的唯一字段的记录
on the where condition. 在WHERE条件。 It summarizes the data based on the Data type and 它总结了基于数据类型和数据
field list in the target internal table. 字段列表中的目标内部表。
如何使数据库表能够被编辑?
三种办法:
第一种:当通过SE11创建新的数据库表时,选择“Table maintenance allowed”. 这样用户就能通过SE16编辑表的内容。
第二种:通过SM30编辑. 首先通过SE11使表处于编辑状态。去菜单:实用程序 〉表格维护生成器〉创建
第三种:
Edit via SM30: SE11 à menu Utilities>table maintenance generator à “Create” button à Input “Auth. 编辑通过SM30:SE11 菜单实用程序 “> 表维修发电机 à”创建“ 按钮 , 输入”认证。 groups” à Input “Functional group” à check “one step” à screen number in “Overview screen” 团体?à输入”功能组“ 支票 ”一步到位“ 屏幕号码”概述屏幕“
Define a transaction code to edit à after above steps to create maintenance screen for the table à SE93 to create a transaction code à check “ Transaction with parameters ” à Transaction “SM30” à check “Skip initial screen” à parameters: “VIEWNAME =” and “UPDATE = X”. 定义一个交易代码编辑上述步骤后创建的表维护屏幕 SE93创建一个交易代码 检查“ 交易与参数 ” 一宗 “SM30” 开支票 “跳过初始画面” 一个 参数:“视图名=”表名“”和“update = X”的。
编译任何程序最基本的技能就是对程序的调试(debugging). 所以让我们先熟悉一下SAP ABAP程序的调试手段。
如何调试ABAP程序?
在这本书中,我假设你使用的是ABAP编辑器(事务代码 SE38)开发ABAP程序。 但是,如果你使用的是Object Navigator (事务代码 SE80)做开发工作,过程也是相同的。
在ABAP编辑器屏幕,采取以下步骤设置你的调试断点:
选择你要开始调试的代码行。
按“Session断点“钮。
如果要删除断点, 只要双电击程序行上的Session断点图标(icone)即可删除断点。
提示:
如果你的SAP版本较老,点击断点图标后,会有一个画面弹出, 让你选择是“Session断点“还是”External断点“。
如果你要管理程序里设置的所有断点, 你可以去菜单:实用程序 (Utilities)> 断点。
如何调试Web应用程序?
如果你需要调试一个Web应用程序,设置断点的步骤和你设置ABAP程序断点完全相同,只是你设置的不是Session断点,而是外部断点(External Breakpoint)。
假设你在ABAP编辑器里编辑Web应用程序, 请按照下面的步骤设置断点:
1.在Web应用程序里,选择你想要调试的代码行。
2.点击“External断点”按钮。
3.如果要删除断点,只要双电击程序行上的External断点图标(icone)即可删除断点
提示:
在较老版本上,点击断点图标后,会有一个画面弹出, 让你选择是“Session断点“还是”External断点“。
你也可以去菜单:“实用程序 (Utilities)> External 断点“,去管理所有External断点。
如何在程序里手动设置断点?
你可以在你的程序里设置断点语句,让程序在运行时只会为预先设定的用户停在断点。 这样,其他用户可以自自如地运行程序,而你可以自由地调试程序。
语法
Break
如果你代码中的登录ID和用户的登录ID相匹配的话, 该程序运行到断点时会停止。
如何调试一个SAP事务(Transaction)?
你可以在事务命令代码框里使用“/H”命令,让后运行SAP事务。事务会停在最开始的程序行。
如何调试弹出屏幕?
前面提到,你可以在事务代码框里使用“/H”来调试事务。不过,如果你想调试在程序运行中弹出的屏幕,你就不能使用命令“/H”了。
这里给你个技巧提示,如何在屏幕弹出时进行调试:
在你的计算机上,用下面的代码创建一个文本文件, 然后将其保存起来。
在SAPGUI窗口弹出时,把文本文件从Windows资源管理器的窗口里拖拉到SAPGUI弹出窗口。 这时,SAPGUI就进入调试模式了。 (在屏幕下,你可以看到”调试被激活“的信息。)
代码 范例
[FUNCTION]
Command=/H
Title=Debugger
Type=SystemCommand
如何调试在背景工作的程序?
如果你有权限可以更改程序,你可以使用这个小技巧调试在背景工作的程序。
在程序中你要调试的地方,加一个无限循环的逻辑。 在这个无限循环的逻辑里,添加一个检查条件以便退出循环。 例如,检查一个变量的值是否被更改。
· 开始在背景里运行程序。
· 运行事务SM50,等到你的程序显示在列表中。
· 到菜单: 处理》程序》调试。 (菜单路径可能在不同的版本中略有不同)
· 现在你的程序正在无限循环逻辑中。 你可以改变变量的值 , 以便退出循环。
第二章 程序基础
2.1数据处理
如何从一个文本字符串中删除尾随或前置的'0'或空格?
代码 范例
SHIFT c RIGHT DELETING TRAILING c1.
SHIFT c LEFT DELETING LEADING c1.
在上面代码中的“C1”变量可以被定义为“空格”或“0”。
如何转移负号?
在SAP的世界里,负号标志是在数字的右侧,如“123.45-”。然而,在某些情况下,用户通常会要求把负号转移到左侧。 例如,如果你的报表列表要下载到个人电脑上的Excel文件,用户将要求你重新安排负号。下面是转移负号的代码 范例。
代码 范例
Data: p_amt(18).
P_amt = ' 12345.67-'.
shift p_amt right deleting trailing '-'.
shift p_amt left deleting leading space.
concatenate '-' p_amt into p_amt.
如何替换字符串?
你可以使用“TRANSLATE”语句来代替字符串中的字符。 下面的代码范例可以把字符串里的‘X' 替换成”Y“。
代码 范例
translate
如何分割一个被tab分隔(tab-delimited)的字符串?
你可以方便地使用“SPLIT”命令,分裂一个被分隔符分隔的字符串。 在大多数情况下,分隔符是一个或多个字符,如“|”,"||",或','等,但是,” tab-delimited “分隔符是不同的。它必须定义为值是“09”的'×'类型。
下面的代码范例显示了如何分割tab分隔(tab-delimited)的字符串。请注意” tab-delimited “分隔符变量是如何定义的。
代码 范例
Data: tab_del type x value '09'.
SPLIT
如何删除字符串中的分隔符?
你可以先把分隔符除掉 , 然后再把所有分割后的子字符串串联在一起。
代码 范例
DATA: tab_del TYPE C VALUE '|'.
DATA: field1, field2, ……, fieldn, final_str TYPE string.
SPLIT
CONCATENATE field1 field2 … fieldn INTO final_str.
2.2条件运算符和循环
如何调用在另一个程序中的子程序?
语法
PERFORM
如何在程序之间传输数据?
为了在不同的程序之间传输数据,你可以先将数据保存到global ABAP内存,然后在另一个程序中读取它。
注意 :数据传输完成后, 一定要清干净global ABAP内存。
代码 范例
Program 1
EXPORT obj1 ... objn TO MEMORY ID ‘m_id’.
Program 2
IMPORT obj1 ... objn FROM MEMORY. ID ‘m_id’.
… …
FREE MEMORY ID ‘m_id’.
如何使用“MOVE-CORRESPONDING”在两个结构之间复制数据?
如果你有两个结构 , 你想把同一字段类型(field type)的值从一个结构拷贝到另一个结构, 你只要使用语句“MOVE-CORRESPONDING”来实现这一目标。 只要一行代码即可。
然而,尽管这个命令非常方便 , 但对于CPU来说是非常昂贵的, 因为“MOVE-CORRESPONDING”语句会逐一检查每一个字段的类型。因此,如果程序的运行速度要求很高,你可能需要一个字段一个字段地拷贝。
另外请注意 ,因为 “MOVE-CORRESPONDING”语句会逐一检查每一个字段的类型, 如果你有两个相同类型的字段,你将会得到重复的数据。所以请先弄清楚两个结构的内容, 然后再应用此命令。
语法 。
MOVE-CORRESPONDING struc1 TO struc2.
如何把程序分配到不同的包(package)?
在事务SE38或者SE80窗口里,用右键单击Repository Browser窗口里的程序名。然后 选择“更多功能“ à “更改包(Change package assignment)。
如何在循环(Loop),子程序(Subroutine)或报表程序(Report)里使用“EXIT”?
1。“EXIT”在循环(LOOP)结构里。
EXIT命令可以用来跳出循环结构 , 并终止循环的过程。
注意,在这里所说的“循环”结构不仅是指循环结构本身(Loop),而且还包括诸如DO, WHILE, SELECT等结构,
2。“EXIT”在一个子程序中(Subroutine)。
如果“EXIT”命令用在一个子程序或其它模块里,它是用来离开子程序或模块的。
“子程序”在这里指的是”FORM“结构 , 而“模块”是指 如MODULE, FUNCTION, TOP-OF-PAGE, and END-OF-PAGE等结构。
请注意 ,
如果EXIT是在子程序或其他模块内的循环结构里,它只能让你跳出循环,但不能跳出子程序或模块。
3。“EXIT”在报表程序中(Report)。
如果EXIT既不在一个子程序或模块里,也不在循环结构里,那么它就会终止报表程序或者启动最后的清单显示。
如何使用“CHECK”语句 , 而不是”IF“语句?
1。“CHECK”语句用在循环(LOOP)中。
如果
2。“CHECK”在一个子程序(Subroutine)或报表程序(Report)里
如果
语法
CHECK
和需要若干行的“IF”结构比较,CHECK”语句干净简洁。 往往若干行的“IF”代码可以被只有一行的“CHECK“语句取代。
如何在循环结构中使用“AT…ENDAT”结构?
语法
Loop at itab.
At FIRST.
… … ... ...
ENDAT.
At LAST.
… … ... ...
ENDAT
ENDLOOP
2.3文件输入/输出
如何打开一个文件?
你可以使用下面的语句来打开文件。 但请注意,如果你不使用任何附加值,打开的文件只能进行读取而不能更改。而且是二进制模式。
如果你没有指定目录,系统将使用配置参数DIR_HOME定义的目录作为默认目录。 因此 , 我建议你在文件名变量里使用完整的文件路径 , 以避免混乱。
语法
OPEN DATASET
SY-SUBRC = 0. “文件打开.
SY-SUBRC = 8. “文件无法打开。
如何从文件中读取数据?
如果你想从文件中读取数据,可以使用”OPEN DATASET“ 和”READ DATASET 语句. 只要用户有更改权限, 这个语句就能以“读取/更新”模式打开文件。
如果用户没有更改权限,文件只以'读取'模式打开。 如果这仍然不能打开文件,错误信息就会出现。
下面的代码范例显示如何打开一个文件,一行行读出数据,并保存数据到一个内部表中。
代码 范例
DATA: input_file(40) TYPE c,
itab(94) OCCURS 0 WITH HEADER LINE,
msg(100).
OPEN DATASET input_file FOR INPUT IN TEXT MODE
ENCODING DEFAULT MESSAGE msg.
IF sy-subrc NE 0.
WRITE:/ 'ERROR opening file', input_file, 'with message',
ELSE.
DO.
READ DATASET input_file INTO itab.
IF sy-subrc = 0.
APPEND itab.
ENDIF.
ENDDO.
CLOSE DATASET input_file.
ENDIF.
如何到一个文件中填写数据?
如果你需要保存数据到一个文件中,你可以使用“OPEN DATASET”
对于OUTPUT的语句, 只要用户有文件读取的授权, 此语句试图以'写/更新'模式打开文件。 如果用户没有授权,系统中打开'写'模式文件。
如果该文件已存在,其现有的内容被删除。
如果该文件不存在,系统会创建一个新文件。
代码范例通过循环(LOOP)从 内表中读取数据, 然后一行行地转移到文件中。
代码 范例
DATA: output_file(40) TYPE c,
itab(94) OCCURS 0 WITH HEADER LINE,
msg(100).
OPEN DATASET output_file FOR OUTPUT IN TEXT MODE
ENCODING DEFAULT MESSAGE msg.
IF sy-subrc EQ 0.
LOOP AT itab.
TRANSFER itab TO output_file.
ENDLOOP.
CLOSE DATASET output_file.
ELSE.
WRITE:/ 'ERROR: Writing file with message', msg.
ENDIF.
如何将数据加到一个文件的尾部?
前面的范例是把数据加到一个文件中。
如果文件在系统中存在,旧的内容会被删除然后加进新的数据。 但在很多情况下,你不想清除现有的内容。
你只是想追加新的内容到文件的末尾。
要做到这一点,你可以使用“OPEN DATASET... FOR APPENDING“语句. 这个语句会试图打开文件成”追加'模式, 然后你可以把新的数据加到文件的末尾。
?????? 代码 范例??????
如何使你的文件I / O程序可以在不同的操作系统下运行?
正如你在下面的例子中看到,你需要提供一个逻辑文件名和所属操作系统的名称,从而获得实时的物理文件名。
If you don't specify the operating system, the function module will use system defined operating system name, sy-opsys, by default. 如果你不指定操作系统,功能模块将使用系统定义的默认操作系统的名(SY - opsys)。
代码 范例
DATA: lv_filenam TYPE string.
CALL FUNCTION 'FILE_GET_NAME'
EXPORTING
* CLIENT = SY-MANDT
logical_filename = '
* OPERATING_SYSTEM = SY-OPSYS
* PARAMETER_1 = ' '
* PARAMETER_2 = ' '
* PARAMETER_3 = ' '
* USE_PRESENTATION_SERVER = ' '
* WITH_FILE_EXTENSION = ' '
* USE_BUFFER = ' '
* ELEMINATE_BLANKS = 'X'
* IMPORTING *进口
* EMERGENCY_FLAG =
* FILE_FORMAT =
file_name = lv_filenam
EXCEPTIONS
file_not_found = 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.
如何在ABAP程序里运行Windows /Unix命令?
如果你是一个Unix或Windows操作系统,下面的代码范例显示如何在该操作系统上运行命令。
该机制其实就是打开一个文件 , 运行命令。 然后将运行结果写入一个文件。
代码范例显示了如何运行的Unix命令。
如果你在Windows系统上,你只需把文件的路径和命令更改成Windows格式。
代码 范例
DATA: result_file(50) VALUE '/tmp/test',
msg_text(50),
command(255) VALUE 'ls'.
OPEN DATASET result_file FOR OUTPUT IN TEXT MODE ENCODING DEFAULT
FILTER command MESSAGE msg_text.
CLOSE DATASET result_file.
DELETE DATASET result_file.
如何从应用服务器(Application Server)上检索到文件列表?
使用功能模块“RZL_READ_DIR_LOCAL”, 你可以从应用服务器上得到给定的文件目录中的文件列表。
下面的代码范例显示了如何从当前目录检索文件列表。
代码范例:
DATA: lv_fdir TYPE pfeflnamel VALUE '.',
it_files LIKE salfldir OCCURS 0 WITH HEADER LINE.
CALL FUNCTION 'RZL_READ_DIR_LOCAL'
EXPORTING
name = lv_fdir
TABLES
file_tbl = it_files.
LOOP AT it_files.
WRITE: / it_files-name.
ENDLOOP.
2.4其他有用的建议
如何转换不同的时区的日期和时间?
日期和时间的转换可以通过先转换日期和时间到格林尼治标准时区(GMT), 然后从格林尼治时区的日期和时间转换到所需时区的日期和时间。
首先,你可以使用功能模块“IB_CONVERT_INTO_TIMESTAMP”转换日期和时间到GMT时区。 输入参数是日期,时间和时区。 输出参数就是格林尼治时间。
然后,你使用功能模块“IB_CONVERT_FROM_TIMESTAMP”再转换日期和时间到你所需的时区。
输入参数是从上面的功能模块获得时间和所需转换的时区。 输出参数是需要的时区的日期和时间。
Please note some related system fields here.
请注意一些相关的系统域值。
域值SY -DATUM和SY - UZEIT分别是系统的日期和时间。
如果你需要得到本地日期,时间,而所在时区,你可以分别使用域值SY - DATLO,SY - TIMLO与SY - ZONLO。
代码 范例
DATA :
timestamp LIKE tzonref-tstamps,
time LIKE sy-uzeit,
date LIKE sy-datum.
time = sy-uzeit.
date = sy-datum.
WRITE :/ 'Current system Date and Time is ',date, time.
WRITE :/ 'Current system located at Time Zone is ', sy-zonlo.
CALL FUNCTION 'IB_CONVERT_INTO_TIMESTAMP'
EXPORTING
i_datlo = date
i_timlo = time
i_tzone = sy-zonlo
IMPORTING
e_timestamp = timestamp.
CALL FUNCTION 'IB_CONVERT_FROM_TIMESTAMP'
EXPORTING
i_timestamp = timestamp
i_tzone = 'PST'
IMPORTING
e_datlo = date
e_timlo = time.
WRITE :/ 'Current Date and Time at PST zone is ',date, time.
如何使用Field Symbols?
在ABAP里,Field symbol就像是C语言里的指针。 它有一个参考值指向内部表记录或一个变量。 它的本身不包含任何数据。
Field Symbol的最大优点就是灵活性。 它不关心指向数据是什么类型。当然它的不利之处也是由于这种灵活性。编译器不检查field symbol的类型。由于没有类型检查,编译器几乎不可能在运行前检测到错误。
field symbol的语法是它总是由尖括号括起来。ASSIGN命令用于把变量或内部表记录分配给field symbol。
语法
FIELD-SYMBOLS
代码 范例
DATA: itab TYPE TABLE OF spfli,
wa LIKE LINE OF itab.
* 传统的方法更新内部表的记录。
* 1. 把记录读入工作区
* 2. 在工作区里改值。
* 3. 从工作区修改内部表的记录。
READ TABLE itab INTO wa INDEX 3.
wa-carrid = 'AA'.
MODIFY itab FROM wa INDEX 3.
*使用field symbol修改内部表的记录。
FIELD-SYMBOLS
READ TABLE itab ASSIGNING
什么是系统域值(System Field)?
系统域值提供了极其有用的系统运行时的数据。 系统域值的语法是SY -《名称》, 如SY - SUBRC。
系统域值的总数超过170,其中包括曾经一些现在已经过时系统域值。 为了你的方便,我在这里给出一个常常在我们的日常工作中使用的系统域值列表。
? SY-SYSID – 正在使用的R / 3系统的名字。
? SY-DYNNR – 屏幕数字。在对话程序中,你可以使用此系统域值来确定你需要的屏幕。 语法是“ LEAVE TO SCREEN SY-DYNNR.”。
? SY-LANGU - 用户的登录语言(一个字节) , 例如英语是E和德语是D。
? SY-MANDT – 你所在的系统客户端号。
? SY-UNAME – 你的系统用户名。
? SY-DATLO – 用户的本地日期。
? SY-DATUM – 当前服务器的日期。
? SY-TIMLO – 用户的本地时间。
? SY-TCODE – 目前的交易(Transaction)代码。
? SY-ULINE/VLINE – 水平/垂直的屏幕输出线。
? SY-INDEX - 在DO或WHILE循环,SY-INDEX给出目前通过循环数
? SY-TABIX – 当前内部表行号。
? SY-DBCNT – 当前“select … from …”语句读到的行数。
? SY-TFILL - 当运行完“DESCRIBE TABLE“或”LOOP AT“或”READ TABLE”后, SY - TFILL给出内部表的总行数目
? SY-UCOMM – 用户命令。 你可以到菜单 “系统》状态...“去查找SY_UCOMM值。
如果我只能在运行期间得到数据库表名,我该如何在运行时动态地指定数据库表名?
下面的代码范例显示了如何在SELECT语句中使用数据库表名变量。
在运行时,程序先获取数据库表的名称- SFLIGHT,并把该数据库表的名称赋予一个变量-
在稍后的SELECT语句中,使用这个数据库表名称的变量。
请注意 , 在SQL语句里, 变量必须放在括号里。
代码 范例
DATA: tablename TYPE tabname16,
rows TYPE i.
tablename = 'SFLIGHT'.
SELECT COUNT(*) FROM (tablename) INTO rows.
WRITE: rows.
如何在多个程序中搜索特定的字符串?
在某些情况下,你需要在某些程序里寻找特定的字符串。这里几个搜索的办法。
1.使用程序“RPR_ABAP_SOURCE_SCAN”。然而,在4.6C及更高版本, 这一程序不再适用。
2.如果你找不到上面的程序,试试程序RSRSCAN1。 不幸的是,这一程序在新的NetWeaver 6.20平台上也过时了。
3.还有另一种方便的方法可以在某些程序字符串搜索。在transaction SE38的第一个屏幕,进入菜单 “实用程序”》 在源代码中查找“。
如何解开压缩域值(packed field)?
下面的代码范例显示了如何解开压缩域值,并包在域值前置零。压缩域值“p_field”打印出“123”。解压缩后的域值“unp_field”打印出“00000123”。
代码 范例
DATA: p_field(2) TYPE p VALUE 123,
unp_field(8) TYPE c.
WRITE: 'packed filed: ', p_field.
UNPACK p_field TO unp_field.
WRITE: / 'unpacked field: ', unp_field.
打印结果
packed filed: 123
unpacked field: 00000123
如何显示Domain Fixed Value的简短文字?
你可以通过运行transaction SE16来打开表视图(Table View)DD07V。 然后根据Domain (DOMNAME), 固定值(DOMVALUE_L)和语言(DDLANGUAGE)来搜索简短文字(DDTEXT)。
第三章数据库表
如何数据库表选择数据?
select a b into (l_a, l_b) from
If sy-subrc = 0. 如果型号:SY - subrc = 0。
it_tab_wa-a = l_a. it_tab_wa - 1 = l_a。
it_tab_wa-b = l_b. it_tab_wa -乙= l_b。
append it_tab_wa to it_tab. 追加it_tab_wa的it_tab。
clear it_tab_wa. 明确it_tab_wa。
Else. 其他的。
Exit. 退出。
Endif. Endif。
endselect. endselect。
Sy-dbcnt gives number of lines read from “select” 翟思dbcnt提出了一些“行数选择阅读”
Where
Where
* name and field type in
Select a b Into (appending) corresponding fields of table it_tab
from
where c = 'XXX'. 其中c ='三十'。
Select ab 选择抗体
into (appending) table it_tab 成(附加)表it_tab
from
for all entries in it_tab2 在it_tab2所有条目
where c = it_tab2-c 其中c = it_tab2 - ?
and d = it_tab2-d. 和d = it_tab2三维。
Select A~a B~b 选择A?1乙?b
into corresponding fields of table it_tab 到相应的字段表it_tab
from
on A~id = B~id 对阿??= B的身份证号
where A~id = '12345' 其中A?编号= '12345'
and A~date between param_open and param_close. 和A之间param_open和param_close?日期。
Data: condition_str(100) type c, 数据:condition_str(100)C型,
I_condition like condition_str occurs 0 with header line. 像condition_str I_condition发生与标题行0。
Concatenate 'Y =' y into condition_str separated by space. 串联'? ='Y到用空格分隔condition_str。
Append condition_str to I_condition. 追加condition_str的I_condition。
If NOT z is initial. 如果没有Z是最初的。
Concatenate 'Z =' z into condition_str separated by space. 串联的'Z ='?进入空间分隔condition_str。
Append condition_str to I_condition. 追加condition_str的I_condition。
Endif. Endif。
Select x into y from db_tble X到辎请从db_tble
Where x = a 其中x = 1
And ( I_condition ). 和(I_condition)。
当用“FOR ALL ENTIRES IN”语句作选择时的最佳方式。
Beware when using 'FOR ALL ENTRIES' in select statement. 小心使用为所有参赛作品的'在选择语句。 Although this addition to the select statement is an efficient way to fetch distinct records from DB table, follow the below steps to ensure data consistency and efficiency. 虽然这对选择语句除了是一种有效的方法 , 从数据库表中提取不同的记录,请按照下列步骤 , 以确保数据的一致性和效率。
1. 1。 Sort the Internal table used in the 'FOR ALL ENTRIES IN' clause. 排序表使用内部的所有参赛作品'中'的条款。
2. 2。 make sure they do not contain duplicates. 确保它们不包含重复。
3. 3。 last and most importantly include a primary key field(Unique entry) 最后 , 也是最重要的是包括一个主键字段(唯一项)
in the select list. 在选择列表中。 The reason, the system gets unique field records based 究其原因,该系统获得的唯一字段的记录
on the where condition. 在WHERE条件。 It summarizes the data based on the Data type and 它总结了基于数据类型和数据
field list in the target internal table. 字段列表中的目标内部表。
如何使数据库表能够被编辑?
三种办法:
第一种:当通过SE11创建新的数据库表时,选择“Table maintenance allowed”. 这样用户就能通过SE16编辑表的内容。
第二种:通过SM30编辑. 首先通过SE11使表处于编辑状态。去菜单:实用程序 〉表格维护生成器〉创建
第三种:
Edit via SM30: SE11 à menu Utilities>table maintenance generator à “Create” button à Input “Auth. 编辑通过SM30:SE11 菜单实用程序 “> 表维修发电机 à”创建“ 按钮 , 输入”认证。 groups” à Input “Functional group” à check “one step” à screen number in “Overview screen” 团体?à输入”功能组“ 支票 ”一步到位“ 屏幕号码”概述屏幕“
Define a transaction code to edit à after above steps to create maintenance screen for the table à SE93 to create a transaction code à check “ Transaction with parameters ” à Transaction “SM30” à check “Skip initial screen” à parameters: “VIEWNAME =