03-19-2014 8:37 PM
I need to create a program which can Load a ZTABLE from a flat file structure (delimited and fixed options required). We have many ZTables where this will be required so I was hoping to do it dynamically somehow. Otherwise I will have to create one ABAP for every ZTable we have to load.
My Inputs should be
PARAMETERS: p_ztable TYPE ddobjname, "Z Table Name
p_infile(132) LOWER CASE, "File Name
p_delim(1). "Delimiter
I know that I can read the file by using gui_upload
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = c_infile
has_field_separator = p_delim
TABLES
data_tab = indata
EXCEPTIONS
file_open_error = 1
file_read_error = 2
OTHERS = 9.
I know that I can split the contents of this file (if a delimiter is used). However I will not know the actual field names of the table until runtime as to what to fields to split it into. In the example below I have the actual table (t_rec) and each of the fields (pernr, lgart, etc) in the code but each table I
need to load will be different – it will have a different # of fields as well.
FORM read_data_pc.
LOOP AT indata.
PERFORM splitdata USING indata.
APPEND t_rec.
CLEAR t_rec.
ENDLOOP.
ENDFORM.
FORM splitdata USING p_infile.
SPLIT p_infile AT p_delim INTO
t_rec-pernr "Employee #
t_rec-lgart "Wage Type
t_rec-begda "Effective date
t_rec-endda. "End date
ENDFORM.
Once I split the data into the fields then I can just look and insert the record.
Does anyone have any ideas? Specific code examples would be great if you do. Thx!!
03-19-2014 9:09 PM
Hi Janice,
You can also try this code
DATA: I_TMP(100) OCCURS 0 WITH HEADER LINE. "Split internal table
DATA : V_HEX TYPE X VALUE '09'. "Tab delimiter
FIELD-SYMBOLS: <FS1>, "Points to Table work area
<FS2>. "Points to Table Field
*---Create a new data object of table specified in parameter (p_table)
*---Reference is stored in dref variable. dref now contains a pointer
*---to newly created object.
CREATE DATA DREF TYPE (P_ZTABLE).
*--Asssign the reference to field-symbol
ASSIGN DREF->* TO <FS1>.
LOOP AT I_DATA.
REFRESH I_TMP.
*--Split each input row data into tokens with Tab delimiter
SPLIT P_INFILE AT V_HEX INTO TABLE I_TMP.
* CLEAR .
*---Assign each field of table to field-symbol
DO.
ASSIGN COMPONENT SY-INDEX OF STRUCTURE <FS1> TO <FS2>.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
READ TABLE I_TMP INDEX SY-INDEX.
IF SY-SUBRC EQ 0.
<FS2> = I_TMP.
ENDIF.
ENDDO.
*--Now will have all the data - Modify the table
MODIFY (P_ZTABLE) FROM <FS1>.
ENDLOOP.
03-19-2014 8:48 PM
Hi Janice,
Pass the P_ZTABLE value to DDIF_FIELDINFO_GET Function Module and get all the fields (& their respective properties) of the table and now match that Field names of the flat structure file. So that you can map accordingly.
Thanks,
Joel Cutinho
03-19-2014 8:52 PM
thx for the response. I did something similar to that
*Get Structure of Z table you want to load into the t_itab table
CALL FUNCTION 'DDIF_NAMETAB_GET'
EXPORTING
tabname = p_ztable
TABLES
dfies_tab = t_itab
EXCEPTIONS
not_found = 1
OTHERS = 2.
The t_itab table returned actually contains all of the fieldnames, but I am lost as to how to split the data at the demilter (see code in orginal question) without hardcoding the field names. I am sure the amswer is simple, but I am a little lost right now.
Can you help?
03-19-2014 8:59 PM
Hi janice,,
Try this sample code where you can upload data from a flat file into the internal table.
REPORT z_test.
TABLES: mara.
FIELD-SYMBOLS : <fs> .
DATA : fldname(50) TYPE c.
DATA : col TYPE i.
DATA : cmp LIKE TABLE OF rstrucinfo WITH HEADER LINE.
DATA: progname LIKE sy-repid,
dynnum LIKE sy-dynnr.
DATA itab TYPE TABLE OF alsmex_tabline WITH HEADER LINE.
DATA: BEGIN OF ZUPLOAD1_T OCCURS 0 ,
matnr like mara-matnr,
ersda like mara-ersda,
ernam like mara-ernam,
laeda like mara-laeda,
END OF ZUPLOAD1_T.
*DATA: ZUPLOAD1_T LIKE mara OCCURS 0 WITH HEADER LINE.
DATA: wa_data LIKE TABLE OF ZUPLOAD1_T WITH HEADER LINE.
SELECTION-SCREEN: BEGIN OF BLOCK blk WITH FRAME TITLE text-001.SELECTION-SCREEN : SKIP 1. PARAMETERS : p_file LIKE rlgrap-filename.SELECTION-SCREEN : SKIP 1.SELECTION-SCREEN : END OF BLOCK blk
. AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
CALL FUNCTION 'KD_GET_FILENAME_ON_F4' EXPORTING
static = 'X'
CHANGING file_name = p_file EXCEPTIONS mask_too_long = 1 OTHERS = 2
. IF sy-subrc <> 0.
ENDIF.
START-OF-SELECTION.
CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
EXPORTING filename = P_FILE
i_begin_col = 1
i_begin_row = 1
i_end_col = 5
i_end_row = 12507
tables
intern = ITAB
EXCEPTIONS
INCONSISTENT_PARAMETERS = 1
UPLOAD_OLE = 2
OTHERS = 3. .
IF sy-subrc <> 0.
ENDIF.
CALL FUNCTION 'GET_COMPONENT_LIST'
EXPORTING
program = SY-REPID
fieldname = 'ZMARA'
tables
components = CMP.
LOOP AT itab. AT NEW row.
IF sy-tabix = 1. APPEND ZUPLOAD1_T.
ENDIF.
ENDAT.
col = itab-col.
READ TABLE cmp INDEX col.
CONCATENATE 'ZUPLOAD1_T-' cmp-compname INTO fldname.
ASSIGN (fldname) TO <fs>.
<fs> = itab-COL.
APPEND ZUPLOAD1_T. ENDLOOP.
DELETE ZUPLOAD1_T where matnr eq space.
LOOP AT ZUPLOAD1_T INTO wa_data.
WRITE: / ZUPLOAD1_T-matnr, 20 ZUPLOAD1_T-ersda , 45 ZUPLOAD1_T-ernam, 55 ZUPLOAD1_T-laeda.
*HERE IAM JUST CHECKING I NEED TO UPDATE A ZTABLE
ENDLOOP.
insert ZMARA FROM table itab ACCEPTING DUPLICATE KEYS.
I have tried it for mara.Please let me know whether it was helful.
Regards,
Kannan
03-19-2014 8:56 PM
Hi Janice,
I do not get your problem at all. You have different files you want to load into a z_table ( in case fo the file, you want to save the input in different tables and you just want to create one report to handle all of them? Am I right?
Where's your problem. Just develop a report all your valid tables are declared and use dynamic programming. There is a lot of examples available here in SCN. Just use the search
Dynamic Internal table - ABAP Development - SCN Wiki
To split your file into a valid structure, you just could use the splitcommand itself. It pass everything you need in your direction.
DATA: gt_split type table of string.
SPLIT yourstring AT '/' INTO TABLE gt_split.
I can imagine a report you pass the file and the tablename you want to insert the stuff.
Afterwards you assign the dynamic variables and pass the content of your file to the correct fields in the internal table and now you just have to update the table.
This is the simple way, a bit more difficult is to let the system choose the table by the unique file-identifier. Perhaps the headerinformation, if passed.
But in case you didn't share anything about the incoming file and how many tables you have to fight with it is just a pure suggestion of mine
~Florian
03-19-2014 9:05 PM
Hi Florian,
I have flat file "A" that needs to be loaded into ZTABLE_A, Flat File "B" that needs to be loaded into ZTABLE_B, Flat File "C" that needs to be loaded into ZTABLE_C, and so on and so on.
I can dynamically determine the table and the fields ... I just don't know how to split the data by the delimiter without hard coding the field names or the # of fields. Each table is different
LOOP AT indata.
SPLIT p_infile AT p_delim INTO
t_rec-pernr "Employee #
t_rec-lgart "Wage Type
t_rec-begda "Effective date
t_rec-endda. "End date
APPEND t_rec.
CLEAR t_rec.
ENDLOOP.
How can I do this dynamically?
03-19-2014 9:14 PM
Hi Janice,
there are two ways, by uploading the file you can modify your file in that way, that you know, the first character is delimiter.
You can deliver a fixed position ( Prhaps your first field in the flat file is always the same length)
or
You have a set of delimiters and which are always delimiter and you can prove the file which is in the current file passed.
You know with the keyword FIND first occuronce of....
But in any case, a cpu isn't smart enough, that it can identify a delimiter without anything knowing before
Hope this gives you a clue how to handle this issue.
IF you need further information, you might share two or three different example-files, so we can dive more into it.
Regards
Florian
03-19-2014 9:09 PM
Hi Janice,
You can also try this code
DATA: I_TMP(100) OCCURS 0 WITH HEADER LINE. "Split internal table
DATA : V_HEX TYPE X VALUE '09'. "Tab delimiter
FIELD-SYMBOLS: <FS1>, "Points to Table work area
<FS2>. "Points to Table Field
*---Create a new data object of table specified in parameter (p_table)
*---Reference is stored in dref variable. dref now contains a pointer
*---to newly created object.
CREATE DATA DREF TYPE (P_ZTABLE).
*--Asssign the reference to field-symbol
ASSIGN DREF->* TO <FS1>.
LOOP AT I_DATA.
REFRESH I_TMP.
*--Split each input row data into tokens with Tab delimiter
SPLIT P_INFILE AT V_HEX INTO TABLE I_TMP.
* CLEAR .
*---Assign each field of table to field-symbol
DO.
ASSIGN COMPONENT SY-INDEX OF STRUCTURE <FS1> TO <FS2>.
IF SY-SUBRC NE 0.
EXIT.
ENDIF.
READ TABLE I_TMP INDEX SY-INDEX.
IF SY-SUBRC EQ 0.
<FS2> = I_TMP.
ENDIF.
ENDDO.
*--Now will have all the data - Modify the table
MODIFY (P_ZTABLE) FROM <FS1>.
ENDLOOP.
03-20-2014 1:42 PM
Thank-you Joel!
Your coding examples gave me the idea that perhaps I need to look at doing the gui_upload differently and load the data as tab delimitted. The root of my problem was that I was not able to split the fields dynamically by using .csv. I did some playing around and now have my solution. I will show the code below in case anyone else comes across this same need in the future. I still need to put the data into the internal table at the end of this, but that is simple.
*Get Structure of Z table you want to load into the t_itab table
CALL FUNCTION 'DDIF_NAMETAB_GET'
EXPORTING
tabname = p_ztable
TABLES
dfies_tab = t_itab
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
FIELD-SYMBOLS:
<gw_wa> TYPE ANY,
<gt_itab> TYPE STANDARD TABLE. "TYPE ANY TABLE.
data: gt_components TYPE abap_component_tab,
gw_component TYPE LINE OF abap_component_tab,
gr_wa TYPE REF TO data,
gr_itab TYPE REF TO data,
gr_tabledescr TYPE REF TO cl_abap_tabledescr,
gt_keys TYPE abap_keydescr_tab,
gw_key TYPE LINE OF abap_keydescr_tab,
gr_structdescr TYPE REF TO cl_abap_structdescr.
Loop at t_itab into s_itab.
MOVE s_itab-fieldname TO gw_component-name.
gw_component-type ?= cl_abap_elemdescr=>get_string( ).
INSERT gw_component INTO TABLE gt_components.
endloop. "t_itab
*get structure descriptor -> GR_STRUCTDESCR
gr_structdescr ?= cl_abap_structdescr=>create( gt_components ).
* create work area of structure GR_STRUCTDESCR -> GR_WA
CREATE DATA gr_wa TYPE HANDLE gr_structdescr.
ASSIGN gr_wa->* TO <gw_wa>.
* create descriptor for internal table -> GR_TABLEDESCR
gr_tabledescr ?= cl_abap_tabledescr=>create( p_line_type = gr_structdescr
p_table_kind = cl_abap_tabledescr=>tablekind_std ).
CREATE DATA gr_itab TYPE handle gr_tabledescr.
ASSIGN gr_itab->* TO <gt_itab>.
c_infile = p_infile. "Convert filename to string type
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = c_infile
has_field_separator = p_delim
TABLES
data_tab = <gt_itab> "<fs_table> "t_rec <gt_itab>
EXCEPTIONS
file_open_error = 1
file_read_error = 2
no_batch = 3
gui_refuse_filetransfer = 4
invalid_type = 5
no_authority = 6
unknown_error = 7
bad_data_format = 8
OTHERS = 9.