Tip: You can use filters for better results
-
Latest News
-
Getting Started
-
Work Place
-
-
-
-
- About Buttons
- Action Buttons
- Schedule Tickets
- Ticket Info and COMS Buttons
- Add Parts
- Assign Partners
- Remove Tickets from the Ticket Clipboard
- Inline Skill Editing
- Create Intervention Info
- Create Intervention Reports
- Cancel Tickets
- Cancel Appointments
- Clone Tickets
- Edit Ticket Details
- Edit Privat Notes
- Report Tickets
- Close Tickets
-
-
Admin Panel
-
FMA 2 App
-
Customer Portal
Preparing a Document Template
A document template is an ordinary document file, such as a Word file (.docx), that contains placeholders in curly braces, such as {d.ticket.cne}. When Fieldcode generates a document, it replaces each placeholder with data from the ticket and produces the finished file, for example a service report showing the customer’s address, the parts used, photos and a signature.
You design the layout yourself: logo, tables, fonts and colours work exactly as in any other Word document. Fieldcode changes only the placeholders, so everything else appears in the output as you designed it.
You can build a template in Microsoft Word, LibreOffice Writer or any other word processor that saves in .docx or .odt format. Fieldcode accepts .odt, .ods, .odp, .docx, .xlsx, .pptx and .odg files, so a template can also be a spreadsheet or a presentation. This page covers word processor documents.
With placeholders, a template can:
- insert single values, such as the work order number, customer name or device serial number
- format dates and times
- pick a specific entry out of a list, such as the work time or a photo with a particular tag
- repeat a table row for every item in a list, such as the parts used
- insert images, such as photos and the customer’s signature
Each of these is explained in the sections below, followed by a fully annotated example template.
Placeholder basics
A placeholder is the path to a value in the ticket data, written between curly braces and starting with d., for example {d.ticket.device.serial}. The d stands for the data Fieldcode sends when it generates the document.
Each dot in the path steps one level deeper into the data, much like folders in a file path. {d.ticket.device.serial} reads as: in the data, open the ticket, then the device, then retrieve the serial number.
Keep these rules in mind when you type a placeholder:
- Paths are case-sensitive.
{d.ticket.device.Serial}will not find the serial number. - Empty values leave an empty space. If the ticket has no value for a field, the placeholder is removed and nothing is printed in its place.
- The value takes the placeholder’s styling. Font, size, colour and bold applied to the placeholder are applied to the value, so format the whole placeholder the same way.
- Several placeholders can share one line or cell. Normal text, spaces and line breaks between them are kept. The address block in the example template combines five placeholders:
{d.ticket.affected.addressData.address.street} {d.ticket.affected.addressData.address.number}
{d.ticket.affected.addressData.address.city}, {d.ticket.affected.addressData.address.state}
{d.ticket.affected.addressData.address.zip}Headers and footers work too. A placeholder in the header, such as the work order number, is filled in on every page.
Common fields
The table lists the paths needed most often. Copy a path into your template exactly as shown. The first rows are taken from the example template.
| Field | Path | Description |
|---|---|---|
| Tenant/Reseller company name | {d.tenantResource.name.company} | The company name of the tenant or reseller |
| Project name | {d.ticket.project.name} | The name of the ticket's project |
| CNI | {d.ticket.cni} | The ticket number assigned by Fieldcode |
| CNE | {d.ticket.cne} | A unique identifier you can assign to the ticket, such as a work order number |
| Customer name (combined) | {d.signatures.customerName} | The customer's first and last name in one value |
| Customer company | {d.ticket.affected.addressData.name.company} | The customer's company name |
| Customer first name | {d.ticket.affected.addressData.name.firstName} | The customer's first name |
| Customer last name | {d.ticket.affected.addressData.name.lastName} | The customer's last name |
| Customer street | {d.ticket.affected.addressData.address.street} | The street of the service location |
| Customer address number | {d.ticket.affected.addressData.address.number} | The house number of the service location |
| Customer city | {d.ticket.affected.addressData.address.city} | The city of the service location |
| Customer state | {d.ticket.affected.addressData.address.state} | The state of the service location |
| Customer postal code | {d.ticket.affected.addressData.address.zip} | The postal code of the service location |
| Customer phone | {d.ticket.affected.addressData.contact.phone1} | The customer's main phone number |
| Additional address information | {d.ticket.affected.addressData.address.note} | Extra details for the address, such as a floor or access notes |
| Ticket category | {d.ticket.categoryConstant.enumeration} | The ticket category, as its fixed technical value |
| Description | {d.ticket.request.description} | The description of the service request |
| Device installation date | {d.ticket.device.installationDate} | The date the device was installed. Add formatD to print it in a readable form. |
| Device type | {d.ticket.device.type} | The type of the device being serviced |
| Device serial number | {d.ticket.device.serial} | The serial number of the device being serviced |
| Device model | {d.ticket.device.model} | The model of the device being serviced |
| Engineer's work note | {d.ticket.lastIntervention.reporting.workNote} | The work note from the latest intervention report |
| Engineer name | {d.signatures.engineerName} | The name of the engineer who signed the report |
Custom fields and checklists
Custom fields created in the Custom Fields Designer can be placed in a template like any other field. In the paths above, replace customField with the Custom field name of your field.
Use the custom field name, not the label. The name is the field’s unique database name and cannot contain spaces or special characters, so it always works in a path. The label is only what users see in forms and is ignored by the template.
| Field | Object | Path | Description |
|---|---|---|---|
| Custom ticket field | Ticket | {d.ticket.customField} | The value of a custom field added to a ticket's overview tab |
| Custom device field | Device | {d.ticket.device.customField} | The value of a custom field added to a ticket's device tab |
| Custom report field | Report | {d.ticket.lastIntervention.reporting.customField} | The value of a custom field from the latest intervention report |
| Custom checklist | Checklist | {d.ticket.lastIntervention.reporting.checklist.customField} | All selected answers, separated by commas |
| Custom checklist, first item | Checklist | {d.ticket.lastIntervention.reporting.checklist.customField[0]} | The first answer of a checklist custom field, if it was selected |
For a checklist-style field, add a number in square brackets to print one specific answer.
The first item is number 0, not number 1. So [0] stands for the first answer in the checklist, [1] for the second, [2] for the third, and so on. Each placeholder prints its answer only if that answer was selected during reporting. Otherwise it prints nothing.
For example, a checklist offers the answers Filter replaced, Fan cleaned and Firmware updated. The engineer selects the first and the third. [0] prints Filter replaced, [1] prints nothing, and [2] prints Firmware updated.
To print all selected answers on one line, separated by commas, use the field without a number:
{d.ticket.lastIntervention.reporting.checklist.customField} To list the selected answers below each other instead, give each answer its own line. Because unselected answers print nothing, they would leave empty lines, so add a drop tag to each line to remove them:
{d.ticket.lastIntervention.reporting.checklist.customField[0]}{d.ticket.lastIntervention.reporting.checklist.customField[0]:ifEM:drop(p)}
{d.ticket.lastIntervention.reporting.checklist.customField[1]}{d.ticket.lastIntervention.reporting.checklist.customField[1]:ifEM:drop(p)}
{d.ticket.lastIntervention.reporting.checklist.customField[2]}{d.ticket.lastIntervention.reporting.checklist.customField[2]:ifEM:drop(p)}In the example above, this prints Filter replaced and Firmware updated directly below each other, with no gap for Fan cleaned.
Add one line for every answer the checklist offers. Press Enter at the end of each line, not Shift+Enter. The drop tag removes a whole paragraph, and lines separated with Shift+Enter belong to the same paragraph, so they would all be removed together. Dropping is explained in more detail in Hiding empty content.
Formatting dates, times, and durations
Dates and times are stored in a technical format, such as 2026-10-14T14:26:20-04:00. To print them in a readable form, add the formatD formatter to the end of the placeholder, separated by a colon:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].start:formatD('L')}The letters between the quotes are the pattern. They decide whether the date, the time or both are printed. The example template uses the same value, the start of the work time, twice: once with 'L' to print the date, and once with 'LTS' to print the time.
Common patterns
These patterns print dates and times in English (US) style, with the month before the day. The examples show a work start of 2:26:20 PM on the 14th of October 2026.
| Pattern | Prints | Example |
|---|---|---|
| L | Date, short | 10/14/2026 |
| LL | Date, written out | October 14, 2026 |
| LT | Time | 2:26 pm |
| LTS | Time with seconds | 2:26:20 pm |
| LLL | Date and time | October 14, 2026 2:26 PM |
| LLLL | Weekday, date and time | Wednesday, October 14, 2026 2:26 PM |
Fixed patterns
To print dates in another layout, such as day before month, build the pattern from these codes instead:
| Code | Meaning | Example |
|---|---|---|
| DD | Day, two digits | 14 |
| MM | Month, two digits | 10 |
| MMMM | Month name | October |
| YYYY | Year | 2026 |
| dddd | Weekday | Wednesday |
| HH | Hour, 24-hour clock | 14 |
| mm | Minutes | 26 |
Combine the codes with any separator you like. For example, formatD('DD.MM.YYYY') prints 14.10.2026 and formatD('HH:mm') prints 14:26.
After uploading, check the dates and times in a test document against the ticket. This confirms they appear in the expected time zone and layout. The time zone is set when you upload the template, as described in Saving, uploading and testing.
Durations
Durations, such as the work time and drive time, are stored as a number of seconds. A work time of 1 hour, 30 minutes and 30 seconds is stored as 5430. To print a duration in minutes, hours, or as a clock time, add calculation formatters to the placeholder.
The examples use the work time. For the drive time, replace WORKTIME with DRIVE.
Seconds, for example 5430:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration}Minutes, for example 91:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:div(60):round(0)}Hours, for example 2:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:div(3600):round(0)}Hours:Minutes, for example 01:30. Two placeholders with a colon between them:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:div(3600):floor():padl(2,'0')}:{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:mod(3600):div(60):floor():padl(2,'0')}Hours:Minutes:Seconds, for example 01:30:30. Three placeholders with a colon between each:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:div(3600):floor():padl(2,'0')}:{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:mod(3600):div(60):floor():padl(2,'0')}:{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].duration:mod(60):floor():padl(2,'0')} The clock-time formats combine two or three placeholders, one for each part, separated by a colon typed as normal text. Each formatter does one calculation, from left to right:
| Formatter | What it does |
|---|---|
| div(60) | Divides by 60, turning seconds into minutes. div(3600) turns seconds into hours. |
| mod(3600) | Keeps only what is left over after full hours. mod(60) keeps what is left over after full minutes. |
| round(0) | Rounds to a whole number, up or down. |
| floor() | Rounds down to a whole number, so 1.5 hours counts as 1 full hour. |
| padl(2,'0') | Adds a leading zero to single digits, so 1 becomes 01. |
round(0) rounds to the nearest whole number, so 1 hour and 30 minutes prints as 2 hours. Use the clock-time formats when the exact time matters.
Filtering data
Some data is a list of entries rather than a single value. A filter in square brackets picks one entry from the list. For example, an intervention report stores its times as a list of durations, with one entry for drive time and one for work time:
durations
├─ entry: constant.enumeration = DRIVE, duration = 900
└─ entry: constant.enumeration = WORKTIME, start = 2026-10-14T14:26:20, end = 2026-10-14T15:26:20To print the start of the work time, add a filter directly after the list name:
{d.ticket.lastIntervention.reporting.durations[constant.enumeration='WORKTIME'].start}This reads as: from the durations, take the entry whose constant.enumeration is WORKTIME, then print its start. Everything after the closing bracket continues the path inside that entry, and formatters such as :formatD('L') still go at the very end.
Word may change ' into curly quotes (‘ ’) as you type, and a filter with curly quotes matches nothing. If Word changes a quote, press Ctrl+Z straight away to undo it, or paste the whole placeholder from a plain-text editor.
Keep these rules in mind:
- Values are case-sensitive.
'WORKTIME'matches,'Worktime'does not. - Filter on the enumeration, not the display text. Each entry also has a
displayText, such as “Worktime”, but it can change with the language. Theenumerationvalue stays the same. - No match prints nothing. If the ticket has no matching entry, the placeholder is removed and the space stays empty.
- Several matches print the first one. Use a value that identifies exactly one entry.
- Position works too.
[0]picks the first entry in a list,[1]the second, as with checklist answers.
Common filters
| List | Filter | Picks |
|---|---|---|
| durations | [constant.enumeration='WORKTIME'] | The work time, with start and end |
| durations | [constant.enumeration='DRIVE'] | The drive time |
| attachments | [tags.documentTags='ATTACHMENT_TAG'] | The attachment with that tag, such as a before or after photo |
Attachment filters pick an attachment by the document tag it was given in Fieldcode. Replace ATTACHMENT_TAG with one of your own tags. You create these in the Admin panel under Value Sets, in the value set called Attachment type. Use the tag in the filter exactly as it is stored there, including capital letters and underscores.
How to place a photo in the template is covered in Images and signatures.
Repeating rows
A parts table prints one row for every part used on the ticket, however many there are. You build it once with two template rows, and Fieldcode repeats them for each part.
| Part number | Name | Quantity | Status |
|---|---|---|---|
| {d.items[i].partNumber} | {d.items[i].name} | {d.items[i].quantity} | {d.items[i].status} |
| {d.items[i+1].partNumber} | {d.items[i+1].name} | {d.items[i+1].quantity} | {d.items[i+1].status} |
- The
[i]row is the pattern for each part. It is repeated once per part, with that part’s values. - The
[i+1]row marks where the repetition ends. It is removed from the finished document. - The header row has no placeholders, so it appears once at the top.
With two parts on the ticket, the table above prints:
| Part number | Name | Quantity | Status |
|---|---|---|---|
| PSU-650 | Power supply 650W | 1 | Used |
| CBL-SATA | SATA cable | 2 | Used |
How to add a parts table
- Insert a table with one header row and two more rows.
- Type the column titles in the header row.
- In the second row, type a placeholder in each column using
[i], such as{d.items[i].name}. - Copy the second row into the third row and change every
[i]to[i+1].
Keep these rules in mind:
- Keep the two rows together. The
[i]and[i+1]rows must sit directly below each other, with the same columns. - Use the index in every placeholder. Each placeholder in the two rows needs
[i]or[i+1], otherwise it is not repeated. - Style the
[i]row. Its fonts, borders and shading are applied to every printed row. Styling in the[i+1]row does not appear. - No parts, no rows. If no parts were used, both rows are removed and only the header row remains.
Images and signatures
Images work differently from text. Instead of typing the placeholder into the page, you insert a stand-in picture and put the placeholder in that picture’s Alt Text. When the document is generated, Fieldcode swaps the stand-in for the real photo or signature, in the same position and at the same size.
How to add a photo
- Insert any picture where the photo should appear. A plain grey square works well, because it is easy to recognise as a stand-in.
- Resize the picture to the space the photo may take up. The real photo is fitted inside this frame.
- Right-click the picture and select Edit Alt Text (View Alt Text in some versions of Word).
- Make sure Mark as decorative is not ticked. Word clears the Alt Text of decorative pictures.
- Paste the placeholder into the Alt Text field, for example:
{d.attachments[tags.documentTags='ATTACHMENT_TAG'].source:imageFit(contain)}Replace ATTACHMENT_TAG with the tag of the photo you want, as explained in Filtering data. The :imageFit(contain) at the end scales the photo to fit inside the frame without stretching it or cutting anything off.
In other word processors, look for the picture’s alternative text or description field.
Putting each stand-in picture in its own table cell keeps photos aligned and stops them from moving other content when they are swapped in.
How to add a signature
Signatures are added the same way: insert a stand-in picture where the signature should appear, size it, and paste this placeholder into its Alt Text:
{d.signatures.signaturesV2.customerSignature.data:prepend('data:image/png;base64,'):imageFit(contain)}The signature is stored as raw image data. The :prepend('data:image/png;base64,') part adds the label that marks it as a PNG image, so it can be displayed. Copy the placeholder exactly as shown.
To print the signer’s name under the signature, add a text placeholder such as {d.signatures.customerName} below the picture. The engineer’s name is available as {d.signatures.engineerName}.
If a photo or signature is missing, the stand-in picture shows an empty frame with a cross. To remove it instead, see Hiding empty content.
Hiding empty content
An empty placeholder prints nothing, but its label, table row or picture frame stays in the document. A drop tag removes that element when the value is empty:
{d.ticket.lastIntervention.reporting.workNote:ifEM:drop(row)}This reads as: if the work note is empty (ifEM), drop the table row (drop(row)). The drop tag prints nothing itself. Place it anywhere inside the element it should remove.
What you can drop
| Element | Removes | Where to put the tag |
|---|---|---|
| p | A paragraph | Anywhere in the paragraph |
| row | A table row | In any cell of the row |
| col | A table column | In one cell of the column |
| table | A whole table | In any cell of the table |
| img | A picture | In the picture's Alt Text, after the image placeholder |
Dropping a paragraph
To remove a line with a label when its value is empty, add the drop tag at the end of the line:
Customer company: {d.ticket.affected.addressData.name.company}{d.ticket.affected.addressData.name.company:ifEM:drop(p)} Dropping table rows
To remove a table row when its value is empty, add the drop tag to any cell in the row. In the example template, the Engineer’s Notes row disappears when there is no work note:
| Engineer's Notes: | {d.ticket.lastIntervention.reporting.workNote}{d.ticket.lastIntervention.reporting.workNote:ifEM:drop(row)} |
Add a number to drop several rows at once. drop(row, 2) removes the row with the tag and the row below it. Placed in the Parts title row, this tag removes the title and the column headers when no parts were used:
{d.items:len:ifEQ(0):drop(row, 2)}Here len counts the parts and ifEQ(0) checks whether there are none.
Dropping pictures and signatures
If a ticket has no photo with the tag, or no signature, the stand-in picture is replaced by an empty frame with a cross through it. To remove the picture instead, add a drop tag to the same Alt Text, directly after the image placeholder:
{d.attachments[tags.documentTags='ATTACHMENT_TAG'].source:imageFit(contain)}{d.attachments[tags.documentTags='ATTACHMENT_TAG'].source:ifEM:drop(img)}Only that picture is removed, so other photos in the same table row stay in place.
For a signature, check the signature data without the prepend part:
{d.signatures.signaturesV2.customerSignature.data:prepend('data:image/png;base64,'):imageFit(contain)}{d.signatures.signaturesV2.customerSignature.data:ifEM:drop(img)}This matters because prepend adds text to the value, so a check that includes it never sees the signature as empty.
Rules
- Put the tag inside the element. A drop tag only removes the paragraph, row, table or picture it sits in.
- End each line with Enter, not Shift+Enter.
drop(p)removes a whole paragraph. Lines separated with Shift+Enter belong to the same paragraph, so they are all removed together. - Check the raw value. Leave out formatters such as
prependorformatDin the check, so an empty value is recognised as empty. An image formatter such asimageFitin the check can even stop the template from loading. keepworks the other way.keepinstead ofdropkeeps the element only when the check is true, and removes it otherwise.
Known limitations
ODStemplates only support dropping/keepingcol,row,img, andsheet.XLSXtemplates only support dropping/keepingrowandcol.PPTXtemplates only support dropping/keepingcol,row,img,p,shape,chart, andtable.HTMLtemplates only support dropping/keepingtable,col,row,p,div, andspan.
Saving, uploading and, testing
Save the template as a .docx file (Word) or an .odt file (LibreOffice Writer), then upload it in the Admin panel under Projects and More → Templates. The full upload steps are described in Template Settings.
Three settings in the document template form affect how your template is filled:
- Object – The object the document is created from. For a service report like the example template, select the ticket.
- Format – The file type of the finished document. The default is PDF.
- Timezone – The time zone used for dates and times. For ticket documents, the default is the ticket’s time zone.
How to test a template
- Upload the template and click Save.
- Check the preview in the document template form. Select a ticket from the list of most recent tickets, or use the search to find a specific one. For a report of completed work, choose a ticket that has already been reported, with the status RESOLVED or CLOSED, so that the report data is filled in.
- Test with a ticket that has all the data the template uses, such as parts, tagged photos, a signature and logged work time. A test ticket works well for this.
- Test again with a ticket that is missing some of that data, to check that empty content is hidden as intended.
In each test document, check that:
- every placeholder has been replaced, and none appears as plain text
- dates and times show the right values, in the right time zone
- photos and signatures appear in the right frames
- the parts table shows one row per part, without the
[i+1]row - empty rows, paragraphs and pictures are removed where you added drop tags
If something is wrong, correct the template in Word, upload it again and repeat the test.
Common mistakes and troubleshooting
Most problems come from a placeholder that does not exactly match the data. Find the symptom in the table, then check the likely causes.
| Problem | Likely cause | Fix |
|---|---|---|
| A placeholder appears as plain text in the document | A missing or extra curly brace, a typo in d., or a tag that Fieldcode does not support | Compare the placeholder with the examples on this page, character by character. Remove tags that are not described here. |
| A value stays empty | The path is wrong, uses the wrong capital letters, or the ticket has no value for that field | Copy the path from the field tables. Check in Fieldcode that the ticket actually has the value. |
| A filtered value stays empty | The filter contains curly quotes, or the value in quotes does not match exactly | Retype the quotes as straight quotes. Check the spelling and capital letters of the value. |
| The template is refused when you upload it | Broken placeholder syntax, such as a missing closing brace, imageFit inside a drop check, or a feature that Fieldcode does not support | Remove recently added placeholders one at a time and upload again to find the one causing the problem. |
| A photo or signature shows an empty frame with a cross | The ticket has no attachment with that tag, or no signature | Add a drop tag, as described in Hiding empty content. Check the tag name in the Attachment type value set. |
| Times are off by a few hours | The time zone setting of the document template | Check the Timezone setting in the document template form. |
| The parts table shows an extra or empty row | The [i] and [i+1] rows are not directly below each other, or a placeholder is missing its index | Place the two rows together and add [i] or [i+1] to every placeholder in them. |
| Text formatting looks different from the template | Only part of the placeholder was formatted | Select the whole placeholder, including the braces, and apply the formatting again. |
Word may change ' into curly quotes (‘ ’) as you type, and a filter with curly quotes matches nothing. If Word changes a quote, press Ctrl+Z straight away to undo it, or paste the whole placeholder from a plain-text editor.
If a placeholder still does not work, delete it and type it again in one go. Editing a placeholder in several steps can leave hidden formatting inside it.
Example template
The example template is a complete service report for Swift Tech Services, a fictional company. It uses every technique described on this page, so you can download it, upload it to Fieldcode and see how each part works with your own tickets.
The report is built from one table, divided into the parts below. Each part links to the section of this page that explains it.
- Work Order – The work order number, as a single placeholder. See Placeholder basics.
- Logo – An ordinary picture with no placeholder, so it appears unchanged in every report.
- Service Location – The customer’s name, company and address. The address combines several placeholders on three lines. See Placeholder basics.
- Service Request – The description of the request, as a single placeholder.
- Device Details – The device type and serial number, as single placeholders.
- Parts – One row for every part used, built with the
[i]and[i+1]rows. See Repeating rows. - Action Taken – The date, work start and work end. A filter picks the work time, and
formatDprints the date or time. See Filtering data and Formatting dates, times and durations. - Engineer – The engineer’s name and work note, as single placeholders.
- Photos – The before, after and additional photos, with placeholders in the pictures’ Alt Text and drop tags for missing photos. See Images and signatures and Hiding empty content.
- Signatures – The engineer’s and customer’s names, and the customer’s signature as a picture with a drop tag. See Images and signatures.
Adapting the example
To turn the example into a template for your own company:
- Replace the logo with your own. Right-click it and select Change Picture.
- Change the photo tags in the Alt Text, such as
BEFORE_PHOTO, to the tags in your Attachment type value set. - Remove the parts you do not need, or add fields from the tables on this page.
- Upload the template and test it, as described in Saving, uploading, and testing.
0 out of 5 stars
| 5 Stars | 0% | |
| 4 Stars | 0% | |
| 3 Stars | 0% | |
| 2 Stars | 0% | |
| 1 Stars | 0% |
