MichaelB.
7/25/2018 - 7:37 PM

Create a Subroutine (PERFORM)

A small modular unit of code that is self-contained and called from the program in which they are defined (local) Groups together n lines of code, wrapping it up in a sub-program and moving it to the end of your program right down at the bottom Still in the same file, but in its own container We can use subroutines to write functions that we use many times within our programs Forms, function modules are similar to methods / functions in other languages Any ABAP program can use subroutines Helps give program structure, by modularizing code in program: provides encapsulation of functionality Easiest way of creating a sub routine is by forward navigation. Called by PERFORM statement. System will perform any code we put inside the FORM ENDFORM structure. Once the system encounters the ENDFORM statement, system will go to next statement under the original PERFORM statement. Therefore, despite the pieces of code for the Sub Routines are at the bottom, they are not the end of the program. USING lets you use parameters, and automatically includes them in the FORM ENDFORM syntax when using forward navigation. Global variables are defined in the header of the program Form can access the global variables Local variables can only be accessed / referenced from subroutine Can save on memory usage this way plus makes everything self-contained We can use local variables in the subroutines to be used in the interface We can give them any name we want Calling program can use its own variables as well, does not have to use the same name as in the subroutine We can declare variables to be used in the interface of our form, when we do that we tell the system we’re going to transfer data throughout the subroutine interface. Name the interface fields so that they represent what you're passing through. Fields that are used in the interface do not contain a data type. The fields are declared exactly the same way as the fields used after USING. When reaching PERFORM the contents of the main program fields will be copied to the interface fields. If you change the contents of the local fields of the FORM header, you inmediately also change the values of the global fields in the PERFORM statement when using USING. You can also pass tables or combinations of fields and tables with the TABLES addition. But you always have to get the sequence of fields correct from main program to the form. It is the sequence that determines which field is passed to the interface variable of your form. With tables contents of the main program internal table are transferred to subroutine and stored in local internal 'p' table. Once processing reaches end of form, contents of local internal table are passed back to the global internal table (technique for tables without a header line). To pass an internal table with a header line you need to use brackets: itab01[]. However the local sub routine internal table is always declared with a header line. You can declare a local work area regardless and use it instead of the header line. Subroutines were designed for structuring and modularizing your programs.

They can be extended so that they can be called externally from other programs. Better to use function modules if you want to make a function instead of an external subroutine. When an external subroutine is finished, control is also passed back to your program. There are 2 ways to call a subroutine of an external program (try to always use the first, in able to use ABAP objects). In the first form you can actually use variables to identify the program that contains the sub routine, instead of hard coding the name throughout the code. Need to specify the program where the subroutine exists after IN PROGRAM. Other way to call a subroutine is by using brackets (cannot use this form in the context of ABAP objects). However, almost all subroutines are contained in the body of the main programs themselves. Very rarely are they called from other programs.

Typically, subroutines are placed at the end of program source code (internal) or in external includes or programs (external) Subroutines can see & manipulate global program data, but it is bad practice to do so: breaks encapsulation principles

Parameters: Actual parameters (caller) are copied / transferred to the parameters listed in the subroutine interface. Methods of passing parameters:

  • Call by Value: the parameter value is copied to the subroutine. Subroutine places the parameter name within value(). Indicated it is the value of the data object which is passed (copied).
  • Call by Reference: the parameter memory location is passed to the subroutine resulting in the subroutine operating on the actual parameter - no copy is made. When value() is not used, it indicates the value of the data object is not used. Instead the original variable of the calling program is used. Any changes made to the variable in the subroutine are seen in the original variable when the subroutine completes.
  • Call by Value and Result: the parameter value is copied to the subroutine. If the end of the subroutine is reached without any errors, the subroutines parameters values are copied back to the actual (caller) parameters. Subroutine places the parameter name within value(). Indicates it is a COPY of the calling programs data objects value being used. By using CHANGING, the final value of the subroutines parameter will be copied back to the actual parameter of the calling program if the subroutine completes successfully.

Parameter Data types:

  • When we want to use parameters, we have to extend the syntax
  • Parameters data types are determined by the main calling program.
  • In the subroutine the parameters can be listed:
  • Without a type or with TYPE ANY. This allows any data type to be passed to the subroutine
  • With a type clause. This is the safer option. Helps to understand how the subroutine can be used and less prone to runtime errors (e.g. calculations on character fields). Instead of having to go to the calling program and determine what type the parameters are from there.
INCLUDE z_employee_definitions.

TABLES zemployees.

**Declare a Line Type
*TYPES: BEGIN OF line01_typ,
*         surname LIKE zemployees-surname,
*         dob     LIKE zemployees-dob,
*       END OF line01_typ.

*Declare the 'Table Type' based on the Line Type.
TYPES itab02_typ TYPE STANDARD TABLE OF line01_typ.

*Declare the table based on the 'Table Type'
DATA itab02 TYPE itab02_typ.

*Declare the Work Area to use with our Internal Table
DATA wa_itab02 TYPE line01_typ.

DATA line_cnt TYPE i.

DATA: z_field1 LIKE zemployees-surname,
      z_field2 LIKE zemployees-forename.

*****************************************

PERFORM itab02_fill.

PERFORM sub_1 IN PROGRAM zemployee_hire USING z_field1 z_field2.

PERFORM sub_2(zemployee_hire) TABLES itab02 USING z_field1 z_field2.


z_field1 = 'ANDREWS'.
z_field2 = 'SUSAN'.

PERFORM itab02_fill_again USING z_field1 z_field2. 

PERFORM itab02_write TABLES itab02.

PERFORM itab02_multi TABLES itab02 USING z_field1 z_field2.

*SELECT * FROM zemployees
*  INTO CORRESPONDING FIELDS OF TABLE itab02.

LOOP AT itab02 INTO wa_itab02.
  WRITE wa_itab02-surname.
ENDLOOP.

CLEAR: itab02,
       wa_itab02.

LOOP AT itab02 INTO wa_itab02.
  IF wa_itab02-surname = 'JONES'.
    wa_itab02-surname = 'SMITH'.
    MODIFY itab02 FROM wa_itab02.
  ENDIF.
ENDLOOP.

DESCRIBE TABLE itab02 LINES line_cnt.
IF line_cnt > 0.
  INSERT wa_itab02 INTO itab02 INDEX line_cnt.

  READ TABLE itab02 INDEX 5 INTO wa_itab02.

  READ TABLE itab02 INTO wa_itab02
       WITH KEY surname = 'SMITH'.
ENDIF.

************************************************
* Example of Passing By Value

PERFORM mysub USING myvar1.
..

FORM mysub USING value(subvar1) TYPE i.
    1 or more statements..
    ..
ENDFORM.

************************************************
* Example of Passing By Reference

PERFORM mysub USING [or CHANGING] myvar1.
..

FORM mysub USING [or CHANGING] subvar1 TYPE i.
    1 or more statements..
    ..
ENDFORM.

************************************************
* Example of Passing By Value and Result

PERFORM mysub CHANGING myvar1.
..

FORM mysub CHANGING value(subvar1) TYPE ANY.
    1 or more statements..
    ..
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  ITAB02_FILL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM itab02_fill .

  DATA zempl LIKE zemployees-surname.

  SELECT * FROM zemployees
    INTO CORRESPONDING FIELDS OF TABLE itab02.

ENDFORM.


*&---------------------------------------------------------------------*
*&      Form  ITAB02_FILL_AGAIN
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_Z_FIELD1  text
*      -->P_Z_FIELD2  text
*----------------------------------------------------------------------*
FORM itab02_fill_again  USING    p_zsurname 
                                 p_zforename.

  WRITE / p_zsurname.
  WRITE / p_zforename.

  p_zsurname = 'abcde'.
ENDFORM.


*&---------------------------------------------------------------------*
*&      Form  ITAB02_WRITE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_ITAB02  text
*----------------------------------------------------------------------*
FORM itab02_write  TABLES   p_itab02.

  DATA wa_tmp TYPE line01_typ.

  LOOP AT p_itab02 INTO wa_tmp.
    WRITE wa_tmp-surname.
  ENDLOOP.

ENDFORM.


*&---------------------------------------------------------------------*
*&      Form  ITAB02_MULTI
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_ITAB02  text
*      -->P_Z_FIELD1  text
*      -->P_Z_FIELD2  text
*----------------------------------------------------------------------*
FORM itab02_multi  TABLES   p_itab02
                   USING    p_z_field1
                            p_z_field2.

ENDFORM.