Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

pass by value & pass by reference ?

Former Member
0 Likes
5,615

what is a pass by value & pass by reference ?difference between them ?

explain with example >plzzzzzzzzzzz?

1 ACCEPTED SOLUTION
Read only

Former Member
0 Likes
2,205

Hi

<b>The Parameter Interface</b>

The USING and CHANGING additions in the FORM statement define the formal parameters of a subroutine. The sequence of the additions is fixed. Each addition can be followed by a list of any number of formal parameters. When you call a subroutine, you must fill all formal parameters with the values from the actual parameters. At the end of the subroutine, the formal parameters are passed back to the corresponding actual parameters.

Within a subroutine, formal parameters behave like dynamic local data. You can use them in the same way as normal local data objects that you would declare with the DATA statement. They mask global data objects with the same name. The value of the parameters at the start of the subroutine is the value passed from the corresponding actual parameter.

<b>Subroutines can have the following formal parameters:</b>

Parameters Passed by Reference

You list these parameters after USING or CHANGING without the VALUE addition:

FORM <subr> USING ... <pi> [TYPE <t>|LIKE <f>] ...

CHANGING ... <pi> [TYPE <t>|LIKE <f>] ...

The formal parameter occupies no memory of its own. During a subroutine call, only the address of the actual parameter is transferred to the formal parameter. The subroutine works with the field from the calling program. If the value of the formal parameter changes, the contents of the actual parameter in the calling program also change.

For calling by reference, USING and CHANGING are equivalent. For documentation purposes, you should use USING for input parameters which are not changed in the subroutine, and CHANGING for output parameters which are changed in the subroutine.

To avoid the value of an actual parameter being changed automatically, you must pass it by value.

<b>Input Parameters That Pass Values</b>

You list these parameters after USING with the VALUE addition:

FORM <subr> USING ... VALUE(<pi>) [TYPE <t>|LIKE <f>] ...

The formal parameter occupies its own memory space. When you call the subroutine, the value of the actual parameter is passed to the formal parameter. If the value of the formal parameter changes, this has no effect on the actual parameter.

<b>Output Parameters That Pass Values</b>

You list these parameters after CHANGING with the VALUE addition:

FORM <subr> CHANGING ... VALUE(<pi>) [TYPE <t>|LIKE <f>] ...

The formal parameter occupies its own memory space. When you call the subroutine, the value of the actual parameter is passed to the formal parameter. If the subroutine concludes successfully, that is, when the ENDFORM statement occurs, or when the subroutine is terminated through a CHECK or EXIT statement, the current value of the formal parameter is copied into the actual parameter.

If the subroutine terminates prematurely due to an error message, no value is passed. It only makes sense to terminate a subroutine through an error message in the PAI processing of a screen, that is, in a PAI module, in the AT SELECTION-SCREEN event, or after an interactive list event.

<b>Specifying the Type of Formal Parameters</b>

Formal parameters can have any valid ABAP data type. You can specify the type of a formal parameter, either generically or fully, using the TYPE or LIKE addition. If you specify a generic type, the type of the formal parameter is either partially specified or not specified at all. Any attributes that are not specified are inherited from the corresponding actual parameter when the subroutine is called. If you specify the type fully, all of the technical attributes of the formal parameter are defined with the subroutine definition.

The following remarks about specifying the types of parameters also apply to the parameters of other procedures (function modules and methods). If you have specified the type of the formal parameters, the system checks that the

corresponding actual parameters are compatible when the subroutine is called. For internal subroutines, the system checks this in the syntax check. For external subroutines, the check cannot occur until runtime. By specifying the type, you ensure that a subroutine always works with the correct data type. Generic formal parameters allow a large degree of freedom when you call subroutines, since you can pass data of any type. This restricts accordingly the options for processing data in the subroutine, since the operations must be valid for all data types. For example, assigning one data object to another may not even be possible for all data types. If you specify the types of subroutine parameters, you can perform a much wider range of operations, since only the data appropriate to those operations can be passed in the call. If you want to process structured data objects component by component in a subroutine, you must specify the type of the parameter.

<b>Passing Parameters to Subroutines</b>

If a subroutine has a parameter interface, you must supply values to all of the formal parameters in its interface when you call it. You list the actual parameters after the USING or CHANGING addition in the PERFORM statement.

When you pass the values, the sequence of the actual parameters in the PERFORM statement is crucial. The value of the first actual parameter in the list is passed to the first formal parameter, the second to the second, and so on. The additions USING and CHANGING have exactly the same meaning. You only need to use one or the other. However, for documentary reasons, it is a good idea to divide the parameters in the same way in which they occur in the interface definition.

Actual parameters can be any data objects or field symbols of the calling program whose technical attributes are compatible with the type specified for the corresponding formal parameter. When you specify the actual parameters, note that any that you pass by reference to a formal parameter, and any that you pass by value to an output parameter, can be changed by the subroutine. You should therefore ensure that only data objects that you want to be changed appear in the corresponding position of the actual parameter list.

If a subroutine contains TABLES parameters in its interface, you must specify them in a TABLES addition of the PERFORM statement before the USING and CHANGING parameters. TABLES parameters are only supported to ensure compatibility with earlier releases, and should no longer be used.

You can use offset addressing for actual parameters in the same way as offset addressing for field symbols. That is, you can select memory areas that lie outside the boundaries of the specified actual parameter.

PROGRAM form_test.

DATA: a1 TYPE p DECIMALS 3,

a2 TYPE i,

a3 TYPE d,

a4 TYPE spfli-carrid,

a5(1) TYPE c.

...

PERFORM subr USING a1 a2 a3 a4 a5.

...

PERFORM subr CHANGING a1 a2 a3 a4 a5.

...

PERFORM subr USING a1 a2 a3

CHANGING a4 a5.

...

FORM subr USING

value(f1) TYPE p

value(f2) TYPE i

f3 LIKE a3

CHANGING

value(f4) TYPE spfli-carrid

f5.

...

ENDFORM.

This example defines a subroutine SUBR with a parameter interface consisting of five formal parameters, F1 to F5. The subroutine is called internally three times. The actual parameters are the data objects A1 to A5. The three subroutine calls are all equally valid. There are further PERFORM statements that are also equally valid, so long as the sequence of the actual parameters remains unchanged. In each call, A1 is passed to F1, A2 to F2, and so on. When the subroutine ends, A3, A4, and A5 receive the values of F3, F4, and F5 respectively. The third of the subroutine calls documents in the program what the parameter interface of the subroutine shows, namely that only A4 and A5 are changed. Whether A3 is changed depends on the way in which the subroutine is programmed.

The following example shows how generically-typed formal parameters inherit their technical attributes from their corresponding actual parameters.

REPORT demo_mod_tech_describe.

DATA:

date1 TYPE d, date2 TYPE t,

string1(6) TYPE c, string2(8) TYPE c,

number1 TYPE p DECIMALS 2, number2 TYPE p DECIMALS 0,

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(1) TYPE c.

DESCRIBE FIELD now TYPE t.

WRITE: / 'Type of NOW is', 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.

This produces the following output:

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

An internal subroutine TYPETEST is called twice with different actual parameters. All actual and formal parameters are compatible and no error message occurs during the syntax check. Had you declared COUNT2 with type F instead of type I, the syntax check would have returned an error, since the formal parameter INT is specified with type I. The formal parameters with generic types adopt different technical attributes depending on their corresponding technical attributes.

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.

<b>Example of passing internal tables</b>

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.

<b>Reward if usefull</b>

5 REPLIES 5
Read only

Former Member
0 Likes
2,205

Hi,

By Value:

The value of the parameter is transmited, no feed back, no update possible.


PERFORM subr USING a1 a2 a3 a4 a5

For more sample code, please check this link. http://help.sap.com/saphelp_47x200/helpdata/en/9f/db979d35c111d1829f0000e829fbfe/frameset.htm

By Reference:

A pointer to the field is transmited, so the parameter can be updated in the calling program.


PERFORM subr CHANGING a1 a2 a3 a4 a5

For more sample code, please check this link.

http://help.sap.com/saphelp_47x200/helpdata/en/9f/db979035c111d1829f0000e829fbfe/frameset.htm

Regards,

Ferry Lianto

Read only

Former Member
0 Likes
2,205

Ferry noted the main differences, but you should also note that passing by value can be very costly in terms of memory and CPU cycles when the parameter being passed is large, since the entire value is copied to a new location in memory, even if it is a large structure or table. This is especially problematic if the routine is called frequently.

Passing by reference just passes a pointer to the original field, and is generally more efficient.

Good luck

Brian

Read only

varma_narayana
Active Contributor
0 Likes
2,205

Hi..

Pass by Value : in this case the Formal parameters will receive the values of Actual parameters. So changes to the Formal parameters will not be reflected to Actual parameters.

Pass by Reference: in this case the Formal parameters will not have any memory. They are just pointers to Actual parameters. So changes to the Formal parameters will be reflected to Actual parameters.

Eg:

DATA: A TYPE I VALUE 1,

B TYPE I VALUE 2.

PERFORM F_SWAP_VAL USING A B.

WRITE:/ A,B.

PERFORM F_SWAP_REF USING A B.

WRITE:/ A,B.

FORM F_SWAP_VAL USING VALUE(X) VALUE(Y). "PASS BY VALUE

DATA : TEMP TYPE I.

TEMP = X.

X = Y.

Y = TEMP.

ENDFORM.

FORM F_SWAP_REF USING X Y. "PASS BY REF

DATA : TEMP TYPE I.

TEMP = X.

X = Y.

Y = TEMP.

ENDFORM.

<b>Reward if Helpful.</b>

Read only

uwe_schieferstein
Active Contributor
0 Likes
2,205

Hello Akash

The following sample report ZUS_SDN_BY_VALUE_VS_REFERENCE shows you the different effects of passing USING or CHANGING parameters either BY VALUE or BY REFERENCE. As you can see from the results you may end up with wrong data returned from your subroutine if you are not aware of the differences.

When I use subroutines I treat the USING parameters (which I pass BY VALUE) within the subroutine almost like constants. Only the CHANGING parameters will be changed in the subroutine.

*&---------------------------------------------------------------------*
*& Report  ZUS_SDN_BY_VALUE_VS_REFERENCE
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT  zus_sdn_by_value_vs_reference.


DATA:
  gd_value_1    TYPE  kunnr,
  gd_value_2    TYPE  kunnr,
  gd_value_3    TYPE  kunnr,
  gd_value_4    TYPE  kunnr.


START-OF-SELECTION.



  gd_value_1 = gd_value_2 = gd_value_3 = gd_value_4 = '1'.
  WRITE: / 'Values before subroutine:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  PERFORM routine_1
                USING
                   gd_value_1
                   gd_value_2
             CHANGING
                   gd_value_3
                   gd_value_4.
  WRITE: / 'ROUTINE_1: all BY REFERENCE:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  SKIP.


  gd_value_1 = gd_value_2 = gd_value_3 = gd_value_4 = '1'.
  WRITE: / 'Values before subroutine:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  PERFORM routine_2
                USING
                   gd_value_1
                   gd_value_2
             CHANGING
                   gd_value_3
                   gd_value_4.
  WRITE: / 'ROUTINE_1: USING passed BY VALUE:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  SKIP.

  gd_value_1 = gd_value_2 = gd_value_3 = gd_value_4 = '1'.
  WRITE: / 'Values before subroutine:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  PERFORM routine_3
                USING
                   gd_value_1
                   gd_value_2
             CHANGING
                   gd_value_3
                   gd_value_4.
  WRITE: / 'ROUTINE_3: CHANGING passed BY VALUE:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  SKIP.



  gd_value_1 = gd_value_2 = gd_value_3 = gd_value_4 = '1'.
  WRITE: / 'Values before subroutine:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  PERFORM routine_4
                USING
                   gd_value_1
                   gd_value_2
             CHANGING
                   gd_value_3
                   gd_value_4.
  WRITE: / 'ROUTINE_4: all BY VALUE:',
           AT 50 gd_value_1, gd_value_2, gd_value_3, gd_value_4.
  SKIP.


END-OF-SELECTION.


*&---------------------------------------------------------------------*
*&      Form  ROUTINE_1
*&---------------------------------------------------------------------*
*       Pass all parameters BY REFERENCE
*----------------------------------------------------------------------*
*      -->P_GD_VALUE_1  text
*      -->P_GD_VALUE_2  text
*      <--P_GD_VALUE_3  text
*      <--P_GD_VALUE_4  text
*----------------------------------------------------------------------*
FORM routine_1  USING
                   ud_value_1
                   ud_value_2
                CHANGING
                   cd_value_3
                   cd_value_4.
  " NOTE: all values will be changed!!!
  ADD 1 TO: ud_value_1,
            ud_value_2,
            cd_value_3,
            cd_value_4.

ENDFORM.                                                    " ROUTINE_1

*&---------------------------------------------------------------------*
*&      Form  ROUTINE_2
*&---------------------------------------------------------------------*
*       Pass USING parameters BY VALUE
*----------------------------------------------------------------------*
*      -->P_GD_VALUE_1  text
*      -->P_GD_VALUE_2  text
*      <--P_GD_VALUE_3  text
*      <--P_GD_VALUE_4  text
*----------------------------------------------------------------------*
FORM routine_2  USING
                   value(ud_value_1)
                   value(ud_value_2)
                CHANGING
                   cd_value_3
                   cd_value_4.
  " NOTE: only values passed BY REFERENCE will be changed!!!
  ADD 1 TO: ud_value_1,
            ud_value_2,
            cd_value_3,
            cd_value_4.

ENDFORM.                                                    " ROUTINE_2


*&---------------------------------------------------------------------*
*&      Form  ROUTINE_3
*&---------------------------------------------------------------------*
*       Pass CHANGING parameters BY VALUE
*----------------------------------------------------------------------*
*      -->P_GD_VALUE_1  text
*      -->P_GD_VALUE_2  text
*      <--P_GD_VALUE_3  text
*      <--P_GD_VALUE_4  text
*----------------------------------------------------------------------*
FORM routine_3  USING
                   ud_value_1
                   ud_value_2
                CHANGING
                   value(cd_value_3)
                   value(cd_value_4).
  " NOTE: ALL values will be changed!!!
  ADD 1 TO: ud_value_1,
            ud_value_2,
            cd_value_3,
            cd_value_4.

ENDFORM.                                                    " ROUTINE_3




*&---------------------------------------------------------------------*
*&      Form  ROUTINE_4
*&---------------------------------------------------------------------*
*       Pass all parameters BY VALUE
*----------------------------------------------------------------------*
*      -->P_GD_VALUE_1  text
*      -->P_GD_VALUE_2  text
*      <--P_GD_VALUE_3  text
*      <--P_GD_VALUE_4  text
*----------------------------------------------------------------------*
FORM routine_4  USING
                   value(ud_value_1)
                   value(ud_value_2)
                CHANGING
                   value(cd_value_3)
                   value(cd_value_4).
  " NOTE: only CHANGING values will be changed!!!
  ADD 1 TO: ud_value_1,
            ud_value_2,
            cd_value_3,
            cd_value_4.

ENDFORM.                                                    " ROUTINE_4

The following sample report <b>ZUS_SDN_ALV_VALUE_VS_REFERENCE</b> demonstrates that you cannot pass the output itab for an ALV list BY VALUE to the grid instance.

Why?

The output itab is a CHANGING parameter of method SET_TABLE_FOR_FIRST_DISPLAY. The grid instance must have access to the original itab in order to perform changes like sorting, filtering, etc. If you pass the output itab BY VALUE then the grid instance works on a copy of the original itab which does not make sense because changes of the ALV list cannot be propagated back to the output itab in the ABAP program.

*&---------------------------------------------------------------------*
*& Report  ZUS_SDN_ALV_VALUE_VS_REFERENCE
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT  zus_sdn_alv_value_vs_reference.

TYPES:
  zus_knb1_ttyp    TYPE STANDARD TABLE OF knb1.

DATA:
  gt_knb1      TYPE zus_knb1_ttyp.  " table type of KNB1



PARAMETERS:
  p_byval      RADIOBUTTON GROUP grp,  " pass by value
  p_byref      RADIOBUTTON GROUP grp.  " pass by reference


*---------------------------------------------------------------------*
*       CLASS lcl_myclass DEFINITION
*---------------------------------------------------------------------*
*
*---------------------------------------------------------------------*
CLASS lcl_myclass DEFINITION.

  PUBLIC SECTION.
    CLASS-DATA:
      mt_itab      TYPE zus_knb1_ttyp,
*
      ms_layout    TYPE lvc_s_layo,
      mo_docking   TYPE REF TO cl_gui_docking_container,
      mo_alvgrid   TYPE REF TO cl_gui_alv_grid.

    CLASS-METHODS:
      changing_itab_byref
        CHANGING
          ct_itab  TYPE zus_knb1_ttyp,

      changing_itab_byval
        CHANGING
          value(ct_itab)  TYPE zus_knb1_ttyp,


      create_controls.


ENDCLASS.                    "lcl_myclass DEFINITION









*---------------------------------------------------------------------*
*       CLASS lcl_myclass IMPLEMENTATION
*---------------------------------------------------------------------*
*
*---------------------------------------------------------------------*
CLASS lcl_myclass IMPLEMENTATION.


  METHOD changing_itab_byref.

    CALL METHOD mo_alvgrid->set_table_for_first_display
      EXPORTING
        i_structure_name              = 'KNB1'
*        IS_VARIANT                    =
*        I_SAVE                        =
*        I_DEFAULT                     = 'X'
        is_layout                     = ms_layout
      CHANGING
        it_outtab                     = ct_itab
      EXCEPTIONS
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
        OTHERS                        = 4.
    IF sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.

  ENDMETHOD.                    "changing_itab_byref


  METHOD changing_itab_byval.
    CALL METHOD mo_alvgrid->set_table_for_first_display
      EXPORTING
        i_structure_name              = 'KNB1'
*        IS_VARIANT                    =
*        I_SAVE                        =
*        I_DEFAULT                     = 'X'
        is_layout                     = ms_layout
      CHANGING
        it_outtab                     = ct_itab
      EXCEPTIONS
        invalid_parameter_combination = 1
        program_error                 = 2
        too_many_lines                = 3
        OTHERS                        = 4.
    IF sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.

  ENDMETHOD.                    "changing_itab_byval




  METHOD create_controls.
    CREATE OBJECT mo_docking
      EXPORTING
        parent                      = cl_gui_container=>screen0
*        REPID                       =
*        DYNNR                       =
*        SIDE                        = DOCK_AT_LEFT
*        EXTENSION                   = 50
         ratio                       = 90
      EXCEPTIONS
        OTHERS                      = 99.
    IF sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.

    CALL METHOD mo_docking->set_extension
      EXPORTING
        extension  = 99999  " use full screen size
      EXCEPTIONS
        cntl_error = 1
        OTHERS     = 2.
    IF sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.


    CREATE OBJECT mo_alvgrid
      EXPORTING
        i_parent          = mo_docking
      EXCEPTIONS
        OTHERS            = 99.
    IF sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.


*    ms_layout-edit = 'X'.  " editable ALV grid


  ENDMETHOD.                    "create_controls


ENDCLASS.                    "lcl_myclass IMPLEMENTATION





START-OF-SELECTION.


  SELECT        * FROM  knb1 INTO TABLE gt_knb1
         WHERE  bukrs  = '2000'.

  lcl_myclass=>mt_itab = gt_knb1.
  lcl_myclass=>create_controls( ).


  IF ( p_byref = 'X' ).
    CALL METHOD lcl_myclass=>changing_itab_byref
      CHANGING
        ct_itab = lcl_myclass=>mt_itab.

  ELSE.  " p_byval = 'X'
    CALL METHOD lcl_myclass=>changing_itab_byval
      CHANGING
        ct_itab = lcl_myclass=>mt_itab.
  ENDIF.



  CALL METHOD lcl_myclass=>mo_docking->link
    EXPORTING
      repid                       = syst-repid
      dynnr                       = '0100'
*      CONTAINER                   =
    EXCEPTIONS
      cntl_error                  = 1
      cntl_system_error           = 2
      lifetime_dynpro_dynpro_link = 3
      OTHERS                      = 4.
  IF sy-subrc <> 0.
*   MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*              WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
  ENDIF.


* NOTE: dynpro contains no elements
  CALL SCREEN '0100'.


END-OF-SELECTION.


*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.

  CASE syst-ucomm.
    WHEN 'REFRESH'.
      lcl_myclass=>mo_alvgrid->refresh_table_display( ).

    WHEN OTHERS.
      SET SCREEN 0. LEAVE SCREEN.
  ENDCASE.
ENDMODULE.                 " USER_COMMAND_0100  INPUT

Regards

Uwe

Read only

Former Member
0 Likes
2,206

Hi

<b>The Parameter Interface</b>

The USING and CHANGING additions in the FORM statement define the formal parameters of a subroutine. The sequence of the additions is fixed. Each addition can be followed by a list of any number of formal parameters. When you call a subroutine, you must fill all formal parameters with the values from the actual parameters. At the end of the subroutine, the formal parameters are passed back to the corresponding actual parameters.

Within a subroutine, formal parameters behave like dynamic local data. You can use them in the same way as normal local data objects that you would declare with the DATA statement. They mask global data objects with the same name. The value of the parameters at the start of the subroutine is the value passed from the corresponding actual parameter.

<b>Subroutines can have the following formal parameters:</b>

Parameters Passed by Reference

You list these parameters after USING or CHANGING without the VALUE addition:

FORM <subr> USING ... <pi> [TYPE <t>|LIKE <f>] ...

CHANGING ... <pi> [TYPE <t>|LIKE <f>] ...

The formal parameter occupies no memory of its own. During a subroutine call, only the address of the actual parameter is transferred to the formal parameter. The subroutine works with the field from the calling program. If the value of the formal parameter changes, the contents of the actual parameter in the calling program also change.

For calling by reference, USING and CHANGING are equivalent. For documentation purposes, you should use USING for input parameters which are not changed in the subroutine, and CHANGING for output parameters which are changed in the subroutine.

To avoid the value of an actual parameter being changed automatically, you must pass it by value.

<b>Input Parameters That Pass Values</b>

You list these parameters after USING with the VALUE addition:

FORM <subr> USING ... VALUE(<pi>) [TYPE <t>|LIKE <f>] ...

The formal parameter occupies its own memory space. When you call the subroutine, the value of the actual parameter is passed to the formal parameter. If the value of the formal parameter changes, this has no effect on the actual parameter.

<b>Output Parameters That Pass Values</b>

You list these parameters after CHANGING with the VALUE addition:

FORM <subr> CHANGING ... VALUE(<pi>) [TYPE <t>|LIKE <f>] ...

The formal parameter occupies its own memory space. When you call the subroutine, the value of the actual parameter is passed to the formal parameter. If the subroutine concludes successfully, that is, when the ENDFORM statement occurs, or when the subroutine is terminated through a CHECK or EXIT statement, the current value of the formal parameter is copied into the actual parameter.

If the subroutine terminates prematurely due to an error message, no value is passed. It only makes sense to terminate a subroutine through an error message in the PAI processing of a screen, that is, in a PAI module, in the AT SELECTION-SCREEN event, or after an interactive list event.

<b>Specifying the Type of Formal Parameters</b>

Formal parameters can have any valid ABAP data type. You can specify the type of a formal parameter, either generically or fully, using the TYPE or LIKE addition. If you specify a generic type, the type of the formal parameter is either partially specified or not specified at all. Any attributes that are not specified are inherited from the corresponding actual parameter when the subroutine is called. If you specify the type fully, all of the technical attributes of the formal parameter are defined with the subroutine definition.

The following remarks about specifying the types of parameters also apply to the parameters of other procedures (function modules and methods). If you have specified the type of the formal parameters, the system checks that the

corresponding actual parameters are compatible when the subroutine is called. For internal subroutines, the system checks this in the syntax check. For external subroutines, the check cannot occur until runtime. By specifying the type, you ensure that a subroutine always works with the correct data type. Generic formal parameters allow a large degree of freedom when you call subroutines, since you can pass data of any type. This restricts accordingly the options for processing data in the subroutine, since the operations must be valid for all data types. For example, assigning one data object to another may not even be possible for all data types. If you specify the types of subroutine parameters, you can perform a much wider range of operations, since only the data appropriate to those operations can be passed in the call. If you want to process structured data objects component by component in a subroutine, you must specify the type of the parameter.

<b>Passing Parameters to Subroutines</b>

If a subroutine has a parameter interface, you must supply values to all of the formal parameters in its interface when you call it. You list the actual parameters after the USING or CHANGING addition in the PERFORM statement.

When you pass the values, the sequence of the actual parameters in the PERFORM statement is crucial. The value of the first actual parameter in the list is passed to the first formal parameter, the second to the second, and so on. The additions USING and CHANGING have exactly the same meaning. You only need to use one or the other. However, for documentary reasons, it is a good idea to divide the parameters in the same way in which they occur in the interface definition.

Actual parameters can be any data objects or field symbols of the calling program whose technical attributes are compatible with the type specified for the corresponding formal parameter. When you specify the actual parameters, note that any that you pass by reference to a formal parameter, and any that you pass by value to an output parameter, can be changed by the subroutine. You should therefore ensure that only data objects that you want to be changed appear in the corresponding position of the actual parameter list.

If a subroutine contains TABLES parameters in its interface, you must specify them in a TABLES addition of the PERFORM statement before the USING and CHANGING parameters. TABLES parameters are only supported to ensure compatibility with earlier releases, and should no longer be used.

You can use offset addressing for actual parameters in the same way as offset addressing for field symbols. That is, you can select memory areas that lie outside the boundaries of the specified actual parameter.

PROGRAM form_test.

DATA: a1 TYPE p DECIMALS 3,

a2 TYPE i,

a3 TYPE d,

a4 TYPE spfli-carrid,

a5(1) TYPE c.

...

PERFORM subr USING a1 a2 a3 a4 a5.

...

PERFORM subr CHANGING a1 a2 a3 a4 a5.

...

PERFORM subr USING a1 a2 a3

CHANGING a4 a5.

...

FORM subr USING

value(f1) TYPE p

value(f2) TYPE i

f3 LIKE a3

CHANGING

value(f4) TYPE spfli-carrid

f5.

...

ENDFORM.

This example defines a subroutine SUBR with a parameter interface consisting of five formal parameters, F1 to F5. The subroutine is called internally three times. The actual parameters are the data objects A1 to A5. The three subroutine calls are all equally valid. There are further PERFORM statements that are also equally valid, so long as the sequence of the actual parameters remains unchanged. In each call, A1 is passed to F1, A2 to F2, and so on. When the subroutine ends, A3, A4, and A5 receive the values of F3, F4, and F5 respectively. The third of the subroutine calls documents in the program what the parameter interface of the subroutine shows, namely that only A4 and A5 are changed. Whether A3 is changed depends on the way in which the subroutine is programmed.

The following example shows how generically-typed formal parameters inherit their technical attributes from their corresponding actual parameters.

REPORT demo_mod_tech_describe.

DATA:

date1 TYPE d, date2 TYPE t,

string1(6) TYPE c, string2(8) TYPE c,

number1 TYPE p DECIMALS 2, number2 TYPE p DECIMALS 0,

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(1) TYPE c.

DESCRIBE FIELD now TYPE t.

WRITE: / 'Type of NOW is', 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.

This produces the following output:

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

An internal subroutine TYPETEST is called twice with different actual parameters. All actual and formal parameters are compatible and no error message occurs during the syntax check. Had you declared COUNT2 with type F instead of type I, the syntax check would have returned an error, since the formal parameter INT is specified with type I. The formal parameters with generic types adopt different technical attributes depending on their corresponding technical attributes.

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.

<b>Example of passing internal tables</b>

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.

<b>Reward if usefull</b>