SAP Forms – SmartForms, Adobe PDF, Output Management: A Complete Hands-On Developer Tutorial
Day 4 of the S/4HANA ABAP Development & Fiori Track
By @FreeLearning365 and Tech Partner @techbook24
Introduction: The Form That Stopped the Business
It’s Monday morning at TechBook24. The procurement team releases a rush purchase order for a critical supplier. Usually, the system automatically emails a PDF purchase order form to the vendor. Today, nothing happens. The spool is empty. The output determination log shows a cryptic error: “No form assigned to output type ZPOF.” The legacy SAPscript form that had worked for a decade silently broke during the S/4HANA upgrade because SAPscript is deprecated for new installations and the old driver program wasn’t compatible. The supplier refuses to ship without the official PO form. The production line is at risk.
Arjun, our ABAP developer, is called in. He has to rebuild the PO form from scratch, set up output determination to send it via email automatically, and even make it interactive so that suppliers can confirm receipt directly in the PDF. This is not just about making something look pretty — it’s about restoring a critical business process. And he must do it fast.
In this extensive hands-on tutorial, you’ll join Arjun on this journey. You’ll learn both the classic SmartForms technology (still widely used) and the modern Adobe Forms (now the standard in S/4HANA). You’ll configure output determination using NACE, set up email output via SOST, and even build an interactive PDF that captures user input and returns it to SAP. I’ll share every transaction code, every configuration step, every pitfall, and the architecture decisions that make you the go-to forms expert. No theory fluff — we build everything together, with real names, real data, and real code.
1. SmartForms (SE71) – The Workhorse of SAP Output
1.1 Understanding the SmartForms Architecture
SmartForms is a graphical form design tool introduced in SAP R/3 4.6C to replace SAPscript. It provides a drag-and-drop interface to design page layouts, windows, tables, and logic. Unlike SAPscript, SmartForms are client-independent and can generate output in multiple formats: print, PDF, and XML. They are maintained via transaction SE71 and are the default choice for many traditional output scenarios.
A SmartForm consists of:
- Form Interface: defines the input parameters (import/export/tables) that the calling program passes. For a PO form, you’d import the purchase order header and item tables.
- Global Definitions: global data, field symbols, and types.
- Pages and Windows: the layout structure. A page contains windows (main window, header, footer).
- Nodes: the hierarchical tree that controls the form’s logic: text nodes, table nodes, loop nodes, program lines, conditions, etc.
The processing is event-driven: the system traverses the tree from top to bottom, executing each node in order. You can insert logic via program lines, hide/show elements with conditions, and repeat blocks with loops.
1.2 TechBook24’s Scenario – Creating a Purchase Order SmartForm
Arjun’s first task is to create a new SmartForm ZSMART_PO that outputs the purchase order in a clean layout. The form should display:
- Header: PO number, vendor name & address, PO date, currency, and net value.
- Item table: item number, material, description, quantity, unit, net price, and total per item.
- Footer: total net value (repeated), delivery terms, and standard company footer.
He will call this form from a driver program, passing the PO number and retrieving the data. But first, let’s design the form in SE71.
1.3 Step-by-Step Form Design in SE71
Transaction: SE71 → Create Form → enter ZSMART_PO → Create.
Form Interface: Arjun clicks on the Form Interface tab. He defines the import parameters:
IS_HEADERtypeZS_PO_HEADER(a structure containing EBELN, LIFNR, NAME1, AEDAT, WAERS, NETWR, etc.).IT_ITEMStypeZTT_PO_ITEMS(a table type containing EBELP, MATNR, MAKTX, MENGE, MEINS, NETPR, NETWR_ITEM).
He also defines a global field GV_TOTAL to hold the summed net value, though he can sum in the table itself.
Screenshot Description: SE71 Form Interface tab showing the IMPORT parameters listed with type references.
Global Definitions: He creates a work area and a counter if needed.
Pages and Windows: He creates a single page named PAGE1. He adds the following windows:
HEADER– positioned at top, height 6 cm.MAIN– the main window, height determined by content; this is where the item table goes.FOOTER– at bottom, height 4 cm.
Now he builds the node tree under PAGE1.
Node Tree Construction:
- Under
HEADERwindow, he adds aTextnode with the title “Purchase Order”. He sets font size, bold, and alignment. - He adds a
Tablenode for the header data? Actually, for structured data like addresses, he can use aTemplatenode that draws lines and places texts. He uses a template with two columns: one for labels, one for values. - He adds
Program Linesnode to load the vendor address from ADRC if needed, but for simplicity he assumes the driver program passes the full address. - Under
MAINwindow, he adds aTablenode for the items. The table node has a data source:IT_ITEMS. He defines a line type that matches the structure. He adds columns: Item, Material, Description, Qty, Unit, Net Price, Total. He assigns the corresponding fields from the internal table line. - He enables a footer row in the table to display the sum of the total column, using the
Event: Table Footerand aProgram Linesnode that sumsIT_ITEMS-NETWR_ITEMinto a global variableGV_TOTAL(but the table can compute totals natively: In the Table node properties, there’s a “Totals” tab where you can activate automatic summation per column; he uses that). - Under
FOOTERwindow, he adds company address and a final note.
Screenshot Description: SE71 node tree showing the hierarchical structure with windows and nodes.
1.4 Using Conditions, Loops, and Program Lines
Arjun wants to hide the item table if there are no items (shouldn’t happen, but defensive design). He selects the Table node, goes to Conditions tab, and sets a condition IT_ITEMS[] IS NOT INITIAL. The table only appears if items exist.
For the header, he wants to display a different label based on PO type (standard vs. subcontract). He adds a Condition node that evaluates IS_HEADER-BSART = 'NB' for standard, and an alternative for subcontract. This uses the Alternative node with two branches.
1.5 Driver Program – Calling the SmartForm
Now Arjun needs a program to trigger the form. He creates ZR_PO_PRINT_SF. The program is simple: it retrieves the PO data, fills the interface parameters, and calls function module SSF_FUNCTION_MODULE_NAME to get the generated FM name, then calls that FM.
REPORT zr_po_print_sf.
PARAMETERS: p_ebeln TYPE ebeln OBLIGATORY.
START-OF-SELECTION.
" Fetch header
SELECT SINGLE ebeln, lifnr, aedat, waers, netwr, bsart
FROM ekko
WHERE ebeln = @p_ebeln
INTO @DATA(gs_header).
IF sy-subrc <> 0.
MESSAGE 'PO not found' TYPE 'E'.
ENDIF.
" Fetch vendor name
SELECT SINGLE name1 FROM lfa1 WHERE lifnr = @gs_header-lifnr INTO @DATA(gv_vname).
gs_header-name1 = gv_vname.
" Fetch items
SELECT ebeln, ebelp, matnr, menge, meins, netpr, netwr
FROM ekpo
WHERE ebeln = @p_ebeln
INTO TABLE @DATA(gt_items).
" Call SmartForm
DATA: lv_fm_name TYPE rs38l_fnam.
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
EXPORTING
formname = 'ZSMART_PO'
IMPORTING
fm_name = lv_fm_name
EXCEPTIONS
no_form = 1
no_function_module = 2
OTHERS = 3.
IF sy-subrc <> 0.
MESSAGE 'Error getting SmartForm function module' TYPE 'E'.
ENDIF.
DATA: ls_output_options TYPE ssfcompop.
ls_output_options-tddest = 'LOCL'. "output to default printer, or use a spool
CALL FUNCTION lv_fm_name
EXPORTING
control_parameters = ls_output_options
is_header = gs_header
TABLES
it_items = gt_items
EXCEPTIONS
formatting_error = 1
internal_error = 2
send_error = 3
user_canceled = 4
OTHERS = 5.
IF sy-subrc <> 0.
MESSAGE 'Form output failed' TYPE 'E'.
ENDIF.
When executed, a print preview appears showing the PO form. Arjun tests it with a real PO and adjusts the layout.
2. Adobe Forms (SFP) – The Modern PDF Standard
2.1 Why Adobe Forms in S/4HANA?
SmartForms are still supported, but SAP’s strategic direction is Adobe Forms. Adobe Forms offer superior graphic design, support for interactive PDF (XFA forms), digital signatures, and integration with Adobe Document Services. In S/4HANA, many standard outputs are being redeveloped as Adobe forms. For new developments, SAP recommends Adobe Forms.
Transaction SFP is the Form Builder. You create an interface (like SmartForm’s Form Interface) and a layout (the visual design). The layout is designed using Adobe LiveCycle Designer (or the integrated Web-based designer in newer versions) and saved as an XDP file. The interface is an ABAP Dictionary structure or a dynamically generated XML schema.
2.2 TechBook24’s Requirement – Adobe PDF PO with Barcode and Interactive Confirmation
Mr. Keller wants the PO form to be a professional PDF that:
- Includes a barcode of the PO number for warehouse scanning.
- Has the TechBook24 logo and corporate colors.
- Contains an interactive “Order Confirmation” button that opens an email reply with the PO number.
- Optionally, in the future, allow the vendor to fill in a delivery date and submit back to SAP (Interactive PDF).
Arjun will first build a basic Adobe PO form, then add interactive elements.
2.3 Building the Adobe Form – Step by Step
Step 1: Create the Interface (ABAP Dictionary structure)
In SE11, he creates a structure ZSPO_ADOBE_HDR for header fields and ZTPO_ADOBE_ITM for items (table type). But Adobe Forms interface can directly use an ABAP Dictionary structure as the context. He creates a root structure ZSPO_ADOBE_ROOT that includes the header fields and a table type for items. Actually, it’s easier to define the interface in SFP using an XML schema based on a DDIC structure. He creates ZPO_ADOBE_DATA with:
- Fields: EBELN, LIFNR, NAME1, AEDAT, WAERS, NETWR, BSART, etc.
- A deep component
ITEMSof typeZTT_PO_ITEMS(table type of line typeZS_PO_ITEMwith fields EBELP, MATNR, MAKTX, MENGE, MEINS, NETPR, NETWR_ITEM).
Screenshot Description: SE11 structure ZPO_ADOBE_DATA with ITEMS as a nested table type.
Step 2: Create the Form in SFP
Transaction: SFP → Create → Form → enter ZADOBE_PO → Create.
- Interface: Use “ABAP Dictionary” as the interface type. Specify the structure
ZPO_ADOBE_DATA. The system generates an XML schema automatically. Activate the interface. - Layout: Click the “Layout” tab. This opens the Adobe LiveCycle Designer (or the integrated HTML5 designer if configured). In the designer, Arjun designs the form:
He drags a “Text Field” for the PO number and binds it to the data field EBELN. He adds a header logo image by importing a JPEG of TechBook24’s logo. He adds a table for items, binding it to the ITEMS node. The table columns are automatically created. He formats the table with alternating row colors. He adds a footer with static text.
Screenshot Description: LiveCycle Designer with the form layout, showing bound data fields and the palette.
He adds a barcode object: he inserts a “Barcode” field, sets it to Code128, and binds it to EBELN.
For the interactive “Confirm Order” button: he adds a regular button field. In its properties, he sets the control type to “Submit” or uses a JavaScript action to compose a mailto link with subject. In LiveCycle, he can add a script on click: event.target.submitForm({cURL:"mailto:?subject=PO%20" + this.resolveNode("EBELN").rawValue}). That opens the default mail client.
After designing, he saves the layout and returns to SFP. He activates the form.
2.4 Driver Program for Adobe Form
The Adobe form is called via function module FP_JOB_OPEN and FP_JOB_CLOSE or using the generated PDF print program. Simpler: use the generated print program name (like ZADOBE_PO as the form name) with the function module FP_FUNCTION_MODULE_NAME. Actually, Adobe forms are called similarly to SmartForms but via the ADS (Adobe Document Services). The call is almost identical.
DATA: lv_fm_name TYPE rs38l_fnam.
CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
EXPORTING
i_name = 'ZADOBE_PO'
IMPORTING
e_funcname = lv_fm_name.
DATA: ls_output_params TYPE sfpoutputparams.
ls_output_params-connection = 'ADS' "or default
ls_output_params-nodialog = abap_true.
ls_output_params-getpdf = abap_true.
DATA: lv_pdf TYPE xstring,
ls_docparams TYPE sfpdocparams.
CALL FUNCTION lv_fm_name
EXPORTING
/1bcdwb/docparams = ls_docparams
outputparams = ls_output_params
data = gs_adobe_data "the structure
IMPORTING
pdf = lv_pdf
EXCEPTIONS
processing_error = 1
OTHERS = 2.
He can then save the PDF or send it via email. That connects to output management.
3. Output Determination – NACE and the Magic Behind Automatic Output
3.1 The Big Picture – From Document to Output
SAP’s output determination uses the NACE configuration to automatically trigger outputs (print, email, EDI) when a document is saved or released. It’s the backbone of all business document distribution. The flow: a business document (like a purchase order) is created, the system checks the output type assigned to the document type, finds the condition record for that output type (based on vendor, purchasing org, etc.), determines the processing program (which includes the form and transmission medium), and schedules an output request. The output is then processed by the output processor (SAPconnect, spool, etc.) to send the email or print.
3.2 Configuring a Custom Output Type for Purchase Orders
Arjun needs to define a new output type for the electronic PDF PO form that gets emailed to vendors. He will use transaction NACE. The application for Purchasing is EF (Purchasing).
Step 1: Create Output Type
- Execute
NACE→ select Application “EF – Purchasing”. - Click “Output Types” → New Entries. Enter:
- Output Type:
ZPOF(Z-PDF Output). - Description: “PO Adobe PDF Email”.
- Access sequence:
0001(Vendor) or a custom one. - Processing routine: this is a program and form routine that will be called to generate the output. He enters the name of a custom program
ZR_PO_OUTPUT_PROCESSand a form routineENTRY. But usually, for simple print, you can use the standard programSAPFM06Pwith a specific FORM routine. He wants to send email, so he’ll create a custom processing routine. - Transmission medium:
5(External send) orINTfor email. He selects5for external. - Partner function:
VN(vendor).
- Output Type:
- Save.
Screenshot Description: NACE output types list with the new entry ZPOF.
Step 2: Create Condition Record
In NACE, under “Condition Records”, select output type ZPOF. Click “Communications” or “Key Combination” (depends on the access sequence). He defines a condition record for vendor 1000 (TechBook24’s main supplier) so that whenever a PO is created for that vendor, output type ZPOF is determined. He sets the transmission medium to 5 and the partner’s email address. He can enter the email in the condition record itself under the communication details (SMTP address).
3.3 Creating the Processing Program for Email Output
The processing program is called by the output determination framework with parameters: output type, application, etc. The program must read the document data, generate the PDF (using the Adobe form), and send the email via SO_NEW_DOCUMENT_ATT_SEND_API1 or the newer CL_BCS class.
Arjun creates program ZR_PO_OUTPUT_PROCESS:
REPORT zr_po_output_process.
FORM entry USING VALUE(i_nast) TYPE nast.
DATA: lv_ebeln TYPE ebeln.
lv_ebeln = i_nast-objky. "the document number
" Fetch PO data as before...
" Generate PDF
DATA lv_pdf TYPE xstring.
PERFORM generate_pdf USING lv_ebeln CHANGING lv_pdf.
" Send email
PERFORM send_email USING lv_pdf i_nast.
ENDFORM.
The generate_pdf form calls the Adobe form function module. The send_email form uses CL_BCS to create the email, attach the PDF, and send. He uses the vendor email from the NACE condition record (i_nast-tdarms = vendor address number, but email is stored in ADR6). He retrieves it using the communication keys from NAST.
This is the core of automated output.
4. Email Output via SOST and Troubleshooting
4.1 SOST (Send Process) – Monitoring and Resending
After output determination triggers the processing program, the email request appears in transaction SOST (Send Process). Here Arjun can monitor sent, waiting, and failed emails. If the email gets stuck (e.g., SMTP server not configured), he can resend after fixing the configuration. He tests the end-to-end flow: create a PO, check NACE, see the output status in SOST, and verify the email arrives.
Screenshot Description: SOST screen with a list of send requests, one marked with status “OK”, showing the recipient and attachment icon.
4.2 Common SOST Issues and Fixes
- SCOT configuration missing: transaction
SCOTto set up SMTP node. - No sender address: maintain default sender in SCOT or in the user profile (SU01).
- Attachment too large: adjust size limit in SCOT or use compressed PDF.
Arjun ensures that SCOT is correctly configured for TechBook24’s Exchange server.
5. Interactive PDF – The Two-Way Document
5.1 The Concept
An interactive PDF contains form fields that the recipient can fill in, and a submit button that sends the data back to SAP. In Adobe Forms, you can design such a form using LiveCycle Designer, setting fields as “User Entered – Required” and adding a submit button that posts the data to an SAP service (via HTTP). The submitted data is received by an ICF service (Internet Communication Framework) and processed in ABAP (typically using a handler class).
For TechBook24, Arjun’s next phase is to allow vendors to confirm the PO delivery date directly in the PDF. The vendor fills in a “Confirmed Delivery Date” field, clicks “Submit”, and the data updates the PO confirmation in SAP.
5.2 Creating an Interactive PDF Form
In the Adobe form layout, Arjun adds a text field ZCONF_DATE bound to a node in the data that is initially empty. He also adds a submit button with an action to “Submit Form” to a URL. He creates an ICF service in transaction SICF under the path /sap/bc/zpo_confirm that points to a handler class ZCL_PO_CONFIRM_HANDLER implementing IF_HTTP_EXTENSION.
In the handler’s HANDLE_REQUEST method, he reads the incoming XML (XDP data), extracts the PO number and confirmed date, and updates the PO confirmation (table EKKO-ERS, or a custom table). He then returns a success response.
This gives the supplier a zero-training method to confirm orders.
6. Migration Path: SmartForms to Adobe in S/4HANA
6.1 Why Migrate?
SAP recommends migrating from SAPscript and SmartForms to Adobe Forms to take advantage of modern PDF features, digital signatures, and better compatibility with cloud and mobile scenarios. However, it’s not mandatory for existing forms to be converted immediately; they still work. For new developments, always use Adobe Forms.
Migration tools exist: program SFP_ADOBE_FORM_MIGRATE can convert a SmartForm to an Adobe form, but the result often requires manual adjustment of the layout. Arjun will only use it as a starting point for future migrations. For now, he’s building natively in Adobe.
7. Complete Hands-On Lab – Building and Testing the Full Output Chain
We’ll now consolidate everything into a step-by-step lab that takes you from zero to automatic email with PDF.
- Create the Adobe form ZADOBE_PO with interface, layout, and activate.
- Create driver program ZR_PO_PRINT to test the form.
- Create output type ZPOF in NACE (application EF).
- Create processing program ZR_PO_OUTPUT_PROCESS with FORM entry that generates PDF and sends email.
- Create condition record for vendor 1000, enter email.
- Create a PO (ME21N) for vendor 1000; after save, check SOST for email.
- Verify email received with PDF attachment.
- Optional: enhance form with barcode and interactive fields, and test submission via ICF service.
Throughout, Arjun tests each component, debugging the driver program, verifying NACE logs, and checking the email queue. He documents all steps in the team wiki.
8. Pros, Cons, and Alternatives of Form Technologies
| Technology | Pros | Cons | Use Case |
|---|---|---|---|
| SmartForms | Mature, well-known, easy to debug, no external server needed | Lacks advanced PDF features, no interactive fields, design limited | Standard print forms where layout needs are simple, or existing landscapes that haven't migrated yet |
| Adobe Forms | Rich layout, interactive PDF, digital signatures, strategic direction | Requires ADS (Adobe Document Services), more complex design tool, higher learning curve | New developments, customer-facing documents, any form that needs professional appearance or interactivity |
| SAPscript | Legacy, still runs many old forms | Deprecated, extremely difficult to edit, no GUI designer | Only for maintaining very old forms; plan migration |
| Cloud Output Management (S/4HANA Cloud) | Managed service, no local ADS, integrates with external printers | Only for cloud edition, limited custom logic | S/4HANA Public Cloud |
9. Common Pitfalls and Pro Tips
- SmartForm loops not working: Check that you have selected the correct table and that the node type is “Table” (not “Template” for dynamic rows). Also ensure the internal table is not empty; always wrap with a condition.
- Adobe form not activating: Ensure the ADS configuration is correct (transaction SFP, Settings → Check ADS). Also check that the layout file (XDP) is valid.
- NACE output not triggering: Verify the output type is assigned to the document type (in NACE, under “Assign output types to document types”). Also check if the requirement routine (if any) passes.
- Email not sending: Check SCOT, SOST, and also whether the processing program actually finishes without dump. Use ST22 to find any uncaught exceptions.
10. Conclusion and Next Steps
Arjun has restored the critical purchase order output process, upgraded it to a modern, interactive Adobe PDF, and automated email distribution. He learned not just the tools, but the architecture of SAP output management. He also set the stage for future interactive documents. The procurement team is happy, the supplier is happy, and TechBook24’s production line keeps moving.
Tomorrow, we’ll move into ABAP Enhancements — BAdIs, User Exits, and Enhancement Spots — where Arjun will add custom validations to the PO save process, preventing orders above the vendor’s agreed limit. That’s Part 35, and it’s a game-changer for functional-ABAP collaboration.
Keep building, keep learning.
End of Part 34. Brought to you by @FreeLearning365 and tech partner @techbook24.

0 Comments
thanks for your comments!