Saturday 7 April 2012

SUBROUTINES

In order to modularize the program Subroutines are used. Generally Subroutines are called by using PERFORM keyword and defined within FORM and ENDFORM block. There are three ways of passing the data from the calling part to the called part -1. pass by value  2. pass by reference  3 . pass by value and return .
*Subroutine - pass by value method-> using - using value( )******

TYPES : BEGIN OF LINE,
               NAME(10),
              ADD(10),
             END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.

PERFORM DISPLAY USING PER1. " calling the subroutine - Display

WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  USING VALUE(P_PER1) TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
       P_PER1-NAME = 'CCCC'.
       P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT*****************************

AAAA       BBBB
AAAA       BBBB
AAAA       BBBB
**Subroutine - pass by reference method-> using - using***

TYPES : BEGIN OF LINE,
               NAME(10),
              ADD(10),
            END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.

PERFORM DISPLAY USING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  USING P_PER1 TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
         P_PER1-NAME = 'CCCC'.
        P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT**************
AAAA       BBBB
CCCC       DDDD
CCCC       DDDD
**Subroutine - pass by reference method-> using - changing  *

TYPES : BEGIN OF LINE,
              NAME(10),
              ADD(10),
             END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.
PERFORM DISPLAY USING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  CHANGING P_PER1 TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
P_PER1-NAME = 'CCCC'.
P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT*****************
AAAA       BBBB
CCCC       DDDD
CCCC       DDDD

**Subroutine - pass by value and return  method-> using - changing  value( )**

TYPES : BEGIN OF LINE,
              NAME(10),
             ADD(10),
             END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.
PERFORM DISPLAY USING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  CHANGING VALUE(P_PER1) TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
P_PER1-NAME = 'CCCC'.
P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT******************
AAAA       BBBB
AAAA       BBBB
CCCC       DDDD

*Subroutine - pass by reference method-> changing - using  ***

TYPES : BEGIN OF LINE,
               NAME(10),
              ADD(10),
              END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.
PERFORM DISPLAY CHANGING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  USING P_PER1 TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
P_PER1-NAME = 'CCCC'.
P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT****************
AAAA       BBBB
CCCC       DDDD
CCCC       DDDD

*Subroutine - pass by value method-> changing - using  value( ) *

TYPES : BEGIN OF LINE,
              NAME(10),
             ADD(10),
            END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.
PERFORM DISPLAY CHANGING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  USING VALUE(P_PER1) TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
P_PER1-NAME = 'CCCC'.
P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT*****************
AAAA       BBBB
AAAA       BBBB
AAAA       BBBB

**Subroutine - pass by reference method-> changing - changing **

TYPES : BEGIN OF LINE,
              NAME(10),
             ADD(10),
             END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.
PERFORM DISPLAY CHANGING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  CHANGING P_PER1 TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
P_PER1-NAME = 'CCCC'.
P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT************
AAAA       BBBB
CCCC       DDDD
CCCC       DDDD

*Subroutine - pass by value and return  method-> changing - changing value( ) *

TYPES : BEGIN OF LINE,
              NAME(10),
             ADD(10),
            END OF LINE.

DATA : PER1 TYPE LINE.
PER1-NAME = 'AAAA'.
PER1-ADD = 'BBBB'.
PERFORM DISPLAY CHANGING PER1.
WRITE :/ PER1-NAME, PER1-ADD.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_PER1  text
*----------------------------------------------------------------------*
FORM DISPLAY  CHANGING VALUE(P_PER1) TYPE LINE.
  WRITE :/ P_PER1-NAME, P_PER1-ADD.
P_PER1-NAME = 'CCCC'.
P_PER1-ADD = 'DDDD'.
  WRITE :/ PER1-NAME, PER1-ADD.
ENDFORM.                    " DISPLAY

****************OUTPUT******************
AAAA       BBBB
AAAA       BBBB
CCCC       DDDD

**Subroutine - both type of parameters in subroutine ****
data : num1 type I,
         NUM2 TYPE I,
         RES TYPE I.
NUM1 = 5.
NUM2 = 8.

PERFORM MUL_DSIP USING NUM1 NUM2 CHANGING RES.
WRITE :/ 'VALUE OF RES = ' , RES.
*&---------------------------------------------------------------------*
*&      Form  MUL_DSIP
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_NUM1  text
*      -->P_NUM2  text
*      <--P_RES  text
*----------------------------------------------------------------------*
FORM MUL_DSIP  USING    VALUE(P_NUM1)
                                                 VALUE(P_NUM2)
                                                  CHANGING VALUE(P_RES).

  P_RES = P_NUM1 * P_NUM2.

  WRITE :/ 'VALUE OF P_RES = ', P_RES.
  WRITE :/ 'VALUE OF RES = ', RES.

ENDFORM.                    " MUL_DSIP

***********OUTPUT**************
VALUE OF P_RES =          40
VALUE OF RES =           0
VALUE OF RES =          40

**********Subroutine -factorial of a number  **********

PARAMETERS NUM TYPE I.
DATA FACT TYPE I VALUE 0.
PERFORM FACTORIAL USING NUM
                                         CHANGING FACT.
WRITE :/ 'FACTORIAL OF ', NUM,'=', FACT.
*&---------------------------------------------------------------------*
*&      Form  FACTORIAL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_NUM  text
*      <--P_FACT  text
*----------------------------------------------------------------------*
FORM FACTORIAL  USING   VALUE(P_NUM)
                                                  CHANGING P_FACT.
P_FACT = 1.
WHILE P_NUM > 1.
  P_FACT = P_FACT * P_NUM.
  P_NUM = P_NUM - 1.
  ENDWHILE.
ENDFORM.                    " FACTORIAL

******************OUTPUT***************
FACTORIAL OF           5  =        120

**********Subroutine -local and global data  **********

DATA TEXT(5) TYPE C VALUE 'ABCDE'.
WRITE :/ TEXT.
PERFORM DISPLAY.
WRITE :/ TEXT.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM DISPLAY .
  DATA TEXT TYPE CHAR5 VALUE 'EDCBA'.
  WRITE :/ TEXT.
ENDFORM.                    " DISPLAY

******************OUTPUT**************
ABCDE
EDCBA
ABCDE

**********Subroutine - with exit statement **********

perform exit_unconditionally.
write :/ 'Get back control again after uncoditionally stop nby exit'.

*&---------------------------------------------------------------------*
*&      Form  EXIT_UNCONDITIONALLY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM EXIT_UNCONDITIONALLY .
write :/ 'one'.
write :/ 'two'.
write :/ 'three'.
write :/ 'four'.
exit.
write :/ 'five'.

ENDFORM.                    " EXIT_UNCONDITIONALLY

****************** OUTPUT **************
one
two
three
four
Get back control again after uncoditionally stop nby exit

**********Subroutine - with check statement **********
DATA : NUM1 TYPE I,
            NUM2 TYPE I,
            RES TYPE P DECIMALS 2.

NUM1 = 10. NUM2 = 3.
perform CHECK_DISPALY USING NUM1 NUM2 CHANGING RES.

NUM1 = 10. NUM2 = 0.
perform CHECK_DISPALY USING NUM1 NUM2 CHANGING RES.


NUM1 = 20. NUM2 = 8.
perform CHECK_DISPALY USING NUM1 NUM2 CHANGING RES.
*&---------------------------------------------------------------------*
*&      Form  CHECK_DISPALY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_NUM1  text
*      -->P_NUM2  text
*      <--P_RES  text
*----------------------------------------------------------------------*
FORM CHECK_DISPALY  USING    P_NUM1
                                                             P_NUM2
                                            CHANGING P_RES.
CHECK P_NUM2 NE 0.

P_RES = P_NUM1 / P_NUM2.
WRITE :/ 'DIVISION = ', P_RES.
ENDFORM.                    " CHECK_DISPALY

*************OUTPUT****************
DIVISION =              3,33
DIVISION =              2,50

**Subroutine - multiple call of subroutine in a single line ****
DO 2 TIMES.
PERFORM SY-INDEX OF SUBROUT1 SUBROUT2.
ENDDO.

*&---------------------------------------------------------------------*
*&      Form  SUBROUT1
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SUBROUT1 .
WRITE :/ 'SUBROUTINE 1 OF PROGRAM ZPGM'.
ENDFORM.                    " SUBROUT1
*&---------------------------------------------------------------------*
*&      Form  SUBROUT2
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SUBROUT2 .
WRITE :/ 'SUBROUTINE 2 OF PROGRAM ZPGM'.
ENDFORM.                    " SUBROUT2

*******************OUTOUT*****************
SUBROUTINE 1 OF PROGRAM ZPGM
SUBROUTINE 2 OF PROGRAM ZPGM

**********Subroutine - nested  subroutine  **********
DATA : NUM1 TYPE I,
             NUM2 TYPE I,
             RES TYPE I.

 NUM1 = 10.
 NUM2 = 3.
perform ADDITION.
*&---------------------------------------------------------------------*
*&      Form  ADDITION
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM ADDITION .
RES = NUM1 + NUM2.
PERFORM DISPLAY.
ENDFORM.                    " ADDITION
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM DISPLAY .
WRITE :/ NUM1 , '+', NUM2 , '=', RES.
ENDFORM.                    " DISPLAY

*******OUTPUT********************
        10  +          3  =         13

**Subroutine - uses of data and static data in subroutine  ****

PERFORM FUNCTION1.
PERFORM FUNCTION1.
SKIP 2.
ULINE.
PERFORM FUNCTION2.
PERFORM FUNCTION2.
*&---------------------------------------------------------------------*
*&      Form  FUNCTION1
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM FUNCTION1 .
DATA : TEXT1 TYPE C LENGTH 5 VALUE 'ABCDE'.
WRITE :/ TEXT1.
TEXT1 = '12345'.
WRITE :/ TEXT1.
ENDFORM.                    " FUNCTION1
*&---------------------------------------------------------------------*
*&      Form  FUNCTION2
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM FUNCTION2 .
STATICS TEXT2 TYPE C LENGTH 5 VALUE 'PQRST'.
WRITE :/ TEXT2.
TEXT2 = '54321'.
WRITE :/ TEXT2.
ENDFORM.                    " FUNCTION2

******************OUTPUT***************

ABCDE
12345
ABCDE
12345

PQRST
54321
54321
54321
*Subroutine - uses of  global and local work area in subroutine  **
TABLES : SFLIGHT.

PERFORM ASSIGN1.
WRITE :/ SFLIGHT-CARRID, SFLIGHT-CONNID.
PERFORM ASSIGN2.
WRITE :/ SFLIGHT-CARRID, SFLIGHT-CONNID.
*&---------------------------------------------------------------------*
*&      Form  ASSIGN1
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM ASSIGN1 .
*TABLES : SFLIGHT. " DECLARATION NOT POSSIBLE ALREDAY EXISTS
  SFLIGHT-CARRID = 'SSS'.
  SFLIGHT-CONNID = '1234'.
  WRITE :/ SFLIGHT-CARRID , SFLIGHT-CONNID.
ENDFORM.                    " ASSIGN1
*&---------------------------------------------------------------------*
*&      Form  ASSIGN2
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM ASSIGN2 .
  LOCAL SFLIGHT.
SFLIGHT-CARRID = 'PPP'.
  SFLIGHT-CONNID = '4321'.
  WRITE :/ SFLIGHT-CARRID , SFLIGHT-CONNID.
ENDFORM.                    " ASSIGN2

******************OUTPUT******************
SSS 1234
SSS 1234
PPP 4321
SSS 1234

*Subroutine - calling a subroutine of other program  ****
REPORT ZPGM.

PERFORM DISPLAY.
*&---------------------------------------------------------------------*
*&      Form  DISPALY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM DISPLAY .
WRITE :/ 'SUBROUTINE OF THE PROGRAM = ', SY-CPROG.
ENDFORM.                    " DISPALY


********CALLING THIS SUBROUTINE FROM ZPGM1 **********

REPORT ZPGM1.
PERFORM DISPLAY(ZPGM) IF FOUND.
*********************OUTPUT OF ZPGM1******************

SUBROUTINE OF THE PROGRAM =  ZPGM1

**Subroutine - dynamic calling a subroutine from  other program  *
REPORT ZPGM.
PERFORM SUBROUT1.
PERFORM SUBROUT2.

*&---------------------------------------------------------------------*
*&      Form  SUBROUT1
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SUBROUT1 .
WRITE :/ 'SUBROUTINE 1 OF PROGRAM ZPGM'.
ENDFORM.                    " SUBROUT1
*&---------------------------------------------------------------------*
*&      Form  SUBROUT2
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM SUBROUT2 .
WRITE :/ 'SUBROUTINE 2 OF PROGRAM ZPGM'.
ENDFORM.                    " SUBROUT2

*******************************************************
REPORT ZPGM1.
DATA : PROGRAM_NAME TYPE C LENGTH 5 VALUE 'ZPGM'.
DATA : SUB_NAME TYPE C LENGTH 8 VALUE 'SUBROUT1'.

PERFORM (SUB_NAME) IN PROGRAM (PROGRAM_NAME) IF FOUND.
  SUB_NAME = 'SUBROUT2'.
PERFORM (SUB_NAME) IN PROGRAM (PROGRAM_NAME) IF FOUND.

********************OUTPUT *******************
SUBROUTINE 1 OF PROGRAM ZPGM
SUBROUTINE 2 OF PROGRAM ZPGM
**Subroutine - passing work area to a subroutine and handled by field symbol  **
DATA : BEGIN OF LINE,
           COL1 TYPE C VALUE 'A',
           COL2 TYPE C VALUE 'B',
           END OF LINE.

DATA : COL(4) TYPE C VALUE 'COL1'.

PERFORM DISPLAY USING LINE.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LINE  text
*----------------------------------------------------------------------*
FORM DISPLAY  USING    P_LINE . " P_line type any
FIELD-SYMBOLS <FS>.
assign component col of structure p_line to <FS>.
write :/ <FS>.
assign component 2 of structure p_line to <FS>.
write :/ <FS>.
ENDFORM.                    " DISPLAY

*************OUTPUT***********
A
B
**Subroutine - passing work area to a subroutine and handled by field symbol  **
data : begin of line,
          col1 value 'x',
          col2 value 'y',
         end of line.
data : comp(4) type c value 'COL2'.
perform display using line.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LINE  text
*----------------------------------------------------------------------*
FORM DISPLAY  USING    P_LINE type any.
field-symbols : <fs>.
assign component 1 of structure p_line to <fs>.
write :/ <fs>.
ASSIGN COMPONENT COMP OF STRUCTURE P_LINE TO <FS>.
WRITE /  <FS>.
ENDFORM.                    " DISPLAY

************** OUTPUT ******************
x
y
-------------------------------------------------------------------------------------------------------------

2 comments:

Unknown said...

Really good one.. complete details abour subroutines...

Unknown said...

wonderful document. hats off to the posted person

Comments system

Disqus Shortname