Examples of Subroutines 

Example of Passing Parameters by Reference

PROGRAM FORM_TEST.

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

NUM1 = 2. NUM2 = 4.
PERFORM ADDIT USING NUM1 NUM2 CHANGING SUM.

NUM1 = 7. NUM2 = 11.
PERFORM ADDIT USING NUM1 NUM2 CHANGING SUM.

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.

The produces the following output:

Sum of 2 and 4 is 6

Sum of 7 and 11 is 18

In this example, the actual parameters NUM1, NUM2, and SUM are passed by reference to the formal parameters of the subroutine ADDIT. After changing ADD_SUM, the latter parameters are then passed to the formal parameters OUT_NUM1, OUT_NUM2, and OUT_SUM of the subroutine OUT.

Input parameters which are changed in the subroutine are also changed in the calling program. To prevent this, you must pass the parameter by value in a USING addition.

Example of passing parameters by reference

PROGRAM FORM_TEST.

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

PERFORM FACT USING NUM CHANGING FAC.

WRITE: / 'Factorial of', NUM, 'is', FAC.

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.

The produces the following output:

Factorial of 5 is 120

To ensure that an input parameter is not changed in the calling program, even if it is changed in the subroutine, you can pass data to a subroutine by value. In this example, the factorial of a number NUM is calculated. The input parameter NUM is passed to the formal parameter F_NUM of the subroutine. Although F_NUM is changed in the subroutine, the actual parameter NUM keeps its old value. The output parameter FAC is passed by reference.

Example of output parameters

PROGRAM FORM_TEST.

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.

The produces the following output:

Inside subroutine:

R= 12 RES= 0

After subroutine:

              RES= 12

To return a changed formal parameter once the subroutine has finished successfully, you can use a CHANGING parameter and pass the parameter by reference. In this example, the actual parameters OP1 and OP2 are passed by value in the USING addition to the formal parameters O1 and O2. The actual parameter RES is passed by value to the formal parameter R using CHANGING. By writing R and RES onto the screen from within the subroutine, it is demonstrated that RES has not changed its contents before the ENDFORM statement. After returning from the subroutine, its contents have changed.

Example of passing structures

PROGRAM FORM_TEST.

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

DATA WHO TYPE LINE.

WHO-NAME = 'Karl'. WHO-AGE = '10'. WHO-COUNTRY = 'D'.

PERFORM COMPONENTS CHANGING WHO.

WRITE: / WHO-NAME, WHO-AGE, WHO-COUNTRY.

FORM COMPONENTS
       CHANGING VALUE(PERSON) TYPE LINE.

  WRITE: / PERSON-NAME, PERSON-AGE, PERSON-COUNTRY.
  PERSON-NAME = 'Mickey'.
  PERSON-AGE = '60'.
  PERSON-COUNTRY = 'USA'.

ENDFORM.

The produces the following output:

Karl       10 D

MICKEY 60 USA

The actual parameter WHO with the user-defined, structured data type LINE is passed to the formal parameter PERSON. The formal parameter PERSON is typed with TYPE LINE. Since LINE is a user-defined data type, the type of PERSON is completely specified. The subroutine accesses and changes the components of PERSON. They are then returned to the components of WHO in the calling program.

Example of passing internal tables

PROGRAM FORM_TEST.

DATA: BEGIN OF LINE,
COL1 TYPE I,
COL2 TYPE I,
END OF LINE.

DATA ITAB LIKE STANDARD TABLE OF LINE.

PERFORM FILL CHANGING ITAB.

PERFORM OUT USING 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.

The produces the following output:

         1          1

         2          4

         3          9

You can define the types of the formal parameters of the parameter interfaces of procedures as internal tables. In the example, the subroutines FILL and OUT each have one formal parameter defined as an internal table. An internal table without header line is passed to the subroutines. Each subroutine declares a work area F_LINE as a local data object. Were ITAB a table with a header line, you would have to replace ITAB with ITAB[] in the PERFORM and FORM statements.

Example of the TABLES parameter

This example is provided for completeness. The TABLES parameter is only supported for the sake of compatibility and should not be used.

PROGRAM FORM_TEST.

TYPES: BEGIN OF LINE,
COL1 TYPE I,
COL2 TYPE I,
END OF LINE.

DATA: ITAB TYPE STANDARD TABLE OF LINE WITH HEADER LINE,
      JTAB TYPE STANDARD TABLE OF LINE.

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.

The produces the following output:

         1          1

         2          4

         3          9

In this example, an internal table ITAB is declared with a header line and an internal table JTAB is declared without a header line. The actual parameter ITAB is passed to the formal parameter F_ITAB of the subroutine FILL in the TABLES addition. The header line is passed with it. After the body of the table has been copied from ITAB to JTAB, the actual parameter is passed to the formal parameter F_ITAB of the subroutine OUT using the TABLES addition. The header line F_ITAB, which is not passed, is generated automatically in the subroutine.