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:
- Table E071 contains the objects in form "R3TR TABU TABLENAME"
- TABU means table contents
- When you specify TABU in a transport the you are expcted to specify also che keys you would like to transport
- These keys are written to table E071K
- 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.
- Often these functions are bypassed and the tables e071 and the keys are written directly to the database. I wouldn't reccomend this.
- 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
- 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