Monday, October 12, 2009

ABAP Report: Download a file from SAP to desktop

This is a follow up to the posting which discusses uploading a file to an internal table. We will see how to download a table to a file. This also will use the RTTS services to create an internal table from the structure name. In this report we also have the log displaying the number records processed and the actual table entries that are downloaded. This example has the table T001 which has the list of companies downloaded.

Selection screen:

image

Output showing the table values

image

and the log tab

image

The program has three screens attached to it. The first screen has the tabs and the other two screens are the subscreens of these tabs. To create a tab strip is easy, just click on the wizard and it will do that for your. On the subscreens I have created custom control to show ALV and log outputs.

*&---------------------------------------------------------------------*
*& Report  ZDOWNLOAD
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT  zdownload MESSAGE-ID zx_message.
*----------------------------------------------------------------------*
*       CLASS download DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS download DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS open_file.
    METHODS start.
    METHODS end.
    METHODS free_log.
    METHODS display_output.
    METHODS display_log.
  PRIVATE SECTION.
    CONSTANTS c_max_ranges TYPE i VALUE 100.
    CONSTANTS c_seperator TYPE abap_char1 VALUE cl_abap_char_utilities=>horizontal_tab.
    DATA download_file TYPE REF TO data.
    DATA t_tab_file TYPE TABLE OF string.
    DATA o_struc_type TYPE REF TO cl_abap_structdescr.
    DATA s_log TYPE bal_s_log.
    DATA log_handle         TYPE balloghndl.
    DATA t_log_handle       TYPE bal_t_logh.
    DATA o_ccont_display TYPE REF TO cl_gui_custom_container.
    DATA o_ccont_log TYPE REF TO cl_gui_custom_container.
    DATA dummy.
    METHODS select_data.
    METHODS copy_to_tab_file.
    METHODS create_table.
    METHODS open_log.
    METHODS add_msg.
ENDCLASS.                    "download DEFINITION
DATA o_download TYPE REF TO download.
DATA s_t001 TYPE t001.
*--------------------------------------------------------------------*
* File Location
SELECTION-SCREEN BEGIN OF BLOCK file WITH FRAME TITLE text-f01.
PARAMETERS:
  p_file   TYPE rlgrap-filename OBLIGATORY,
  p_header AS CHECKBOX DEFAULT abap_true.
SELECTION-SCREEN END OF BLOCK file.
*--------------------------------------------------------------------*
* Material selection
SELECTION-SCREEN BEGIN OF BLOCK bukrs WITH FRAME TITLE text-001.
*--- company options
SELECT-OPTIONS s_bukrs FOR s_t001-bukrs.
SELECTION-SCREEN END OF BLOCK bukrs.
*--------------------------------------------------------------------*
* Defaults
SELECTION-SCREEN BEGIN OF BLOCK intr WITH FRAME TITLE text-t03.
PARAMETERS:
  p_struc TYPE strukname DEFAULT 'T001'.
SELECTION-SCREEN END OF BLOCK intr.
*--------------------------------------------------------------------*
* F4
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  download=>open_file( ).
*--------------------------------------------------------------------*
START-OF-SELECTION.
  CREATE OBJECT o_download.
  o_download->start( ).
*--------------------------------------------------------------------*
END-OF-SELECTION.
  o_download->end( ).
  CALL SCREEN 0100.
*----------------------------------------------------------------------*
*       CLASS download IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS download IMPLEMENTATION.
  METHOD open_file.
    DATA:
        l_t_file_table TYPE TABLE OF file_table,
        l_s_file_table TYPE file_table.
    DATA l_subrc TYPE i.
    CALL METHOD cl_gui_frontend_services=>file_open_dialog
      CHANGING
        file_table              = l_t_file_table
        rc                      = l_subrc
      EXCEPTIONS
        file_open_dialog_failed = 1
        cntl_error              = 2
        error_no_gui            = 3
        not_supported_by_gui    = 4
        OTHERS                  = 5.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
    READ TABLE l_t_file_table INTO l_s_file_table INDEX 1.
    p_file = l_s_file_table-filename.
  ENDMETHOD.                    "open_file
  METHOD start.
    open_log( ).
    create_table( ).
    select_data( ).
    copy_to_tab_file( ).
  ENDMETHOD.                    "start
  METHOD create_table.
    DATA l_type TYPE string.
    DATA lo_type TYPE REF TO cl_abap_typedescr.
    DATA lo_tabletype TYPE REF TO cl_abap_tabledescr.
    l_type = p_struc.
    CALL METHOD cl_abap_structdescr=>describe_by_name
      EXPORTING
        p_name         = l_type
      RECEIVING
        p_descr_ref    = lo_type
      EXCEPTIONS
        type_not_found = 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.
    o_struc_type ?= lo_type.
    TRY.
        CALL METHOD cl_abap_tabledescr=>create
          EXPORTING
            p_line_type  = o_struc_type
*    P_TABLE_KIND = TABLEKIND_STD
*    P_UNIQUE     = ABAP_FALSE
*    P_KEY        =
*    P_KEY_KIND   = KEYDEFKIND_DEFAULT
          RECEIVING
            p_result     = lo_tabletype
            .
      CATCH cx_sy_table_creation .
    ENDTRY.
    CREATE DATA download_file TYPE HANDLE lo_tabletype.
* Structure mapped successfully
    MESSAGE s181 INTO dummy.
    add_msg( ).
  ENDMETHOD.                    "create_table
  METHOD select_data.
    FIELD-SYMBOLS <l_download_file> TYPE table.
    DATA l_lines TYPE i.
    ASSIGN download_file->* TO <l_download_file>.
    SELECT * INTO CORRESPONDING FIELDS OF TABLE <l_download_file>
      FROM t001
      WHERE bukrs IN s_bukrs.
  ENDMETHOD.                    "select_data
  METHOD copy_to_tab_file.
    DATA l_row TYPE string.
*    DATA lt_component TYPE abap_component_tab.
*    DATA lst_component TYPE abap_componentdescr.
    DATA lt_fielddesc TYPE ddfields.
    DATA lst_fielddesc TYPE dfies.
    DATA lt_tempstring TYPE TABLE OF string.
    DATA l_o_type TYPE REF TO cl_abap_typedescr.
    DATA l_extdate TYPE string.
    DATA l_lines TYPE i.
    FIELD-SYMBOLS <l_tab_file> TYPE string.
    FIELD-SYMBOLS <l_download_file> TYPE table.
    FIELD-SYMBOLS <l_file_row> TYPE ANY.
    FIELD-SYMBOLS <l_string_row> TYPE ANY.
    FIELD-SYMBOLS <l_field> TYPE ANY.
* Get the field list.
    lt_fielddesc = o_struc_type->get_ddic_field_list( ).
    IF p_header IS NOT INITIAL. " Add header in the first row
      APPEND INITIAL LINE TO t_tab_file ASSIGNING <l_tab_file>.
      LOOP AT lt_fielddesc INTO lst_fielddesc.
        APPEND INITIAL LINE TO lt_tempstring ASSIGNING <l_string_row>.
        <l_string_row> = lst_fielddesc-scrtext_m.
      ENDLOOP.
      CONCATENATE LINES OF lt_tempstring INTO <l_tab_file>
        SEPARATED BY c_seperator.
    ENDIF.
    CLEAR lt_tempstring[].
    ASSIGN download_file->* TO <l_download_file>.
    SORT <l_download_file>.
* Add data now
    LOOP AT <l_download_file> ASSIGNING <l_file_row>.
      APPEND INITIAL LINE TO t_tab_file ASSIGNING <l_tab_file>.
      WHILE sy-subrc IS INITIAL.
        ASSIGN COMPONENT sy-index OF STRUCTURE <l_file_row> TO <l_field>.
        IF sy-subrc IS NOT INITIAL.
          EXIT.
        ENDIF.
        APPEND INITIAL LINE TO lt_tempstring ASSIGNING <l_string_row>.
        <l_string_row> = <l_field>.
* Convert dates
        l_o_type = cl_abap_typedescr=>describe_by_data( <l_field> ).
* For date type convert from YYYYMMDD to DD.MM.YYYY
        IF l_o_type->type_kind = cl_abap_typedescr=>typekind_date.
          TRY.
              CALL METHOD cl_abap_datfm=>conv_date_int_to_ext
                EXPORTING
                  im_datint   = <l_field>
                  im_datfmdes = '1' " DD.MM.YYYY
                IMPORTING
                  ex_datext   = l_extdate.
              <l_string_row> = l_extdate.
            CATCH cx_abap_datfm_no_date cx_abap_datfm_invalid_date
                  cx_abap_datfm_format_unknown cx_abap_datfm_ambiguous .
* Invalide date format in the field &1 for row &2
          ENDTRY.
        ENDIF.
      ENDWHILE.
      CONCATENATE LINES OF lt_tempstring INTO <l_tab_file>
        SEPARATED BY c_seperator.
      CLEAR lt_tempstring[].
    ENDLOOP.
    DESCRIBE TABLE t_tab_file LINES l_lines.
* & Records transfered to Tab limited table
    MESSAGE s183 WITH l_lines INTO dummy.
    add_msg( ).
  ENDMETHOD.                    "copy_to_tab_file
  METHOD end.
    DATA l_filename TYPE string.
    l_filename = p_file.
    CALL METHOD cl_gui_frontend_services=>gui_download
      EXPORTING
*    BIN_FILESIZE              =
        filename                  = l_filename
*    FILETYPE                  = 'ASC'
*    APPEND                    = SPACE
*    WRITE_FIELD_SEPARATOR     = SPACE
*    HEADER                    = '00'
*    TRUNC_TRAILING_BLANKS     = SPACE
*    WRITE_LF                  = 'X'
*    COL_SELECT                = SPACE
*    COL_SELECT_MASK           = SPACE
*    DAT_MODE                  = SPACE
*    CONFIRM_OVERWRITE         = SPACE
*    NO_AUTH_CHECK             = SPACE
*    CODEPAGE                  = SPACE
*    IGNORE_CERR               = ABAP_TRUE
*    REPLACEMENT               = '#'
*    WRITE_BOM                 = SPACE
*    TRUNC_TRAILING_BLANKS_EOL = 'X'
*    WK1_N_FORMAT              = SPACE
*    WK1_N_SIZE                = SPACE
*    WK1_T_FORMAT              = SPACE
*    WK1_T_SIZE                = SPACE
*  IMPORTING
*    FILELENGTH                =
      CHANGING
        data_tab                  = t_tab_file
      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.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDMETHOD.                    "end
  METHOD open_log.
* create a log
    s_log-extnumber  = 'Application Log in Subscreen'(001).
    CALL FUNCTION 'BAL_LOG_CREATE'
      EXPORTING
        i_s_log      = s_log
      IMPORTING
        e_log_handle = log_handle
      EXCEPTIONS
        OTHERS       = 1.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
    INSERT log_handle INTO TABLE t_log_handle.
* Log opened successfully
    MESSAGE s180 INTO dummy.
    add_msg( ).
  ENDMETHOD.                    "open_log
  METHOD add_msg.
    DATA:
      l_s_msg   TYPE bal_s_msg.
* define data of message for Application Log
    l_s_msg-msgty     = sy-msgty.
    l_s_msg-msgid     = sy-msgid.
    l_s_msg-msgno     = sy-msgno.
    l_s_msg-msgv1     = sy-msgv1.
    l_s_msg-msgv2     = sy-msgv2.
    l_s_msg-msgv3     = sy-msgv3.
    l_s_msg-msgv4     = sy-msgv4.
* add this message to log file
    CALL FUNCTION 'BAL_LOG_MSG_ADD'
      EXPORTING
        i_log_handle = log_handle
        i_s_msg      = l_s_msg
      EXCEPTIONS
        OTHERS       = 1.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDMETHOD.                    "add_msg
  METHOD free_log.
* free all data (this must NOT be forgotten !)
    CALL FUNCTION 'BAL_DSP_OUTPUT_FREE'
      EXCEPTIONS
        OTHERS = 1.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDMETHOD.                    "free_log
  METHOD display_output.
    DATA:
      l_r_table   TYPE REF TO cl_salv_table,
*      l_r_event_handler TYPE REF TO l_cl_event_handler,
      l_r_events TYPE REF TO cl_salv_events_table,
      l_t_salv_t_int4_column TYPE salv_t_int4_column,
      l_s_salv_t_int4_column TYPE LINE OF salv_t_int4_column.
    FIELD-SYMBOLS <l_download_file> TYPE table.
    ASSIGN download_file->* TO <l_download_file>.
*--------------------------------------------------------------------*
    IF o_ccont_display IS INITIAL.
* Create holder container
      CREATE OBJECT o_ccont_display
        EXPORTING
*    PARENT                      =
          container_name              = 'CCONTROL_0101'
*    STYLE                       =
*    LIFETIME                    = lifetime_default
*    REPID                       =
*    DYNNR                       =
*    NO_AUTODEF_PROGID_DYNNR     =
        EXCEPTIONS
          cntl_error                  = 1
          cntl_system_error           = 2
          create_error                = 3
          lifetime_error              = 4
          lifetime_dynpro_dynpro_link = 5
          OTHERS                      = 6
          .
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                   WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.
*--------------------------------------------------------------------*
* Create AVL table
      TRY.
          cl_salv_table=>factory(
            EXPORTING
              r_container = o_ccont_display
            IMPORTING
              r_salv_table = l_r_table
            CHANGING
              t_table      = <l_download_file> ).
        CATCH cx_salv_msg.                              "#EC NO_HANDLER
      ENDTRY.
*--------------------------------------------------------------------*
* Functions
      DATA:
        lr_functions TYPE REF TO cl_salv_functions_list.
      lr_functions = l_r_table->get_functions( ).
*  lr_functions->set_aggregation_total( abap_true ).
      lr_functions->set_default( abap_true ).
* Columns
      DATA:
        lr_columns TYPE REF TO cl_salv_columns_table,
        lr_column TYPE REF TO cl_salv_column.
      lr_columns = l_r_table->get_columns( ).
      lr_columns->set_optimize( abap_true ).
      TRY.
          CALL METHOD lr_columns->set_exception_column
            EXPORTING
              value     = 'TRAFFIC_LIGHT'
              group     = '2'
              condensed = if_salv_c_bool_sap=>false.
        CATCH cx_salv_data_error .
      ENDTRY.
      TRY.
          CALL METHOD lr_columns->set_cell_type_column
            EXPORTING
              value = 'CELL_TYPE'.
        CATCH cx_salv_data_error .
      ENDTRY.
      l_r_table->display( ).
    ENDIF.
  ENDMETHOD.                    "get_e1maktm
  METHOD display_log.
    DATA:
      l_r_table   TYPE REF TO cl_salv_table,
*      l_r_event_handler TYPE REF TO l_cl_event_handler,
      l_r_events TYPE REF TO cl_salv_events_table,
      l_t_salv_t_int4_column TYPE salv_t_int4_column,
      l_s_salv_t_int4_column TYPE LINE OF salv_t_int4_column.
    DATA ls_display_profile  TYPE bal_s_prof.
    DATA l_control_handle     TYPE balcnthndl.
    FIELD-SYMBOLS <l_download_file> TYPE table.
*--------------------------------------------------------------------*
* Create holder container
    IF o_ccont_log IS INITIAL.
      CREATE OBJECT o_ccont_log
        EXPORTING
*    PARENT                      =
          container_name              = 'CCONTROL_0102'
*    STYLE                       =
*    LIFETIME                    = lifetime_default
*    REPID                       =
*    DYNNR                       =
*    NO_AUTODEF_PROGID_DYNNR     =
        EXCEPTIONS
          cntl_error                  = 1
          cntl_system_error           = 2
          create_error                = 3
          lifetime_error              = 4
          lifetime_dynpro_dynpro_link = 5
          OTHERS                      = 6
          .
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                   WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.
*       get a display profile which describes how to display messages
      CALL FUNCTION 'BAL_DSP_PROFILE_NO_TREE_GET'
        IMPORTING
          e_s_display_profile = ls_display_profile.
      ls_display_profile-no_toolbar = 'X'.
*--------------------------------------------------------------------*
*       create control to display data
      CALL FUNCTION 'BAL_CNTL_CREATE'
        EXPORTING
          i_container         = o_ccont_log
          i_s_display_profile = ls_display_profile
          i_t_log_handle      = t_log_handle
        IMPORTING
          e_control_handle    = l_control_handle
        EXCEPTIONS
          OTHERS              = 1.
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDIF.
    ENDIF.
  ENDMETHOD.                    "display_log
ENDCLASS.                    "download IMPLEMENTATION
*&---------------------------------------------------------------------*
*&      Module  status_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
* set status and title
  SET PF-STATUS 'STATUS'.
  SET TITLEBAR 'TITLE'.
* flush data to frontend
  CALL METHOD cl_gui_cfw=>flush.
ENDMODULE.                 " status_0100  OUTPUT
*&SPWIZARD: FUNCTION CODES FOR TABSTRIP 'TAB_STRIP'
CONSTANTS: BEGIN OF c_tab_strip,
             tab1 LIKE sy-ucomm VALUE 'TAB_STRIP_FC1',
             tab2 LIKE sy-ucomm VALUE 'TAB_STRIP_FC2',
           END OF c_tab_strip.
*&SPWIZARD: DATA FOR TABSTRIP 'TAB_STRIP'
CONTROLS:  tab_strip TYPE TABSTRIP.
DATA:      BEGIN OF g_tab_strip,
             subscreen   LIKE sy-dynnr,
             prog        LIKE sy-repid VALUE 'ZDOWNLOAD',
             pressed_tab LIKE sy-ucomm VALUE c_tab_strip-tab1,
           END OF g_tab_strip.
DATA:      ok_code LIKE sy-ucomm.
*&SPWIZARD: OUTPUT MODULE FOR TS 'TAB_STRIP'. DO NOT CHANGE THIS LINE!
*&SPWIZARD: SETS ACTIVE TAB
MODULE tab_strip_active_tab_set OUTPUT.
  tab_strip-activetab = g_tab_strip-pressed_tab.
  CASE g_tab_strip-pressed_tab.
    WHEN c_tab_strip-tab1.
      g_tab_strip-subscreen = '0101'.
    WHEN c_tab_strip-tab2.
      g_tab_strip-subscreen = '0102'.
    WHEN OTHERS.
*&SPWIZARD:      DO NOTHING
  ENDCASE.
ENDMODULE.                    "TAB_STRIP_ACTIVE_TAB_SET OUTPUT
*&SPWIZARD: INPUT MODULE FOR TS 'TAB_STRIP'. DO NOT CHANGE THIS LINE!
*&SPWIZARD: GETS ACTIVE TAB
MODULE tab_strip_active_tab_get INPUT.
  ok_code = sy-ucomm.
  CASE ok_code.
    WHEN c_tab_strip-tab1.
      g_tab_strip-pressed_tab = c_tab_strip-tab1.
    WHEN c_tab_strip-tab2.
      g_tab_strip-pressed_tab = c_tab_strip-tab2.
    WHEN OTHERS.
*&SPWIZARD:      DO NOTHING
  ENDCASE.
ENDMODULE.                    "TAB_STRIP_ACTIVE_TAB_GET INPUT
*&---------------------------------------------------------------------*
*&      Module  user_command_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0100 INPUT.
  CASE ok_code.
*   leave this screen
    WHEN 'ABBR' OR 'BACK' OR 'BEEN'.
      LEAVE TO SCREEN 0.
    WHEN OTHERS.
  ENDCASE.
* Delete log profile
  o_download->free_log( ).
* call dispatch method of control framwork
  CALL METHOD cl_gui_cfw=>dispatch.
ENDMODULE.                 " user_command_0100  INPUT
*&---------------------------------------------------------------------*
*&      Module  display_output  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE display_output OUTPUT.
  o_download->display_output( ).
ENDMODULE.                 " display_output  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  display_log  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE display_log OUTPUT.
  o_download->display_log( ).
ENDMODULE.                 " display_log  OUTPUT

No comments: