Send ALV Report Output as CSV Email Attachement

This utility report runs specified ALV report behind the scene and extract its output, converts that to csv and send it to email recipients. Very useful if you want to send output of report to user(s) periodically.

Program takes report name and variant as input. It runs specified report with specified variant and export list to memory using statement.


  SUBMIT (p_report)
  USING SELECTION-SET p_vari
         LINE-SIZE sy-linsz
        EXPORTING LIST TO MEMORY AND RETURN.

Then using function module LIST_FROM_MEMORY program imports list from memory, convert it into ascii format using function module LIST_TO_ASCI. After some text processing it converts output in csv format and compose email with attachment using class CL_BCS.


REPORT  zpw_run_email.

*&---------------------------------------------------------------------*
*&      Types and Data
*&---------------------------------------------------------------------*

CONSTANTS:
  gc_tab  TYPE c VALUE cl_bcs_convert=>gc_tab,
  gc_crlf TYPE c VALUE cl_bcs_convert=>gc_crlf.

TYPES :  BEGIN OF ty_fin ,
            line TYPE string ,
          END OF ty_fin .

DATA : g_email         TYPE char200 .
DATA : ascilines(1024) TYPE c OCCURS 0 WITH HEADER LINE.
DATA : list            TYPE TABLE OF abaplist WITH HEADER LINE.
DATA : i_final         TYPE TABLE OF ty_fin .

*&---------------------------------------------------------------------*
*&      Selection Screen
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME .
PARAMETERS : p_report TYPE trdir-name    OBLIGATORY,
             p_vari   TYPE rsvar-variant OBLIGATORY.
SELECTION-SCREEN SKIP 1 .

PARAMETER : p_trim TYPE char01 AS   CHECKBOX ,
            p_neg  TYPE char01 AS CHECKBOX .
SELECTION-SCREEN SKIP 1 .

SELECT-OPTIONS : s_to FOR g_email NO INTERVALS OBLIGATORY,
                 s_cc FOR g_email NO INTERVALS .
SELECTION-SCREEN END OF BLOCK b1 .

*&---------------------------------------------------------------------*
*&      Start of Selection
*&---------------------------------------------------------------------*
START-OF-SELECTION .
  PERFORM execute_report .
  PERFORM process_output .
  PERFORM send_email .

*&---------------------------------------------------------------------*
*&      Form  execute_report
*&---------------------------------------------------------------------*
FORM execute_report .
* Call report and export output in memory
  SUBMIT (p_report)
  USING SELECTION-SET p_vari
         LINE-SIZE sy-linsz
        EXPORTING LIST TO MEMORY AND RETURN.
ENDFORM.                    "execute_report


*&---------------------------------------------------------------------*
*&      Form  process_output
*&---------------------------------------------------------------------*
FORM process_output .

  TYPES : BEGIN OF ty_split ,
             token TYPE char50 ,
          END OF ty_split .

  DATA : li_split TYPE TABLE OF ty_split ,
         lv_str   TYPE string            ,
         ls_final TYPE ty_fin            ,
         lv_token TYPE char50            .

  FIELD-SYMBOLS <fs_slip> TYPE ty_split .

* Get report output from memory
  CALL FUNCTION 'LIST_FROM_MEMORY'
    TABLES
      listobject = list
    EXCEPTIONS
      not_found  = 1
      OTHERS     = 2.

* Convert it to ascii
  CALL FUNCTION 'LIST_TO_ASCI'
    TABLES
      listobject         = list
      listasci           = ascilines
    EXCEPTIONS
      empty_list         = 1
      list_index_invalid = 2
      OTHERS             = 3.

* Convert ascii to csv file
  LOOP AT ascilines .
*   Skip separater lines
    CHECK ascilines+0(10) <> '----------' .
    CLEAR li_split .
    SPLIT ascilines AT '|' INTO TABLE li_split .

    CLEAR lv_str .
    LOOP AT li_split ASSIGNING <fs_slip> .

      CLEAR lv_token .
      lv_token = <fs_slip>-token .

*     Post processing
      IF p_trim = abap_true .
        CONDENSE lv_token .
      ENDIF .

      IF p_neg = abap_true .
        CONDENSE lv_token .
        TRY.
            FIND REGEX '(\d+(\,\d+)?)+(\.\d+)?-' IN lv_token .
            IF sy-subrc = 0 .
              REPLACE '-' IN lv_token WITH space .
              CONCATENATE '-' lv_token INTO lv_token .
            ENDIF.
          CATCH cx_root .
            MESSAGE 'Error in regular expression' TYPE 'A'.
        ENDTRY .
      ENDIF.

      CASE sy-tabix.
        WHEN 1 .
        WHEN 2.
          lv_str = lv_token.
        WHEN OTHERS.
          CONCATENATE lv_str lv_token INTO lv_str SEPARATED BY gc_tab.
      ENDCASE.
    ENDLOOP .
    CLEAR ls_final .
    ls_final-line = lv_str   .
    APPEND ls_final TO i_final .
  ENDLOOP.
ENDFORM.                    "process_output


*&---------------------------------------------------------------------*
*&      Form  send_email
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM send_email .

  DATA lv_string TYPE string.
  DATA : ls_final TYPE ty_fin .

  DATA main_text      TYPE bcsy_text.
  DATA binary_content TYPE solix_tab.
  DATA size           TYPE so_obj_len.
  DATA : email      TYPE adr6-smtp_addr.

  DATA send_request   TYPE REF TO cl_bcs.
  DATA document       TYPE REF TO cl_document_bcs.
  DATA recipient      TYPE REF TO if_recipient_bcs.
  DATA bcs_exception  TYPE REF TO cx_bcs.
  DATA sent_to_all    TYPE os_boolean.

  DATA : lv_subject TYPE so_obj_des .


  LOOP AT i_final INTO ls_final .
    CASE sy-tabix.
      WHEN 1.
        CONCATENATE ls_final-line gc_crlf INTO lv_string .
      WHEN OTHERS.
        CONCATENATE lv_string ls_final-line gc_crlf INTO lv_string .
    ENDCASE.
  ENDLOOP.

* --------------------------------------------------------------
* convert the text string into UTF-16LE binary data including
* byte-order-mark. Mircosoft Excel prefers these settings
* all this is done by new class cl_bcs_convert (see note 1151257)

  TRY.
      cl_bcs_convert=>string_to_solix(
        EXPORTING
          iv_string   = lv_string
          iv_codepage = '4103'  "suitable for MS Excel, leave empty
          iv_add_bom  = 'X'     "for other doc types
        IMPORTING
          et_solix  = binary_content
          ev_size   = size ).
    CATCH cx_bcs.
      MESSAGE e445(so).
  ENDTRY.


  TRY.

*     -------- create persistent send request ------------------------
      send_request = cl_bcs=>create_persistent( ).

*     -------- create and set document with attachment ---------------
*     create document object from internal table with text

      CONCATENATE p_report p_vari sy-datum sy-uzeit INTO lv_subject SEPARATED BY space.

      PERFORM create_body_of_email CHANGING main_text .

*     APPEND 'Email from SAP background Job' TO main_text.  "#EC NOTEXT
      document = cl_document_bcs=>create_document(
        i_type    = 'HTM'
        i_text    = main_text
        i_subject = lv_subject ).                           "#EC NOTEXT

      DATA : lv_name TYPE sood-objdes .

      lv_name = p_report .
*     add the spread sheet as attachment to document object
      document->add_attachment(
        i_attachment_type    = 'csv'                        "#EC NOTEXT
        i_attachment_subject = lv_name                      "#EC NOTEXT
        i_attachment_size    = size
        i_att_content_hex    = binary_content ).

*     add document object to send request
      send_request->set_document( document ).

*      DATA : l_receipient_soos TYPE soos1.

*     --------- add recipient (e-mail address) -----------------------
      LOOP AT s_to .
*       create recipient object
        email = s_to-low .
        recipient = cl_cam_address_bcs=>create_internet_address( email ).
*       add recipient object to send request
        send_request->add_recipient( recipient ).
      ENDLOOP .

      CALL METHOD send_request->set_status_attributes
        EXPORTING
          i_requested_status = 'E'.

      LOOP AT s_cc .
*       create recipient object
        email = s_cc-low .
        recipient = cl_cam_address_bcs=>create_internet_address( email ).

*       add recipient object to send request
        send_request->add_recipient( EXPORTING i_recipient = recipient i_copy = abap_true ).
      ENDLOOP .


*     ---------- send document ---------------------------------------
      sent_to_all = send_request->send( i_with_error_screen = 'X' ).

      COMMIT WORK.

      IF sent_to_all IS INITIAL.
        MESSAGE i500(sbcoms) WITH s_to-low.
      ELSE.
        MESSAGE s022(so).
      ENDIF.

*   ------------ exception handling ----------------------------------
*   replace this rudimentary exception handling with your own one !!!
    CATCH cx_bcs INTO bcs_exception.
      MESSAGE i865(so) WITH bcs_exception->error_type.
  ENDTRY.



ENDFORM .                    "send_email

*&---------------------------------------------------------------------*
*&      Form  CREATE_BODY_OF_EMAIL
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_MAIN_TEXT  text
*----------------------------------------------------------------------*
FORM create_body_of_email  CHANGING body_html TYPE bcsy_text.

  DATA : ls_line TYPE so_text255 .

  APPEND '<html>' TO body_html .
  APPEND '<title>Email</title>' TO body_html .
  APPEND '<body>' TO body_html  .
  APPEND '<p>Data attached</p>' TO body_html .
  APPEND '</body>' TO body_html .
  APPEND '</html>' TO body_html .

ENDFORM.                    " CREATE_BODY_OF_EMAIL

I tried above program with MB52.

email sap alv report csv attachment

email sap alv report csv attachment

10 Replies to “Send ALV Report Output as CSV Email Attachement

  1. Just came across your post 4 years after:) This is a great program, very versatile, thank you very much for posting.

  2. Saw this and this is great but I do get “Cannot process message; maximum size exceeded”. How to address this since if I use the same csv file that i downloaded to my pc and attach to my outlook, i dont get the maximum size issue.

  3. Hello.

    After more than 8 years found this piece of art that solved a requirement in a snap – it was copy and paste!

    Many, many thanks for that.

    Now, just have to personalize it for our needs but the structure and simplicity are awsome!

    Regards, From Portugal.
    Manuel Antunes

Leave a Reply