一、 将数据声明 为公共部分
要将数据声 明为公共部 分,请使用 DATA 语句,用法 如下: 语法:DATA: BEGIN OF COMMON PART [<name>], <data declaration>, 在 <data declaration> 中,按 DATA 语句所述,对要包含到公共部分中的所有数据加以声明。 子程序和调 用程序自动共享 TABLES 语句定义的 表格工作区 。 要在调用程序和子程序中使用公共部分,必须在所涉及的全部程序中都使用完全相同的声明。因此,应将公共部分声明放到INCLUDE 程序中。 一个程序中可使用多个公共部分。但必须给每个公共部分分配一个名称 <name>。 如果每个程序中只使用一个公共部分,则名称 <name> 可选。 为了避免在 具有不同公共部分声明 的程序之间 发生冲突, 公共部分的名称应始终 保持唯一。 假定某个 INCLUDE 程序 INCOMMON 包含公共部分 NUMBERS 的声明。公共部分由三个数字字段组成: NUM1、 NUM2 以及 SUM: ***INCLUDE INCOMMON. DATA: BEGIN OF COMMON PART NUMBERS, 假定程序 FORMPOOL 包含 INCOMMON, 同时包含子 程序 ADDIT 和 OUT: PROGRAM FORMPOOL. INCLUDE INCOMMON. FORM ADDIT. FORM OUT. 假定调用程 序 SAPMZTST 时包含 INCOMMON, 并从程序 FORMPOOL 中调用 ADDIT。 PROGRAM SAPMZTST. INCLUDE INCOMMON. NUM1 = 2. NUM2 = 4. NUM1 = 7. NUM2 = 11. 启动 SAPMZTST 后,输出如 下: Sum of 2 and 4 is 6 Sum of 7 and 11 is 18 该示例与 调用内部子程序的示例功能相同。在当前示例中 ,必须将程序所用数据对象声明为公共部分,因为子程序 ADDIT 和 OUT 都被外部调 用。
二、通过参数进行数据传递【Important】
可以用参数 在调用程序 和子程序之 间进行数据 传递。 _ 在定义子 程序期间用 FORM 语句定义的 参数叫做形式参数。 _ 在调用子 程序期间用 PERFORM 语句指定的 参数叫做实参数。 可以区分不 同种类的参 数: _ 输入参数 用于向子程 序传递参数 _ 输出参数 用于从子程 序传递参数 _ 输入/输 出参数用于 与子程序进 行参数传递 在 FORM 和 PERFORM 语句的 <pass> 选项中定义 参数,方法 如下: 语法FORM <subr> [TABLES <formal table list>]
PERFORM <subr>[(<prog>)] [TABLES <actual table list>]
选项 TABLES、 USING 和 CHANGING 必须按上述 顺序编写。 列表中 USING 和 CHANGING 后面的参数 可以是所有类型的数据对象和字段符 号。列表中 TABLES 后面的参数既可以是有表头行的内表,也可以是不带表头行的内表。可以采用 TABLES、 USING 或 CHANGING 传送内表。
对于 FORM 语句中 USING 和 CHANGING后 面列表中的 每个形式参 数,可以指 定不同数据 传递方式: _ 通过参考 值调用:在子程序调用期间,仅将实参数的地址传送给形式参数。形式参数本身没有内存。 在子程序中使用调用程序的字段。更改形式参数之后,调用程序中的字段内容也会变动。 _ 通过值调 用:在子程序调用期间 ,形式参数是作为实参数的副本创建的。形式参数有自己的内存。更改形式参数并不影响实参数。 _ 通过值和 结果调用: 在子程序调用期间,形式参数是作为实参数的副本创建的 。形式参数有自己的内存空间。在子程序末尾 ,将对形式参数的更改复制给实参数。
由 TABLES 传递的内表 均通过参考 值调用。
指定形式参数的数据类型对于向子程序传递结构化数据非常重要。有关如何传递结构化数据的内容(字段串和内表)在以下章节中有专门解释: (一) 通过参考传递
要通过参考值在调用程序和子程序之间进行数据传递,请使用 FORM 和 PERFORM 语句 <pass> 选项的 USING 或 CHANGING, 用法如下: 语法:FORM ..... [USING <fi1> ... <fin>] [CHANGING <fo1> ... <fon>] ... PERFORM... [USING <ai1> ... <ain>] [CHANGING <ao1> ... <aon>] ... 在 USING 和 CHANGING 后面的列表 中指定形式 参数和实参数,而不需附加任何内容。 FORM 语句中形式参数的名称 可以与PERFORM 语句中实参数 <ai1> ... <ain> and <ao1> ... <aon> 的名称不同 。PERFORM 语句列表中的第一个参数传递给 FORM 语句相应列表中的第一个参数,以此类推。 对于通过参考值调用, USING 和CHANGING 完全相同。对于文档, USING 用于子程序中的固定输入参数,而 CHANGING 则用于子程序中变化的输出参数。 子程序中变化的输入参数在调用程序中也会变化。要避免这一点,必须通过值传递参数。 假定程序 FORMPOOL 包含两个子程序 ADDIT 和 OUT: PROGRAM FORMPOOL. FORM ADDIT USING ADD_NUM1 ADD_NUM2 CHANGING ADD_SUM. FORM OUT USING OUT_NUM1 OUT_NUM2 OUT_SUM. 假定某个调 用程序调用 ADDIT 和 OUT: PROGRAM SAPMZTST. DATA: NUM1 TYPE I, NUM1 = 2. NUM2 = 4. NUM1 = 7. NUM2 = 11. 启动 SAPMZTST 后,输出如 下: Sum of 2 and 4 is 6 Sum of 7 and 11 is 18 该示例与 将数据声明 为公共部分中的示例功能相同。 当前示例中 ,通过参考值将实参数 NUM1、NUM2 和 SUM 从 SAPMZTST 传递给子程序 ADDIT 的形式参数 。更改 ADD_SUM 后,后面的参数就传递给子程序 OUT 的形式参数 OUT_NUM1、 OUT_NUM2 和 OUT_SUM。 备注:不能在子程序中更改 USING 后加的实参数 Eg: PROGRAM FORMPOOL. FORM ADDIT USING ADD_NUM1 ADD_NUM2 CHANGING ADD_SUM. * ADD_NUM1 = 5. * ADD_NUM2 = 5. * A USING reference parameter should not be used. * Instead, define the parameter as a USING-VALUE(...) or CHANGING parameter.
(二)通过值传递
要确保输入参数在调用程序中保持不变(即使 子程序中已 被更改), 可以通过值 将数据传递 给子程序。 为此,请使 用 FORM 和 PERFORM 语句 <pass> 选项的 USING, 用法如下: 语法FORM ..... USING ...VALUE(<fii>) .. PERFORM... USING .......<aii> .. 通过对 FORM 语句中 USING 后面列表中的形式输入参数写入 VALUE(<fii>)而 不是 <fii>,相应参数就通过值进行传递。与实字段 <ai> 属性相同的 PERFORM 语句调用该 子程序时, 就会创建一个新的局域字段 <fi>。系统处理独立于调用程序中参考字段的该字段。 假定 FORMPOOL 程序包含子 程序 FACT: PROGRAM FORMPOOL. FORM FACT USING VALUE(F_NUM) CHANGING F_FACT. 假定程序 SAPMZTST 调用子程序 FACT: PROGRAM SAPMZTST. DATA: NUM TYPE I VALUE 5, PERFORM FACT(FORMPOOL) USING NUM CHANGING FAC. WRITE: / 'Factorial of', NUM, 'is', FAC. 在启动 SAPMZTST 后,输出如下: Factorial of 5 is 120 在该示例中 ,计算数字 NUM 的阶乘。输入参数 NUM 被传递给子 程序的形式 参数 F_NUM。 尽管 F_NUM 在子程序中 已被更改, 实参数 NUM 仍然保持其 初始值。输 出参数 FAC 通过参考值 进行传递。
(三)通过值和结果进行传递
如果仅希望在子程序运行成功之后 ,才将更改过的输出参数从子程序返回给调用程序,请使 用 FORM 和 PERFORM 语句 <pass> 选项的 CHANGING, 用法如下: 语句FORM ..... CHANGING ...VALUE(<fii>) .. PERFORM... CHANGING .......<aii> .. 通过对 FORM 语句中 CHANGING后面列表 中的形式输 入参数写入 VALUE(<fii>)而 不是 <fii>, 相应参数通过值和结果调用进行传递。与实字段 <ai> 属性相同的 PERFORM 语句调用该子程序时,就会创建一个新的局域字段 <fi>。系统处 理独立于调用程序中参考字段的字段。 仅在运行到 ENDFORM 语句时,系 统才将 <fii> 的当前值传 递给 <aii>。 如果子程序 因为某个对话信息而中断, 则实参数 <aii> 保持不变。 仅在编写对话程序时,通过对话信息终止子程序才有意义。在报表程序中,子程序中的对话信息终止整个程序。在时间事件 AT SELECTION SCREEN 期间,或交互报表期间,该规则存在例外。交互报表的选项屏幕和工具使用现存对话程序。该对话程序是作为 ABAP/4 中的关键字提供的。 在用 PERFORM 调用子程序 时,可以用 USING 代替 CHANGING。 但对于文档 ,则应使用 FORM 语句中相同 的字。 PROGRAM SAPMZTST. DATA: OP1 TYPE I, OP1 = 3. PERFORM MULTIP USING OP1 OP2 CHANGING RES. WRITE: / 'After subroutine:', FORM MULTIP USING VALUE(O1) VALUE(O2) CHANGING VALUE(R). 在启动 SAPMZTST 后,输出如下: Inside subroutine: R= 12 RES= 0 After subroutine: RES= 12 在该示例中 ,从调用程序调用内部子程序 MULTIP。 参数 OP1 和 OP2 通过值传递给形式参数 O1 和 O2。输出参数 RES 通过值和结果传递给形式参数 R。通过将 R 和 RES 从子程序内部写到屏幕上,证明 RES 在 ENDFORM 语句之前未被更改。从子程序中返回之后,其内容已更改 。 三、键入形式参 数
要确保子程序的形式参数属于某个类型,可在 FORM 语句中指定该类型。为此,请在 TABLES、 USING 或 CHANGING 后面列表中的形式参数 后输入 TYPE <t> 或 LIKE <f>。该类型规范可选。
用 PERFORM 调用子程序 时,系统检查 PERFORM 语句中实参数的类型是否与分配给形式参数的类型兼容。下表给出了兼容规则。 不存在类型转换。如果类型不兼容 ,系统会在内部子程序调用的语法检查期间输出错误信息 ,或在外部 子程序调用时出现运行错误。 以下兼容规则应用于确定形式参数类型:
(<ud> 是用户定义 的) REPORT SAPMZTST. DATA: PERFORM TYPETEST USING DATE1 STRING1 NUMBER1 COUNT1. FORM TYPETEST USING NOW DESCRIBE FIELD TXT LENGTH T IN CHARACTER MODE. 在 SAPMZTST 后,输出如 下: TYPE of NOW is D TYPE of NOW is T 采用不同的实参数,两次调用内部子程序 TYPETEST 。所有实参数和形式参数均兼容, 在语法检查中没有出现错误信息。 例如,如果在调用程序中将 COUNT2声明为 TYPE F 而不是 TYPE I ,则在语法检查中会报告错误,因为形式参数 INT 是用TYPE I 指定的。请注意,类型规范不同, 每次调用子程序时,形式参数的类型和属性也可以有所不同。 四、向子程序传 递字段串
如果要向子程序传递字段串,并访问子程序中字段串的组件,则必须指定相应形式参数的类型。这里使 用的数据类型必须与字段串类型相同。 对于内部子程序,可以使用 TYPE 或 LIKE 参考要直接传递的字段串的结构。对于外部子程序,还必须在包含子程序的程序中指定结构定义。为此,可以使用下列任何一种: _ 包含程序 _ 类型组 _ ABAP/4 词典结构
下例就上述 内容加以说 明: 1. 包含程序可以在包含程序中定义结构。该方法适用于这种结构:只用于几个子程序中,并且仅由几个开发者使用。 包含程序 DECLARE: ***INCLUDE DECLARE. TYPES: BEGIN OF LINE, 程序 FORMPOOL 包含程序 DECLARE 和 COMPONENTS 子程序: PROGRAM FORMPOOL. INCLUDE DECLARE. FORM COMPONENTS CHANGING VALUE(PERSON) TYPE LINE. 程序 SAPMZTST 包含程序 DECLARE, 并调用子程 序 COMPONENTS: REPORT SAPMZTST. INCLUDE DECLARE. DATA WHO TYPE LINE. WHO-NAME = 'Karl'. WHO-AGE = '10'. WHO-COUNTRY = 'D'. PERFORM COMPONENTS(FORMPOOL) CHANGING WHO. WRITE: / WHO-NAME, WHO-AGE, WHO-COUNTRY. SAPMZTST 随后输出: KARL 10 D MICKEY 60 USA 实参数 WHO (具有用户 定义的、结构化数据类 型 LINE) 传递给形式 参数 PERSON。 形式参数 PERSON 的类型由 TYPE LINE 确定。因为 LINE 是由用户定 义的数据类 型,因此 PERSON 的类型就被 完全指定。 子程序访问 并更改 PERSON 的组件。然 后返回给调 用程序中 WHO 的组件。 2. 类型组可在类型组中定义结构。该方法 适用于几个开发者共同工作的大型程序所用的结构中。 DECLA 类型组: TYPE-POOL DECLA . TYPES: BEGIN OF DECLA_LINE, 程序 FORMPOOL 使用 DECLA 类型组,并包含子程序 COMPONENTS 。 PROGRAM FORMPOOL. TYPE-POOLS DECLA. FORM COMPONENTS CHANGING VALUE(PERSON) TYPE DECLA_LINE. 程序 SAPMZTST 使用 DECLA 类型组,并 调用子程序 COMPONENTS : REPORT SAPMZTST. TYPE-POOLS DECLA. DATA WHO TYPE DECLA_LINE. WHO-NAME = 'Karl'. WHO-AGE = '10'. WHO-COUNTRY = 'D'. PERFORM COMPONENTS(FORMPOOL) CHANGING WHO. WRITE: / WHO-NAME, WHO-AGE, WHO-COUNTRY. SAPMZTST 随后输出: KARL 10 D MICKEY 60 USA 除了类型定 义不在包含 程序中出现 ,而在 DECLA 类型组中出 现之外,该 示例与上例完全一样。
3. ABAP/4 词典结构可以使用 ABAP/4 词典中的表 格结构。该 方法始终可 选,因为总 能访问 ABAP/4 词典结构。 程序 FORMPOOL 包含子程序 COMPONENTS : PROGRAM FORMPOOL. FORM COMPONENTS CHANGING VALUE(CITIES) LIKE SPFLI. 程序 SAPMZTST 调用子程序 COMPONENTS: REPORT SAPMZTST. DATA FLIGHT LIKE SPFLI. FLIGHT-CITYFROM = 'Berlin'. FLIGHT-CITYTO = 'London'. PERFORM COMPONENTS(FORMPOOL) CHANGING FLIGHT. WRITE: / FLIGHT-CITYFROM, FLIGHT-CITYTO. SAPMZTST 随后输出: Berlin London New York San Francisco 在子程序 COMPONENTS 中,用 LIKE SPFLI 确定形式参 数 CITIES 的类型。在 ABAP/4 词典中,CITIES 结构与表格 SPFLI 相同。在程 序 SAPMZTST 中,使用相 同结构对字 段串 FLIGHT 加以说明, 然后填充和 传递给子程 序 COMPONENTS 的结构 CITIES 组件。该子 程序处理组 件并将其传 递给调用程 序。 五、向子程序传递内表1. 用USING 和 CHANGING 传递在 FORM 和 PERFORM 语句中,可以将内表当作 USING 或 CHANGING 后面列表中的参数传递 。如果要访问内表组件 ,则必须指定相应形式参数的类型。否则,只能在子程序中执行行操作。 同时还必须 区分有表头 行或无表头 行的内表。 对于有表头行的内表, 必须在表格名之后用方括号([]) 指定表格体 ,以便与表头行区分开。 对于内部子程序,可以 用 TYPE 或 LIKE 参考要直接 传递的内表 。对于外部 子程序,还必须在包含 子程序的程序中定义结构。为此,请按照定义字段串结构的方法进行。 PROGRAM SAPMZTST. DATA: BEGIN OF LINE, DATA ITAB LIKE LINE OCCURS 10. PERFORM FILL CHANGING ITAB. *【ITAB 无表头行内表】 FORM FILL CHANGING F_ITAB LIKE ITAB. FORM OUT USING VALUE(F_ITAB) LIKE ITAB. 启动 SAPMZTST 后,输出如 下: 1 1 2 4 3 9 在该示例中 ,定义并调用了两个子程序: FILL 和 OUT。无表头行的内表 ITAB 传递给子程序。通过参考值传递给 FILL, 通过值传递给 OUT。请注意,在两个子程序中都将工作域 F_LINE 创建为局部数据对象。如果 ITAB 为有表头行的表格,则 在 PERFORM 和 FORM 中必须用 ITAB[] 代替 ITAB。 用 TABLES 传递在 FORM 和 PERFORM 语句中,可以将所有内表当作 TABLES 后面列表中的参数进行传递。如果要在子程序中访问表格行的组件,则必须指定形式参数的数据类型。否则, 只能执行整行操作。由 TABLES 传递的内表总是通过参考值调用。 如果传递有表头行的内 表,则将表格体和表格工作域传递给子程序。 如果传递无表头行的内表,则在子程序中自动创建作为局部数据对象的表头行。 PROGRAM SAPMZTST. TYPES: BEGIN OF LINE, DATA: ITAB TYPE LINE OCCURS 10 WITH HEADER LINE, *【ITAB 有表头行内表】 *【JTAB 无表头行内表】 PERFORM FILL TABLES ITAB. FORM FILL TABLES F_ITAB LIKE ITAB[]. * 必须用[]来引用 FORM OUT TABLES F_ITAB LIKE JTAB. 启动 SAPMZTST 后,输出如 下: 1 1 2 4 3 9 在该示例中 ,内表 ITAB 有表头行,而内表 JTAB 无表头行。 ITAB 被传递给子程序 FILL, 从中使用表格工作域 F_ITAB 进行填充。 在调用程序 中,将 ITAB 的表格体复 制到 JTAB 后,JTAB 被传递给子程序 OUT。请 注意,在这种情况下,将无表头行 的实表格传递给有表头行的形式表格,并在子程序中使用了表格工作 域 F_ITAB。 |
|