第九章 模块化 abap4 程序Word文档格式.docx
《第九章 模块化 abap4 程序Word文档格式.docx》由会员分享,可在线阅读,更多相关《第九章 模块化 abap4 程序Word文档格式.docx(34页珍藏版)》请在冰豆网上搜索。
这就定义了宏<
。
必须在DEFINE和END-OF-DEFINITION之间指定完整的语句。
这些语句最多可以包含九个占位符(&
1,&
2,…,&
9)。
完成宏定义之后,就可以进行调用,方法如下:
<
[<
p1>
p2>
...<
p9>
].
在生成程序期间,系统用已定义的语句替换<
,用<
pi>
替换每个占位符&
i。
可以从宏中调用另一个宏,但宏不能调用自己。
DATA:
RESULTTYPEI,
N1TYPEIVALUE5,
N2TYPEIVALUE6.
DEFINEOPERATION.
RESULT=&
1&
2&
3.
OUTPUT&
3RESULT.
DEFINEOUTPUT.
WRITE:
/'
Theresultof&
3is'
&
4.
OPERATION4+3.
OPERATION2**7.
OPERATIONN2-N1.
输出如下:
Theresultof4+3is7
Theresultof2**7is128
TheresultofN2-N1is1
这样就定义了两个宏:
OPERATION和OUTPUT。
OUTPUT嵌套在OPERATION中。
OPERATION先后三次被其他参数调用。
应注意占位符&
1、&
2、…在宏中是如何被替换的。
2包含程序
如果要在多个程序中使用相同的语句序列,则可一次性将其代码编写到包含程序中。
例如,当希望在不同程序中使用的数据声明较长时,这一点将非常重要。
以下主题说明:
不能与包含程序进行显式数据传递,因为包含程序的目的是模块化源代码。
如果想与模块进行数据传递,请使用子程序或功能模块。
2创建包含程序
要创建包含程序,请按以下章节所述步骤进行:
创建简单的ABAP/4程序(页1–1)
对于程序属性类型,必须使用类型I。
具体说明参见:
重要的程序属性(页1–4)通过双击ABAP/4程序中INCLUDE语句后的程序名,还可以创建或更改包含程序(参见使用包含程序(页2))。
这样既可以创建新程序,又可以更改现有程序。
不能单独运行包含程序,而必须从其它程序中调用。
可以从其它包含程序中调用包含程序。
编写INCLUDE程序源代码的唯一限制如下:
_包含程序不能包含PROGRAM或REPORT语句。
_包含程序不能调用自身。
_包含程序必须包含完整语句。
但是,必须确保包含程序语句在逻辑上符合调用它的程序源代码。
在编辑器中编辑包含程序时,选择“检查”通常还无法保证这一点。
***INCLUDEINCL-TST.
TEXT='
Hello!
'
在此,语法检查报告错误,因为没有声明TEXT字段。
但是,在用合适的类型定义了字段TEXT的任何程序中,都可以调用程序INCL-TST。
要想从语法检查中获得有意义的结果,必须为调用包含程序的程序进行语法检查(参见使用包含程序(页2))。
2使用包含程序
要从另一个ABAP/4程序中调用包含程序,请使用INCLUDE语句,用法如下:
INCLUDE<
incl>
在语法检查期间和生成期间,该语句将源代码<
插入到ABAP/4程序中。
INCLUDE语句的功能类似于把<
源代码复制到调用程序中语句的位置上。
INCLUDE语句必须单独占一行,并且不能扩展到多行。
包含程序不是运行时装载的,而是在程序生成前就被解析。
程序生成后,则包含所用全部包含程序的源代码。
假设编写了如下的包含程序:
***INCLUDESTARTTXT.
WRITE:
Programstartedby'
SY-UNAME,
onhost'
SY-HOST,
'
date:
SY-DATUM,'
time:
SY-UZEIT.
ULINE.
可以从任何其它ABAP/4程序调用该程序。
例如,如果希望编写输出功能模块的标准表头,请在PROGRAM或REPORT之后插入INCLUDE语句,方法如下:
PROGRAMSAPMZTST.
INCLUDESTARTTXT.
............
输出结果如下:
ProgramstartedbyFRED
onhosths1077date:
07/19/1995time:
09:
00:
39
___________________________________________________________
................
3子程序
子程序是可以从ABAP/4中调用的程序。
定义子程序的目的是为了避免重复编写程序中频繁使用的某些部分或频繁使用的算法。
可以与子程序进行显式数据传递。
有两种类型的子程序:
_内部子程序:
内部子程序的源代码与调用程序(内部调用)位于同一ABAP/4程序中。
_外部子程序:
外部子程序的源代码位于ABAP/4程序中而不是调用程序(外部调用)中。
尽管内部子程序主要用于模块化及结构化单个程序,某个ABAP/4程序中内部调用的子程序可以从另一个ABAP/4程序中外部调用。
另外,也可以创建只包含子程序的ABAP/4程序。
这些程序不能自己运行,而是被其它ABAP/4程序作为外部子程序库来调用。
下列主题说明
3定义子程序
子程序是以FORM开头、以ENDFORM结尾的代码块。
要定义子程序,请使用下列语法:
FORM<
subr>
pass>
statementblock>
ENDFORM.
定义子程序名。
选项用于指定如何与子程序进行数据传递。
_对于内部子程序,不必使用<
选项,但子程序可以访问主ABAP/4程序中声明的所有数据对象。
_对于外部子程序,必须决定是使用<
选项,还是在内存公用部分声明数据对象。
有关与子程序进行数据传递的详细信息,参见在调用程序与子程序之间进行数据传递(页5)
如果在同一程序中定义内部子程序,并且不使用事件关键字,则应将其分组集中在程序末尾,以免影响程序流程(参见定义过程块(页Error!
Notavalidlink.))。
子程序不能包含嵌套的FORM-ENDFORM块。
FORMHEADER.
ULINE.
这样就创建了子程序HEADER,该子程序可用于创建输出列表的表头(请与使用包含程序(页2)中的示例进行比较)。
3调用子程序
可以调用代码位于同一ABAP/4程序中的子程序(内部调用),也可调用代码位于其它ABAP/4程序中的子程序(外部调用)。
可以运行时指定子程序名,或从给定列表中调用子程序。
不仅可以从子程序中调用子程序(嵌套调用),子程序也可以调用自己(递归调用)。
3调用内部子程序
要调用内部子程序,请使用PERFORM语句,用法如下:
PERFORM<
调用子程序<
在<
选项中,指定如何与子程序进行数据传递。
如果不使用<
选项,子程序也可以访问主ABAP/4程序中声明的所有数据类型和对象。
该数据叫做全局数据,如果不被同名局域数据隐藏,该数据对子程序可见(关于数据传递的详细信息,参见在调用程序与子程序之间进行数据传递(页5))。
NUM1TYPEI,
NUM2TYPEI,
SUMTYPEI.
NUM1=2.NUM2=4.
PERFORMADDIT.
NUM1=7.NUM2=11.
FORMADDIT.
SUM=NUM1+NUM2.
PERFORMOUT.
FORMOUT.
Sumof'
NUM1,'
and'
NUM2,'
is'
SUM.
Sumof2and4is6
Sumof7and11is18
在该示例中,程序末尾定义了两个内部子程序:
ADDIT和OUT。
ADDIT从该程序中调用,OUT从ADDIT调用。
子程序自动具有字段NUM1、NUM2和SUM的访问权限。
4调用外部子程序
要调用外部子程序,请使用PERFORM语句,用法如下:
(<
prog>
)[<
][IFFOUND].
调用程序<
中定义的子程序<
如果希望与子程序进行数据传递,必须定义<
选项或者使用公用部分(关于进行数据传递的详细信息,参见在调用程序与子程序之间进行数据传递(页5))。
如果使用IFFOUND选项,并且程序<
中没有子程序<
sub>
,系统就忽略PERFORM语句。
启动调用外部子程序的程序时,如果定义了子程序的程序不在内存中,ABAP/4就将其装载到内存中。
为了节省存储空间,尽量将不同程序中定义的子程序数目限制到最小。
假定程序包含下列子程序:
PROGRAMFORMPOOL.
SY-HOST,
可以从程序中调用子程序,方法如下:
PERFORMHEADER(FORMPOOL)IFFOUND.
在该示例中,调用程序与子程序之间没有数据传递。
与使用包含程序(页2)中的示例一样,该子程序执行输出语句。
4运行时指定子程序名
运行时,可以指定要调用的子程序名以及存储子程序的程序名。
为此请使用PERFORM语句,用法如下:
PERFORM(<
fsubr>
)[INPROGRAM(<
fprog>
)][<
系统执行字段<
中存储的子程序。
如果使用INPROGRAM选项,系统在字段<
中存储的程序内查找子程序(外部调用)。
否则,系统在当前程序中查找子程序(内部调用)。
使用该语句还可在程序代码中指定子程序名和外部程序名。
为此请忽略括弧。
选项指定如何与子程序进行数据传递(关于数据传递的详细信息,参见在调用程序与子程序之间进行数据传递(页5))。
如果使用IFFOUND选项,找不到子程序<
时,系统就忽略PERFORM语句。
假定程序包含子程序:
FORMSUB1.
Subroutine1'
FORMSUB2.
Subroutine2'
可在运行时指定子程序名,如下所示:
PROGNAME(8)VALUE'
FORMPOOL'
SUBRNAME(8).
SUBRNAME='
SUB1'
PERFORM(SUBRNAME)INPROGRAM(PROGNAME)IFFOUND.
SUB2'
Subroutine1
Subroutine2
字符字段PROGNAME包含程序名,该程序包含子程序。
子程序名被分配给字符字段SUBRNAME。
5从列表中调用子程序
要从列表中调用特定子程序,请使用PERFORM语句,用法如下:
idx>
OF<
form1>
form2>
....<
formn>
系统执行子程序列表中位于<
处的子程序。
PERFORM语句的这一变量只对内部调用有效。
字段<
既可以是变量也可以是文字。
DO2TIMES.
PERFORMSY-INDEXOFSUB1SUB2.
ENDDO.
WRITE/'
在该示例中,从列表中连续调用两个内部子程序:
SUB1和SUB2。
5在调用程序与子程序之间进行数据传递
就内部和外部子程序而言,处理数据的缺省方法有所不同。
_对于内部子程序,如果调用程序的全局数据未被同名局部数据隐藏,可直接从子程序进行访问。
该全局数据由内部数据对象和类型以及ABAP/4词典字段组成。
ABAP/4词典字段由程序中的TABLES引用。
(关于该语句的详细信息,参见BCABAP/4用户指南(页Error!
_如果希望采用与内部子程序相同的方式,从外部子程序访问调用程序数据,就必须在调用程序和包含外部子程序的程序中,将数据声明为公用部分(参见将数据声明为公共部分(页6))。
在子程序中使用全局数据时,可以将全局数据复制到局部数据堆栈上。
这一点对内部子程序中的全局数据和声明为公共部分的数据有效。
为此,必须使用字段符号(关于该主题的详细信息,参见分配全局字段的本地副本(页10–16))。
应该只对简单模块化程序使用公共部分。
尤其在嵌套子程序调用中使用功能模块时(关于功能模块的详细信息,参见功能模块(页16)),访问公共部分的规则会很复杂。
为了使程序更透明,可移植性更好,在调用程序和子程序之间进行数据传递时,应尽量选择下列方法:
在内部和外部子程序中,明确指定所需的及可能更改的数据。
为此,在定义和调用子程序期间,可以使用参数。
这些参数是在FORM(参见定义子程序(页3))和PERFORM(参见调用子程序(页3))语句的<
选项中定义的。
6将数据声明为公共部分
要将数据声明为公共部分,请使用DATA语句,用法如下:
BEGINOFCOMMONPART[<
name>
],
datadeclaration>
..............
ENDOFCOMMONPART[<
在<
中,按DATA语句(页3–14)所述,对要包含到公共部分中的所有数据加以声明。
子程序和调用程序自动共享TABLES语句定义的表格工作区。
要在调用程序和子程序中使用公共部分,必须在所涉及的全部程序中都使用完全相同的声明。
因此,应将公共部分声明放到INCLUDE程序中(参见包含程序(页2))。
一个程序中可使用多个公共部分。
但必须给每个公共部分分配一个名称<
如果每个程序中只使用一个公共部分,则名称<
可选。
为了避免在具有不同公共部分声明的程序之间发生冲突,公共部分的名称应始终保持唯一。
假定某个INCLUDE程序INCOMMON包含公共部分NUMBERS的声明。
公共部分由三个数字字段组成:
NUM1、NUM2以及SUM:
***INCLUDEINCOMMON.
BEGINOFCOMMONPARTNUMBERS,
SUMTYPEI,
ENDOFCOMMONPARTNUMBERS.
假定程序FORMPOOL包含INCOMMON,同时包含子程序ADDIT和OUT:
INCLUDEINCOMMON.
假定调用程序SAPMZTST时包含INCOMMON,并从程序FORMPOOL中调用ADDIT。
PERFORMADDIT(FORMPOOL).
启动SAPMZTST后,输出如下:
该示例与调用内部子程序(页3)中的示例功能相同。
在当前示例中,必须将程序所用数据对象声明为公共部分,因为子程序ADDIT和OUT都被外部调用。
6通过参数进行数据传递
可以用参数在调用程序和子程序之间进行数据传递。
_在定义子程序期间用FORM语句定义的参数叫做形式参数。
_在调用子程序期间用PERFORM语句指定的参数叫做实参数。
可以区分不同种类的参数:
_输入参数用于向子程序传递参数
_输出参数用于从子程序传递参数
_输入/输出参数用于与子程序进行参数传递
在FORM和PERFORM语句的<
选项中定义参数,方法如下:
[TABLES<
formaltablelist>
]
[USING<
formalinputlist>
[CHANGING<
formaloutputlist>
]....
[(<
)][TABLES<
actualtablelist>
actualinputlist>
actualoutputlist>
选项TABLES、USING和CHANGING必须按上述顺序编写。
列表中USING和CHANGING后面的参数可以是所有类型的数据对象(参见声明数据(页3–1))和字段符号(参见使用字畏_号(页10–1))。
列表中TABLES后面的参数既可以是有表头行的内表,也可以是不带表头行的内表。
可以采用TABLES、USING或CHANGING传送内表。
可以用变量偏移量和长度规范指定实参数(关于偏移量规范的详细信息,参见指定数据对象的偏移量(页6–35))。
对于形式参数,不能采取这种方法。
要参考形式参数的一部分,请将该部分分配给字段符号,然后再传递该字段符号(参见使用字畏_号(页10–1))。
实参数的偏移量规范功能与字段符号的偏移量规范相同(参见具有偏移量说明的静_ASSIGN(页10–7))。
可以选择内存区,该内存区位于指定的实参数边界之外。
对于FORM语句中USING和CHANGING后面列表中的每个形式参数,可以指定不同数据传递方式:
_通过参考值调用:
在子程序调用期间,仅将实参数的地址传送给形式参数。
形式参数本身没有内存。
在子程序中使用调用程序的字段。
更改形式参数之后,调用程序中的字段内容也会变动。
_通过值调用:
在子程序调用期间,形式参数是作为实参数的副本创建的。
形式参数有自己的内存。
更改形式参数