From Data to Document: Automating PDF Reports

This step-by-step guide will walk you through a complete, real-world example: building an application that allows a user to fill out and sign an acceptance report, which is then saved to a database and emailed as a PDF.

Before You Begin

To get started, the first step for everyone is to download the blank acceptance_report.pdf file. You will need to upload this file to your File Server to serve as the template's background, regardless of which method you choose below.

Once you have the PDF, you have two options:

  1. Build from Scratch: Follow all the steps in this guide to learn the entire process.

  2. Start from a Template: If you'd like to start with the finished application logic, download the Heisenware Tag (acceptance-report-app.hwt) file below and import it into your account. You will still need to link your uploaded PDF to the template.

Downloads

Step 1: Create the Database Table

First, we need a place to store the submitted reports. We'll use the defineTable function to create a table in the internal PostgreSQL database.

In the Flow Builder, place the defineTable function on the canvas and configure its inputs as shown below.

#name
acceptanceReports
#fields
customerName: string
projectID: string
acceptanceDate: date
comments: text
signature: text

The 'id', 'createdAt', and 'updatedAt' fields are added automatically.

After configuring the function, you must trigger it once to execute the logic and create the table in your database.

Step 2: Build the Form and Submission Logic

Now, we will create the user interface for data entry and build the backend logic to save the submitted data to our database table.

Build the User Interface

First, in the UI Builder, add the widgets for your form.

1

Drag a Form widget onto the canvas. Select it and configure its fields. It is critical that the field names and data types exactly match your database columns (customerName, projectID, acceptanceDate, comments). You can also set user-friendly labels for each field.

2

Drag a Signature widget onto the canvas, placing it below the form.

3

Drag a Button below the Signature widget and change its label to Submit.

Construct the Submission Logic

Next, switch to the Flow Builder to define what happens when the user clicks the Submit button.

1

Prepare the Signature Data

The Signature widget outputs a raw Base64 string, but our database expects an object. We need to format it correctly.

  • Drag a Memory function onto the canvas and connect the output of the Signature widget to its input.

  • Add a JavaScript Modifier after the Memory. Use the following expression in it. This wraps the signature string in an object with the key signature, matching our database column.

{signature: x}
2

Combine All Form Data

Now we'll merge the main form data with our newly created signature object.

  • Drag the mergeObjects function onto the canvas.

  • Connect the Form widget to the first input of mergeObjects.

  • Connect the signature modifier to the second input of mergeObjects.

  • Connect both inputs to the trigger of mergeObjects to trigger the function on input update.

3

Save to the Database & Trigger the Flow

  • Drag the addRow function onto the canvas.

  • Set its table input to acceptanceReports.

  • Connect the output of the mergeObjects function to the data input of addRow.

  • Finally, connect the Submit Button to the trigger of the addRow functions trigger. This makes the button start the entire save process.

4

Clear the Form After Submission:

  • To provide a good user experience, we'll clear the form after a successful submission.

  • Connect the output of the addRow function to the Form widget.

  • Set the command to call clear. This will empty the form for the next entry after the data has been saved.

Step 3: Design and Configure the PDF Template

Now that our data submission logic is in place, we will create the visual PDF template and configure the logic to populate it.

Design the Template Layout

First, we need to create the visual layout in the Template Editor.

1

Upload the acceptance_report.pdf file to the File server via the Resources panel.

2

Navigate to PDF Template Editing mode.

3

Create a new template and name it AcceptanceReport.

4

From the Resources Panel, drag the acceptance_report.pdf file onto the page canvas. This sets it as the static background.

5

Using the Add Text Placeholder and Add Image Placeholder tools, place placeholders on the background for each of your fields (customerName, projectID, acceptanceDate, comments, and signature).

6

Configure each placeholder with the correct Variable Name in its settings. Optionally, adjust sizes and colors of your placeholders.

Construct the PDF Generation Logic

Now, return to the Flow Builder to connect the template to your existing logic.

1

From the Functionality Panel, find your AcceptanceReport instance (under the PDF Templates Class) and drag its fillTemplate function onto the canvas.

2

Connect the output of the mergeObjects function (from Step 2) to the Values input of fillTemplate. This provides the data for the placeholders.

3

Connect the output of the addRow function to the trigger of the fillTemplate function. This ensures the PDF is only generated after the data has been successfully saved to the database.

Our flow is now complete up to the point of generating the PDF. The final step will be to email this document.

Step 4: Send the Report via Email

The final step in our workflow is to automatically email the generated PDF report. We will use the send function from the internal mailer and configure it to send an email automatically whenever a new report is created.

Return to the Flow Builder to add the final piece of logic to your flow.

1

From the Functionality Panel, find your internal mailer instance and drag its send function onto the canvas.

2

Configure the static inputs for the email

#address
to: [your email address]
#subject
New Acceptance Report
#content
A new report has been submitted for review. Please see attached PDF.
3

Format the Attachment Data

The send function's attachment input requires a specific object format. We can create this directly on the fillTemplate function's output using a built-in Modifier.

  • Add a JSONata Modifier to the fillTemplate function.

  • In the Modifier's settings, enter the following JSONata expression. This wraps the raw Base64 output ($) with a filename and encoding:

{
  "filename": "Acceptance Report.pdf",
  "content": $,
  "encoding": "base64"
}
4

Connect the PDF and Set the Trigger

  • Connect the Modifier (from the fillTemplate function) to the attachment input of the send function.

  • Now, connect the attachment input to the trigger of the send function.

  • Set the trigger to on input change.

This creates a simple and powerful data-driven workflow. Whenever a new PDF is generated by the fillTemplate function, its output is passed to the attachment input, and this change automatically triggers the send function.

Step 5: Deployment

Congratulations! 🥳 You have now built a complete application that captures user input, saves it to a database, generates a customized PDF, and emails it as an attachment.

The final step is to deploy your app. Click the Deploy button in the App Builder's toolbar to publish the latest version and make it live.

Once deployed, open the application and test the full workflow. After you fill out and submit the report, the static email address you configured in Step 4 should receive an email with the PDF attachment, which will look similar to the image below.

From here, you can expand on this project by adding more fields, using your own report templates, or integrating this logic into a larger application.

Last updated