Repeating tables
A repeating table is a single row in your template that expands into many rows when Portant runs the workflow. You design one row, Portant clones it for every line item in the source.
This is the mechanic behind quotes, invoices, packing slips, statements of work, and any document that lists a variable number of items.

How it works
A regular tag is replaced with a single value. A line item tag is replaced with a list of values, one per row. Portant looks at where the line item tags are placed and behaves like this:
- If the tags are inside a table row, Portant clones that row, once per item.
- If the tags are outside a table, Portant joins the values into a single block of text instead.
So the rule is simple: to repeat rows, put the tags inside a single row of a table.
Setting up a repeating row
Insert a table in your template with as many columns as you need.
Optionally add a header row at the top with column titles (this row stays the same in the output).
Add one row of line item tags. For example:
| {{Item Name}} | {{Quantity}} | {{Unit Price}} | {{Line Total}} |Optionally add a totals row beneath using a tag formula, for example
{{=SUM(Line Total)}}in the right-hand column.
When the workflow runs, the row of tags is replaced with one row per line item. The header row and the totals row stay where they are. Anything above or below the table is untouched.
What goes inside the row
Only put tags that belong to the line item itself in the repeating row. Things like customer name, address, or quote number are document-level fields and should be placed outside the table.
If you mix the two, Portant will repeat the customer name on every line, which is rarely what you want.
Source-specific recipes
The mechanic is the same everywhere, but how the source provides the line items differs:
- HubSpot. Each HubSpot deal can have multiple line items as a connected object. See add multiple line items into a single document for the full HubSpot setup.
- Google Sheets. A repeating row is paired with a grouping column so Portant knows which rows belong together. See Google Sheets data grouping.
- Webhooks. When the payload includes an array of items, Portant treats each array element as a line item. See webhook data grouping.
Common gotchas
- Tags must be in a single row. If you spread line item tags across two rows, Portant won't recognise the repeating pattern.
- Header and footer rows can be styled independently and won't be cloned.
- Formulas like SUM and AVG only work on fields that are part of the line item set. See tag formulas.