Email ABAP report PDF



The below code to demonstrates how to email ABAP report PDF. It generates an ALV output of personal numbers (PERNRS) and then converts this to a PDF document. Its then sends an external email with the PDF as an attachment

SAP ABAP report functionality used by this report


  • Email address input selection screen fields
  • Display ALV report using Objects cl_salv_table
  • Add custom ALV column header
  • Change colour of ALV rows based on user start year
  • Get ALV Spool from background execution
  • Convert Spool to PDF and send as Email
  • Submit an ABAP report in the background
  • ABAP report submits itself in the background to create spool
  • Pass parameter and select options to report submit ABAP statement
  • Delete SAP spool request

*&-------------------------------*
REPORT ZREP_EMAIL_ALV_SPOOL.

TABLES:  PA0001, PA0000.

SELECTION-SCREEN BEGIN OF block block1 WITH FRAME title text-001.
  SELECT-OPTIONS:   so_pernr for pa0001-pernr.
  Parameters:       p_keydat type datum DEFAULT sy-datum.
  Parameters:       p_email  type AD_SMTPADR default '[email protected]'.
* Ensure you always declare your email parameters using AD_SMTPADR. On one occasion
* when using somlreci1-receiver I found that the entered default resulted in a different
* underlying hexedecimal value which SAP did not recognise as a valid email address.
* For example during runtime take a look at the values contained in gd_email2 and
* gd_email3. You may notice that the hex values are different from p_email. Just
* somthing to think about if your email are not getting sent and SO_DOCUMENT_SEND_API1
* is returning an x_error.
***image***

SELECTION-SCREEN END OF block block1.

*Data Declaration
*----------------
data: r_objid type range of hrp1001-objid.
data: wa_objid like line of r_objid.

TYPES: BEGIN OF t_report,
         pernr       type p0000-pernr,
         vorna       type p0002-vorna,
         nachn       type p0002-nachn,
         ename       type p0001-ename,
         begda       type p0000-begda,
         orgeh       type p0001-orgeh,
         details(20) type c,
         color       TYPE lvc_t_scol, "table for cell colouring
       END OF t_report.
DATA: it_report TYPE STANDARD TABLE OF t_report INITIAL SIZE 0,
      wa_report TYPE t_report.

DATA alv_table    TYPE REF TO cl_salv_table.
DATA alv_columns TYPE REF TO cl_salv_columns_table.
DATA single_column  TYPE REF TO cl_salv_column.

data: objec_tab type STANDARD TABLE OF objec,
      it_dept   type STANDARD TABLE OF objec,
      wa_objtab like line of objec_tab,
      struc_tab type STANDARD TABLE OF STRUC,
      wa_struc  like line of struc_tab,
      ld_orgeh  type orgeh.

DATA: gd_recsize TYPE i.

DATA: gd_eventid                 LIKE tbtcm-eventid,
      gd_eventparm               LIKE tbtcm-eventparm,
      gd_external_program_active LIKE tbtcm-xpgactive,
      gd_jobcount                LIKE tbtcm-jobcount,
      gd_jobname                 LIKE tbtcm-jobname,
      gd_stepcount               LIKE tbtcm-stepcount,
      gd_error                   TYPE sy-subrc,
      gd_reciever                TYPE sy-subrc.

DATA:  w_recsize TYPE i.

DATA: gd_subject         LIKE sodocchgi1-obj_descr,
      it_mess_bod        LIKE solisti1 OCCURS 0 WITH HEADER LINE,
      it_mess_att        LIKE solisti1 OCCURS 0 WITH HEADER LINE,
      gd_sender_type     LIKE soextreci1-adr_typ,
      gd_attachment_desc TYPE so_obj_nam,
      gd_attachment_name TYPE so_obj_des.

* Spool to PDF conversions
DATA: gd_spool_nr    LIKE tsp01-rqident,
      gd_destination LIKE rlgrap-filename,
      gd_bytecount   LIKE tst01-dsize,
      gd_buffer      TYPE string.

* Spool IDs
TYPES: BEGIN OF t_tbtcp.
        INCLUDE STRUCTURE TBTCP.
TYPES: END OF t_tbtcp.
DATA: it_tbtcp TYPE STANDARD TABLE OF t_tbtcp INITIAL SIZE 0,
      wa_tbtcp TYPE t_tbtcp.

* Binary store for PDF
DATA: BEGIN OF it_pdf_output OCCURS 0.
        INCLUDE STRUCTURE TLINE.
DATA: END OF it_pdf_output.

DATA: seltab    type table of rsparams,
      seltab_wa like line of seltab.

data: gd_email type somlreci1-receiver,
      gd_email2 type somlreci1-receiver,  "just for test/demo
      gd_email3 type AD_SMTPADR.          "just for test/demo

data: wa_addreess type sx_address.

************************************************************************
* START-OF-SELECTION
START-OF-SELECTION.
  gd_email = p_email.
  gd_email2 = '#[email protected]'.
  gd_email3 = '#[email protected]'.

  PERFORM data_retrieval.
  PERFORM display_settings.
  perform set_row_colors.

************************************************************************
* END-OF-SELECTION
END-OF-SELECTION.
  perform display_alv_report.

  IF sy-batch EQ 'X'.
    PERFORM get_job_details.
    PERFORM obtain_spool_id.
    PERFORM convert_spool_to_pdf.
    PERFORM send_email_rep.
    PERFORM delete_spool.
  ELSE.
    perform submit_report_in_background.
  endif.


*&-------------------------------*
*& FORM data_retrieval.
*&-------------------------------*
FORM data_retrieval.
  data: ld_deptlines type i.

  select a~pernr a~begda b~vorna b~nachn c~ename  c~orgeh
    from PA0000 as a inner join pa0002 as b
      on b~pernr eq a~pernr
     INNER JOIN pa0001 as c
    on c~pernr eq b~pernr
    into CORRESPONDING FIELDS OF table it_report
   "for ALL ENTRIES IN it_emps
   where "a~pernr eq it_emps-pernr
       a~pernr in so_pernr
     and a~begda le p_keydat
     and a~endda ge p_keydat
     and b~begda le p_keydat
     and b~endda ge p_keydat
     and c~begda le p_keydat
     and c~endda ge p_keydat.
ENDFORM.                    " DATA_RETRIEVAL

*&-------------------------------*
*& FORM display_settings.
*&-------------------------------*
FORM display_settings.
  DATA: err_message   TYPE REF TO cx_salv_msg.

  TRY.
      cl_salv_table=>factory(
      IMPORTING
        r_salv_table = alv_table
      CHANGING
        t_table      = it_report ).

      alv_columns = alv_table->get_columns( ).

      PERFORM build_layout.
      PERFORM build_fieldcatalog.
      PERFORM build_toolbar.
      PERFORM hide_columns.
      PERFORM report_settings.

    CATCH cx_salv_msg INTO err_message.
*   Add error processing
  ENDTRY.
ENDFORM.

*&-------------------------------*
*& FORM display_alv_report.
*&-------------------------------*
FORM display_alv_report.
* set_optimize will set columns optimised based on data and will remove
* any width specification setup within build_fieldcatalog column setup
*  it_columns->set_optimize( ).

  alv_table->display( ).
ENDFORM.

*&-------------------------------*
*& FORM build_layout.
*&-------------------------------*
FORM build_layout.
  DATA: layout TYPE REF TO cl_salv_layout.
  DATA: layout_key      TYPE salv_s_layout_key.

  layout = alv_table->get_layout( ).

  layout_key-report = sy-repid.
  layout->set_key( layout_key ).

  layout->set_save_restriction( if_salv_c_layout=>restrict_none ).
ENDFORM.                    "BUILD_LAYOUT

*&-------------------------------*
*& FORM hide_columns.
*&-------------------------------*
FORM hide_columns.
  DATA: err_notfound TYPE REF TO cx_salv_not_found.

  TRY.
      single_column = alv_columns->get_column( 'VORNA' ).
      single_column->set_visible( if_salv_c_bool_sap=>false ).
      single_column = alv_columns->get_column( 'NACHN' ).
      single_column->set_visible( if_salv_c_bool_sap=>false ).

    CATCH cx_salv_not_found INTO err_notfound.
*   Add error processing
  ENDTRY.
ENDFORM.

*&-------------------------------*
*& FORM build_fieldcatalog.
*&-------------------------------*
*  Your ALV report should get texts from the internal table used but you
*  overwrite them here if you require
*&-------------------------------*
FORM build_fieldcatalog.
  DATA: err_notfound TYPE REF TO cx_salv_not_found.

  TRY.
      single_column = alv_columns->get_column( 'BEGDA' ).
      single_column->set_short_text( 'Start Date' ).  "Will cause syntax error if text is too long
      single_column->set_medium_text( 'Start Date' ).
      single_column->set_long_text( 'Employee Start Date' ).
      single_column->SET_OUTPUT_LENGTH( '10' ). "Force column to be wider to accomodate heading

    CATCH cx_salv_not_found INTO err_notfound.
*   Add error processing
  ENDTRY.
ENDFORM.

*&-------------------------------*
*& FORM build_toolbar.
*&-------------------------------*
*  The code below simply displays all available functions but you can
*  restrict this if you require
*&-------------------------------*
FORM build_toolbar.
  DATA: toolbar_functions TYPE REF TO cl_salv_functions_list.

  toolbar_functions = alv_table->get_functions( ).
  toolbar_functions->set_all( ).
ENDFORM.

*&-------------------------------*
*& FORM report_settings.
*&-------------------------------*
FORM report_settings.
  DATA: report_settings TYPE REF TO cl_salv_display_settings.

  report_settings = alv_table->get_display_settings( ).
  report_settings->set_striped_pattern( if_salv_c_bool_sap=>true ).
  report_settings->set_list_header( 'Demo SAP ALV Report and PDF email' ).
ENDFORM.

*&-------------------------------*
*&      Form  SET_ROW_COLORS
*&-------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  get_columns( ).

*Set column colour
*    TRY.
*        lo_col_tab ?= lo_cols_tab->get_column( 'PERNR' ).
*        ls_color-col = col_total.
*        lo_col_tab->set_color( ls_color ).
*      CATCH cx_salv_not_found.
*    ENDTRY.

  Loop at it_report into wa_report.
    ld_tabix = sy-tabix.

    if wa_report-begda(4) EQ sy-datum(4). "this year.
      ls_s_color-color-col = col_negative.
      ls_s_color-color-int = 1.
      ls_s_color-color-inv = 0.
      APPEND ls_s_color TO lt_s_color.
      CLEAR  ls_s_color.
    else." eq other year
      ls_s_color-color-col =  7.
      ls_s_color-color-int = 1.
      ls_s_color-color-inv = 0.
      APPEND ls_s_color TO lt_s_color.
      CLEAR  ls_s_color.
    endif.

    wa_report-color = lt_s_color.
    MODIFY it_report FROM wa_report index ld_tabix.

    CLEAR  lt_s_color.
  endloop.

*   We will set this COLOR table field name of the internal table to
*   COLUMNS tab reference for the specific colors
  TRY.
      lo_cols_tab->set_color_column( 'COLOR' ).
    CATCH cx_salv_data_error.                           "#EC NO_HANDLER
  ENDTRY.
ENDFORM.                    " SET_ROW_COLORS

*---------------------------------------------------------------------*
*       FORM get_job_details                                          *
*---------------------------------------------------------------------*
FORM get_job_details.
* Get current job details
CALL FUNCTION 'GET_JOB_RUNTIME_INFO'
    IMPORTING
      eventid                 = gd_eventid
      eventparm               = gd_eventparm
      external_program_active = gd_external_program_active
      jobcount                = gd_jobcount
      jobname                 = gd_jobname
      stepcount               = gd_stepcount
    EXCEPTIONS
      no_runtime_info         = 1
      OTHERS                  = 2.
ENDFORM.

*---------------------------------------------------------------------*
*       FORM obtain_spool_id                                          *
*---------------------------------------------------------------------*
FORM obtain_spool_id.
  CHECK NOT ( gd_jobname IS INITIAL ).
  CHECK NOT ( gd_jobcount IS INITIAL ).

  select * from  TBTCP
                 INTO TABLE it_tbtcp
                 WHERE      jobname     = gd_jobname
                 AND        jobcount    = gd_jobcount
                 AND        stepcount   = gd_stepcount
                 AND        listident    '0000000000'
                 ORDER BY   jobname
                            jobcount
                            stepcount.

  READ TABLE it_tbtcp INTO wa_tbtcp INDEX 1.
  IF sy-subrc = 0.
    gd_spool_nr = wa_tbtcp-listident.
    MESSAGE s004(zdd) WITH gd_spool_nr.
  ELSE.
    MESSAGE s005(zdd).
  ENDIF.
ENDFORM.


*---------------------------------------------------------------------*
*       FORM convert_spool_to_pdf                                     *
*---------------------------------------------------------------------*
FORM convert_spool_to_pdf.

CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
    EXPORTING
      src_spoolid              = gd_spool_nr
      no_dialog                = ' '
      dst_device               = 'LOCL'
    IMPORTING
      pdf_bytecount            = gd_bytecount
    TABLES
      pdf                      = it_pdf_output
    EXCEPTIONS
      err_no_abap_spooljob     = 1
      err_no_spooljob          = 2
      err_no_permission        = 3
      err_conv_not_possible    = 4
      err_bad_destdevice       = 5
      user_cancelled           = 6
      err_spoolerror           = 7
      err_temseerror           = 8
      err_btcjob_open_failed   = 9
      err_btcjob_submit_failed = 10
      err_btcjob_close_failed  = 11
      OTHERS                   = 12.

  CHECK sy-subrc = 0.

* Transfer the 132-long strings to 255-long strings
  LOOP AT it_pdf_output.
    TRANSLATE it_pdf_output USING ' ~'.
    CONCATENATE gd_buffer it_pdf_output INTO gd_buffer.
  ENDLOOP.

  TRANSLATE gd_buffer USING '~ '.

  DO.
    it_mess_att = gd_buffer.
    APPEND it_mess_att.
    SHIFT gd_buffer LEFT BY 255 PLACES.
    IF gd_buffer IS INITIAL.
      EXIT.
    ENDIF.
  ENDDO.
ENDFORM.

*---------------------------------------------------------------------*
*       FORM send_email                                               *
*---------------------------------------------------------------------*
*  -->  p_email                                                       *
*---------------------------------------------------------------------*
FORM send_email_rep.
  data: ld_sender type somlreci1-receiver.


  DESCRIBE TABLE it_mess_att LINES gd_recsize.
  CHECK gd_recsize > 0.

  CHECK NOT ( gd_email IS INITIAL ).

  ld_sender = gd_email.

  REFRESH it_mess_bod.

* Default subject matter
  gd_subject         = 'Subject'.
  gd_attachment_desc = 'Attachname'.
*  CONCATENATE 'attach_name' ' ' INTO gd_attachment_name.
  it_mess_bod        = 'Email Message Body text, line 1'.
  APPEND it_mess_bod.
  it_mess_bod        = 'Email message Body text, line 2...'.
  APPEND it_mess_bod.

* If no sender specified - default blank
  IF ld_sender EQ space.
    gd_sender_type  = space.
  ELSE.
    gd_sender_type  = 'INT'.
  ENDIF.


* Send file by email as .pdf attachment
  PERFORM send_file_as_email_attachment
                               TABLES IT_MESS_BOD
                                      it_mess_att
                                using gd_email
                                      'Example pdf document email attachment'
                                      'PDF'
                                      gd_attachment_name
                                      gd_attachment_desc
                                      ld_sender
                                      gd_sender_type
                             changing gd_error
                                      gd_reciever.
ENDFORM.

*&-------------------------------*
*&      Form  SEND_FILE_AS_EMAIL_ATTACHMENT
*&-------------------------------*
*       Send email
*----------------------------------------------------------------------*
FORM SEND_FILE_AS_EMAIL_ATTACHMENT TABLES IT_MESSAGE
                                          it_attach
                                    using p_email
                                          p_mtitle
                                          p_format
                                          p_filename
                                          p_attdescription
                                          p_sender_address
                                          p_sender_addres_type
                                 changing p_error
                                          p_reciever.


  DATA: ld_error               TYPE sy-subrc,
        ld_reciever            TYPE sy-subrc,
        ld_mtitle              LIKE sodocchgi1-obj_descr,
        ld_email               LIKE  somlreci1-receiver,
        ld_format              TYPE  so_obj_tp,
        ld_attdescription      TYPE  so_obj_nam,
        ld_attfilename         TYPE  so_obj_des,
        ld_sender_address      LIKE  soextreci1-receiver,
        ld_sender_address_type LIKE  soextreci1-adr_typ,
        ld_receiver            LIKE  sy-subrc.

  data:   t_packing_list  like sopcklsti1 occurs 0 with header line,
          t_contents      like solisti1 occurs 0 with header line,
          t_receivers     like somlreci1 occurs 0 with header line,
          t_attachment    like solisti1 occurs 0 with header line,
          t_object_header like solisti1 occurs 0 with header line,
          w_cnt           type i,
          w_sent_all(1)   type c,
          w_doc_data      like sodocchgi1.


  ld_email   = p_email.
  ld_mtitle = p_mtitle.
  ld_format              = p_format.
  ld_attdescription      = p_attdescription.
  ld_attfilename         = p_filename.
  ld_sender_address      = p_sender_address.
  ld_sender_address_type = p_sender_addres_type.


* Fill the document data.
  w_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
  w_doc_data-obj_langu = sy-langu.
  w_doc_data-obj_name  = 'SAPRPT'.
  w_doc_data-obj_descr = ld_mtitle .
  w_doc_data-sensitivty = 'F'.

* Fill the document data and get size of attachment
  CLEAR w_doc_data.
  READ TABLE it_attach INDEX w_cnt.
  w_doc_data-doc_size =
     ( w_cnt - 1 ) * 255 + STRLEN( it_attach ).
  w_doc_data-obj_langu  = sy-langu.
  w_doc_data-obj_name   = 'SAPRPT'.
  w_doc_data-obj_descr  = ld_mtitle.
  w_doc_data-sensitivty = 'F'.
  CLEAR t_attachment.
  REFRESH t_attachment.
  t_attachment[] = it_attach[].

* Describe the body of the message
  CLEAR t_packing_list.
  REFRESH t_packing_list.
  t_packing_list-transf_bin = space.
  t_packing_list-head_start = 1.
  t_packing_list-head_num = 0.
  t_packing_list-body_start = 1.
  DESCRIBE TABLE it_message LINES t_packing_list-body_num.
  t_packing_list-doc_type = 'RAW'.
  APPEND t_packing_list.

* Create attachment notification
  t_packing_list-transf_bin = 'X'.
  t_packing_list-head_start = 1.
  t_packing_list-head_num   = 1.
  t_packing_list-body_start = 1.

  DESCRIBE TABLE t_attachment LINES t_packing_list-body_num.
  t_packing_list-doc_type   =  ld_format.
  t_packing_list-obj_descr  =  ld_attdescription.
  t_packing_list-obj_name   =  ld_attfilename.
  t_packing_list-doc_size   =  t_packing_list-body_num * 255.
  APPEND t_packing_list.

* Add the recipients email address
  CLEAR t_receivers.
  REFRESH t_receivers.
  t_receivers-receiver = ld_email.
  t_receivers-rec_type = 'U'.
  t_receivers-com_type = 'INT'.
  t_receivers-notif_del = 'X'.
  t_receivers-notif_ndel = 'X'.
  APPEND t_receivers.

CALL FUNCTION 'SO_DOCUMENT_SEND_API1'
    EXPORTING
      document_data              = w_doc_data
      put_in_outbox              = 'X'
      sender_address             = ld_sender_address
      sender_address_type        = ld_sender_address_type
      commit_work                = 'X'
    IMPORTING
      sent_to_all                = w_sent_all
    TABLES
      packing_list               = t_packing_list
      contents_bin               = t_attachment
      contents_txt               = it_message
      receivers                  = t_receivers
    EXCEPTIONS
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      OTHERS                     = 8.

* Populate zerror return code
  ld_error = sy-subrc.

* Populate zreceiver return code
  LOOP AT t_receivers.
    ld_receiver = t_receivers-retrn_code.
  ENDLOOP.
ENDFORM.

*---------------------------------------------------------------------*
*       FORM delete_spool                                             *
*---------------------------------------------------------------------*
FORM delete_spool.
  DATA: ld_spool_nr TYPE tsp01_sp0r-rqid_char.

  ld_spool_nr = gd_spool_nr.
  check not ld_spool_nr is initial.
CALL FUNCTION 'RSPO_R_RDELETE_SPOOLREQ'
    EXPORTING
      spoolid = ld_spool_nr.
ENDFORM.

*&-------------------------------*
*&      Form  SUBMIT_REPORT_IN_BACKGROUND
*&-------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  

Text pool values

Selection Text: P_ADMAIL = Admin Email
Selection Text: P_KEYDAT = Key date
Selection Text: SO_PERNR = Personnel Selection

About the Author se80