I got tired to create always test-data in R/3 that I'm able to test my delta load.
So the idea to reload the data again into delta queue came up and a development idea was born.
The idea is, to enter what you want to take over: Which datasource, which request, datapack, records.
With this information you enter in R/3 BW reads the data and write them into a table which is created on the fly and hands over this data to R/3 - you can still edit this information and after saving the data is written into deltaqueue and you're able to load the request again.
If you have the RFC'connection setup you would be able to take over some PSA requests from productive to quality/development system - so you can test your load with productive data.
The first problem was how to transfer data from BW to R/3. The rfc table read FM was not working, because its to small. Then the idea was calling an RFC FM in BW which fills a table and then return this data to R/3 again, but I don't wanted to create a table for each datasource.
That's why I did this dynamic solution. I'm not a perfect ABAP programer - so if you have some hints / ideas please let me know.
So first create in R/3 the Report ZBW_FILL_QUEUE with this code and includes
&----
*& Report ZBW_FILL_QUEUE
*&
&----
*&
*&
&----
REPORT ZBW_FILL_QUEUE.
type-pools : abap,
SLIS.
DATA: lt_FIELDCAT TYPE LVC_T_FCAT,
ls_FIELDCAT TYPE LVC_S_FCAT,
ls_LAYOUT TYPE LVC_S_LAYO.
field-symbols: ----
***INCLUDE ZBW_FILL_QUEUE_CREATE_DYNAMF01 .
----
&----
*& Form create_dynamic_itab
&----
----
----
FORM create_dynamic_itab .
- Create dynamic internal table and assign to FS
call method cl_alv_table_create=>create_dynamic_table
exporting
it_fieldcatalog = ifc
importing
ep_table = dy_table.
assign dy_table->* to .
- Create dynamic work area and assign to FS
create data dy_line like line of .
- Create dynamic internal table and assign to FS
call method cl_alv_table_create=>create_dynamic_table
exporting
it_fieldcatalog = ifc_req
importing
ep_table = dy_table.
assign dy_table->* to .
- Create dynamic work area and assign to FS
create data dy_line like line of ----
***INCLUDE ZBW_FILL_QUEUE_GET_STRUCTURF01 .
----
&----
*& Form get_structure
&----
----
----
FORM get_structure .
data : idetails type abap_compdescr_tab,
xdetails type abap_compdescr.
data : ls_dd03l type dd03l,
lt_dd03l type table of dd03l.
data : ref_table_des type ref to cl_abap_structdescr.
- Get the structure of the table.
ref_table_des ?=
cl_abap_typedescr=>describe_by_name( lv_STRUCTURE ).
idetails[] = ref_table_des->components[].
select *
into corresponding fields of table lt_dd03l
from dd03l
where tabname = lv_structure
order by position.
clear xfc.
xfc-fieldname = 'REQUEST' .
xfc-datatype = 'RSREQUNR'.
xfc-inttype = 'C'.
xfc-intlen = '30'.
xfc-decimals = ''.
append xfc to ifc_req.
clear xfc.
xfc-fieldname = 'DATAPAKID' .
xfc-datatype = 'RSDATAPID'.
xfc-inttype = 'N'.
xfc-intlen = '6'.
xfc-decimals = ''.
append xfc to ifc_req.
clear xfc.
xfc-fieldname = 'PARTNO' .
xfc-datatype = 'RSPARTVAL'.
xfc-inttype = 'I'.
xfc-intlen = '4'.
xfc-decimals = ''.
append xfc to ifc_req.
clear xfc.
xfc-fieldname = 'RECORD' .
xfc-datatype = 'RSARECORD'.
xfc-inttype = 'I'.
xfc-intlen = '4'.
xfc-decimals = ''.
append xfc to ifc_req.
Loop at lt_dd03l_fieldsbw into ls_dd03l_fieldsbw.
read table lt_dd03l into ls_dd03l with key fieldname = ls_dd03l_fieldsbw-fieldname.
if sy-subrc = 0.
clear xfc.
xfc-fieldname = ls_dd03l-fieldname.
xfc-datatype = ls_dd03l-rollname.
xfc-inttype = ls_dd03l-inttype.
xfc-intlen = ls_dd03l-leng.
xfc-decimals = ls_dd03l-decimals.
append xfc to ifc_req.
endif.
endloop.
- loop at idetails into xdetails.
- clear xfc.
- xfc-fieldname = xdetails-name .
- xfc-datatype = xdetails-type_kind.
- xfc-inttype = xdetails-type_kind.
- xfc-intlen = xdetails-length.
- xfc-decimals = xdetails-decimals.
- append xfc to ifc_req.
- append xfc to ifc.
- endloop.
loop at lt_dd03l into ls_dd03l.
clear xfc.
if ls_dd03l-fieldname ne 'MANDT'
AND ls_dd03l-fieldname ne '.INCLUDE'
AND ls_dd03l-fieldname ne '.INCLU--AP'.
xfc-fieldname = ls_dd03l-fieldname.
xfc-datatype = ls_dd03l-rollname.
xfc-inttype = ls_dd03l-inttype.
xfc-intlen = ls_dd03l-leng.
xfc-decimals = ls_dd03l-decimals.
append xfc to ifc.
endif.
endloop.
ENDFORM. " get_structureInclude ZBW_FILL_QUEUE_USER_COMMANDF01
----
***INCLUDE ZBW_FILL_QUEUE_USER_COMMANDF01 .
----
&----
*& Form USER_COMMAND
&----
----
----
form user_command using r_ucomm type sy-ucomm
rs_selfield type slis_selfield.
if r_ucomm = '&DATA_SAVE'.
message i000(0k) with 'Die Daten werden jetzt in die Delta Queue geschrieben'.
CALL FUNCTION 'RSC1_TRFC_QUEUE_WRITE'
EXPORTING
I_ISOURCE = lv_DATASOURCE
I_NO_FLUSH = 'X'
IMPORTING
E_SUBRC = lv_subrc
TABLES
I_T_DATA =
EXCEPTIONS
NAME_TOO_LONG = 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.
commit work.
call function 'REUSE_ALV_LIST_DISPLAY'
exporting
i_structure_name = lv_Structure
tables
t_outtab = ----
***INCLUDE ZBW_FILL_QUEUE_ZPSA_TASKINFF01 .
----
&----
*& Form ZPSA_TASKINFO
&----
----
----
FORM ZPSA_TASKINFO USING lv_TASKNAME.
- Receiving Results of aRFC
- RECEIVE RESULTS FROM FUNCTION 'ZPSA_FILL_TABLE'
- importing
- ex_spfli = spfli
- sys = system
- exceptions
- invalid_data = 1.
*
- Processing Wait Condition
- return = sy-subrc.
lv_flag = 'X'.
ENDFORM. " ZPSA_TASKINFO
After you created this in R/3 you have to create the following Objects in BW:Dict. Table ZPSA_TABLE - this table is deleted and recreated when you load data from the several datasources - depending on the structure of the corresponding datasource. But that you can create the functions, you have to create the tabel initialy with some fields. Create this table as a $tmp object - do not put this in a transport package. Othwerwise you cannot change it on the fly. If you transport the code form Dev to Qual system, you have first to create manually ZPSA_TABLE in Qual as $TMP object, and then transport the functions.
Class/Methode in BW: ZCL_BC_DYN
Parameters are:
- VALUE(TABNAME_TARGET) TYPE DD02L-TABNAME
- VALUE(TABNAME_SOURCE) TYPE DD02L-TABNAME
- STATUS TYPE SY-SUBRC
Then create the 4 Functions in BW - make sure they are RFC enabled:
Function ZPSA_CREATE_TABLE
FUNCTION ZPSA_CREATE_TABLE.
*"----
""Lokale Schnittstelle:
*" IMPORTING
*" VALUE(DATASOURCE) TYPE ROOSOURCER
*" VALUE(LOGSYS) TYPE RSSLOGSYS
*"----
DATA: ls_RSDSTS TYPE RSDSTS,
lt_RSDSTS TYPE TABLE OF RSDSTS.
DATA: tabname_target TYPE dd02l-tabname,
tabname_source TYPE dd02l-tabname.
DATA: gt_cl_bc_dyn TYPE REF TO zcl_bc_dyn,
status TYPE sy-subrc.
tabname_target = 'ZPSA_TABLE'.
SELECT * FROM RSDSTS
INTO CORRESPONDING FIELDS OF TABLE lt_RSDSTS
WHERE OBJVERS = 'A'
AND DATASOURCE = DATASOURCE
AND LOGSYS = LOGSYS
ORDER BY PSA_VERSION DESCENDING.
LOOP AT lt_RSDSTS INTO ls_RSDSTS.
tabname_source = ls_RSDSTS-PSA_TABLE.
EXIT.
ENDLOOP.
DELETE FROM ZPSA_TABLE.
CALL FUNCTION 'RS_DD_DELETE_OBJ'
EXPORTING
NO_ASK = 'X'
OBJNAME = tabname_target
OBJTYPE = 'T'
- CHANGING
- CORRNUM = ' '
- EXCEPTIONS
- NOT_EXECUTED = 1
- OBJECT_NOT_FOUND = 2
- OBJECT_NOT_SPECIFIED = 3
- PERMISSION_FAILURE = 4
- DIALOG_NEEDED = 5
- OTHERS = 6
.
CREATE OBJECT gt_cl_bc_dyn.
*START-OF-SELECTION.
CALL METHOD gt_cl_bc_dyn->create_table
EXPORTING
tabname_target = tabname_target
tabname_source = tabname_source
IMPORTING
status = status .
COMMIT WORK AND WAIT.
ENDFUNCTION.
Function ZPSA_EXECUTE
FUNCTION ZPSA_EXECUTE.
*"----
""Lokale Schnittstelle:
*" IMPORTING
*" VALUE(DATASOURCE) TYPE ROOSOURCER
*" VALUE(LOGSYS) TYPE RSSLOGSYS
*" VALUE(REQUEST) TYPE RSREQUNR
*" VALUE(DATAPAKID_LOW) TYPE RSDATAPID
*" VALUE(DATAPAKID_HIGH) TYPE RSDATAPID
*" VALUE(RECORD_LOW) TYPE RSARECORD
*" VALUE(RECORD_HIGH) TYPE RSARECORD
*" VALUE(QUELLSYSTEM) TYPE RSSLOGSYS
*" TABLES
*" FIELDS STRUCTURE DD03L
*"----
DATA: lv_QUELLSYSTEM TYPE RSSLOGSYS,
lv_DATASOURCE TYPE ROOSOURCER,
lv_REQUEST TYPE RSREQUNR,
lv_DATAPAKIDL TYPE RSDATAPID,
lv_DATAPAKIDH TYPE RSDATAPID,
lv_RECORDL TYPE RSARECORD,
lv_RECORDH TYPE RSARECORD.
- lv_TASKINFO TYPE ZTRFC_RETURN_STATUS.
- lv_TASKNAME TYPE C LENGTH 8.
lv_QUELLSYSTEM = QUELLSYSTEM.
lv_REQUEST = REQUEST.
lv_DATASOURCE = DATASOURCE.
lv_DATAPAKIDL = DATAPAKID_LOW.
lv_DATAPAKIDH = DATAPAKID_HIGH.
lv_RECORDL = RECORD_LOW.
lv_RECORDH = RECORD_HIGH.
*lv_RFCSYSTEM = 'D72_603'.
*lv_QUELLSYSTEM = 'D12_565'.
*lv_DATASOURCE = '2LIS_02_S015'.
*lv_REQUEST = 'REQU_43A0NKQXQTFKMYOT91QGJLOOS'. "77 Einträge
*lv_DATASOURCE = '0ARTICLE_ATTR'.
*lv_REQUEST = 'REQU_49M6DMR9RKI5OK9NJZMFRQEKC'. "18388 Einträge
CALL FUNCTION 'ZPSA_CREATE_TABLE'
EXPORTING
DATASOURCE = lv_DATASOURCE
LOGSYS = lv_QUELLSYSTEM
.
COMMIT WORK AND WAIT.
*lv_TASKNAME = '1'.
*CALL FUNCTION 'ZPSA_FILL_TABLE' STARTING NEW TASK lv_TASKNAME
- PERFORMING ZPSA_TASKINFO ON END OF TASK
- EXPORTING
- DATASOURCE = lv_DATASOURCE
- LOGSYS = lv_QUELLSYSTEM
- REQUEST = lv_REQUEST
- DATAPAKID_LOW = lv_DATAPAKIDL
- DATAPAKID_HIGH = lv_DATAPAKIDH
- RECORD_LOW = lv_RECORDL
- RECORD_HIGH = lv_RECORDH
- .
*WAIT UNTIL lv_TASKINFO = 1.
COMMIT WORK AND WAIT.
SELECT *
INTO table FIELDS
FROM DD03L
WHERE TABNAME = 'ZPSA_TABLE'
order by position.
ENDFUNCTION.
Function ZPSA_FILL_TABLE
FUNCTION ZPSA_FILL_TABLE.
*"----
""Lokale Schnittstelle:
*" IMPORTING
*" VALUE(DATASOURCE) TYPE ROOSOURCER
*" VALUE(LOGSYS) TYPE RSSLOGSYS
*" VALUE(REQUEST) TYPE RSREQUNR
*" VALUE(DATAPAKID_LOW) TYPE RSDATAPID
*" VALUE(DATAPAKID_HIGH) TYPE RSDATAPID
*" VALUE(RECORD_LOW) TYPE RSARECORD
*" VALUE(RECORD_HIGH) TYPE RSARECORD
*"----
DATA: ls_RSDSTS TYPE RSDSTS,
lt_RSDSTS TYPE TABLE OF RSDSTS,
lt_TARGET TYPE TABLE OF ZPSA_TABLE.
DATA: tabname_target TYPE dd02l-tabname,
tabname_source TYPE dd02l-tabname.
DATA: gt_cl_bc_dyn TYPE REF TO zcl_bc_dyn,
status TYPE sy-subrc.
DATA: lv_DATAPAKID TYPE RSDATAPID,
lv_RECORD TYPE RSARECORD.
RANGES: lr_DATAPAKID FOR lv_DATAPAKID,
lr_RECORD FOR lv_RECORD.
IF NOT DATAPAKID_LOW IS INITIAL.
lr_DATAPAKID-SIGN = 'I'.
lr_DATAPAKID-LOW = DATAPAKID_LOW.
IF NOT DATAPAKID_HIGH IS INITIAL.
lr_DATAPAKID-OPTION = 'BT'.
lr_DATAPAKID-HIGH = DATAPAKID_HIGH.
ELSE.
lr_DATAPAKID-OPTION = 'EQ'.
ENDIF.
APPEND lr_DATAPAKID.
ENDIF.
IF NOT RECORD_LOW IS INITIAL.
lr_RECORD-SIGN = 'I'.
lr_RECORD-LOW = RECORD_LOW.
IF NOT RECORD_HIGH IS INITIAL.
lr_RECORD-OPTION = 'BT'.
lr_RECORD-HIGH = RECORD_HIGH.
ELSE.
lr_RECORD-OPTION = 'EQ'.
ENDIF.
APPEND lr_RECORD.
ENDIF.
tabname_target = 'ZPSA_TABLE'.
SELECT * FROM RSDSTS
INTO CORRESPONDING FIELDS OF TABLE lt_RSDSTS
WHERE OBJVERS = 'A'
AND DATASOURCE = DATASOURCE
AND LOGSYS = LOGSYS
ORDER BY PSA_VERSION DESCENDING.
LOOP AT lt_RSDSTS INTO ls_RSDSTS.
tabname_source = ls_RSDSTS-PSA_TABLE.
EXIT.
ENDLOOP.
SELECT * FROM (tabname_source)
INTO TABLE lt_TARGET
WHERE REQUEST = REQUEST
AND DATAPAKID in lr_DATAPAKID
AND RECORD in lr_RECORD.
INSERT ZPSA_TABLE FROM TABLE lt_TARGET.
commit work and wait.
ENDFUNCTION.
Function ZPSA_READ_TABLE
FUNCTION ZPSA_READ_TABLE.
*"----
""Lokale Schnittstelle:
*" TABLES
*" PSA_DATA STRUCTURE ZPSA_TABLE
*"----
DATA: lt_ZPSA_TABLE TYPE TABLE OF ZPSA_TABLE.
SELECT * FROM ZPSA_TABLE
INTO CORRESPONDING FIELDS OF TABLE lt_ZPSA_TABLE.
PSA_DATA[] = lt_ZPSA_TABLE[].
ENDFUNCTION.
After creating all those objects you should be able to let run the report ZBW_FILL_QUEUE in R/3.
Now enter the
BW System: this must be the same as the RFC Connection and is used
R/3 System: this is needed to find in BW the corresponding PSA Table (it's always the latest version) in table RSTS / RSTSODS
Datasource: Enter the datasource you want to load - format e.g.:2LIS_13_VDITM
PSA Request: technical name of request
Datapacket number and Record only if needed - if empty the whole request is taken over
The Flag "Write Delta Queue" has the following function:
The first time you want to load data you have to run the report without enabled flag. This means, the report just change the ZPSA_TALBE in BW and make it ready to put data in. This you have to do every time you change the Datasource.
After then you can enable the Flag "Write Delta Queue" and let run the report again. Now you get the data from the request in a datagrid - you can change some values and with saving you put the data into delta queue.
Now you can let run the Delta Infopackage again and you should get the data 😉
There are now some development ideas open for this, but it was not necessary at the end to implement this:
Only one user can use this at the time, because the table ZPSA_TABLE is used for all
Implement the solution that you don't have to let run first time for only changing the table ZPSA_TABLE before you let it run with data-takeover
Not all errors are taken in account
Please use this solution on your own risk - I hope you're happy with this. Please let me know what you think about.
I also have a solution to take over MasterData from Production into Quality / Dev. without having to create for each IO export datasource. My solution is one FM in Quality which reads dynamically the MasterData Tables from Production, depending on which InfoObject you want to load (generic datasource with FM).