How to Create a PDF Report from Workflow Data

Turn data from any workflow step (a database query, an API response, a spreadsheet) into a clean PDF report with a title, headings, a summary and paginated tables, using simple Markdown and the PDF Tools create-pdf tool.

What This Integration Does

A PDF is still the format people forward, print and file: the weekly sales sheet, the stock report for a supplier, the monthly summary for the board. Spojit's PDF Tools connector has a create-pdf tool that builds one from two inputs you already have. content is the text of the report in simple Markdown: headings, paragraphs, **Label:** value lines and bullet lists. rows is a list from an earlier step, which prints as a table with headers taken from the field names. You do not design a template or write HTML; you write the report the way you would write an email, and point rows at the data.

Each run builds a new PDF from current data and returns it as Base64, ready to attach to an email, save to your File Store or upload to SFTP. Nothing is stored unless you save it, so runs are independent.

Prerequisites

  • A data source with a connection in Spojit. This tutorial uses MySQL; any step that returns a list works the same way (NetSuite SuiteQL, Shopify orders, a CSV parsed with CSV Tools).
  • For delivery: a Resend or SMTP Email connection, or none if you only save to the File Store.

Step 1: Trigger

Add a Trigger node. A Schedule such as 0 8 1 * * (8 AM on the first of the month) suits regular reports; Manual suits on-demand ones.

Step 2: Get the Data

Add a MySQL step with execute-query, for example stock below its reorder point:

SELECT sku, name, on_hand, reorder_point, supplier
FROM inventory
WHERE on_hand < reorder_point
ORDER BY supplier, sku

Name the output stock and run the step once to see where the rows are in its output.

Step 3: Work Out the Headline Numbers

Reports read better with a summary at the top. Use an Array Tools length step named item_count for the count of rows (read it as {{ item_count.result }}), a Date & Time format step named today for the date, and Math Tools sum for totals. For a written summary, add an Agent Mode step on the Text Tools connector (its tools only reshape text) with a prompt such as "In two sentences, summarise this low-stock list for a purchasing manager: {{ stock }}" and name it summary.

Step 4: Write the Report Content

Add a Connector node on PDF Tools with create-pdf and fill in content:

# Low stock report

**Prepared:** {{ today.result }}
**Items below reorder point:** {{ item_count.result }}

{{ summary }}

## What to do

1. Raise purchase orders for the items below.
2. Check open orders for anything marked urgent.

## Items to reorder

This prints a heading, a label and value list, a paragraph, a numbered list and a subheading. Bold, links and code formatting are removed (the PDF uses one text style), and a | a | b | table with a |---|---| line under its header also works in content for small, hand-written tables.

Step 5: Add the Table and Page Settings

In the same create-pdf step:

  • rows: {{ stock.rows }} (use the path you found in Step 2). Field names become headers, so on_hand prints as "On hand" and sku as "SKU". Number columns are right-aligned.
  • columns: ["sku", "name", "on_hand", "reorder_point", "supplier"] to choose and order the columns.
  • title: Low stock report (also set as the PDF's document title).
  • footer: Acme Pty Ltd - internal, and leave pageNumbers on for "Page N of M".
  • orientation: landscape for wide tables; pageSize A4 or Letter.

The table prints after the content, and its header repeats on every page. Name the output report; the PDF is in {{ report.pdf }} and the page count in {{ report.pageCount }}.

Step 6: Deliver It

Save it with a File Store node (Save a file, name low-stock-{{ today.result }}.pdf, content {{ report.pdf }}, content type application/pdf), or email it with Resend send-email, adding an attachment with filename low-stock.pdf and content {{ report.pdf }}.

Tips

  • Several tables: rows holds one table. For more, use the blocks input with extra heading and table blocks, which print after the content and rows.
  • Images: logos and charts go in blocks as an image block with Base64 PNG or JPEG data. The tool never downloads images from URLs.
  • Page breaks: add a pageBreak block to start a section on a new page, for example one page per supplier.
  • Read it back: the extract-text tool on the same connector reads a PDF's text, which is handy for checking a generated report in a test.

Common Pitfalls

  • Order of sections: the rows table always prints after all of content. Put anything that should follow the table (such as totals) in the content above it, or in a later blocks entry.
  • Unsupported characters: the embedded font covers Latin, Greek, Cyrillic and Vietnamese. Chinese, Japanese and Korean characters print as ? and are listed in unsupportedCharacters.
  • Too many columns: tables are limited to 20 columns, and wide tables get cramped. Choose columns with columns and use landscape.
  • File size: fonts are embedded in full, so even a one-page PDF is around 500 KB. That is fine for email, but keep it in mind for very frequent reports.

Testing

Run the workflow manually with LIMIT 10 on the query and open the PDF from the File Store. Check the headings, the table headers, the footer and the page numbers, then remove the limit and run it once more to see how the table flows across pages.

Learn More

Ready to build this?

Start on the free plan: 500 AI credits a month, no card needed.

Start free

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.