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
-------------------------------------------------------------------------------------------------------------