One of the most powerful features of Advanced PDF templates is customizing how line items (products, services, expenses) appear on your transaction forms. Using FreeMarker loops, you can format tables, add subtotals, and apply styles to improve readability.
This page covers building item tables, styling rows, and formatting amounts.
🔹 Basic Line Item Table
<table border="1" width="100%" style="border-collapse: collapse;">
<tr style="background:#f2f2f2; font-weight:bold;">
<th>Item</th>
<th>Description</th>
<th>Quantity</th>
<th>Rate</th>
<th>Amount</th>
</tr>
<#list record.item as i>
<tr>
<td>${i.item}</td>
<td>${i.description}</td>
<td style="text-align:center;">${i.quantity}</td>
<td style="text-align:right;">${i.rate?string["#,##0.00"]}</td>
<td style="text-align:right;">${i.amount?string["#,##0.00"]}</td>
</tr>
</#list>
</table>
✔️ Creates a clean, printable line item table.
✔️ Aligns numbers to the right for better readability.
🔹 Alternating Row Colors (Zebra Striping)
<#list record.item as i>
<tr <#if i_index % 2 == 0>style="background:#f9f9f9;"</#if>>
<td>${i.item}</td>
<td>${i.description}</td>
<td>${i.quantity}</td>
<td style="text-align:right;">${i.rate?string["#,##0.00"]}</td>
<td style="text-align:right;">${i.amount?string["#,##0.00"]}</td>
</tr>
</#list>
✔️ ${i_index % 2}
checks if the row is even/odd.
✔️ Makes long invoices easier to read.
🔹 Adding Subtotals
<#assign subtotal = 0>
<#list record.item as i>
<tr>
<td>${i.item}</td>
<td>${i.description}</td>
<td>${i.quantity}</td>
<td style="text-align:right;">${i.rate?string["#,##0.00"]}</td>
<td style="text-align:right;">
${i.amount?string["#,##0.00"]}
<#assign subtotal += i.amount?number>
</td>
</tr>
</#list>
<tr style="font-weight:bold; background:#f2f2f2;">
<td colspan="4" style="text-align:right;">Subtotal</td>
<td style="text-align:right;">${subtotal?string["#,##0.00"]}</td>
</tr>
✔️ Demonstrates how to calculate totals using assign
.
🔹 Grouping Items by Type
Example: Group by Item Type (Inventory vs. Service).
<h3>Inventory Items</h3>
<table border="1" width="100%">
<#list record.item?filter(i -> i.itemtype == "InvtPart") as inv>
<tr>
<td>${inv.item}</td>
<td>${inv.quantity}</td>
<td>${inv.amount?string["#,##0.00"]}</td>
</tr>
</#list>
</table>
<h3>Service Items</h3>
<table border="1" width="100%">
<#list record.item?filter(i -> i.itemtype == "Service") as svc>
<tr>
<td>${svc.item}</td>
<td>${svc.quantity}</td>
<td>${svc.amount?string["#,##0.00"]}</td>
</tr>
</#list>
</table>
✔️ Splits items into categories for clearer reporting.
🔹 Highlighting Special Items
<#list record.item as i>
<tr <#if i.amount?number > 1000>style="background:#ffe6e6;"</#if>>
<td>${i.item}</td>
<td>${i.description}</td>
<td>${i.quantity}</td>
<td>${i.rate?string["#,##0.00"]}</td>
<td>${i.amount?string["#,##0.00"]}</td>
</tr>
</#list>
✔️ Highlights rows where the line amount is greater than 1000.
✅ Best Practices
- Keep tables lightweight for fast PDF rendering.
- Use CSS inline styles instead of external CSS for reliability.
- Always align numbers to the right.
- Use conditional formatting to highlight important items.
✅ Summary — What You Learned
You now know how to:
- ✅ Build a basic item table with FreeMarker.
- ✅ Apply zebra striping for readability.
- ✅ Calculate subtotals using
<#assign>
. - ✅ Group line items by type or condition.
- ✅ Highlight special rows using conditional formatting.
This sets you up for the next topic: Adding Custom Fields, where you’ll learn to insert custom body and column fields into your Advanced PDF tables.
Leave a Reply