SAP ABAP Mass Download Attachment

SAP ABAP Mass Download Attachment

    Have you ever found yourself needing to mass download all attachments from a specific transaction in SAP? Doing this manually for each record can be very time-consuming. Instead of downloading attachments one by one, imagine being able to export everything at once.

    In this post, I’m sharing a custom ABAP solution that performs mass download of GOS attachments, using SAP Invoices (RBKP) as the example.


How It Works

    The program first selects invoice data from RBKP table, based on user input such as company code, document number, fiscal year, and posting date. This selection logic is flexible and can be adjusted to fit your own business requirements, or even replaced with another SAP object that supports GOS attachments.

    For each selected invoice, the program retrieves all related attachment links from SRGBTBREL, which stores the relationship between SAP business objects and their attached documents. Each attachment is then read using SO_DOCUMENT_READ_API1, converted from binary format, and downloaded to the user’s local directory using GUI_DOWNLOAD. The solution also supports multiple attachments per invoice and automatically handles file naming and extensions.


FORM get_data.
  SELECT DISTINCT a~bukrs, a~belnr, a~gjahr, a~lifnr, b~ebeln
    FROM rbkp AS a
    LEFT JOIN rseg AS b ON b~belnr = a~belnr AND b~gjahr = a~gjahr
    WHERE a~belnr IN @S_BELNR AND
          a~bukrs = @p_bukrs AND
          a~gjahr = @p_gjahr AND
          a~budat IN @s_budat
          INTO TABLE @lt_rbkp.

  IF lt_rbkp IS NOT INITIAL.
    SORT lt_rbkp BY belnr bukrs gjahr ebeln.
    LOOP AT lt_rbkp INTO ls_rbkp.
      PERFORM download USING ls_rbkp.
    ENDLOOP.
    IF lt_output IS NOT INITIAL.
      TRY.
          cl_salv_table=>factory(
            IMPORTING
              r_salv_table = o_alv
            CHANGING
              t_table      = lt_output ).
        CATCH cx_salv_msg INTO lx_msg.
      ENDTRY.

      CALL METHOD o_alv->get_layout
        RECEIVING
          value = o_layout.

      CALL METHOD o_layout->set_key
        EXPORTING
          value = key.

      CALL METHOD o_layout->set_save_restriction
        EXPORTING
          value = if_salv_c_layout=>restrict_none.

      o_cols = o_alv->get_columns( ).
      TRY.
          o_column = o_cols->get_column( 'FILES' ).
          o_column->set_long_text( 'Downloaded Files' ).
          o_column->set_medium_text( 'Downloaded Files' ).
          o_column->set_short_text( 'Files' ).
          o_column->set_output_length( 50 ).
        CATCH cx_salv_not_found.                        "#EC NO_HANDLER
      ENDTRY.

      o_alv->get_functions( )->set_all( ).

      o_cols->set_optimize( 'X' ).

      o_alv->display( ).

    ENDIF.
  ENDIF.

ENDFORM.

FORM download  USING    p_ls_rbkp TYPE gty_rbkp.
  DATA: ls_object        TYPE sibflporb,
        lt_doc_id        TYPE STANDARD TABLE OF srgbtbrel,
        lt_objectheader  TYPE srm_t_solisti1,
        lt_objectcontent TYPE srm_t_solisti1,
        lt_content_hex   TYPE tabtype_solix,
        ls_doc_data      TYPE sofolenti1,
        lt_links_table   TYPE STANDARD TABLE OF srgbtbrel,
        lv_length        TYPE i,
        lv_filename      TYPE string,
        lvfile           TYPE string,
        lv_ext           TYPE char4,
        lv_index         TYPE char4.

  ls_object-instid = p_ls_rbkp-belnr && p_ls_rbkp-gjahr.
  SELECT * FROM srgbtbrel INTO TABLE lt_links_table
       WHERE instid_a = ls_object-instid.
  IF sy-subrc EQ 0 .

    DESCRIBE TABLE lt_links_table LINES DATA(lv_lines).
    IF lv_lines > 1.
      DATA(lv_mult) = abap_true.
    ENDIF.

    LOOP AT lt_links_table INTO DATA(lw_links).
      WRITE sy-tabix TO lv_index.
      MOVE lw_links-instid_b TO doc_id.
      CLEAR :ls_doc_data,lt_content_hex,lt_objectcontent,lt_objectheader,lv_length.
      CALL FUNCTION 'SO_DOCUMENT_READ_API1'
        EXPORTING
          document_id                = doc_id
*         FILTER                     = 'X '
        IMPORTING
          document_data              = ls_doc_data
        TABLES
          object_header              = lt_objectheader
          object_content             = lt_objectcontent
          contents_hex               = lt_content_hex
        EXCEPTIONS
          document_id_not_exist      = 1
          operation_no_authorization = 2
          x_error                    = 3
          OTHERS                     = 4.

      TRANSLATE ls_doc_data-obj_descr TO UPPER CASE.
      lv_length = ls_doc_data-doc_size.
      IF lt_content_hex IS NOT INITIAL.

        lv_filename = p_file .
        IF ls_doc_data-obj_type EQ 'XLS'.
          lv_ext = 'XLSX'.
        ELSEIF  ls_doc_data-obj_type = 'DOC'.
          lv_ext = 'DOCX'.
        ELSE.
          lv_ext = ls_doc_data-obj_type.
        ENDIF.

        CONCATENATE ls_object-instid '_' ls_doc_data-obj_descr INTO lv_filename.

        IF lv_mult EQ abap_true.
          CONDENSE lv_index.
          CONCATENATE p_ls_rbkp-belnr '_' lv_index INTO lv_filename.
        ELSE.
          lv_filename = p_ls_rbkp-belnr  .
        ENDIF.
        CONCATENATE p_file '\' lv_filename '.' lv_ext INTO lvfile.
        ls_output-files = lv_filename && '.' && lv_ext.
        ls_output-belnr = p_ls_rbkp-belnr.
        ls_output-gjahr = p_ls_rbkp-gjahr.
        ls_output-bukrs = p_ls_rbkp-bukrs.
        ls_output-ebeln = p_ls_rbkp-ebeln.
        ls_output-lifnr = p_ls_rbkp-lifnr.
        CALL FUNCTION 'GUI_DOWNLOAD'
          EXPORTING
            filename = lvfile
            filetype = 'BIN'
          TABLES
            data_tab = lt_content_hex.
        IF sy-subrc EQ 0 .
          APPEND ls_output TO lt_output.
          CLEAR ls_output.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDIF.
ENDFORM.





Comments

Popular posts from this blog

Learn How to Use STVARV for Dynamic ABAP Programs

Why Can't I Find This Text in SE16N? Mastering the READ_TEXT Function Module