SAP Forms Deep Dive: SmartForms, Adobe PDF, Output Determination (NACE) & Email Output – Hands-On Tutorial | Part 34 | FreeLearning365

 

SAP Forms Deep Dive: SmartForms, Adobe PDF, Output Determination (NACE) & Email Output – Hands-On Tutorial | Part 34 | FreeLearning365

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_HEADER type ZS_PO_HEADER (a structure containing EBELN, LIFNR, NAME1, AEDAT, WAERS, NETWR, etc.).
  • IT_ITEMS type ZTT_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:

  1. Under HEADER window, he adds a Text node with the title “Purchase Order”. He sets font size, bold, and alignment.
  2. He adds a Table node for the header data? Actually, for structured data like addresses, he can use a Template node that draws lines and places texts. He uses a template with two columns: one for labels, one for values.
  3. He adds Program Lines node to load the vendor address from ADRC if needed, but for simplicity he assumes the driver program passes the full address.
  4. Under MAIN window, he adds a Table node 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.
  5. He enables a footer row in the table to display the sum of the total column, using the Event: Table Footer and a Program Lines node that sums IT_ITEMS-NETWR_ITEM into a global variable GV_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).
  6. Under FOOTER window, 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 ITEMS of type ZTT_PO_ITEMS (table type of line type ZS_PO_ITEM with 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

  1. Execute NACE → select Application “EF – Purchasing”.
  2. 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_PROCESS and a form routine ENTRY. But usually, for simple print, you can use the standard program SAPFM06P with a specific FORM routine. He wants to send email, so he’ll create a custom processing routine.
    • Transmission medium: 5 (External send) or INT for email. He selects 5 for external.
    • Partner function: VN (vendor).
  3. 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 SCOT to 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.

  1. Create the Adobe form ZADOBE_PO with interface, layout, and activate.
  2. Create driver program ZR_PO_PRINT to test the form.
  3. Create output type ZPOF in NACE (application EF).
  4. Create processing program ZR_PO_OUTPUT_PROCESS with FORM entry that generates PDF and sends email.
  5. Create condition record for vendor 1000, enter email.
  6. Create a PO (ME21N) for vendor 1000; after save, check SOST for email.
  7. Verify email received with PDF attachment.
  8. 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

TechnologyProsConsUse Case
SmartFormsMature, well-known, easy to debug, no external server neededLacks advanced PDF features, no interactive fields, design limitedStandard print forms where layout needs are simple, or existing landscapes that haven't migrated yet
Adobe FormsRich layout, interactive PDF, digital signatures, strategic directionRequires ADS (Adobe Document Services), more complex design tool, higher learning curveNew developments, customer-facing documents, any form that needs professional appearance or interactivity
SAPscriptLegacy, still runs many old formsDeprecated, extremely difficult to edit, no GUI designerOnly for maintaining very old forms; plan migration
Cloud Output Management (S/4HANA Cloud)Managed service, no local ADS, integrates with external printersOnly for cloud edition, limited custom logicS/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.

Post a Comment

0 Comments