Menu

How to Create a PDF from a Report in ABAP

2014-08-11       

So, you know how to send e-mails, even with attachments. But how do you send out nice PDFs instead of ugly text files? In this post, I’ll explain how to programmatically convert the output of a report to PDF so that it’s available for download or to send as an e-mail attachment.

Unsere Literaturempfehlung

SAP – Der technische Einstieg: SAP-Technologien und Konzepte

Sind Sie neu in der SAP-Welt und möchten schnell mitreden? Mit diesem Buch finden Sie sich erfolgreich im SAP-Umfeld zurecht! Sie steigen direkt in die Konzepte und Technologien der SAP-Software ein und lernen die unterschiedlichen Systeme und Prozesse kennen. Schritt für Schritt zeigen die Autoren Ihnen die wichtigsten technischen Aufgaben und die Zusammenhänge zwischen den Objekten. Dank der vielen Beispiele und Abbildungen finden Sie sich schnell im SAP-Umfeld zurecht und können direkt in SAP ERP oder SAP S/4HANA anfangen.

Bei amazon.de ansehen →

Creating PDFs from a report with ABAP

After you have learned how to send an e-mail from SAP and how to attach a document to an e-mail, it’s time to discuss how to take this concept a little further. I’m describing a fairly common scenario here; often it is required to send out monthly reporting e-mails with PDF documents attached.

I will explain the process by discussing bits of a sample program. You can find the program in its entirety on the second page of this blog post. Creating a PDF from a report in ABAP consists of three steps:

  1. Submit the report to the spool to create a new spool request that contains the desired output
  2. Identify the correct spool request
  3. Convert the spool request to PDF

Submitting an ABAP report to the spool

Let’s start with the first step right away. The key to this is the ABAP instruction SUBMIT TO SAP-SPOOL. Before we can do that however, we need to featch the print parameters for the spool. This is done by calling the function module GET_PRINT_PARAMETERS with certain input values. The execution of the target report is done cirectly afterwards.

* Import the current print parameters
CALL FUNCTION 'GET_PRINT_PARAMETERS'
   EXPORTING
     expiration             = 1
     immediately            = space
     no_dialog              = 'X'
   IMPORTING
     out_parameters         = ls_pri_params
   EXCEPTIONS
     archive_info_not_found = 1
     invalid_print_params   = 2
     invalid_archive_params = 3
     OTHERS                 = 4.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
 
* Submit the report program into the spool
SUBMIT zoutput TO SAP-SPOOL
   SPOOL PARAMETERS ls_pri_params
   WITHOUT SPOOL DYNPRO
   AND RETURN.

Looking at this code sample, you can see that the print parameters are imported into a local structure. We then execute the target report (I called it zoutput in my example) by calling the SUBMIT instruction with certain additions:

Here, no parameters are passed to the executed report. This can however easily be achieved by using the WITH addition or by using import/export parameters.

Finding the correct spool request

Finding the spool request number after you’ve submitted the report is not hard. Unfortunately, it’s not returned as a parameter, but there’s a function module to find it. This function module is RSPO_FIND_SPOOL_REQUESTS . Let’s look at the code:

* Get a list of the current user's spool requests
CALL FUNCTION 'RSPO_FIND_SPOOL_REQUESTS'
   EXPORTING
     rqowner       = sy-uname
   TABLES
     spoolrequests = lt_spool_requests
   EXCEPTIONS
     no_permission = 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.

* Sort and read the first (newest) spool request
SORT lt_spool_requests BY rqcretime DESCENDING.
READ TABLE lt_spool_requests INTO ls_spool_requests INDEX 1.
lv_spool_id = ls_spool_requests-rqident.

All of the current user’s spool requests are imported in the internal table lt_spool_requests. All we need to do in addition is sort them by date in descending order and then reading the first line of the table to get the spool number.

Convert the spool request to PDF

Another easy job is to generate the actual PDF data from that spool request: the function module  CONVERT_ABAPSPOOLJOB_2_PDF does that for us. The call is easy:

CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
   EXPORTING
     src_spoolid   = lv_spool_id
   IMPORTING
     pdf_bytecount = lv_pdf_bytecount
   TABLES
     pdf           = lt_pdf
   EXCEPTIONS
     OTHERS        = 12.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

We just provide the spool number and take two parameters back: the size of the PDF (which is needed if the PDF is to be sent as an e-mail attachment) and the binary PDF data itself, which is imported into an internal table.

That’s everything that is needed – you now know how to generate a PDF from an ABAP report! You could use this now to attach it to an e-mail or to make it available to the user by using a GUI download. The entire sample program is listed on the next page. Happy coding!

Sample program to create a PDF from an ABAP report

REPORT  zreport2pdf.
 
DATA ls_pri_params TYPE pri_params.
DATA lt_spool_requests TYPE STANDARD TABLE OF rsporq.
DATA ls_spool_requests TYPE rsporq.
DATA lv_param TYPE char40.
DATA lv_spool_id TYPE rspoid.
DATA lt_pdf TYPE STANDARD TABLE OF tline.
DATA lv_pdf_bytecount TYPE i.
 
* Import the current print parameters
CALL FUNCTION 'GET_PRINT_PARAMETERS'
   EXPORTING
     expiration             = 1
     immediately            = space
     no_dialog              = 'X'
   IMPORTING
     out_parameters         = ls_pri_params
   EXCEPTIONS
     archive_info_not_found = 1
     invalid_print_params   = 2
     invalid_archive_params = 3
     OTHERS                 = 4.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
 
* Submit the report program into the spool
SUBMIT zoutput TO SAP-SPOOL
   SPOOL PARAMETERS ls_pri_params
   WITHOUT SPOOL DYNPRO
   AND RETURN.
 
* Get a list of the current user's spool requests
CALL FUNCTION 'RSPO_FIND_SPOOL_REQUESTS'
   EXPORTING
     rqowner       = sy-uname
   TABLES
     spoolrequests = lt_spool_requests
   EXCEPTIONS
     no_permission = 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.
 
* Sort and read the first (newest) spool request
SORT lt_spool_requests BY rqcretime DESCENDING.
READ TABLE lt_spool_requests INTO ls_spool_requests INDEX 1.
lv_spool_id = ls_spool_requests-rqident.
 
* Use that request to create a PDF
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
   EXPORTING
     src_spoolid   = lv_spool_id
   IMPORTING
     pdf_bytecount = lv_pdf_bytecount
   TABLES
     pdf           = lt_pdf
   EXCEPTIONS
     OTHERS        = 12.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
 
* Now the PDF binary data is in the variable lt_pdf
* and the length in variable lv_pdf_bytecount.
* Go ahead and attach that to an e-mail!