Apparel Size Matrix Advanced PDF Template in NetSuite
Standard NetSuite POs print one line per item, hard to scan for apparel brands. Build an Advanced PDF template that groups lines into a size/color matrix.

On this page
Standard NetSuite purchase orders print one line per item, making them difficult to read quickly for apparel brands with multiple sizes and colors. Advanced PDF/HTML templates solve this by grouping transaction lines into a style/color matrix with sizes as columns. This article guides you through creating and implementing this template in NetSuite.
What the Matrix Template Does
The template snippet below reorganizes purchase order line items into blocks, showing one style and color combination per block with columns for each size ordered. Quantities for each size appear in their respective columns, and the template rolls up totals per group.
This approach also works on sales orders and invoices because it relies on the same record.item line structure those transactions share.
Configuration Before You Start
The template needs to know which custom fields hold your style, color, and size values. Set these at the top of the template:
<#assign STYLE_FIELD = "custitem_psgss_style_number" />
<#assign COLOR_FIELD = "custitem_psgss_product_color" />
<#assign SIZE_FIELD = "custitem_psgss_product_size_desc" />
<#assign IMAGE_FIELD = "custitem_item_image" />
<#assign SHOW_ITEM_IMAGE_COLUMN = true />
<#assign MATRIX_DEBUG = false />
<#assign COLOR_OPTION_LABEL = "color" />
<#assign SIZE_OPTION_LABEL = "size" />Use internal field IDs only. Do not prefix them with item. even if you see that format elsewhere in NetSuite documentation. The template's helper functions handle the lookup across line-level and item-level fields automatically.
Size Sorting Logic
Apparel sizes do not sort alphabetically. The template includes a rank map that assigns a numeric order to each size:
<#assign APPAREL_RANK = {
"XXXS": 5,
"XXS": 10,
"XS": 20,
"XS/S": 25,
"S": 30,
"S/M": 35,
"M": 40,
"M/L": 45,
"L": 50,
"L/XL": 55,
"XL": 60,
"XXL": 70,
"2XL": 70,
"XXXL": 80,
"3XL": 80,
"4XL": 90,
"5XL": 100,
"6XL": 110
} />Add your own sizes to this map if your product line includes numeric sizes, kids' sizing, or extended sizes. The sort uses the rank value, so keep the numbers spaced to allow room for additions.
Handling Matrix Item Options
If you use NetSuite matrix items, the color and size values arrive as line options rather than custom fields. The template's getOptionValue function parses the options string on each line, which follows this format:
color: Navy, size: MThe function splits on the option label you configured in COLOR_OPTION_LABEL and SIZE_OPTION_LABEL, then extracts the value. This means the same template works whether you store attributes as custom fields or as matrix item options.
The Core Grouping Logic
The template builds a hash map where each key is a style + color combination. Every product line gets added to its group, and the size quantity accumulates into a nested map:
<#assign groupKey = styleVal + "||" + colorVal />
<#if !matrixGroups[groupKey]?has_content>
<#assign matrixGroups = matrixGroups + {
(groupKey): {
"style": styleVal,
"color": colorVal,
"sizeMap": {},
"sizeAmtMap": {},
"sizeList": [],
"totalQty": 0,
"totalAmt": 0
}
} />
</#if>Non-product lines like discounts, shipping, and tax get separated during this pass. Their totals appear in the summary section instead of cluttering the matrix.
Debugging Your Fields
Before you spend hours testing output, set MATRIX_DEBUG = true. This renders every line's raw field values directly in the document, showing you exactly what the template sees for style, color, size, quantity, and amount.
This step matters because NetSuite exposes different field shapes depending on how your account stores the data. A custom field on the item record behaves differently from a matrix option, and the template's fallback logic handles both. Debug mode tells you which path each line took.
Where to Paste the Template
Open the Advanced PDF/HTML template you want to modify:
- Navigate to Customization > Forms > Advanced PDF/HTML Templates
- Click Edit next to your purchase order template
- Switch to Code mode using the toggle at the top of the editor
- Locate the
<#list record.item as line>loop in your existing template - Insert the matrix block where you want the table to appear
- Click Save, then test with a real purchase order
The matrix block replaces the standard line-item table. Keep the rest of your template intact for headers, addresses, terms, and footer content.
Known Limitation: Item Images
The template supports showing product images in a dedicated column, but NetSuite's image serving can behave unpredictably. Images sometimes fail to render because the URL NetSuite generates requires authentication that the PDF renderer does not pass through.
If you hit this issue, set SHOW_ITEM_IMAGE_COLUMN = false and rely on the text-based matrix. The rest of the template works normally.
Why This Beats the Spreadsheet Workaround
Before this template, apparel teams often exported purchase order lines to Excel, rebuilt the matrix manually, and attached the spreadsheet to the PDF. That process introduced transcription errors and broke the audit trail, since the spreadsheet did not link back to the NetSuite transaction.
With the matrix template, the purchase order itself carries the grouped view. Your warehouse team reads sizes across the top and quantities in the body, and your auditors see one document with the full transaction detail. The template also handles the totals, so the bottom of the matrix matches the transaction total exactly.
If you need to adapt this for your own fields, the configuration block at the top is the only part you should have to touch. The grouping, sorting, and rendering logic works as a drop-in snippet.
Links for Further Reading
Author Note
This article was written by Sarah Jenkins, CPA, Principal Finance Automation Specialist. She specializes in helping finance teams optimize NetSuite for month-end close automation, GAAP compliance, and multi-currency reporting.


