调用程序与子程序之间进行数据传递的方式

调用程序与子程序之间进行数据传递的方式
一、         将数据声明 为公共部分

 

要将数据声 明为公共部 分,请使用 DATA 语句,用法 如下:

语法:

DATA: BEGIN OF COMMON PART [<name>],

               <data declaration>,
               ..............
      END OF COMMON PART [<name>].

<data declaration> 中,按 DATA 语句所述,对要包含到公共部分中的所有数据加以声明。

子程序和调 用程序自动共享 TABLES 语句定义的 表格工作区 。

要在调用程序和子程序中使用公共部分,必须在所涉及的全部程序中都使用完全相同的声明。因此,应将公共部分声明放到INCLUDE 程序中。

一个程序中可使用多个公共部分。但必须给每个公共部分分配一个名称 <name>。 如果每个程序中只使用一个公共部分,则名称 <name> 可选。

为了避免在 具有不同公共部分声明 的程序之间 发生冲突, 公共部分的名称应始终 保持唯一。

假定某个 INCLUDE 程序 INCOMMON 包含公共部分 NUMBERS 的声明。公共部分由三个数字字段组成: NUM1 NUM2 以及 SUM

***INCLUDE INCOMMON.

DATA: BEGIN OF COMMON PART NUMBERS,
         NUM1 TYPE I,
         NUM2 TYPE I,
         SUM  TYPE I,
      END OF COMMON PART NUMBERS.

假定程序 FORMPOOL 包含 INCOMMON, 同时包含子 程序 ADDIT OUT

PROGRAM FORMPOOL.

INCLUDE INCOMMON.

FORM ADDIT.
   SUM = NUM1 + NUM2.
   PERFORM OUT.
ENDFORM.

FORM OUT.
   WRITE: / 'Sum of', NUM1, 'and', NUM2, 'is', SUM.
ENDFORM.

假定调用程 序 SAPMZTST 时包含 INCOMMON, 并从程序 FORMPOOL 中调用 ADDIT

PROGRAM SAPMZTST.

INCLUDE INCOMMON.

NUM1 = 2. NUM2 = 4.
PERFORM ADDIT(FORMPOOL).

NUM1 = 7. NUM2 = 11.
PERFORM ADDIT(FORMPOOL).

启动 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>]
             [USING <formal  input list>]
          [CHANGING <formal output list>]....

 

PERFORM <subr>[(<prog>)] [TABLES <actual  table list>]
                          [USING <actual  input list>]
                       [CHANGING <actual output 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.
   ADD_SUM = ADD_NUM1 + ADD_NUM2.
   PERFORM OUT USING ADD_NUM1 ADD_NUM2 ADD_SUM.
ENDFORM.

FORM OUT USING OUT_NUM1 OUT_NUM2 OUT_SUM.
...WRITE: / 'Sum of',OUT_NUM1,'and',OUT_NUM2,'is',OUT_SUM.
ENDFORM.

假定某个调 用程序调用 ADDIT OUT

PROGRAM SAPMZTST.

DATA: NUM1 TYPE I,
      NUM2 TYPE I,
      SUM  TYPE I.

NUM1 = 2. NUM2 = 4.
PERFORM ADDIT(FORMPOOL) USING NUM1 NUM2 CHANGING SUM.

NUM1 = 7. NUM2 = 11.      
PERFORM ADDIT(FORMPOOL) USING NUM1 NUM2 CHANGING SUM.

启动 SAPMZTST 后,输出如 下:

Sum of          2 and          4 is          6

Sum of          7 and         11 is         18

该示例与 将数据声明 为公共部分中的示例功能相同。 当前示例中 ,通过参考值将实参数 NUM1NUM2 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_SUM = ADD_NUM1 + ADD_NUM2.
   PERFORM OUT USING ADD_NUM1 ADD_NUM2 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.


ENDFORM.

 

 

 

(二)通过值传递

 

要确保输入参数在调用程序中保持不变即使 子程序中已 被更改), 可以通过值 将数据传递 给子程序。 为此请使 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.
   F_FACT = 1.
   WHILE F_NUM GE 1.
      F_FACT = F_FACT * F_NUM.
      F_NUM = F_NUM - 1.
   ENDWHILE.
ENDFORM.

假定程序 SAPMZTST 调用子程序 FACT

PROGRAM SAPMZTST.

DATA: NUM  TYPE I VALUE 5,
      FAC  TYPE I VALUE 0.

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,
      OP2  TYPE I,
      RES  TYPE I.

OP1 = 3.
OP2 = 4.

PERFORM MULTIP USING OP1 OP2 CHANGING RES.

WRITE: / 'After subroutine:',
       / 'RES=' UNDER 'RES=', RES.

FORM MULTIP USING VALUE(O1) VALUE(O2) CHANGING VALUE(R).
    R = O1 * O2.
    WRITE: / 'Inside subroutine:',
           /  'R=', R, 'RES=', RES.
ENDFORM.

在启动 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 语句中实参数的类型是否与分配给形式参数的类型兼容。下表给出了兼容规则。 不存在类型转换。如果类型不兼容 ,系统会在内部子程序调用的语法检查期间输出错误信息 ,或在外部 子程序调用时出现运行错误。

以下兼容规则应用于确定形式参数类型:

确定类型

实参数的语法检查

无类型规范
TYPE ANY

系统接受任意类型的实参数 。

将实参数的所有属性传递给形式参数。

TYPE TABLE

系统检查实参数是否为内表。

将表格的所有属性和结构从实参数传递给形式参数。

TYPE C N P X

系统检查实参数的类型是否为 C N P X

将参数的长度和其 DECIMALS 规范(对类 型 P

从实参数传递给形式参数。

TYPE DF IT
LIKE <f>,
TYPE <ud>

完全确定这些类型。

系统检查实参数的数据类型是否完全与形式参数的类型相兼容 。

 

<ud> 是用户定义 的)

REPORT SAPMZTST.

DATA:
  DATE1      TYPE D,             DATE2      TYPE T,
  STRING1(6) TYPE C,             STRING2(8) TYPE C,
  NUMBER1    TYPE P DECIMALS 2,  NUMBER2    TYPE P,
  COUNT1     TYPE I,             COUNT2     TYPE I.

PERFORM TYPETEST USING DATE1 STRING1 NUMBER1 COUNT1.
SKIP.
PERFORM TYPETEST USING DATE2 STRING2 NUMBER2 COUNT2.

FORM TYPETEST USING NOW
                    TXT TYPE C
                    VALUE(NUM) TYPE P
                    INT TYPE I.
   DATA: T.
   DESCRIBE FIELD NOW TYPE T.
   WRITE: / 'Type of NOW is', T.
   * DESCRIBE FIELD TXT LENGTH T.

DESCRIBE FIELD TXT LENGTH T IN CHARACTER MODE.
   WRITE: / 'Length of TXT is', T.
   DESCRIBE FIELD NUM DECIMALS T.
   WRITE: / 'Decimals of NUM are', T.
   DESCRIBE FIELD INT TYPE T.
   WRITE: / 'Type of INT is', T.
ENDFORM.

SAPMZTST 后,输出如 下:

TYPE of NOW is D
Length of TXT is 6
Decimals of NUM are 2
Type of INT is I

TYPE of NOW is T
Length of TXT is 8
Decimals of NUM are 0
Type of INT is I

采用不同的实参数,两次调用内部子程序 TYPETEST 。所有实参数和形式参数均兼容, 在语法检查中没有出现错误信息。 例如,如果在调用程序中将 COUNT2 声明为 TYPE F 而不是 TYPE I ,则在语法检查中会报告错误,因为形式参数 INT 是用TYPE I 指定的。请注意,类型规范不同, 每次调用子程序时,形式参数的类型和属性也可以有所不同。

 四、向子程序传 递字段串

 

如果要向子程序传递字段串,并访问子程序中字段串的组件,则必须指定相应形式参数的类型。这里使 用的数据类型必须与字段串类型相同。

对于内部子程序,可以使用 TYPE LIKE 参考要直接传递的字段串的结构。对于外部子程序,还必须在包含子程序的程序中指定结构定义。为此,可以使用下列任何一种:

_ 包含程序

_ 类型组

_ ABAP/4 词典结构

 

 

下例就上述 内容加以说 明:

1. 包含程序

可以在包含程序中定义结构。该方法适用于这种结构:只用于几个子程序中,并且仅由几个开发者使用。

包含程序 DECLARE

***INCLUDE DECLARE.

TYPES: BEGIN OF LINE,
          NAME(10)   TYPE C,
          AGE(2)     TYPE N,
          COUNTRY(3) TYPE C,
       END OF LINE.

程序 FORMPOOL 包含程序 DECLARE COMPONENTS 子程序

PROGRAM FORMPOOL.

INCLUDE DECLARE.

FORM COMPONENTS CHANGING VALUE(PERSON) TYPE LINE.
   WRITE: / PERSON-NAME, PERSON-AGE, PERSON-COUNTRY.
   PERSON-NAME = 'Mickey'.
   PERSON-AGE = '60'.
   PERSON-COUNTRY = 'USA'.
ENDFORM.

程序 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,
          NAME(10)   TYPE C,
          AGE(2)     TYPE N,
          COUNTRY(3) TYPE C,
       END OF DECLA_LINE.

程序 FORMPOOL 使用 DECLA 类型组,并包含子程序 COMPONENTS

PROGRAM FORMPOOL.

TYPE-POOLS DECLA.

FORM COMPONENTS CHANGING VALUE(PERSON) TYPE DECLA_LINE.
   WRITE: / PERSON-NAME, PERSON-AGE, PERSON-COUNTRY.
   PERSON-NAME = 'Mickey'.
   PERSON-AGE = '60'.
   PERSON-COUNTRY = 'USA'.
ENDFORM.

程序 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.
   WRITE: / CITIES-CITYFROM, CITIES-CITYTO.
   CITIES-CITYFROM = 'New York'.
   CITIES-CITYTO   = 'San Francisco'.
ENDFORM.

程序 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,
         COL1 TYPE I,
         COL2 TYPE I,
      END OF LINE.

DATA ITAB LIKE LINE OCCURS 10.

PERFORM FILL CHANGING ITAB.
PERFORM OUT  USING    ITAB. 

*ITAB 无表头行内表】

FORM FILL CHANGING F_ITAB LIKE ITAB.
   DATA F_LINE LIKE LINE OF F_ITAB.
   DO 3 TIMES.
      F_LINE-COL1 = SY-INDEX.
      F_LINE-COL2 = SY-INDEX ** 2.
      APPEND F_LINE TO F_ITAB.
   ENDDO.
ENDFORM.

FORM OUT USING VALUE(F_ITAB) LIKE ITAB.
   DATA F_LINE LIKE LINE OF F_ITAB.
   LOOP AT F_ITAB INTO F_LINE.
      WRITE: / F_LINE-COL1, F_LINE-COL2.
   ENDLOOP.
ENDFORM.

启动 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,
         COL1 TYPE I,
         COL2 TYPE I,
       END OF LINE.

DATA: ITAB TYPE LINE OCCURS 10 WITH HEADER LINE,
      JTAB TYPE LINE OCCURS 10.

*ITAB 有表头行内表】

*JTAB 无表头行内表】

PERFORM FILL TABLES ITAB.
MOVE ITAB[] TO JTAB.
PERFORM OUT  TABLES JTAB.

FORM FILL TABLES F_ITAB LIKE ITAB[].  * 必须用[]来引用
   DO 3 TIMES.
      F_ITAB-COL1 = SY-INDEX.
      F_ITAB-COL2 = SY-INDEX ** 2.
      APPEND F_ITAB.
   ENDDO.
ENDFORM.

FORM OUT TABLES F_ITAB LIKE JTAB.
   LOOP AT F_ITAB.
      WRITE: / F_ITAB-COL1, F_ITAB-COL2.
   ENDLOOP.
ENDFORM.

启动 SAPMZTST 后,输出如 下:

         1          1

         2          4

         3          9

在该示例中 ,内表 ITAB 有表头行,而内表 JTAB 无表头行。 ITAB 被传递给子程序 FILL, 从中使用表格工作域 F_ITAB 进行填充。 在调用程序 中,将 ITAB 的表格体复 制到 JTAB 后,JTAB 被传递给子程序 OUT。请 注意,在这种情况下,将无表头行 的实表格传递给有表头行的形式表格,并在子程序中使用了表格工作 域 F_ITAB

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值