Tables in Templates - Dynamic Table Guide
Tables are fundamental components of professional documents, providing structured presentation of data for easy comparison, reference, and analysis. PDF4me's document generation engine efficiently creates dynamic tables populated with data from your sources.
Multi-Column Table Structure
Generate tables with multiple columns by defining merge fields within table cells. Each row repeats based on the data collection.
Basic Table Syntax
Create a table structure in your Word template with the following pattern:
Column 1: <<foreach [product in products]>><<[product.productName]>>
Column 2: <<[product.manufactured]:"yyyy.MM.dd">>
Column 3: <<[product.price]>><</foreach>>
Template Structure:
- Create a table in Word with desired number of columns
- Place foreach loop in first cell
- Add merge fields in subsequent cells of the same row
- Close foreach loop in the last cell
Example: Product Inventory Table
Data Source (JSON):
{
"vendorName": "Instamart",
"products": [
{
"productName": "Laptops",
"price": 160000,
"manufactured": "25/07/2022"
},
{
"productName": "Keyboard",
"price": 10000,
"manufactured": "12/04/2022"
},
{
"productName": "Speakers",
"price": 25000,
"manufactured": "08/05/2022"
}
]
}
Generated Output:
| Product Name | Manufactured | Price |
|---|---|---|
| Laptops | 2022.07.25 | 160000 |
| Keyboard | 2022.04.12 | 10000 |
| Speakers | 2022.05.08 | 25000 |
Table Calculations and Totals
Calculate aggregate values like sums, averages, and counts within your table structures using enumeration methods.
Sum Calculation
Add a total row to calculate the sum of numeric columns:
Column 1: <<foreach [product in products]>><<[product.productName]>>
Column 2: <<[product.manufactured]:"yyyy.MM.dd">>
Column 3: <<[product.price]>><</foreach>>
Column 1: Total
Column 2:
Column 3: $<<[products.Sum(c => c.price)]>>
Generated Output:
| Product Name | Manufactured | Price |
|---|---|---|
| Laptops | 2022.07.25 | 160000 |
| Keyboard | 2022.04.12 | 10000 |
| Speakers | 2022.05.08 | 25000 |
| Total | $195000 |
Other Aggregate Functions
Average:
Average Price: $<<[products.Average(p => p.price)]:"F2">>
Count:
Total Products: <<[products.Count()]>>
Maximum:
Highest Price: $<<[products.Max(p => p.price)]>>
Minimum:
Lowest Price: $<<[products.Min(p => p.price)]>>
Single-Column Tables
Generate tables with a single column containing multiple lines of information per row. Use the -greedy switch to ensure each collection item occupies one row.
Single-Column Template Syntax
<<foreach [product in products]>>Product: <<[product.productName]>>, Manufactured On: <<[product.manufactured]:"yyyy.MM.dd">>, Product Price: $<<[product.price]>><</foreach -greedy>>
Key Point: The -greedy switch treats the entire content block as a single row, preventing unwanted row breaks.
Generated Output:
| Product Details |
|---|
| Product: Laptops, Manufactured On: 2022.07.25, Product Price: $160000 |
| Product: Keyboard, Manufactured On: 2022.04.12, Product Price: $10000 |
| Product: Speakers, Manufactured On: 2022.05.08, Product Price: $25000 |
Advanced Table Examples
Example 1: Invoice Line Items Table
Template:
Item | Description | Qty | Unit Price | Total
<<foreach [item in lineItems]>><<[item.code]>> | <<[item.description]>> | <<[item.quantity]>> | $<<[item.unitPrice]:"F2">> | $<<[item.quantity * item.unitPrice]:"F2">><</foreach>>
| | | Subtotal: | $<<[lineItems.Sum(i => i.quantity * i.unitPrice)]:"F2">>
Example 2: Employee Directory Table
Template:
Name | Department | Email | Phone
<<foreach [emp in employees.OrderBy(e => e.lastName)]>><<[emp.firstName]>> <<[emp.lastName]>> | <<[emp.department]>> | <<[emp.email]>> | <<[emp.phone]>><</foreach>>
Total Employees: <<[employees.Count()]>>
Example 3: Sales Report Table
Template:
Month | Revenue | Expenses | Profit
<<foreach [month in salesData]>><<[month.name]>> | $<<[month.revenue]:"F2">> | $<<[month.expenses]:"F2">> | $<<[month.revenue - month.expenses]:"F2">><</foreach>>
Annual Total | $<<[salesData.Sum(m => m.revenue)]:"F2">> | $<<[salesData.Sum(m => m.expenses)]:"F2">> | $<<[salesData.Sum(m => m.revenue - m.expenses)]:"F2">>
Conditional Table Rows
Generate table rows conditionally based on data properties or business logic.
Filtered Rows
Template:
Product | Stock Status
<<foreach [product in products.Where(p => p.inStock == true)]>>
<<[product.name]>> | Available
<</foreach>>
Conditional Formatting
Template:
Employee | Status
<<foreach [emp in employees]>>
<<[emp.name]>> | <<if [emp.active]>>Active<<else>>Inactive<</if>>
<</foreach>>
Table Formatting Best Practices
Design Guidelines
- Header rows - Create clear, descriptive column headers
- Consistent alignment - Align numeric data right, text data left
- Appropriate widths - Set column widths based on expected content
- Formatting - Apply formatting (borders, shading) in the Word template
- Totals placement - Place aggregate calculations in appropriate summary rows
Data Preparation
- Clean data - Ensure data is properly formatted before template processing
- Handle nulls - Provide default values for null fields
- Limit rows - Consider pagination for very large datasets
- Sort data - Pre-sort data or use OrderBy in templates
Complex Table Structures
Multi-Level Grouping
Template:
Category | Product | Price
<<foreach [cat in categories]>>
<<[cat.name]>> | |
<<foreach [prod in cat.products]>>
| <<[prod.name]>> | $<<[prod.price]>>
<</foreach>>
| Category Total | $<<[cat.products.Sum(p => p.price)]>>
<</foreach>>
Tables with Conditional Sections
Template:
Item | Quantity | Price | Discount | Total
<<foreach [item in orderItems]>>
<<[item.name]>> | <<[item.qty]>> | $<<[item.price]>> | <<if [item.discount > 0]>><<[item.discount]>>%<<else>>-<</if>> | $<<[item.total]>>
<</foreach>>
Special Table Features
Greedy Switch Usage
The -greedy switch controls how content is distributed across table cells:
Without -greedy: Each property may create a new row With -greedy: Entire content block stays in one row
Example:
<<foreach [item in items]>>
<<[item.prop1]>>, <<[item.prop2]>>, <<[item.prop3]>>
<</foreach -greedy>>
Vertical Merging
For cells that should span multiple rows, set up cell merging in the Word template before adding merge fields.
Troubleshooting Table Generation
Common Issues and Solutions
Issue: Table rows not repeating correctly
Solution: Ensure foreach loop spans across all cells in the row
Issue: Unwanted extra rows
Solution: Use -greedy switch for single-row content
Issue: Incorrect calculations
Solution: Verify expression syntax and data types
Issue: Formatting lost after generation
Solution: Apply formatting to template cells, not just merge field syntax
Issue: Empty tables when data exists
Solution: Check property names match data source exactly
Complete Example: Sales Invoice
Template:
Invoice Date: <<[invoiceDate]:"MMMM dd, yyyy">>
Customer: <<[customerName]:caps>>
Item No. | Description | Qty | Unit Price | Amount
<<foreach [item in lineItems]>>
<<[item.itemNo]>> | <<[item.description]>> | <<[item.quantity]>> | $<<[item.unitPrice]:"F2">> | $<<[item.quantity * item.unitPrice]:"F2">>
<</foreach>>
| | | Subtotal: | $<<[lineItems.Sum(i => i.quantity * i.unitPrice)]:"F2">>
| | | Tax (10%): | $<<[lineItems.Sum(i => i.quantity * i.unitPrice) * 0.10]:"F2">>
| | | **Total:** | **$<<[lineItems.Sum(i => i.quantity * i.unitPrice) * 1.10]:"F2">>**
Design your table structure in Word first with appropriate formatting, borders, and styling. Then add merge fields and foreach loops to the designed table for best results.