Convert Floe output to PDF

There are various tools available to convert HTML to PDF, and we have tested Floe with 3:

  •  HTMLPDFAPI
  • PDFCROWD
  • HTML2PDFROCKET

The approach for all three providers is the same:

Set up an SM59 connection to the service

Register for the service to get the username and password key.

This sample function shows how to invoke the services (note hard-coded passwords to be stored elsewhere)

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
FUNCTION z_html_to_pdf.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IM_HTML) TYPE  STRING
*"     REFERENCE(IM_RFC) TYPE  RFCDEST
*"     REFERENCE(IM_HTTP_PARAMETERS) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     REFERENCE(EX_STATUS) TYPE  I
*"     REFERENCE(EX_REASON) TYPE  STRING
*"     REFERENCE(EX_LENGTH) TYPE  STRING
*"     REFERENCE(EX_PDF) TYPE  STRING
*"----------------------------------------------------------------------

  DATA: lo_http_client     TYPE REF TO if_http_client,
        lo_rest_client     TYPE REF TO cl_rest_http_client,
        lv_body            TYPE        string,
        lo_response        TYPE REF TO if_rest_entity,
        lo_request         TYPE REF TO if_rest_entity,
        l_html_email       TYPE string.

  l_html_email = im_html.

  cl_http_client=>create_by_destination(
   EXPORTING
     destination              = im_rfc
  IMPORTING
     client                   = lo_http_client    " HTTP Client Abstraction
  EXCEPTIONS
    argument_not_found       = 1
    destination_not_found    = 2
    destination_no_authority = 3
    plugin_not_active        = 4
    internal_error           = 5
    OTHERS                   = 6
  ).
*
  if sy-subrc ne 0.
    return.
  endif.
*
  CREATE OBJECT lo_rest_client EXPORTING io_http_client = lo_http_client.
*
  lo_http_client->request->set_version( if_http_request=>co_protocol_version_1_0 ).

* Clean up spaces
  REPLACE ALL OCCURRENCES OF ' ' IN l_html_email WITH ` `.

* Clean up carriage return/line feed from editor.
  REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN l_html_email WITH ` `.

* Remove remaining &
  REPLACE ALL OCCURRENCES OF '&' IN l_html_email WITH '+'.

* Set calling parameters
  CASE im_rfc.
*
    WHEN 'HTMLPDFAPI'.
*
      CONCATENATE 'html=' l_html_email
                  im_http_parameters
                  INTO lv_body.
*
      CALL METHOD lo_rest_client->if_rest_client~set_request_header
        EXPORTING
          iv_name  = 'Authentication'
          iv_value = 'Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.
*
    WHEN 'PDFCROWD'.
*
      CONCATENATE 'username=xxxxxxxx&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
                   '&src=' l_html_email
                   '&pdf_scaling_factor=1'
                   '&margin_top=10mm'
                   im_http_parameters
                   INTO lv_body.
*
    WHEN 'HTML2PDFROCKET'.
*
      CONCATENATE 'apikey=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx'
                  '&value=' l_html_email
                  '&MarginTop=10mm'
                  im_http_parameters
                  INTO lv_body.
*
  ENDCASE.
*
* Set Payload
  lo_request = lo_rest_client->if_rest_client~create_request_entity( ).
  lo_request->set_content_type( iv_media_type = 'application/x-www-form-urlencoded' ).
  lo_request->set_string_data( lv_body ).

* POST
  lo_rest_client->if_rest_resource~post( lo_request ).

* Collect response
  lo_response = lo_rest_client->if_rest_client~get_response_entity( ).
  ex_status = lo_response->get_header_field( '~status_code' ).
  ex_reason = lo_response->get_header_field( '~status_reason' ).
  ex_length = lo_response->get_header_field( 'content-length' ).
  ex_pdf = lo_response->get_binary_data( ).
*
ENDFUNCTION.

The function can be called from a custom trigger program.  In this example we call Floe to generate the HTML, then call the function to convert to PDF, and then call Floe once again, adding the generated PDF as an attachment.

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
*&---------------------------------------------------------------------*
*& Report  ZNODDY
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT z_flm_to_pdf_email.

DATA: ls_fpe           TYPE /flm/fpe,
      l_pdf            TYPE string,
      lt_return        TYPE bapiret2_t,
      lt_addsmtp       TYPE TABLE OF bapiadsmtp,
      ls_addsmtp       TYPE bapiadsmtp,
      l_html_email     TYPE string,
      l_subrc          TYPE sysubrc,
      lt_mess          TYPE bapiret2_t,
      ls_mess          TYPE bapiret2,
      ls_rec           TYPE /floe/rec_email_s,
      lt_rec           TYPE /floe/rec_email_t,
      ls_att           TYPE /floe/att_s,
      lt_att           TYPE /floe/att_t,
      l_dest           TYPE rfcdest.

SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME TITLE text-001.

PARAMETERS: p_ftype TYPE /flm/ftype_code,
            p_flang TYPE /flm/flang DEFAULT 'E',
            p_fver  TYPE /flm/fver DEFAULT '00',
            p_fid   TYPE /flm/fid,
            p_fidvar TYPE /flm/id_var.

SELECTION-SCREEN END OF BLOCK a.

SELECTION-SCREEN SKIP 1.

SELECTION-SCREEN BEGIN OF BLOCK b WITH FRAME TITLE text-002.

PARAMETERS: p_etype TYPE /floe/etype_code MATCHCODE OBJECT /floe/etype OBLIGATORY,
            p_elang TYPE /floe/elang,
            p_rec   TYPE /floe/rec_email.

SELECTION-SCREEN END OF BLOCK b.

INITIALIZATION.
*
  CALL FUNCTION 'BAPI_USER_GET_DETAIL'
    EXPORTING
      username = sy-uname
    TABLES
      return   = lt_return
      addsmtp  = lt_addsmtp.
*
  READ TABLE lt_addsmtp INTO ls_addsmtp INDEX 1.
  p_rec = ls_addsmtp-e_mail.
*
  p_elang = sy-langu.
*
END-OF-SELECTION.

  ls_fpe-ftype  = p_ftype.
  ls_fpe-ccode  = 'ACL'.
  ls_fpe-flang  = p_flang.
  ls_fpe-fver   = p_fver.
  ls_fpe-id     = p_fid.
  ls_fpe-id_var = p_fidvar.

  CALL FUNCTION 'Z_FLM_CONVERT_HTML_TO_PDF'
    EXPORTING
      im_fpe    = ls_fpe
*     IM_DEST   = 'HTML2PDFROCKET'
    IMPORTING
*     EX_SUBRC  =
      ex_pdf    = l_pdf
    CHANGING
      ch_return = lt_return.


  ls_att-att_data = l_pdf.
  ls_att-att_filename = 'PDFconversionTest.PDF'.
  ls_att-att_description = 'PDF conversion test'.

  APPEND ls_att TO lt_att.

* Set up receiver
  ls_rec-email =  p_rec.
  ls_rec-type = 1.
  APPEND ls_rec TO lt_rec.

  CALL FUNCTION '/FLOE/EMAIL_OUT'
    EXPORTING
      im_etype            = p_etype
      im_elang            = p_elang
*     IM_ESUBJECT_LONG    =
*     IM_DOCUMENT         =
      im_rec_emails       = lt_rec
*     IM_VARIABLES        =
*     IM_FORM_DATA        =
      im_attachments      = lt_att
      im_send_immediately = 'X'
*     IM_IMPORTANCE       = '1'
*     im_preview          = 'X'
    IMPORTING
      ex_subrc            = l_subrc
      ex_mess             = lt_mess
      ex_ebody            = l_html_email.

  IF l_subrc IS INITIAL.
    WRITE:/ 'Email successfully sent.'(003).
  ELSE.
    WRITE:/ 'Error sending email.'(004).
  ENDIF.

  SKIP 1.
  FORMAT INTENSIFIED ON.
  WRITE:/ 'Type'(005), 'Message'(006).
  FORMAT INTENSIFIED OFF.
  ULINE.
  LOOP AT lt_mess INTO ls_mess.
    WRITE:/ ls_mess-type    UNDER text-005,
            ls_mess-message UNDER text-006.
  ENDLOOP.