REPORT z_upload_any_table.
PARAMETERS: p_tab TYPE dd02l-tabname DEFAULT 'MY_TAB' OBLIGATORY.
SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME.
PARAMETERS: p_datf TYPE c LENGTH 10 OBLIGATORY DEFAULT 'DD/MM/YYYY',
p_header AS CHECKBOX DEFAULT 'X',
p_mandt AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b01.
PARAMETERS: p_wipe AS CHECKBOX DEFAULT ' ',
p_test AS CHECKBOX DEFAULT 'X'.
PARAMETERS: p_max TYPE tbmaxsel DEFAULT 0.
CLASS z_csv_import DEFINITION.
*--[
*--[ From: https://blogs.sap.com/2015/04/04/tip-how-to-upload-csv-files-via-abap-easily/
*--[
PUBLIC SECTION.
DATA: modo_test TYPE xfeld,
data_format TYPE string,
has_header TYPE xfeld,
has_mandt TYPE xfeld,
has_max TYPE tbmaxsel.
METHODS Constructor.
METHODS load_csv_file
IMPORTING
VALUE(i_filename) TYPE String OPTIONAL.
METHODS transform_csv_data
IMPORTING
VALUE(i_tablename) TYPE String.
METHODS get_csv_data
IMPORTING
VALUE(i_tablename) TYPE String.
METHODS set_data
IMPORTING VALUE(i_data) TYPE any
EXPORTING e_data TYPE sy-datum.
PROTECTED SECTION.
DATA g_csv_data TYPE stringtab .
DATA g_error_flag TYPE abap_bool VALUE abap_false.
DATA g_tab_fields TYPE STANDARD TABLE OF String .
PRIVATE SECTION.
ENDCLASS.
CLASS z_csv_import IMPLEMENTATION.
METHOD set_data.
FIND REGEX '[^A-Za-z0-9]' IN data_format MATCH OFFSET DATA(moff).
IF sy-subrc EQ 0 .
*--[ Descrompimimos los valores
SPLIT i_data AT data_format+moff(1) INTO DATA(var_01)
DATA(var_02)
DATA(var_03).
SPLIT data_format AT data_format+moff(1) INTO TABLE DATA(T_tab).
LOOP AT t_tab INTO DATA(lin).
DATA(l) = 'var_0' && sy-tabix.
ASSIGN (l) TO FIELD-SYMBOL(<fs>).
IF lin CA 'dD'. e_data+6(2) = <fs>. ENDIF.
IF lin CA 'mM'. e_data+4(2) = <fs>. ENDIF.
IF lin CA 'yY'. e_data+0(4) = <fs>. ENDIF.
ENDLOOP.
ELSE.
e_data = i_data.
ENDIF.
ENDMETHOD.
METHOD Constructor.
"-Begin-----------------------------------------------------------------
CLEAR g_csv_data.
"-End-------------------------------------------------------------------
ENDMETHOD.
METHOD get_csv_data.
"-Begin-----------------------------------------------------------------
"-Structures----------------------------------------------------------
TYPES: BEGIN OF l_typ_Confrontation,
IntFieldName TYPE String,
IntFieldPos TYPE i,
IntFieldTyp TYPE String,
CSVFieldPos TYPE i,
CSVFieldName TYPE String,
END OF l_typ_Confrontation.
"-Variables-----------------------------------------------------------
DATA l_rda_data TYPE REF TO Data.
DATA l_rda_wa TYPE REF TO Data.
DATA l_rcl_descr_tab TYPE REF TO cl_abap_tabledescr.
DATA l_rcl_descr_struc TYPE REF TO cl_abap_structdescr.
DATA l_comp_descr TYPE abap_compdescr.
DATA l_tab_content TYPE STANDARD TABLE OF String.
DATA l_Line TYPE String VALUE ''.
DATA l_tab_confrontation TYPE STANDARD TABLE OF l_typ_Confrontation
WITH KEY CSVFieldPos.
DATA l_FieldName TYPE String VALUE ''.
DATA l_Content TYPE String VALUE ''.
DATA l_Conf TYPE l_typ_Confrontation.
FIELD-SYMBOLS <l_Table> TYPE STANDARD TABLE.
FIELD-SYMBOLS <l_comp> TYPE Any.
FIELD-SYMBOLS <l_wa> TYPE Any.
"-Main----------------------------------------------------------------
IF g_csv_data IS NOT INITIAL AND g_error_flag = abap_false.
"-Reference to Table----------------------------------------------
CREATE DATA l_rda_data TYPE STANDARD TABLE OF (i_tablename).
ASSIGN l_rda_data->* TO <l_Table>.
"-Get Structure of Table------------------------------------------
l_rcl_descr_tab ?= cl_abap_typedescr=>describe_by_data( <l_Table> ).
l_rcl_descr_struc ?= l_rcl_descr_tab->get_table_line_type( ).
"-Define Line of Table--------------------------------------------
CREATE DATA l_rda_wa LIKE LINE OF <l_Table>.
ASSIGN l_rda_wa->* TO <l_wa>.
"-Compare Field Names of the Table with Headline of CSV-----------
"-
"- With this step is the position of the column indifferent. It
"- is only necessary that the field of the table and the column
"- of the CSV file must have the same name.
"-
"-----------------------------------------------------------------
LOOP AT l_rcl_descr_struc->components INTO l_comp_descr.
l_Conf-intfieldname = l_comp_descr-name.
l_Conf-intfieldpos = sy-tabix.
l_Conf-intfieldtyp = l_comp_descr-type_kind.
LOOP AT g_tab_fields INTO l_FieldName.
l_Conf-csvfieldpos = -1.
l_Conf-csvfieldname = 'UNKNOWN'.
IF l_comp_descr-name = l_FieldName.
l_Conf-csvfieldname = l_FieldName.
l_Conf-csvfieldpos = sy-tabix.
EXIT.
ENDIF.
ENDLOOP.
APPEND l_Conf TO l_tab_confrontation.
ENDLOOP.
DELETE l_tab_confrontation WHERE csvfieldpos = -1.
SORT l_tab_confrontation BY csvfieldpos.
"-Copy Data-------------------------------------------------------
DATA(l_from) = COND #( WHEN has_header = abap_true THEN 2 ELSE 1 ).
LOOP AT g_csv_data INTO l_Line FROM l_from.
SPLIT l_Line AT ';' INTO TABLE l_tab_content.
LOOP AT l_tab_content INTO l_Content.
CONDENSE l_Content.
READ TABLE l_tab_confrontation WITH KEY CSVFieldPos = sy-tabix
INTO l_Conf.
IF sy-subrc = 0.
ASSIGN COMPONENT l_Conf-intfieldname OF STRUCTURE <l_wa>
TO <l_comp>.
IF l_Conf-intfieldtyp = 'P'.
IF l_Content CA ','.
REPLACE ALL OCCURRENCES OF '.' IN l_Content WITH ''.
REPLACE ',' IN l_Content WITH '.'.
ENDIF.
<l_comp> = l_Content.
ELSEIF l_Conf-intfieldtyp = 'D'.
set_data( EXPORTING i_data = l_Content
IMPORTING e_data = <l_comp> ).
ELSE.
<l_comp> = l_Content.
ENDIF.
ENDIF.
ENDLOOP.
APPEND <l_wa> TO <l_Table>.
CLEAR <l_wa>.
ENDLOOP.
"-Write Data into Table-------------------------------------------
IF modo_test IS INITIAL.
INSERT (i_tablename) FROM TABLE <l_Table>.
ELSE.
*--[ Para ver que ha ido bien, sin ALV ni cosas raras, este programa es
*--[ Para gente con conocimientos y con responsabilidad :D :D
DATA alv TYPE REF TO cl_salv_table.
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = alv
CHANGING
t_table = <l_Table> ).
CATCH cx_salv_msg INTO DATA(message) .
" error handling
ENDTRY.
if has_max > 0.
has_max = lines( <l_Table> ).
message s398(00) with 'Muestra de' has_max ' registros.'.
endif.
alv->display( ).
ENDIF.
IF sy-subrc <> 0.
g_error_flag = abap_true.
ENDIF.
ENDIF.
"-End-------------------------------------------------------------------
ENDMETHOD.
METHOD load_csv_file.
DATA: l_filename TYPE string,
l_filetable TYPE filetable,
l_rc TYPE i.
"- Begin-----------------------------------------------------------------
IF i_filename IS INITIAL.
CALL METHOD cl_gui_frontend_services=>file_open_dialog
EXPORTING
window_title = 'Importar CSV'
* default_extension =
* default_filename =
* file_filter =
* with_encoding =
* initial_directory =
multiselection = ' '
CHANGING
file_table = l_filetable
rc = l_rc
* user_action =
* file_encoding =
EXCEPTIONS
file_open_dialog_failed = 1
cntl_error = 2
error_no_gui = 3
not_supported_by_gui = 4
OTHERS = 5.
IF sy-subrc NE 0 OR lines( l_filetable ) NE 1.
EXIT.
ELSE.
READ TABLE l_filetable INDEX 1 INTO DATA(l_file).
IF sy-subrc EQ 0.
l_filename = l_file-filename.
ELSE.
EXIT.
ENDIF.
ENDIF.
ELSE.
l_filename = i_filename.
ENDIF.
l_Filename = l_filename.
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = l_FileName
filetype = 'ASC'
TABLES
data_tab = g_csv_data
EXCEPTIONS
OTHERS = 1.
IF sy-subrc <> 0.
g_error_flag = abap_true.
ENDIF.
"-End-------------------------------------------------------------------
ENDMETHOD.
METHOD transform_csv_data.
"-Begin-----------------------------------------------------------------
"-Variables-----------------------------------------------------------
DATA l_Fld1 TYPE String VALUE ''.
DATA l_Fld2 TYPE String VALUE ''.
DATA l_Fld3 TYPE String VALUE ''.
DATA l_FldRest TYPE String VALUE ''.
FIELD-SYMBOLS <Line> TYPE String.
"-Main----------------------------------------------------------------
IF g_csv_data IS NOT INITIAL AND g_error_flag = abap_false.
"-Manipulate Headline---------------------------------------------
READ TABLE g_csv_data INDEX 1 ASSIGNING <Line>.
IF has_mandt IS INITIAL AND NOT has_header IS INITIAL.
<Line> = 'MANDT;' && <Line>.
ENDIF.
CONDENSE <Line> NO-GAPS.
SPLIT <Line> AT ';' INTO TABLE g_tab_fields.
IF has_mandt IS INITIAL.
LOOP AT g_csv_data FROM 2 ASSIGNING <Line>.
<Line> = sy-mandt && ';' && <Line>.
ENDLOOP.
ENDIF.
ENDIF.
IF has_max > 0 .
IF NOT has_header IS INITIAL. ADD 1 TO has_max. ENDIF. "<-
IF has_max < lines( g_csv_data ).
add 1 to has_max.
DELETE g_csv_data FROM has_max ."TO lines( g_csv_data ) .
ENDIF.
ENDIF.
"-End-------------------------------------------------------------------
ENDMETHOD.
ENDCLASS.
end-of-SELECTION.
"-End-------------------------------------------------------------------
"-Variables-----------------------------------------------------------
DATA: csv TYPE REF TO z_csv_import,
l_tab TYPE string.
"-Main----------------------------------------------------------------
IF NOT p_wipe IS INITIAL.
DELETE FROM (p_tab).
COMMIT WORK.
ENDIF.
CREATE OBJECT csv.
csv->Load_CSV_File( ).
l_tab = p_tab.
CHECK NOT l_tab IS INITIAL.
*--[ Configuración
csv->modo_test = p_test.
csv->has_header = p_header.
csv->data_format = p_datf.
csv->has_mandt = p_mandt.
csv->has_max = p_max.
*--[ Transformación
csv->Transform_CSV_Data( l_tab ).
csv->Get_CSV_Data( l_tab ).