Comma-Separated Values (CSV) is a popular file format known for its simplicity and versatility. Its human- and machine-readable nature makes it ideal for transferring data between different systems. While TrueContext offers a built-in CSV 'Structured Data' document type with basic formatting options, you may encounter scenarios requiring complex logic or granular control over formatting to meet specific third-party system requirements. This is where leveraging 'Template-driven' Handlebars and FreeMarker document types becomes essential.
Handlebars vs FreeMarker
Handlebars and FreeMarker are both powerful document templating languages that offer similar core functionalities but differ in their syntax and complexity. Handlebars utilizes custom helper functions tailored for TrueContext data, such as `#each`, `#pf:if`/`#if`, and `@last`. This more constrained structure often makes it easier to learn. Conversely, FreeMarker provides a complete function set with extensive capabilities, which can result in a steeper initial learning investment.
This post will guide you through the process of generating CSV files using these templating languages. We will explore static references using hardcoded question labels, dynamic references for processing pages, sections, and questions (employing `#each` in Handlebars and `<#list>` in FreeMarker), conditional logic implementation, and handling repeatable sections.
All template examples provided in this post reference a sample JSON snippet derived from a TrueContext Data Record JSON file. For any data record within the portal, you can easily download its associated JSON file by hovering over the arrow adjacent to the Data Record ID and selecting Download Standard JSON.
The example JSON snippet originates from an 'Inspection Form' that includes a repeatable 'Checks' section. TrueContext supports various JSON referencing options (data node formats) for both languages. However, for the sake of clarity and consistency in our examples, we will focus on the 'standard' option.
In this post, static means you use fixed field names in your template-for example, always showing the "Inspector Name" field. This approach works well when you know exactly which questions are in the form. Dynamic means the template adjusts automatically. It scans the form and includes any questions or answers it finds, even if they change. This is especially useful when your form includes sections that repeat or vary between submissions.
Important: When generating CSV files, it is crucial to enclose printed field values in double quotation marks (`"`). This precaution prevents commas within the input text from being misinterpreted as delimiters, ensuring data integrity.
Example JSON Snippet
{
"dataRecord": {
"name": "Inspection Form",
"form": { "identifier": "18761289222281" },
"pages": [{
"name": "Inspection Details",
"sections": [{
"name": "General Information",
"type": "QuestionTextColumn",
"answers": [{
"label": "InspectorName", "question": "Inspector Name",
"values": ["Jane Dougherty"]
}, {
"label": "InspectionDate", "question": "Inspection Date",
"values": ["2025-03-30"]
}, {
"label": "SafetyScore", "question": "Safety Score",
"values": [85]
}]
}, {
"name": "Checks",
"type": "Repeat",
"rows": [{
"answers": [{
"label": "Item", "question": "Item",
"values": ["Light"]
}, {
"label": "Status", "question": "Status",
"values": ["Pass"]
}]
}, {
"answers": [{
"label": "Item", "question": "Item",
"values": ["Door"]
}, {
"label": "Status", "question": "Status",
"values": ["Fail"]
}]
}]}]}]}}
File Type (This should be the first line in the template file)
Handlebars
|
{{pf:outputFormat "CSV"}}
|
FreeMarker
|
<#assign outputFormat = "CSV">
|
Metadata
Handlebars
|
"Data Record ID", "User " {{!-- Header row --}}
"{{dataRecord.identifier}}", " {{dataRecord.username}}"
|
FreeMarker
|
"Data Record ID", "User " <#--Header row-->
"${dataRecord.identifier}", "${dataRecord.user.username}"
|
Output
|
"Data Record ID", "User " "18399906794", " TrueContext.User"
|
Data Referencing - Static
Handlebars
|
"Inspector","Date" {{!--Header row--}}
"{{answers.InspectorName.[0]}}","{{answers.InspectionDate.[0]}}"
|
FreeMarker
|
"Inspector","Date" <#--Header row-->"${answers.InspectorName[0]}","${answers.InspectionDate[0]}"
|
Output
|
"Inspector","Date" "Jane Dougherty","2025-03-30"
|
Data Referencing – Dynamic (Non-repeatable Sections).
Handlebars
|
"Question","Value" {{!--Header row--}}
{{#each dataRecord.pages}}
{{#each this.sections}}
{{#each this.answers}}
"{{question}}","{{values.[0]}}"
{{/each}}
{{/each}}
{{/each}}
|
FreeMarker
|
"Question","Value" <#--Header row-->
<#list dataRecord.pages as page>
<#list page.sections as section>
<#if !section.rows??> <#-- Check if it's a non-repeatable section -->
<#list section.answers as answer>
"${answer.question}","${answer.values[0]}"
</#list>
</#if>
</#list>
</#list>
|
Output
|
"Question","Value" "Inspector Name", "Jane Dougherty" "Inspection Date","2025-03-30" "SafetyScore","85"
|
Repeatable Sections (Dynamic References)
Handlebars
|
"Item","Result" {{!-- Header row --}}
{{#each dataRecord.pages.[0].sections.[1].rows}}
{{#with this.pages.[0].sections.[0].answers}}
"{{this.[0].values.[0]}}","{{this.[1].values.[0]}}"
{{/with}}
{{/each}}
|
FreeMarker
|
"Item","Result" <#--Header row-->
<#list dataRecord.pages[0].sections[1].rows as row>
<#assign answers = row.pages[0].sections[0].answers>
"${answers[0].values[0]}","${answers[1].values[0]}"
</#list>
|
Output
|
"Item","Result" "Light","Pass" "Door","Fail"
|
Conditional Logic (Static References)
Handlebars
|
"Score","Result" {{!--Header row--}}
"SafetyScore:"{{#pf:if answers.SafetyScore.[0] ">" "80"}} "Pass" {{else}} "Fail" {{/pf:if}}
|
FreeMarker
|
"Score","Result" <#--Header row-->
SafetyScore:<#if answers.SafetyScore[0]?number gt 80>Pass<#else>Fail</#if>
|
Output
|
"Score,"Result" "SafetyScore:","Pass"
|
Closing Thoughts
Handlebars and FreeMarker provide powerful and flexible options for generating template-driven CSV files within TrueContext, enabling versatile data sharing and facilitating integrations with third-party systems. We encourage you to explore the techniques discussed and to share your experiences and results in the comments below. Let's collaborate on enhancing CSV generation capabilities together!
Additional Resources
You can learn more about configure CSV documents, escape special characters and line breaks in your template-driven documents, and how to use either Handlebars or FreeMarker to create custom layouts and template-driven documents by going to the following pages and sections in our product documentation:
#TechTalkImplementation
------------------------------
Rob Dods
Analytics Implementation Specialist
TrueContext
------------------------------