Read non-global variable from another program in runtime

10,009

I think the documentation says it all :

For internal use only, the name in name can also have the form "(PROG)DOBJ", where "PROG" is the name of an ABAP program and "DOBJ" the name of a global data object of this program (these names are not case-sensitive). If the program "PROG" is loaded into the same internal session as the current program when the statement ASSIGN is executed, the data object "DOBJ" is found in this program and the field symbol points to this data object if the assignment was successful.

Note the "for internal use only", i.e. this special form of ASSIGN may be removed in any future ABAP version (but I doubt).

So, probably you want to access a variable that is not global, i.e. either local, instance attribute, or private/protected static attribute...

ASSIGN ('PROG(DOBJ)') works with a common part because it has a global scope. Note that a common part may also be used without ASSIGN by other programs which belong to the same "group" (1), by declaring the same name of "common part".

If you can adapt the program (because it's custom), prefer refactoring it a little bit so that the data can be accessed externally, rather than using the below trick.

If you can't adapt the program (because it's standard), there is the following workaround to access a local data object.

Let's say this program is "PROG" and it contains the procedure "X", which contains the local data object "LOCVAR" that you want to read. You may use the Enhancement Framework to do that. So, to make it accessible from external programs:

  • In PROG, declare a global data reference variable (2), say DATA ZZ_REF_LOCVAR TYPE REF TO DATA (recommendation: prefix it "ZZ" to limit conflicts with future patches of the program)
  • At the beginning of the procedure "X", initialize ZZ_REF_LOCVAR by the code ASSIGN ('LOCVAR') TO FIELD-SYMBOL(<zz_locvar>). zz_ref = ref #( <zz_locvar> ). (3)
  • In your own program, if the procedure "X" is currently in the call stack, that you may check with the class CL_ABAP_GET_CALL_STACK, you may now access the global data reference which points to the local variable with this code: FIELD-SYMBOLS <ref_locvar> TYPE REF TO DATA. FIELD-SYMBOLS <locvar>. ASSIGN ('(PROG)ZZ_REF_LOCVAR') TO <ref_locvar>. ASSIGN <ref_locvar>->* TO <locvar>.
  • A little variant of this solution is to declare ZZ_REF_LOCVAR as a static public attribute in a custom class pool, and access it from both the standard program PROG and your own code.

Be careful, it may not work anymore if a future patch removes the local variable. This remark is valid for global variables too, anyway.


(1) Note: a "group" of programs is formed of programs called via PERFORM IN PROGRAM or CALL SUBSCREEN by PROG, and they have a common memory area called "interface work area".

(2) Note: I propose a global data reference variable rather than a global field symbol, because field symbols cannot be declared globally in programs like class pools.

(3) Note: an implicit enhancement at the beginning of the procedure "X" cannot access the local variables directly by naming them, because their DATA is after the enhancement; the workaround is to use a field symbol to access the local variable at run-time.

Share:
10,009
Pedro Accorsi
Author by

Pedro Accorsi

Updated on June 06, 2022

Comments

  • Pedro Accorsi
    Pedro Accorsi over 1 year

    I'd like to access a variable from level 5 when I'm at level 11 of the stack.

    Both levels are of different programs:

    lvl    type       event              program                 include 
    11     METHOD     SET_PERNRS_TAB     <my_program>            <my_include>.
    ...
    05     FORM       PUT_PERNR          <ldb_program>          <ldb_include>.
    04     FORM       %_ROOT             <ldb_program>          <ldb_include>.
    ...
    

    This is how I'm currently doing it:

    constants lc_ldb_pernr_tab   type string value `(LDB_PROGRAM)INDEX[]`.
    field-symbols <lt_pernr_tab> type any table.
    
    assign (lc_ldb_pernr_tab) to <lt_pernr_tab>.
    

    And now I can use <lt_pernr_tab>, which is a 'copy' of the variable index[] that came from the LDB, in another program.

    The problem here is that it works only with some variables, but not with others... please find below the declaration of two variables, inside the ldb progam.

    I'm trying to get to their value from my progam, but only one works.

    1. the one that works, index:
    DATA: BEGIN OF COMMON PART $pnp-index$.
      DATA: BEGIN OF index OCCURS 1000,
              pernr LIKE pernr-pernr,
            END OF index.
    DATA: END   OF COMMON PART.
    
    1. the one that doesnt, index_all:
      DATA: index_all TYPE t_t_pernr.
    

    This means that this process of (program)variable only works with variables that are declared as "common part" by the ldb?

    In other words, it is impossible to get the content of index_all from the LDB program when I'm inside my program, since it is not of "common part"?

    -> to give a little context, index_all has all the entries I need, whilst index is just a partition of index_all. The ldb iterates through index and when its done, it updates it with the next indexes of index_all.