Friday, December 23, 2011

SAP ABAP Write a cluster object to a correction request (transport)

Today i would like to illustrate how to write an object to a transport file.
As usual i provide some real life example.
I this case writing a Payroll cluster to a CR, in order to trasport it.

The local class lcl_tabu_k_2_trkorr_writer encapsulates the writing logic.
Even though it can be definitely improved, it is designed so that further special objects like a PCL table can be added easily.

The key concepts are:
  1. Table E071 contains the objects in form "R3TR TABU TABLENAME"
  2. TABU means table contents
  3. When you specify TABU in a transport the you are expcted to specify also che keys you would like to transport
  4. These keys are written to table E071K
  5. In the program standard structures are used for the keys and transport entries. This allows to use standard functions and thus to check the correctness of what we are transporting with regard to the type of system (production, test, development, SAP o customer system etc) and to the type of object (name space, development class) etc.
  6. Often these functions are bypassed and the tables e071 and the keys are written directly to the database. I wouldn't reccomend this.
  7. Be very careful: if you transport TABU * then the whole table is erased before importing the data in the trasport files. This means that you cannot use TABU * to add data to a table without actually losing data
  8. The behaviour described in point 7 might be release dependent therefore its use is highly discouraged

Here is the coding



**&---------------------------------------------------------------------*
*& Report   zCLUSTER_2_CR                                           *
*&                                                                     *
*&---------------------------------------------------------------------*
*&                                                                     *
*&                                                                     *
*&---------------------------------------------------------------------*

REPORT   zcluster_2_cr                 .

TABLES: pernr.


*PARAMETERS:     trkorr    TYPE trkorr.
PARAMETERS:     wbtrkorr TYPE trkorr.
PARAMETERS:     uname     TYPE sy-uname.
PARAMETERS:     test      TYPE boole_d DEFAULT 'X'.


INITIALIZATION.
  uname = sy-uname.
*  limit = 99999999.

*AT SELECTION-SCREEN ON VALUE-REQUEST FOR trkorr.
*
*  PERFORM select_tr_korr USING uname 'CUST' CHANGING trkorr.


AT SELECTION-SCREEN ON VALUE-REQUEST FOR wbtrkorr.

  PERFORM select_tr_korr USING uname 'SYST' CHANGING wbtrkorr.


*---------------------------------------------------------------------*
*       CLASS lcl_tabu_k_2_trkorr_writer DEFINITION
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
CLASS lcl_tabu_k_2_trkorr_writer DEFINITION.
  PUBLIC SECTION.


* gets the name of the receiver given the temse file type.
    METHODS: init    IMPORTING p_trkorr        TYPE trkorr
                               p_wb_trkorr     TYPE trkorr
                               p_tabname       TYPE tabname
                     CHANGING  p_error         TYPE i.

    METHODS: write_to_trkorr     CHANGING p_error TYPE i.
    METHODS: write_to_trkorr_blk CHANGING p_error TYPE i.

    METHODS: add_line_key IMPORTING p_line     TYPE any
                          CHANGING  p_error TYPE i .
    METHODS: add_object   IMPORTING pgmid     TYPE pgmid
                                    object    TYPE trobjtype
                                    obj_name  TYPE trobj_name
                                    p_trkorr  TYPE trkorr
                          CHANGING  p_error TYPE i .
    METHODS: add_star_key CHANGING  p_error TYPE i .

    METHODS: get_metahead CHANGING p_error TYPE i.

  PRIVATE SECTION.

    DATA: a_trkorr        TYPE trkorr.
    DATA: a_wb_trkorr     TYPE trkorr.
    DATA: as_obj          TYPE LINE OF tredt_objects.
    DATA: as_metahead     TYPE x030l.
    DATA: a_tabname       TYPE tabname.
    DATA: ar_typedescr    TYPE REF TO cl_abap_typedescr.
    DATA: ar_tableline    TYPE REF TO data.
    DATA: at_key          TYPE tredt_keys.


ENDCLASS.                    "DEFINITION


*---------------------------------------------------------------------*
*       CLASS lcl_tabu_k_2_trkorr_writer IMPLEMENTATION
*---------------------------------------------------------------------*
*       ........                                                      *
*---------------------------------------------------------------------*
CLASS lcl_tabu_k_2_trkorr_writer IMPLEMENTATION.


  METHOD: init.

    CLEAR:   as_obj,
             as_metahead,
             ar_typedescr,
             ar_tableline,
             a_tabname,
             at_key.
    FREE at_key.

    a_trkorr     = p_trkorr.
    a_wb_trkorr  = p_wb_trkorr.
    a_tabname    = p_tabname.

    CALL METHOD get_metahead CHANGING p_error = p_error.

  ENDMETHOD.

  METHOD: add_object.
*                          IMPORTING pgmid     TYPE pgmid
*                                    object    type TROBJTYPE
*                                    obj_name  type TROBJ_NAME
*                                    p_trkorr  type trkorr
*                          CHANGING  p_error TYPE i .

    as_obj-trkorr   = p_trkorr.
    as_obj-pgmid    = pgmid.
    as_obj-object   = object.
    as_obj-obj_name = obj_name.
    as_obj-objfunc  = space.


  ENDMETHOD.

  METHOD: add_star_key.
* MAKE TABU *
    DATA: ls_key          TYPE LINE OF tredt_keys.

* Transport object
    as_obj-trkorr   = a_trkorr.
    as_obj-pgmid    = 'R3TR'.
    as_obj-object   = 'TABU'.
    as_obj-obj_name = as_metahead-tabname.
    as_obj-objfunc  = 'K'.

* Initialize entry for table key transport
    MOVE-CORRESPONDING as_obj TO ls_key.
    ls_key-objname    = as_obj-obj_name.
    ls_key-objfunc    = space.
    ls_key-mastername = as_obj-obj_name.
    ls_key-mastertype = as_obj-object.
    ls_key-tabkey     = '*'.


*   Insert key of tableline into transport request
    INSERT ls_key INTO TABLE at_key.
  ENDMETHOD.

  METHOD: add_line_key.
*MAKE TABU K
    FIELD-SYMBOLS:
      <ls_tableline>  TYPE ANY,
      <lv_xtableline> TYPE x,
      <lv_xtabkey>    TYPE x.

    DATA: ls_key          TYPE LINE OF tredt_keys.

*4.7 Only
* Get metadata of the linetype of the given table
*  lo_typedescr = cl_abap_typedescr=>describe_by_data(
*      p_data = line ).
*  CALL METHOD lo_typedescr->get_ddic_header
*    RECEIVING
*      p_header = ls_metahead
*    EXCEPTIONS
*      OTHERS   = 1.
*  IF sy-subrc <> 0.
*    pv_error = 1.
*    EXIT.
*  ENDIF.

* Transport object
    as_obj-trkorr   = a_trkorr.
    as_obj-pgmid    = 'R3TR'.
    as_obj-object   = 'TABU'.
    as_obj-obj_name = as_metahead-tabname.
    as_obj-objfunc  = 'K'.

* Initialize entry for table key transport
    MOVE-CORRESPONDING as_obj TO ls_key.
    ls_key-objname    = as_obj-obj_name.
    ls_key-objfunc    = space.
    ls_key-mastername = as_obj-obj_name.
    ls_key-mastertype = as_obj-object.


*   Extract tablekey
    CLEAR ls_key-tabkey.
    ASSIGN ls_key-tabkey TO <lv_xtabkey> CASTING.

*   If table has fields of type STRING or RAWSTRING, casting to type
*   'X' is not possible -> generic solution unknown -> indiv. handling
    CASE as_metahead-tabname.
      when 'PCL2'.
        DATA l_key(46) type c.
        l_key+0(45) = p_line.
        l_key+45(1) = '*'.
        ASSIGN l_key TO <lv_xtableline> CASTING.
        <lv_xtabkey>(46) = <lv_xtableline>(46).
        INSERT ls_key INTO TABLE at_key.
        exit.
      WHEN OTHERS.
        ASSIGN p_line TO <lv_xtableline> CASTING.
    ENDCASE.

*   Copy key prefix
    <lv_xtabkey>(as_metahead-keylen) = <lv_xtableline>.

*   Insert key of tableline into transport request
    INSERT ls_key INTO TABLE at_key.
  ENDMETHOD.


  METHOD: write_to_trkorr_blk.
    DATA lt_ko200 TYPE TABLE OF ko200.
    DATA ls_e071 TYPE e071.
    DATA lt_key  TYPE tredt_keys.
    DATA blk_size TYPE i VALUE 10000.

    IF as_obj IS INITIAL OR
       at_key IS INITIAL.
      EXIT.
    ENDIF.

    APPEND as_obj TO lt_ko200.
    MOVE-CORRESPONDING as_obj TO ls_e071.

    DO.

      IF at_key IS INITIAL.
        EXIT.
      ENDIF.

      REFRESH lt_key.

      APPEND LINES OF at_key FROM 1 TO blk_size TO lt_key.
      DELETE at_key FROM 1 TO blk_size.

** Check data for transport request
* Add data to transport request
      CALL FUNCTION 'TR_OBJECTS_CHECK'
           TABLES
                wt_ko200 = lt_ko200
                wt_e071k = lt_key
           EXCEPTIONS
                OTHERS   = 1.

*This one only swallows a Task
      CALL FUNCTION 'TR_APPEND_TO_COMM'
           EXPORTING
                pi_korrnum                     = a_trkorr
                wi_e071                        = ls_e071
                wi_simulation                  = test
                wi_suppress_key_check          = 'X'
           TABLES
                wt_e071k                       = lt_key
           EXCEPTIONS
                no_authorization               = 1
                no_systemname                  = 2
                no_systemtype                  = 3
                tr_check_keysyntax_error       = 4
                tr_check_obj_error             = 5
                tr_enqueue_failed              = 6
                tr_ill_korrnum                 = 7
                tr_key_without_header          = 8
                tr_lockmod_failed              = 9
                tr_lock_enqueue_failed         = 10
                tr_modif_only_in_modif_order   = 11
                tr_not_owner                   = 12
                tr_no_append_of_corr_entry     = 13
                tr_no_append_of_c_member       = 14
                tr_no_shared_repairs           = 15
                tr_order_not_exist             = 16
                tr_order_released              = 17
                tr_order_update_error          = 18
                tr_repair_only_in_repair_order = 19
                tr_wrong_order_type            = 20
                wrong_client                   = 21
                OTHERS                         = 22.
      IF sy-subrc <> 0.
        CALL FUNCTION 'TR_APPEND_TO_COMM'
             EXPORTING
                  pi_korrnum                     = a_wb_trkorr
                  wi_e071                        = ls_e071
                  wi_simulation                  = test
                  wi_suppress_key_check          = 'X'
             TABLES
                  wt_e071k                       = lt_key
             EXCEPTIONS
                  no_authorization               = 1
                  no_systemname                  = 2
                  no_systemtype                  = 3
                  tr_check_keysyntax_error       = 4
                  tr_check_obj_error             = 5
                  tr_enqueue_failed              = 6
                  tr_ill_korrnum                 = 7
                  tr_key_without_header          = 8
                  tr_lockmod_failed              = 9
                  tr_lock_enqueue_failed         = 10
                  tr_modif_only_in_modif_order   = 11
                  tr_not_owner                   = 12
                  tr_no_append_of_corr_entry     = 13
                  tr_no_append_of_c_member       = 14
                  tr_no_shared_repairs           = 15
                  tr_order_not_exist             = 16
                  tr_order_released              = 17
                  tr_order_update_error          = 18
                  tr_repair_only_in_repair_order = 19
                  tr_wrong_order_type            = 20
                  wrong_client                   = 21
                  OTHERS                         = 22.
      ENDIF.
      COMMIT WORK.
*This one swallows correction requests too
*    CALL FUNCTION 'TR_EDIT_CHECK_OBJECTS_KEYS'
*         EXPORTING
*              wi_order                     = a_trkorr
*              wi_with_dialog               = 'D'
*              wi_send_message              = ' '
**            iv_no_show_option            = iv_no_show_option
**            iv_no_standard_editor        = iv_no_standard_editor
**            iv_externalps                = iv_externalps
**            iv_externalid                = iv_externalid
**            iv_no_ps                     = iv_no_ps
*         IMPORTING
*              we_order                     = a_trkorr
**            we_task                      = we_task
*         TABLES
*              wt_e071                      = lt_ko200
*              wt_e071k                     = at_key
**            wt_tadir                     = tt_tadir
*         EXCEPTIONS
*              show_only_user_after_error   = 1
*              cancel_edit_user_after_error = 2
*              OTHERS                       = 2.
*
*    IF sy-subrc NE 0.
*      CALL FUNCTION 'TR_EDIT_CHECK_OBJECTS_KEYS'
*           EXPORTING
*                wi_order                     = a_wb_trkorr
*                wi_with_dialog               = 'D'
*                wi_send_message              = ' '
**            iv_no_show_option            = iv_no_show_option
**            iv_no_standard_editor        = iv_no_standard_editor
**            iv_externalps                = iv_externalps
**            iv_externalid                = iv_externalid
**            iv_no_ps                     = iv_no_ps
*           IMPORTING
*                we_order                     = a_wb_trkorr
**            we_task                      = we_task
*           TABLES
*                wt_e071                      = lt_ko200
*                wt_e071k                     = at_key
**            wt_tadir                     = tt_tadir
*           EXCEPTIONS
*                show_only_user_after_error   = 1
*                cancel_edit_user_after_error = 2
*                OTHERS                       = 2.
*      IF sy-subrc NE 0.
* *      ENDIF.
*    ENDIF.

    ENDDO.

    CLEAR:   as_obj,
             as_metahead,
             ar_typedescr,
             ar_tableline,
             a_tabname,
             at_key.
    REFRESH at_key.

  ENDMETHOD.

  METHOD: write_to_trkorr.
    DATA lt_ko200 TYPE TABLE OF ko200.
    DATA ls_e071 TYPE e071.

    IF as_obj IS INITIAL.
      EXIT.
    ENDIF.

    IF as_obj-objfunc = 'K' AND
       at_key IS INITIAL.
      EXIT.
    ENDIF.

    APPEND as_obj TO lt_ko200.

** Check data for transport request
* Add data to transport request
    CALL FUNCTION 'TR_OBJECTS_CHECK'
         TABLES
              wt_ko200 = lt_ko200
              wt_e071k = at_key
         EXCEPTIONS
              OTHERS   = 1.


*This one swallows correction requests too
    CALL FUNCTION 'TR_EDIT_CHECK_OBJECTS_KEYS'
         EXPORTING
              wi_order                     = a_trkorr
              wi_with_dialog               = 'X' "'D'
              wi_send_message              = 'X' "' '
*            iv_no_show_option            = iv_no_show_option
*            iv_no_standard_editor        = iv_no_standard_editor
*            iv_externalps                = iv_externalps
*            iv_externalid                = iv_externalid
*            iv_no_ps                     = iv_no_ps
         IMPORTING
              we_order                     = a_trkorr
*            we_task                      = we_task
         TABLES
              wt_e071                      = lt_ko200
              wt_e071k                     = at_key
*            wt_tadir                     = tt_tadir
         EXCEPTIONS
              show_only_user_after_error   = 1
              cancel_edit_user_after_error = 2
              OTHERS                       = 2.

    IF sy-subrc NE 0.
      CALL FUNCTION 'TR_EDIT_CHECK_OBJECTS_KEYS'
           EXPORTING
                wi_order                     = a_wb_trkorr
                wi_with_dialog               = 'D'
                wi_send_message              = ' '
*            iv_no_show_option            = iv_no_show_option
*            iv_no_standard_editor        = iv_no_standard_editor
*            iv_externalps                = iv_externalps
*            iv_externalid                = iv_externalid
*            iv_no_ps                     = iv_no_ps
           IMPORTING
                we_order                     = a_wb_trkorr
*            we_task                      = we_task
           TABLES
                wt_e071                      = lt_ko200
                wt_e071k                     = at_key
*            wt_tadir                     = tt_tadir
           EXCEPTIONS
                show_only_user_after_error   = 1
                cancel_edit_user_after_error = 2
                OTHERS                       = 2.
      IF sy-subrc NE 0.
        WRITE:/ 'Errore scrittura trkorr tabella', a_tabname.
      ENDIF.
    ENDIF.


    CLEAR:   as_obj,
             as_metahead,
             ar_typedescr,
             ar_tableline,
             a_tabname,
             at_key.
    REFRESH at_key.

  ENDMETHOD.


  METHOD: get_metahead.

* call dictionary interface
    CALL FUNCTION 'DDIF_NAMETAB_GET'
      EXPORTING
        tabname           = a_tabname
        all_types         = 'X'
*     LFIELDNAME        = ' '
*     GROUP_NAMES       = ' '
*     UCLEN             =
      IMPORTING
        x030l_wa          = as_metahead
*     DTELINFO_WA       =
*     TTYPINFO_WA       =
*     DDOBJTYPE         =
*     DFIES_WA          =
*     LINES_DESCR       =
*   TABLES
*     X031L_TAB         =
*     DFIES_TAB         =
      EXCEPTIONS
        not_found         = 1
        OTHERS            = 2
              .
    IF sy-subrc <> 0.
      p_error = 1.
    ENDIF.

  ENDMETHOD.

ENDCLASS.                    "lcl_tabu_k_2_trkorr_writer IMPLEMENTATION

START-OF-SELECTION.
  DATA l_cnt      TYPE i.
  DATA l_cnt_cid  TYPE i.

  CLEAR l_cnt.
  CLEAR l_cnt_cid.


GET pernr.
  DATA l_pernrsel TYPE pcl2-srtfd.
  DATA lt_pcl2    TYPE TABLE OF pcl2.
  DATA ls_pcl2    TYPE pcl2.
  DATA l_error    TYPE i.
  DATA l_tabname  TYPE tabname VALUE 'PCL2'.

  DATA lr_trkk TYPE REF TO lcl_tabu_k_2_trkorr_writer .

  IF lr_trkk IS INITIAL.
    CREATE OBJECT lr_trkk.
  ENDIF.

  REFRESH lt_pcl2. CLEAR ls_pcl2.
  CONCATENATE pernr-pernr '%' INTO l_pernrsel.

  SELECT * FROM pcl2 INTO TABLE lt_pcl2 WHERE relid = 'RI' AND
                                              srtfd LIKE l_pernrsel.
  SELECT * FROM pcl2 appending TABLE lt_pcl2 WHERE relid = 'CU' AND
                                              srtfd LIKE l_pernrsel.

  l_cnt = l_cnt + sy-dbcnt.

  CALL METHOD lr_trkk->init EXPORTING p_trkorr    = wbtrkorr
                                      p_wb_trkorr = wbtrkorr
                                      p_tabname   = l_tabname
                            CHANGING  p_error     = l_error.

  LOOP AT lt_pcl2 INTO ls_pcl2.

    CALL METHOD lr_trkk->add_line_key
                             EXPORTING  p_line         = ls_pcl2
                              CHANGING  p_error        = l_error .


  ENDLOOP.

  IF sy-subrc EQ 0.
    CALL METHOD lr_trkk->write_to_trkorr CHANGING p_error = l_error.
    COMMIT WORK.
  ENDIF.

END-OF-SELECTION.

  WRITE: / 'Processed', l_cnt, 'RECORD'.
  WRITE: / 'Processed', l_cnt_cid, 'CID'.

*---------------------------------------------------------------------*
*       FORM select_tr_korr                                           *
*---------------------------------------------------------------------*
FORM select_tr_korr USING     p_uname p_type
                    CHANGING  p_korr.

  DATA lv_user TYPE trexreqhd-author.
  DATA ls_sel_korr TYPE   trexreqhd.
  DATA lv_selected_index TYPE sy-tabix.
  DATA lt_rem_trkorr_list TYPE STANDARD TABLE OF trexreqhd.

  lv_user = p_uname.

*  IF uname = sy-uname.
** Korrekturauftrag für Transportobjekte auswählen
*    CALL FUNCTION 'TR_ORDER_CHOICE_CORRECTION'
*         EXPORTING
*              iv_category            = p_type
*              iv_cli_dep             = ' '
*         IMPORTING
*              ev_order               = p_korr
**            ev_task                = we_task
*         EXCEPTIONS
*              invalid_category       = 1
*              no_correction_selected = 2
*              OTHERS                 = 3.
*
*    IF sy-subrc NE 0.
*      MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
*              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
*    ENDIF.
*  ELSE.

  CALL FUNCTION 'TR_F4_REQUESTS'
   EXPORTING
     iv_username                   = uname
*   IV_TRKORR_PATTERN             =
*   IV_TRFUNCTIONS                =
*   IV_TRSTATUS                   =
*   IV_FROM_DATE                  =
*   IV_TO_DATE                    =
*   IV_CLIENT                     =
*   IV_PROJECT                    =
*   IV_TITLE                      =
*   IV_VIA_SELECTION_SCREEN       = 'X'
*   IV_COMPLETE_REQUESTS          = 'X'
   IMPORTING
     ev_selected_request           = p_korr
*   ES_SELECTED_REQUEST           =
            .
*  ENDIF.



ENDFORM.                    " SELECT_TR_KORR

Wednesday, December 21, 2011

SAP ABAP upload an include into any system ( insert report )


This one is really simple and trivial, but it is worth checking out.
It must be used very cautiosly, because it might cause a lot of harm.
But put in the right hands, specially when there is big trouble (no one to do a transport when your calc is abending at night and your pay date is affected by the delay etc) it can save you.

Dynamic code generation (insert report and generate subroutine pool) are a very powerful abap feature, and are really worth checking out.

For example we realized a consistency check on the payroll output which is fully customizable, and generateas validation rules in abap form directly from the customizing. I would like to write on that in a future post.

Here is the coding.


REPORT zupload_code .

PARAMETERS: pfile TYPE rlgrap-filename DEFAULT 'c:\code.txt'.
PARAMETERS: progr TYPE programm DEFAULT 'Z_CODE'.

TYPES t_code(72) TYPE c.

DATA lt_code TYPE TABLE OF t_code.


START-OF-SELECTION.

  CALL FUNCTION 'HR_99S_UPLOAD'
   EXPORTING
   p_initial_directory         = ''
     p_filename                  = pfile
*   DEFAULT_EXTENSION           =
*   P_FILETYPE_NO_SHOW          = ' '
*   P_FILETYPE                  = 'ASC'
     p_fsdialog                  = ' '
*   P_ITEM                      = ' '
*   P_HAS_FIELD_SEPARATOR       = ' '
* IMPORTING
*   P_FILELENGTH                =
    TABLES
      data_tab                    = lt_code
   EXCEPTIONS
     upload_error                = 1
     OTHERS                      = 2
            .
  IF sy-subrc <> 0.
    WRITE: / 'Error in upload'.
    EXIT.
  ENDIF.

  INSERT REPORT progr FROM lt_code.

  IF sy-subrc <> 0.
    WRITE: / 'Error in insert'.
    EXIT.
  ENDIF.





Friday, December 16, 2011

SAP ABAP Dynamic assign: how to change data you should not change


Hi Folks!
I'll try to post every day a small pearl in ABAP and SAP HCM.
Today i'd like to focus on a very annoying thing: whenever you need some data in a user exit typically you don't have it in the BADI interface or in the CMOD function module interface.
So what to do? What are you options?
  1. Modify the standard 
    • Rather undesirable. Increases maintainance costs when you upgrade or apply patches to the systems.
  1. EXPORT TO MEMORY
    • Often used, but in a concurrent environmenti it is highly dangerous, unless one understands exactly the scoping of the abap memory (Anyone interestd? leave a comment if you wish a post on that topic). In addition it used to cause performance problems.
  2. Open an OSS and ask SAP to add the data to the interface
    • Sometimes works, but it takes a lot of time, and typically one does not have time. It's just when you go to renew your passport. You realize that it  must be renewed only when you need it, (urgently)
  3. Save to a DB table
    • Might be a solution, also affected by performance and concurrency issues. Concurrency issues might be mitigated by the use of a custom cluster (want a post on that? leave a comment if you wish.)
  4. anymore suggestions?
One really nice way to solve the problem is to use the dynamic assign feature in ABAP
SAP says that this language feature can only be used internally, and that it is not guaranteed to work in the future. But it is there since ages. And we used it very often over the years without having any problem ever.

You can put the name of the field you are interested in in a sting by using the syntax

'(PROGRAM NAME)FIELD'

For example to get a pointer (field symbol) pointing to the table BT in the RPCALCX0 you can use the following

str = '(RPCALCX0)BT[]'

Afterwards you assign the string to the field symbols

FIELD-SYMBOLS <fs> type standard table of my_line.
*Or whaterer table type
assign (str) to <fs> .
finally you can access the field:

Loop at  <fs> into l_line.
 ...
endloop.

the great thing is that you can assign ANY data in the call stack!!
So fro example if RPCALCX0 is calling a funciotn in a funcion group which calls a class, wich calls back to another program then you can read or change data in any of the programs in the call stack, this means in any of the programs you run through in the call chain.

Recommendations (common sense but anyway worth writing down)
  1. Never change the contents of data not in your scope, unless you really know what you are doing.
  2. Documento what you do. Leave traces of your approach in the application blueprint or wahtever techincal documentation.
  3. Always check the return values of your field symbols after assigning: your piece of code might be called from a different program without you knowing, and the call stack might be different, and your assign fail.
  4. Always handle all errors in your coding, making them visibile.
Here is a rela life coding example showing how you can access payroll (rpcalcx0 or whatever payroll) data fron the international RDTAB function via the RDTAB custom class in table T5ITIE/T5ITID
I will write a post on that topic to better explain its working.

METHOD if_hrpadit_table_reader_py~read_table .


  DATA l_str TYPE char30.
  DATA l_str2 TYPE char30.
  DATA l_str3 TYPE char30.
  DATA l_imp TYPE maxbt.
  DATA l_num TYPE pranz.
  DATA ls_pa0306 TYPE pa0306.
  DATA ls_var TYPE hrvar.

  FIELD-SYMBOLS: <res> TYPE ANY.
  CREATE DATA a_result TYPE pranz.
  ASSIGN a_result->* TO
<res>.
 
<res> = 0.

  l_str = '(RPCALCI0)P0009'.
  l_str2 = '(RPCALCI0)VAR[]'.
  l_str3 = '(RPCALCI0)BT'.

  FIELD-SYMBOLS:
<p0009>  TYPE p0009.
  TYPES: t_hrvar TYPE STANDARD TABLE OF hrvar.
  FIELD-SYMBOLS: <var>  TYPE t_hrvar.
  FIELD-SYMBOLS: 
<bt> TYPE pc209.

  ASSIGN (l_str) TO
<p0009>.

  IF sy-subrc NE 0.
 
<res> = 1. "KO
    EXIT.
* error.
  ENDIF.

  ASSIGN (l_str2) TO
<var>.

  IF sy-subrc NE 0.
 
<res>  = 1. "KO
    EXIT.
* error.
  ENDIF.

  ASSIGN (l_str3) TO
<bt>.

  IF sy-subrc NE 0.
 
<res>  = 1. "KO
    EXIT.
* error.
  ENDIF.

  IF
<p0009>-subty EQ 'MY'.

    DELETE WHERE lgart = 'Syyy'.
    ls_var-lgart = 'SETF'.
    ls_var-betpe = ls_pa0306-setfr.
    ls_var-anzhl = ls_pa0306-setfr.
    ls_var-betrg = ls_pa0306-setfr.
    ls_var-rte_curr = 'EUR'.
    ls_var-amt_curr = 'EUR'.
    APPEND ls_var TO
<var>.

  ENDIF.


  IF
<bt>-subty EQ 'ZZ' OR <bt>-subty EQ 'TT'.

    
<bt>-stras  = ls_pa0021-address.
    
<bt>-bkort  = ls_pa0021-town.

   ENDIF.

ENDMETHOD.