A practical ABAP guide to merging SAPscript, Smart Forms & Adobe Form output with external PDFs
Business requirements often go beyond standard SAP output. In many scenarios, users need to include additional PDF documents—such as engineering drawings, specifications, or supporting attachments—directly with SAP-generated output.
In this blog, we walk through an ABAP-based approach for attaching external PDFs to output generated from SAPscript, Smart Forms, and Adobe Forms. The objective is to standardize each source as PDF data, merge the documents, and deliver one complete output to end users.
The High-Level Approach
Regardless of the form technology used to produce the original output, the merge process follows the same six logical stages:
- Get OTF data from the form
- Convert OTF to PDF
- Add the PDF Content to the Merge Sequence
- Get the external PDF (also as XSTRING)
- Merge both PDFs together
- Send or store the final merged PDF
Each SAP form technology produces output differently. SAPscript and Smart Forms generate OTF, while Adobe Forms generate PDF directly through Adobe Document Services. To merge documents consistently, every source must ultimately be available as a PDF byte stream, typically handled as XSTRING in ABAP.
| Stage | SAPscript / Smart Forms | Adobe Forms |
| Native output | OTF | PDF (direct) |
| Conversion needed | CONVERT_OTF → TLINE → XSTRING | None — already XSTRING |
| Key flag/param | TDGETOTF / GETOTF = ‘X’ | Native via ADS, no flag needed |
| Merge-ready format | XSTRING (after conversion) | XSTRING (as-is) |
Let’s Go Through the Steps Involved
1. Getting OTF from each form type
SAPscript :
To enable PDF merging and spool processing, set the SAPscript output interface parameter TDGETOTF to ‘X’. This is done by setting PRINT_OPTS-TDGETOTF = ‘X’ before calling OPEN_FORM, so the form output is generated as OTF data instead of being sent directly to the printer.
After form processing is complete, retrieve the generated OTF data from CLOSE_FORM:
CALL FUNCTION 'CLOSE_FORM'
IMPORTING
result = pr_result
" Get OTF Data
TABLES
otfdata = gt_otf_data.
SmartForms:
For Smart Forms, set the GETOTF flag in the control structure so the output is returned as OTF instead of being printed immediately:
ls_control_param-getotf = 'X'.
Adobe Forms:
Adobe Forms work differently because they generate PDF output natively through Adobe Document Services. There is no OTF conversion step; call the generated function module and read the PDF directly from the output structure:
CALL FUNCTION lv_fm_name
EXPORTING
/1bcdwb/docparams = ls_docparams
IMPORTING
/1bcdwb/formoutput = ls_output
lv_pdf = ls_output-pdf. " Already in PDF format
2. Convert OTF to PDF
Once OTF data has been captured from SAPscript or Smart Forms, convert it into PDF content using the standard function module CONVERT_OTF:
" Convert OTF format to PDF content
CALL FUNCTION 'CONVERT_OTF'
EXPORTING
format = 'PDF'
IMPORTING
bin_filesize = lv_binfilesize
bin_file = lv_bin_script
TABLES
otf = gt_otf_data " Input table with OTF format
lines = gt_pdf_script.
SmartForms:
For Smart Forms, an additional conversion step may be required to move the binary table into an XSTRING buffer:
" Convert TLINE binary table to XSTRING
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lv_pdf_size
IMPORTING
buffer = lv_pdf_smartform
TABLES
binary_tab = lt_lines.
3. Add the PDF content to the merge sequence
After the PDF content is available as XSTRING, register it with the merge object using ADD_DOCUMENT. Each call appends one PDF to the merge sequence in the required order:
DATA: lo_pdf_merged TYPE REF TO cl_rspo_pdf_merge.
lo_pdf_merged->add_document( document = lv_bin_script ).
4. Get the external PDF from the application server
Next, read the external PDF—for example, an engineering drawing—from the application server in binary mode. Once the PDF content is available, add it to the same merge sequence.
DATA: lt_raw_pdfdata TYPE STANDARD TABLE OF x255,
lt_raw_pdf TYPE TABLE OF rspolpbi,
lv_line TYPE xstring.
OPEN DATASET gv_filename FOR INPUT IN BINARY MODE.
IF sy-subrc IS NOT INITIAL.
REPLACE '.pdf' IN gv_filename WITH '.PDF'.
" Read the file from application server (try alt. case)
OPEN DATASET gv_filename FOR INPUT IN BINARY MODE.
ENDIF.
IF sy-subrc = 0.
DO.
READ DATASET gv_filename INTO lv_line.
IF sy-subrc IS NOT INITIAL.
EXIT.
ENDIF.
APPEND lv_line TO lt_raw_pdfdata.
" Add second PDF: move to the document table
IF lv_line IS NOT INITIAL.
lo_pdf_merged->add_document( lv_line ).
ENDIF.
ENDDO.
ENDIF.
" Close dataset
CLOSE DATASET gv_filename.
5. Merge the documents
After all PDF sources are added to the merge object, call MERGE_DOCUMENTS to generate one combined PDF:
DATA: lo_pdf_merged TYPE REF TO cl_rspo_pdf_merge.
lo_pdf_merged->merge_documents(
IMPORTING
merged_document = DATA(lv_merged_pdf)
rc = DATA(rc_code)).
For mass processing, suppress the print dialog so the job can run unattended:
" During mass-processing, no popup for print dialog.
" !! The printer ZPDF is set as a fixed value;
" for dynamic values, 'dest' must be swapped out !!
DATA(ls_outputparams) = VALUE sfpoutputparams(
nodialog = abap_true
dest = 'ZPDF' ).
6. Generate the external output as PDF
Finally, send the merged PDF to a spool job through Adobe Document Services. Start by opening the job and setting immediate printing if required:
ls_outputparams-reqimm = 'X'.
CALL FUNCTION 'FP_JOB_OPEN'
CHANGING
ie_outputparams = ls_outputparams
EXCEPTIONS
cancel = 1
usage_error = 2
system_error = 3
internal_error = 4
OTHERS = 5.
lv_copies = ls_outputparams-copies.
lv_lifetime = ls_outputparams-lifetime.
Then create the spool job from the merged PDF data using ADS_CREATE_PDF_SPOOLJOB.
CALL FUNCTION 'ADS_CREATE_PDF_SPOOLJOB'
EXPORTING
dest = ls_outputparams-dest
pages = 100
pdf_data = lv_pdf
name = ls_outputparams-dataset
suffix1 = ls_outputparams-suffix1
suffix2 = ls_outputparams-suffix2
copies = lv_copies_ads
immediate_print = ls_outputparams-reqimm
auto_delete = ls_outputparams-reqdel
titleline = ls_outputparams-covtitle
receiver = ls_outputparams-receiver
division = ls_outputparams-division
authority = ls_outputparams-authority
lifetime = lv_lifetime
IMPORTING
spoolid = lv_spoolid_ads.
After the spool request is created, close the job using FP_JOB_CLOSE.
This approach is technology-agnostic at the merge layer. Whether the original output comes from SAPscript, Smart Forms, or Adobe Forms, the process becomes consistent once each source is available as PDF XSTRING data. From there, use ADD_DOCUMENT for each PDF, MERGE_DOCUMENTS to combine the files, and ADS_CREATE_PDF_SPOOLJOB or another output channel to deliver the final document.
Conclusion
Merging external PDFs into SAP-generated output doesn’t require a different strategy for every form of technology, it requires one consistent target format. Once SAPscript and Smart Forms output is converted from OTF to XSTRING, and Adobe Forms output is used as-is (since it’s already PDF), all three sources speak the same language: PDF byte streams that CL_RSPO_PDF_MERGE can combine through a simple ADD_DOCUMENT / MERGE_DOCUMENTS sequence. This gives you a reusable pattern rather than a one-off solution. That is what makes the approach practical to standardize across multiple forms and reuse on future requirements, rather than building a separate merge process for every form type that comes up.




