NetSuite’s Advanced PDF/HTML Templates are powered by FreeMarker, a Java-based templating engine that lets you turn static layouts into dynamic, data-driven documents. While our previous post covered branding your invoices and statements, this guide goes a step deeper: showing how to use FreeMarker syntax to control logic, loops, conditions, and formatting so your PDFs adapt to every transaction.
Why FreeMarker Matters in Advanced PDF Templates
Out of the box, NetSuite’s drag-and-drop PDF designer is great for simple layouts. But once you need conditional sections, custom calculations, or repeating data, you’ll need to drop into the Source Code view and write FreeMarker. With FreeMarker you can:
- Show or hide blocks based on transaction data (e.g., only display tax breakdown when tax applies).
- Loop through line items, subsidiaries, or custom records.
- Format numbers, dates, and currencies consistently across documents.
- Reference custom fields and saved searches for richer reporting.
- Build multi-language templates that adapt to the customer’s locale.
FreeMarker Basics You Should Know
FreeMarker uses a simple syntax built around three core constructs:
- ${expression} โ outputs the value of a variable or expression.
- <#if> / <#else> / </#if> โ conditional logic.
- <#list … as …> / </#list> โ iterate over collections such as line items.
Example: Conditional Discount Message
<#if record.discountrate?has_content && record.discountrate != 0>
<p>You saved ${record.discountrate}% on this order. Thank you!</p>
</#if>
Example: Looping Through Line Items
<#list record.item as item>
<tr>
<td>${item.item}</td>
<td>${item.quantity}</td>
<td>${item.rate}</td>
<td>${item.amount}</td>
</tr>
</#list>
Formatting Numbers, Dates, and Currency
Consistent formatting is one of the biggest wins of FreeMarker. Use built-ins like ?string, ?date, and ?number to format values precisely:
Invoice Date: ${record.trandate?date}
Total: ${record.total?string.currency}
Quantity: ${item.quantity?string["0.##"]}
Tips for Building Maintainable Templates
- Comment your code. Use
<#-- comment -->to document complex logic. - Test in a sandbox. Always preview changes in a non-production account before deploying.
- Use macros. Wrap repeated blocks (headers, footers, totals) in
<#macro>definitions for reuse. - Handle missing data. Use
?has_contentor default values (!"") to avoid runtime errors. - Keep CSS inline. NetSuite’s PDF engine (BFO) supports limited CSS โ use inline styles for reliability.
Common Pitfalls to Avoid
- Forgetting to escape special characters in field values (use
?htmlwhen needed). - Using unsupported CSS properties like
flexboxorgrid. - Hard-coding values that should come from records or preferences.
- Skipping null checks, which often causes “Expression is undefined” errors.
Final Thoughts
FreeMarker turns NetSuite’s Advanced PDF Templates from static documents into intelligent, dynamic reports. By mastering conditionals, loops, and formatting built-ins, you can deliver invoices, statements, and purchase orders that look professional and reflect the exact data your business needs. In the next post in this series, we’ll explore how to integrate saved searches into PDF templates for advanced reporting scenarios.
Discover more from The NetSuite Pro
Subscribe to get the latest posts sent to your email.
Leave a Reply