Wednesday, 30 June 2021

Merging Multiple Adobe Forms and Downloading it as a single PDF

ABAPERS, sometimes we could a client requirement of merging multiple adobe forms and displaying it as one single pdf to the end-user.

However, after doing a lot of googling and reading numerous threads, I came across various solutions but some gave output as spool or some merged the forms but didn’t gave user to download the generated pdf into the system with desired location and name.

So, here I’ll provide the complete end-to-end solution with steps as well as the complete code, so that it really helps you. So let’s get started..

STEP 1:

Call function module FP_JOB_OPEN, with below parameters-

Data:ls_fp_outputparams TYPE sfpoutputparams.

    ls_fp_outputparams-dest     = 'LP01'"Depends on user settings

    ls_fp_outputparams-nodialog = abap_true.

    ls_fp_outputparams-preview  = abap_false.

    ls_fp_outputparams-getpdf   = 'M'."(Default value = 'X')

    ls_fp_outputparams-assemble = 'S'."bigger data

    ls_fp_outputparams-bumode   = 'M'."This is Bundle Mode

    ls_fp_outputparams-reqnew   = abap_true.

    CALL FUNCTION 'FP_JOB_OPEN'           

      CHANGING

        ie_outputparams = ls_fp_outputparams

      EXCEPTIONS

        cancel          = 1

        usage_error     = 2

        system_error    = 3

        internal_error  = 4

        OTHERS          = 5.

    IF sy-subrc <> 0.

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

SAP ABAP Tutorial and Material, SAP ABAP Exam Prep, SAP ABAP Preparation, SAP ABAP Career

*Remember all the values should be passed exactly the same in order to achieve the functionality.

STEP 2:

Get the Adobe Form function Module using FP_FUNCTION_MODULE_NAME and call the generated unction module for your 1st Adobe Form.

Data:lv_fm_inv     TYPE rs38l_fnam,

ls_fp_docparams    TYPE sfpdocparams,

ls_pdf_file        TYPE fpformoutput.

   TRY.

        CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'  

          EXPORTING

            i_name     = 'ZFORM1'

          IMPORTING

            e_funcname = lv_fm_inv.

      CATCH cx_fp_api_repository.

      CATCH cx_fp_api_usage.

      CATCH cx_fp_api_internal.

    ENDTRY.

*&--- Call the generated function module

    CALL FUNCTION lv_fm_inv     

      EXPORTING

        /1bcdwb/docparams  = ls_fp_docparams

      IMPORTING

        /1bcdwb/formoutput = ls_pdf_file

      EXCEPTIONS

        usage_error        = 1

        system_error       = 2

        internal_error     = 3.

    IF sy-subrc <> 0.

*  <error handling>

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

STEP 3:

Repeat Step 2, for 2nd Adobe Form. Call ‘FP_JOB_CLOSE’  to close the spool job.

*&---- Close the spool job

    CALL FUNCTION 'FP_JOB_CLOSE'

*    IMPORTING

*     E_RESULT             =

      EXCEPTIONS

        usage_error    = 1

        system_error   = 2

        internal_error = 3

        OTHERS         = 4.

    IF sy-subrc <> 0.

*   <error handling>

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

Note: You can use LOOP..ENDLOOP to call FP_FUNCTION_MODULE_NAME and it’s generated function module if you have more than two adobe forms.

TYPES: BEGIN OF lty_forms,

form TYPE fpname,

END OF lty_forms,

lty_t_forms TYPE STANDARD TABLE OF lty_forms WITH EMPTY KEY..

Data:lt_forms type lty_t_forms.

LOOP AT lt_forms INTO DATA(lwa_forms).

TRY.

CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'

EXPORTING

i_name = lwa_forms-form

IMPORTING

e_funcname = lv_fm_name.

CATCH cx_fp_api.

ENDTRY.

CALL FUNCTION lv_fm_name

EXPORTING

/1bcdwb/docparams = ls_fp_docparams

iv_final = lwa_final

IMPORTING

/1bcdwb/formoutput =ls_pdf_file

EXCEPTIONS

usage_error = 1

system_error = 2

internal_error = 3

OTHERS = 4.

IF sy-subrc <> 0.

ENDIF.

CLEAR: lwa_forms, lv_fm_name.

ENDLOOP

STEP 4:

Call function module,’ FP_GET_PDF_TABLE’, to merge multiple generated files into a single pdf.

    DATA:lt_data            TYPE STANDARD TABLE OF tabl1024, "RAWSTRING

         lo_pdf_merger      TYPE REF TO cl_rspo_pdf_merge,

         lt_pdf_table       TYPE tfpcontent,

         lv_merged_document TYPE xstring,

         lv_len             TYPE i,

         lv_rc              TYPE i VALUE 0.

*&&-- Merging different PDF files into one

    CREATE OBJECT lo_pdf_merger.

    CALL FUNCTION 'FP_GET_PDF_TABLE'

      IMPORTING

        e_pdf_table = lt_pdf_table.

We will use standard class cl_rspo_pdf_merge methods which can be 

reffered from the program:RSPO_TEST_MERGE_PDF_FILES.The same class 

can be used to write to a SAP application server.

* Add documents to attribute table of PDF merger

    LOOP AT lt_pdf_table INTO DATA(lwa_form).

      lo_pdf_merger->add_document( lwa_form ).

    ENDLOOP.

* Call kernel method to do the merge of the specified files.

    lo_pdf_merger->merge_documents( IMPORTING merged_document = lv_merged_document

                                                           rc = lv_rc ).

    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'

      EXPORTING

        buffer        = lv_merged_document

      IMPORTING

        output_length = lv_len

      TABLES

        binary_tab    = lt_data.

Step 5:

We will call the method cl_gui_frontend_services=>file_save_dialog, which gives user choice to name and save the pdf at the desired location.

    DATA:lv_file            TYPE string,

         lv_path            TYPE string,

         lv_file_name       TYPE string.

   CALL METHOD cl_gui_frontend_services=>file_save_dialog

      EXPORTING

        window_title              = 'Save Form'    "You can pass any value as per your choice

        default_extension         = '.pdf'

        default_file_name         = 'Invoice.pdf'

        prompt_on_overwrite       = 'X'

      CHANGING

        filename                  = lv_file_name

        path                      = lv_path

        fullpath                  = lv_file

      EXCEPTIONS

        cntl_error                = 1

        error_no_gui              = 2

        not_supported_by_gui      = 3

        invalid_default_file_name = 4

        OTHERS                    = 5.

    IF sy-subrc <> 0.

* Implement suitable error handling here

    ENDIF

STEP 6:

Finally,We will call the method cl_gui_frontend_services=>gui_download, for downloading the file and cl_gui_frontend_services=>execute, to automatically open the pdf, after it is downloaded.

    DATA:lt_data            TYPE STANDARD TABLE OF tabl1024,

         lv_file            TYPE string,

         lv_len             TYPE i,

         lv_rc              TYPE i VALUE 0

    CALL METHOD cl_gui_frontend_services=>gui_download

      EXPORTING

        bin_filesize            = lv_len

        filename                = lv_file

        filetype                = 'BIN'

      CHANGING

        data_tab                = lt_data

      EXCEPTIONS

        file_write_error        = 1

        no_batch                = 2

        gui_refuse_filetransfer = 3

        invalid_type            = 4

        no_authority            = 5

        unknown_error           = 6

        header_not_allowed      = 7

        separator_not_allowed   = 8

        filesize_not_allowed    = 9

        header_too_long         = 10

        dp_error_create         = 11

        dp_error_send           = 12

        dp_error_write          = 13

        unknown_dp_error        = 14

        access_denied           = 15

        dp_out_of_memory        = 16

        disk_full               = 17

        dp_timeout              = 18

        file_not_found          = 19

        dataprovider_exception  = 20

        control_flush_error     = 21

        not_supported_by_gui    = 22

        error_no_gui            = 23

        OTHERS                  = 24.

    IF sy-subrc IS NOT INITIAL.

    ENDIF.

    CALL METHOD cl_gui_frontend_services=>execute

      EXPORTING

        document               = lv_file

        synchronous            = 'X'

      EXCEPTIONS

        cntl_error             = 1

        error_no_gui           = 2

        bad_parameter          = 3

        file_not_found         = 4

        path_not_found         = 5

        file_extension_unknown = 6

        error_execute_failed   = 7

        synchronous_failed     = 8

        not_supported_by_gui   = 9

        OTHERS                 = 10.

    IF sy-subrc IS NOT INITIAL.

    ENDIF.

Below I’m also posting the complete code-

    DATA: lv_fm_dpr          TYPE rs38l_fnam,      " CHAR 30 0 Name of Function Module

          lv_fm_inv          TYPE rs38l_fnam,

          ls_fp_docparams    TYPE sfpdocparams,    " Structure  SFPDOCPARAMS    Short Description  Form Parameters for Form Processing

          ls_fp_outputparams TYPE sfpoutputparams, " Structure  SFPOUTPUTPARAMS Short Description  Form Processing Output Parameter

          ls_pdf_file        TYPE fpformoutput.

    DATA:lt_data            TYPE STANDARD TABLE OF tabl1024,

         lo_pdf_merger      TYPE REF TO cl_rspo_pdf_merge,

         lt_pdf_table       TYPE tfpcontent,

         lv_file            TYPE string,

         lv_path            TYPE string,

         lv_file_name       TYPE string,

         lv_merged_document TYPE xstring,

         lv_len             TYPE i,

         lv_rc              TYPE i VALUE 0.

    ls_fp_outputparams-dest     = 'LP01'. "Depends on user settings

    ls_fp_outputparams-nodialog = abap_true.

    ls_fp_outputparams-getpdf   = 'M'.

    ls_fp_outputparams-assemble = 'S'.

    ls_fp_outputparams-bumode   = 'M'.

    ls_fp_outputparams-reqnew   = abap_true.

* Sets the output parameters and opens the spool job

    CALL FUNCTION 'FP_JOB_OPEN'                   "& Form Processing: Call Form

      CHANGING

        ie_outputparams = ls_fp_outputparams

      EXCEPTIONS

        cancel          = 1

        usage_error     = 2

        system_error    = 3

        internal_error  = 4

        OTHERS          = 5.

    IF sy-subrc <> 0.

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

              WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

    TRY.

        CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'           "& Form Processing Generation

          EXPORTING

            i_name     = 'ZFORM1'

          IMPORTING

            e_funcname = lv_fm_inv.

      CATCH cx_fp_api_repository.

      CATCH cx_fp_api_usage.

      CATCH cx_fp_api_internal.

    ENDTRY.

**&---- Get the name of the generated function module

    TRY.

        CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'           "& Form Processing Generation

          EXPORTING

            i_name     = 'ZFORM2'

          IMPORTING

            e_funcname = lv_fm_dpr.

      CATCH cx_fp_api_repository.

      CATCH cx_fp_api_usage.

      CATCH cx_fp_api_internal.

    ENDTRY.

* Language and country setting (here US as an example)

    ls_fp_docparams-langu   = 'E'.

    ls_fp_docparams-country = 'US'.

*&--- Call the generated function module

    CALL FUNCTION lv_fm_inv

      EXPORTING

        /1bcdwb/docparams  = ls_fp_docparams

      IMPORTING

        /1bcdwb/formoutput = ls_pdf_file

      EXCEPTIONS

        usage_error        = 1

        system_error       = 2

        internal_error     = 3.

    IF sy-subrc <> 0.

*  <error handling>

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

*&--- Call the generated function module

    CALL FUNCTION lv_fm_dpr

      EXPORTING

        /1bcdwb/docparams  = ls_fp_docparams

      IMPORTING

        /1bcdwb/formoutput = ls_pdf_file

      EXCEPTIONS

        usage_error        = 1

        system_error       = 2

        internal_error     = 3.

    IF sy-subrc <> 0.

*  <error handling>

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

*

*    ENDLOOP.

*&---- Close the spool job

    CALL FUNCTION 'FP_JOB_CLOSE'

*    IMPORTING

*     E_RESULT             =

      EXCEPTIONS

        usage_error    = 1

        system_error   = 2

        internal_error = 3

        OTHERS         = 4.

    IF sy-subrc <> 0.

*   <error handling>

      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno

        WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

      RETURN.

    ENDIF.

*&&-- Merging different PDF files into one

    CREATE OBJECT lo_pdf_merger.

    CALL FUNCTION 'FP_GET_PDF_TABLE'

      IMPORTING

        e_pdf_table = lt_pdf_table.

* Add documents to attribute table of PDF merger

    LOOP AT lt_pdf_table INTO DATA(lwa_form).

      lo_pdf_merger->add_document( lwa_form ).

    ENDLOOP.

* Call kernel method to do the merge of the specified files.

    lo_pdf_merger->merge_documents( IMPORTING merged_document = lv_merged_document

                                                           rc = lv_rc ).

    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'

      EXPORTING

        buffer        = lv_merged_document

      IMPORTING

        output_length = lv_len

      TABLES

        binary_tab    = lt_data.

    CALL METHOD cl_gui_frontend_services=>file_save_dialog

      EXPORTING

        window_title              = 'Save Form'

        default_extension         = '.pdf'

        default_file_name         = 'Invoice.pdf'

        prompt_on_overwrite       = 'X'

      CHANGING

        filename                  = lv_file_name

        path                      = lv_path

        fullpath                  = lv_file

      EXCEPTIONS

        cntl_error                = 1

        error_no_gui              = 2

        not_supported_by_gui      = 3

        invalid_default_file_name = 4

        OTHERS                    = 5.

    IF sy-subrc <> 0.

* Implement suitable error handling here

    ENDIF.

    CALL METHOD cl_gui_frontend_services=>gui_download

      EXPORTING

        bin_filesize            = lv_len

        filename                = lv_file

        filetype                = 'BIN'

      CHANGING

        data_tab                = lt_data

      EXCEPTIONS

        file_write_error        = 1

        no_batch                = 2

        gui_refuse_filetransfer = 3

        invalid_type            = 4

        no_authority            = 5

        unknown_error           = 6

        header_not_allowed      = 7

        separator_not_allowed   = 8

        filesize_not_allowed    = 9

        header_too_long         = 10

        dp_error_create         = 11

        dp_error_send           = 12

        dp_error_write          = 13

        unknown_dp_error        = 14

        access_denied           = 15

        dp_out_of_memory        = 16

        disk_full               = 17

        dp_timeout              = 18

        file_not_found          = 19

        dataprovider_exception  = 20

        control_flush_error     = 21

        not_supported_by_gui    = 22

        error_no_gui            = 23

        OTHERS                  = 24.

    IF sy-subrc IS NOT INITIAL.

    ENDIF.

    CALL METHOD cl_gui_frontend_services=>execute

      EXPORTING

        document               = lv_file

        synchronous            = 'X'

      EXCEPTIONS

        cntl_error             = 1

        error_no_gui           = 2

        bad_parameter          = 3

        file_not_found         = 4

        path_not_found         = 5

        file_extension_unknown = 6

        error_execute_failed   = 7

        synchronous_failed     = 8

        not_supported_by_gui   = 9

        OTHERS                 = 10.

    IF sy-subrc IS NOT INITIAL.

    ENDIF.

    CLEAR:lv_file,lv_len,lv_path,lv_file_name,lt_data.

You can also check this in spool request(SP01) and download it to your system as well.

Source: sap.com

No comments:

Post a Comment