A few days ago, one of my SAP BI/BW friends requested a program that would accept any table as input and download it as a file to the local machine. In short, he needed a utility tool for the mass download of any SAP table. There may be numerous ways to achieve this goal, but creating an effective program to handle the result table structure is crucial. In “Dynamically Download Data From Any SAP Table in ABAP-740 – Part 1,” we will explore how to develop such a utility to streamline this process.
You might ponder, for what reason can they not simply use SE16, SE16N to download the information? I don’t have a persuading reply to that. Yet, I was glad to investigate this necessity and do some powerful table age.
How to give user option to Select Fields of Table?
I attempted and had the option to produce the program. Yet, I needed to give the client choices to pick the fields which they need to find in the last result record. Since I was being languid, I chose to ask our SAP Wire Gathering individuals. Brief came the answer from Ananias who gave his feedback. This program is the code piece given by Ananias.
Capability Modules ‘DD_TABL_GET’ and ‘DD_LIST_TABFIELDS’ would help.
How to handle .INCLUDE and .APPEND in the tables?
The field ROLLNAME would be clear for these metadata. We can securely erase them.
* .INCLUDE, .APPEND and other attributes should be deleted * They have rollname as blank DELETE li_fld_copy WHERE rollname IS INITIAL.
Cautioning People…
In any case, however.. There is a grave issue. There are many fields in the tables where we don’t characterize the information component. We utilize the Predefined Types. Along these lines, we shouldn’t erase where ROLLNAME is clear.
So the protected method for eliminating the Adds and Incorporates is to search for PreDefined Information Type. They can’t be clear for any field.
* .INCLUDE, .APPEND and other attributes should be deleted * They have INTTYPE as blank DELETE li_fld_copy WHERE inttype IS INITIAL.
How to remove fields not chosen?
We have included a field named MARK in our TYPE. We will use it for identifying the chosen fields.
* Remove what the user did not choose DELETE li_fld_copy WHERE mark IS INITIAL.
How to build the list of fields for the SELECT statement?
Simply put the fields in a string separated by SPACE.
* Make the list of fields to be used in SELECT Statement CONCATENATE ls_fields-fieldname gs_field_list INTO gs_field_list SEPARATED BY space.
How to get the Component Details?
ABAP_COMPONENTDESCR table type comes handy here.
data: gs_components TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name, " Components ls_components LIKE LINE OF gs_components. ls_components-name = ls_fields-fieldname. ls_components-type ?= cl_abap_elemdescr=>describe_by_name( ls_fields-rollname ) . APPEND ls_components TO gs_components.
How to Create the Dynamic Structure & Internal Table?
The standard class CL_ABAP_STRUCTDESC method CREATE would do the needful. Get P_COMPONENTS for the structure and P_LINE_TYPE for the internal table type.
lr_struct_result = cl_abap_structdescr=>create( p_components = gs_components ). lr_table_result = cl_abap_tabledescr=>create( p_line_type = lr_struct_result ).
How to SELECT from Table Dynamically?
TYPE HANDLE and ASSIGN lrt_table->* TO dynamic table do the trick.
*&---------------------------------------------------------------------* *& Form SUB_DYNAMIC_SELECT *&---------------------------------------------------------------------* * Dynamically Select from Any Table *----------------------------------------------------------------------* FORM sub_dynamic_select USING lr_table_result TYPE REF TO cl_abap_tabledescr lr_struct_result TYPE REF TO cl_abap_structdescr. DATA: lrt_table TYPE REF TO data, lrs_struct TYPE REF TO data. FIELD-SYMBOLS: TYPE any. CREATE DATA: lrt_table TYPE HANDLE lr_table_result. * lrs_struct TYPE HANDLE lr_struct_result. ASSIGN lrt_table->* TO . * ASSIGN lrs_struct->* TO . IF IS ASSIGNED. * This is the Dynamic Select SELECT (gs_field_list) FROM (p_tab) INTO CORRESPONDING FIELDS OF TABLE . ENDIF. ENDFORM. ENDIF.
Note: Keep the above code snippet as Template to create Dynamic Internal table and work area.
Let’s Check the Output
Can we download all the Fields?
Yes. Why not? Check the output below.
Code Snippet
*---------------------------------------------------------------------* * TYPES *---------------------------------------------------------------------* TYPES: * Type for the table along with Marker Flag BEGIN OF t_fld. INCLUDE STRUCTURE dd03p AS dd03p. " Dictonary Attributes TYPES: mark LIKE rsdxx-mark, " Entry marked type_icon TYPE dd02d-datatype, " Type Icon * fkexi(1), " Flag for existence * mod(1), " Modification Id * actf(1), " Active Flag * switch_id TYPE sfw_switch_id, " Id of a Switch in Switch Framework END OF t_fld, * Type for the table header BEGIN OF ty_str_hdr, field_name TYPE char20, END OF ty_str_hdr. *---------------------------------------------------------------------* * DATA * *---------------------------------------------------------------------* DATA: git_header_text TYPE STANDARD TABLE OF ty_str_hdr, " Header Text gs_field_list TYPE string, " SELECT Field List gref_struct_result TYPE REF TO cl_abap_structdescr, " Structure gref_table_result TYPE REF TO cl_abap_tabledescr, " Table gs_components TYPE STANDARD TABLE OF abap_componentdescr WITH KEY name. " Components *---------------------------------------------------------------------* * FIELD-SYMBOLS * *---------------------------------------------------------------------* FIELD-SYMBOLS: TYPE INDEX TABLE. " Final Table *---------------------------------------------------------------------* * SELECTION SCREEN * *---------------------------------------------------------------------* SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001. PARAMETERS: p_tab TYPE tabname OBLIGATORY, p_file TYPE localfile OBLIGATORY. SELECTION-SCREEN END OF BLOCK b1. *---------------------------------------------------------------------* * AT SELECTION-SCREEN ON VALUE-REQUEST. *---------------------------------------------------------------------* AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file. * F4 Help for File PERFORM sub_f4_for_file CHANGING p_file. *---------------------------------------------------------------------* * START-OF-SELECTION. * *---------------------------------------------------------------------* START-OF-SELECTION. * Option to Select Which Field to download PERFORM sub_pop_up_to_select USING p_tab CHANGING gref_table_result gref_struct_result. *---------------------------------------------------------------------* * END-OF-SELECTION. * *---------------------------------------------------------------------* END-OF-SELECTION. * Do the Dynamic Select from Any Table PERFORM sub_dynamic_select USING gref_table_result gref_struct_result. * Download the Tab Delimited Text File to the Local Machine PERFORM sub_download_file USING p_file. *---------------------------------------------------------------------* * SUB ROUTINES * *---------------------------------------------------------------------* *&---------------------------------------------------------------------* *& Form SUB_F4_FOR_FILE *&---------------------------------------------------------------------* * F4 Help *----------------------------------------------------------------------* FORM sub_f4_for_file CHANGING p_p_file TYPE localfile. CALL FUNCTION 'F4_FILENAME' EXPORTING field_name="p_file" IMPORTING file_name = p_p_file. ENDFORM. *&---------------------------------------------------------------------* *& Form SUB_POP_UP_TO_SELECT *&---------------------------------------------------------------------* * Select Fields for Output *----------------------------------------------------------------------* FORM sub_pop_up_to_select USING p_p_tab TYPE tabname CHANGING lr_table_result TYPE REF TO cl_abap_tabledescr lr_struct_result TYPE REF TO cl_abap_structdescr.. DATA: lv_get_state TYPE dctablget, li_fld_copy TYPE TABLE OF t_fld, li_dd03p TYPE TABLE OF dd03p, ls_components LIKE LINE OF gs_components, ls_header TYPE ty_str_hdr. lv_get_state-tabd = lv_get_state-tabt="A". * Get table metadata CALL FUNCTION 'DD_TABL_GET' EXPORTING get_state = lv_get_state prid = -2 tabl_name = p_p_tab withtext="X" add_typeinfo = 'X' TABLES dd03p_tab_a = li_dd03p EXCEPTIONS OTHERS = 2. * Adding extra fields * Field MARK is used for now to idendify the selected field(s) li_fld_copy = li_dd03p. CALL FUNCTION 'DD_LIST_TABFIELDS' EXPORTING eutype="V" p_with_type="X" TABLES fieldtab = li_fld_copy EXCEPTIONS not_executed = 1 OTHERS = 2. * .INCLUDE, .APPEND and other attributes should be deleted * They have INTTYPE as blank DELETE li_fld_copy WHERE inttype IS INITIAL. * Remove what the user did not choose DELETE li_fld_copy WHERE mark IS INITIAL. LOOP AT li_fld_copy INTO DATA(ls_fields). * Make the list of fields to be used in SELECT Statement CONCATENATE ls_fields-fieldname gs_field_list INTO gs_field_list SEPARATED BY space. ** Header Line (Medium Text) for the Spreadsheet * CONCATENATE ls_fields-scrtext_m gs_header_text INTO gs_header_text SEPARATED BY cl_abap_char_utilities=>horizontal_tab. ls_components-name = ls_fields-fieldname. ls_components-type ?= cl_abap_elemdescr=>describe_by_name( ls_fields-rollname ) . APPEND ls_components TO gs_components. APPEND ls_fields-scrtext_m TO git_header_text. ENDLOOP. TRY . lr_struct_result = cl_abap_structdescr=>create( p_components = gs_components ). lr_table_result = cl_abap_tabledescr=>create( p_line_type = lr_struct_result ). CATCH cx_sy_struct_creation. " CATCH cx_sy_table_creation. ENDTRY. ENDFORM. *&---------------------------------------------------------------------* *& Form SUB_DYNAMIC_SELECT *&---------------------------------------------------------------------* * Dynamically Select from Any Table *----------------------------------------------------------------------* FORM sub_dynamic_select USING lr_table_result TYPE REF TO cl_abap_tabledescr lr_struct_result TYPE REF TO cl_abap_structdescr. DATA: lrt_table TYPE REF TO data, lrs_struct TYPE REF TO data. FIELD-SYMBOLS: TYPE any. CREATE DATA: lrt_table TYPE HANDLE lr_table_result. * lrs_struct TYPE HANDLE lr_struct_result. ASSIGN lrt_table->* TO . * ASSIGN lrs_struct->* TO . IF IS ASSIGNED. * This is the Dynamic Select SELECT (gs_field_list) FROM (p_tab) INTO CORRESPONDING FIELDS OF TABLE . ENDIF. ENDFORM. *&---------------------------------------------------------------------* *& Form SUB_DOWNLOAD_FILE *&---------------------------------------------------------------------* * Download File *----------------------------------------------------------------------* FORM sub_download_file USING p_p_file type localfile. DATA: lv_file TYPE string. * Moving to a type compatible variable lv_file = p_p_file. CALL METHOD cl_gui_frontend_services=>gui_download EXPORTING filename = lv_file filetype="ASC" write_field_separator="X" fieldnames = git_header_text CHANGING data_tab = EXCEPTIONS file_write_error = 1 no_batch = 2 gui_refuse_filetransfer = 3 invalid_type = 4 no_authority = 5 unknown_error = 6 header_not_allowed = 7 separator_not_allowed = 8 filesize_not_allowed = 9 header_too_long = 10 dp_error_create = 11 dp_error_send = 12 dp_error_write = 13 unknown_dp_error = 14 access_denied = 15 dp_out_of_memory = 16 disk_full = 17 dp_timeout = 18 file_not_found = 19 dataprovider_exception = 20 control_flush_error = 21 not_supported_by_gui = 22 error_no_gui = 23 OTHERS = 24. IF sy-subrc = 0. WRITE:/ 'File downloaded successfully' COLOR COL_POSITIVE. ENDIF. ENDFORM.
This is an example program to progressively download any table. There are dependably various ways to arrive at a similar objective. Likewise, there would be other better ways of accomplishing this usefulness. Be that as it may, you can securely utilize this code scrap to begin your utility program. You might upgrade it better and can likewise put one more screen to add fields in the choice screen progressively to choose just those values recorded in the determination screen input.
There are some issues with the above method.
1. Data Element should not be used for creation of dynamic structures.
Reason being – Some tables are created with fields without data elements.
2. Error Handling not done
In the above code scrap, a few special cases are not dealt with. Thus, now and again, it could dump.
In the following article, we will demonstrate how Stephan developed another program in ABAP 751 (NW7.51) using the new syntax features such as DECREASE
, VALUE
, INIT
, COND
, FOR
, etc., and how these features helped overcome the challenges associated with this program. Additionally, we will explore “Dynamically Download Data From Any SAP Table in ABAP-740 – Part 1,” which provides a practical utility for downloading SAP table data.
YOU MAY BE INTERESTED IN
Steampunk Chronicles: Navigating the Cloud with SAP BTP ABAP Environment