Introduction
- What is Creodocs?
- Why Use LaTeX?
Bulk Document Creation
- Introduction
- The Template
- Populating Content
- Creating Documents
Complex Documents
- Introduction
- The Template
- Populating Content
- Creating Document
What is Creodocs?
Creodocs is a resource to promote the use of LaTeX to automate document production, primarily in a business setting. If you have a need to produce PDF documents programatically, consider reading through the resources here to see whether LaTeX may be a good fit.
Creodocs is operated by one person alongside LaTeXTypesetting.com and LaTeXTemplates.com as part of the same small business, Creodocs Limited. The resources provided here are free and will help you get started, but if you need support for any part of the process, the services offered at LaTeXTypesetting.com will be useful to create your document templates and write the automation code to populate them from your data sources.
Why Use LaTeX?
What Is LaTeX?
LaTeX is a document preparation system originally released in 1983 by Leslie Lamport. It is built on top of the TeX typesetting system, released in 1978 by Donald Knuth. LaTeX is widely used in academia and especially for mathematics, but is not commonly used outside these fields due to the relatively steep learning curve for those unfamiliar with text-based markup languages (such as HTML).
In LaTeX, a document design is defined using commands in plain text, instead of using a point-and-click graphical user interface such as Microsoft Word. This plain text code is then compiled (typeset) to produce the document in PDF format. While this approach is too cumbersome for most people to learn, it has immense benefits for the resulting documents and for those who are technically inclined enough to learn it.
Why Use LaTeX for Automated Document Production?
Typography The act of typesetting with LaTeX optimally arranges text on the page using best-practices typographic rules and algorithms. This influences such things as the spacing between words, hyphenation, how fonts are utilised and justification. Practically, resulting documents are more beautiful and feel nicer to read.
Powerful LaTeX has the ability to implement virtually any design through the use of a wide diversity of extensions (called packages). Combined with the ability to typeset mathematics, symbols and custom fonts with presets for any language, there are few document elements that can't be produced.
Programmatic LaTeX is programmatic in nature, which means variables, loops, if statements and switches can be readily utilised. This is particularly useful for Creodocs where small user inputs can be made to have big impacts on the document produced. For example, a single boolean (true/false) switch in the LaTeX code can have conditional impacts in many places in the document, such as whether tax should be calculated in an invoice, and whether the corresponding rows and columns for tax totals should be shown in the invoice table. Since LaTeX documents are plain text, templates are amenable to version control to easily track changes over time.
Free and Open Source LaTeX itself, and almost all LaTeX packages used to add functionality to documents, are free and open source, licensed under the LPPL (LaTeX Project Public License). This means there is no subscription to pay or forced upgrades over time to justify additional payments. Further, there is a large body of code examples, questions with answers and community spirit to LaTeX, opposed to the one-sided nature of a commercial product.
Longevity Documents produced with LaTeX are usually compilable years, or even decades, after they are written. Yearly releases of LaTeX rarely break backwards compatibility and packages tend to receive infrequent updates that don't often interfere with other packages. For extra security, the entirety of LaTeX is very amenable to running in a virtual machine or Docker container to ensure long term stability.
What is Bulk Document Creation?
Bulk document creation is the act of creating one to many documents at once with a very similar layout. An example may be an Internet Service Provider (ISP) producing PDF invoices at midnight each night for archiving on their systems and sending out to customers by email. A key feature of bulk documents is their rigid structure and content, with strictly defined areas where document content can change. Continuing with our ISP invoice example, the PDF invoices need to show each customer's account number, the date, their plan, usage information and total cost due, which all differ from invoice to invoice. However, company logos and information, along with legal disclaimers, are static and do not change from invoice to invoice.
Our goal with bulk document creation is to define a strict template for the document we want to produce, with fixed variables for dynamic content that we want to inject into the template. We then want to replace these fixed variables with document content from an external source (such as a database) and compile the template to produce a PDF. We may want to run this on demand just once, or we may want to produce thousands of documents in parallel.
Creating a Bulk Template
Continuing with our ISP invoice example, we will use the Minimal Invoice LaTeX template as the starting point in our bulk document creation workflow. Note that this template is not licensed for commercial use and cannot be used in this way within your company. We are using it here for example/development purposes only. For commercial use, you will need to create your own internal LaTeX template or have one created for you by LaTeX Typesetting.
Starting Template
The starting point for automation is a fully-functional LaTeX document which can be compiled independently and contains example content. This allows us to tweak the template for automation as needed and manually enter edge-case content to see how the template responds. Our starting template already has example content, but let's modify it to suit an ISP producing monthly invoices for customers. We end up with the following:
Download Pre-Automation Template Code
Adding Dynamic Variables
Our invoice template is currently composed of static example content. To be able to customize it for each customer, we need to specify the locations of dynamic content using automation hooks. Automation hooks are similar to variables in programming. They have unique names that correspond to a single piece of information (e.g. customer number), and they may be used in only one place or repeated in multiple places in a document. The syntax of the variables doesn't matter, as long as the format is something that wouldn't naturally occur in any document you create. For example, a dollar sign (e.g. $variable_name
) used in many programming languages is likely a bad idea, because the code of many LaTeX documents will feature dollar signs with text immediately after them so you may end up with a clash.
For our dynamic variables, we will use three pipe characters, followed by the variable name in all capitals, followed by another three pipe characters, e.g. |||VARNAME|||
. Pipe characters are not special symbols in LaTeX, unlike dollar signs which surround math environments, so are typeset neatly in the document without causing compilation problems. After replacing static example content with variables, we end up with the following:
Download Automated Template Code
The decision for what content should be static and/or handled by LaTeX vs. dynamic and populated automatically will differ for each document. In our case, six variables have been added for the account number, invoice number, customer name, customer address (2 lines) and invoice items. Notice that the invoice date and due date have been left to LaTeX to populate using the \today
command and automatic calculation of the due date 14 days from when the document is typeset. Notice also that the majority of the invoice has remained untouched because it is composed of company/payment information that we want displayed on all invoices.
The last thing to note before we move on to populating our variables is that variables can correspond to anything. For example, our |||ACCOUNTNUMBER|||
variable will always correspond to an account nunber with a fixed number of digits. This means we only need to ensure the places where this variable are used in the template can handle that length of content. You may notice, however, that we have replaced the two invoice table lines in the pre-automation template with a single variable |||INVOICEITEMS|||
. This means when we go to replace this variable, we will need to output the correct LaTeX syntax for however many lines the current invoice has.
Populating Bulk Document Content
In the previous section, we started with an existing LaTeX template and modified it to our business needs, then added dynamic variables to indicate where we want to automatically inject dynamic content. We now move on to replacing the dynamic variables with content from a standard source.
Process
One of the major advantages of using LaTeX for document automation is that LaTeX is plain text. This means all we have to do to populate our automated template is iterate over all the documents we want to produce and replace the variables with real content. Thus, the requirements are:
- Read in the automated LaTeX template file(s) into memory.
- Read in the source data for all the documents we want to produce.
- Iterate over all documents and for each one replace each variable in the LaTeX code with the corresponding content.
- Output the populated LaTeX code to a new file ready for typesetting.
Virtually every programming language is capable of reading and writing text files, replacing content in memory using regular expressions and iterating over a data structure of document data in a loop. Scripting languages are particularly easy to use and we will use Python for our examples because it is currently the most popular scripting language.
Document Data
Before we can populate the dynamic variables, we need example document data. This is a step where every business will widely differ in how the data for documents are stored and extracted. Typically, data for invoices would live in a database and be extracted in a standard format using a database query. Data storage and retrieval are outside the scope of this tutorial, so here we will use a simple tab-separated values (TSV) file where each line corresponds to a separate document and columns store the data for each variable. Here are the first 5 documents of the data file:
ACCOUNTNUMBER INVOICENUMBER CUSTOMERNAME CUSTOMERADDR1 CUSTOMERADDR2 INVOICEITEMS
8109182 15235-735 Mariah Wolf 96 S. Brown Street Aberdeen, SD 57401 Unlimited 300 Mbps Internet,1,50
7870918 92965-417 Jase Ibarra 8834 Miller Ave. Willoughby, OH 44094 Unlimited 500 Mbps Internet,1,50
1423747 43555-576 Madilynn Castaneda 360 South Vernon Drive Middleburg, FL 32068 Unlimited 500 Mbps Internet,1,50
1158708 72385-610 Collin Gould 23 Glen Creek St. Euless, TX 76039 Unlimited 300 Mbps Internet,1,50
1969990 70161-653 Violeta Vincent 29 Shirley St. New Kensington, PA 15068 Unlimited 500 Mbps Internet,1,50
More Coming Soon...
Creating Bulk Documents
Coming soon...
What is Complex Document Creation?
Complex document creation is the act of creating single documents with content that extensively differs from document to document, but with a fixed layout. Complex documents are usually longer and an example may be monthly sales reports for a company showing the latest figures, projections and providing extensive breakdowns per sector. The key feature of complex documents is that the amount of content within them is flexible and diverse. Continuing with our example of monthly sales reports, we may wish to add a new major section one month for an emerging opportunity, which itself will contain subsections, graphs, tables and several pages of text. Despite this flexibility, we want all of our sales reports to feature the same layout, title page, headers/footers and summary information on the first page.
Our goal with complex document creation is to define the general layout of the document in a template, such as the fonts, margins, headers/footers and section styling, and to allow populating the main body of the template with any amount of content the user wishes to input. The template will have a mixture of rigid content containing several fixed dynamic variables, such as the title page, with a fluid main body. We want to allow users to populate the main body of the template with a standard hierarchy of content, without requiring them to learn LaTeX and allowing them to modify the overall design of the document. We want the document to be compilable iteratively as the main body is fleshed out, to eventually end up with a single final PDF version for distribution and/or archiving.
Creating a Complex Template
Coming soon...
Populating Complex Document Content
Coming soon...
Creating Complex Documents
Coming soon...
Creating a Creodocs Template
This page contains a guide for how to create a new document template to appear in your Workshop, hereafter referred to as a Creodocs template, or just template. Creating a template for Creodocs requires three distinct steps:
- Writing the LaTeX code that creates the document layout
- Defining user inputs and groups in the LaTeX code
- Specifying how inputs should be populated by users on Creodocs
This guide will walk through the entire process of creating a basic template. The goal is to introduce you to the process and leave you equipped to create complex templates, such as the default documents available to all users of Creodocs.
Step 1. Creating a LaTeX Document
Creodocs uses LaTeX to define the structure and layout of all documents. It is the compilation (or typesetting) of LaTeX code that gives rise to the PDF documents produced by Creodocs. This makes the underlying LaTeX code the most important part of a Creodocs template. This guide assumes you are familiar with LaTeX and comfortable with using it to create documents. If not, there are a multitude of free guides available on how to use LaTeX, or you can use the Creodocs Template Creation Service to commission a LaTeX template to your specifications.
For the purpose of this guide, let's pretend we are a real estate company with multiple property managers who need to send official letters to tenants notifying them that an inspection of their rental property is due. We first need to create a LaTeX document that lays out the letter and includes company information and the letter body.
Create a file called main.tex in a new folder and add the smallest possible amount of LaTeX code required to generate a document:
\documentclass{letter}
\begin{document}
hello, world
\end{document}
When we compile this with pdflatex we produce the following as a PDF document:
All Creodocs templates must contain a file called main.tex. This is the file that will be compiled, but other .tex files can be present, such as when using \input{}
to include LaTeX code in the main template file.
Let's now create the entire letter with everything we need to communicate to tenants. At this point, it's best to write the LaTeX code as if we are just sending one instance of this document by entering fake information throughout. This will help us in the next step when we need to determine which parts of the document will be populated by users on Creodocs. Our final letter might look something like this:
\documentclass{letter}
\usepackage{palatino}
\signature{Terrence Black \\ \textit{Property Manager} \\ Impact Real Estate}
\address{John Smith \\ Apartment 1315 \\ 126 Albert Street \\ Auckland 1010}
\date{}
\begin{document}
\begin{letter}{Impact Real Estate \\ 72 Queen Street \\ Auckland 1010}
\opening{{\Large\textbf{Notice of Inspection}} \\\\ Dear John Smith,}
This letter is to notify you that I will be conducting a routine inspection of your apartment on \textbf{March 15th, between 2pm-5pm}. The previous inspection was carried out on September 18th and as per your tenancy contract, biannual inspections must be carried out to continue your tenancy.
I will be checking for the following:
\begin{enumerate}
\item{Damage to the property}
\item{Functionality of smoke detectors}
\item{Carpet cleanliness}
\item{Any other maintenance issues}
\end{enumerate}
If you are unavailable on the date listed, please leave a key with the concierge in my name and I will carry out the inspection alone. Please note that I may need to take photographs of any damage found for documentation purposes.
Should you have any questions or concerns, please contact me directly by email at terrence@impactrealestate.nz.
\closing{Yours sincerely,}
\end{letter}
\end{document}
This is what this letter should look like when we compile the code with pdflatex:
Step 2. Defining User Inputs in the LaTeX Document
We made a LaTeX document for the letter we want to send tenants notifying them of upcoming inspections. We have populated it with all the information we expect to send and filled it with dummy data for a fake tenant and property manager. Our next task is to go through the LaTeX code and add special syntax where Creodocs can insert data supplied by users of this template. Each piece of information we want template users to be able to supply is called a variable.
Variables are added inline to our LaTeX code and have the syntax of [[[VARNAME]]]
. The text within the square brackets is the variable identifier (ID) and can only contain upper case letters and numbers with a length of 1 to 30 characters. These IDs should be succinct and descriptive of the purpose of each variable. These variable identifiers are not seen by template users.
Let's go through our letter and replace all occurrences of information we want users of the template to enter with Creodocs variable IDs. This will require carefully thinking about all potential users of the template and what their needs might be, now and in the future. The resulting code is seen below with changes in bold:
\documentclass{letter}
\usepackage{palatino}
\signature{[[[SENDERNAME]]] \\ \textit{[[[SENDERJOBTITLE]]]} \\ Impact Real Estate}
\address{[[[TENANTNAME]]] \\ [[[TENANTADDR1]]] \\ [[[TENANTADDR2]]] \\ [[[TENANTADDR3]]]}
\date{}
\begin{document}
\begin{letter}{Impact Real Estate \\ 72 Queen Street \\ Auckland 1010}
\opening{{\Large\textbf{Notice of Inspection}} \\\\ Dear [[[TENANTNAME]]],}
This letter is to notify you that I will be conducting a routine inspection of your apartment on \textbf{[[[INSPECTIONTIME]]]}. The previous inspection was carried out on [[[PREVINSPECTIONTIME]]] and as per your tenancy contract, biannual inspections must be carried out to continue your tenancy.
I will be checking for the following:
\begin{enumerate}
\item{Damage to the property}
\item{Functionality of smoke detectors}
\item{Carpet cleanliness}
\item{Any other maintenance issues}
\end{enumerate}
[[[EXTRANOTES]]] Please note that I may need to take photographs of any damage found for documentation purposes.
Should you have any questions or concerns, please contact me directly [[[SENDERCONTACTINFO]]].
\closing{Yours sincerely,}
\end{letter}
\end{document}
If we try to compile the new code with pdflatex, we find that it no longer compiles without errors due to the square brackets. If you need to see what it looks like, find and replace [[[
and ]]]
with nothing through the template code and it will compile again. This will show you where the Creodocs variable IDs have been added:
You'll notice some information from our first draft has been kept while other information has been made into variables. This is because some information in the template will never change, while other information needs to change each time one of these letters is created. For example, the company address of Impact Real Estate won't change very often so this is safe to hard code, while the tenant's address will change every time. Often times there will be grey areas where information will usually not change, but it could, so it might be useful to make it into a variable. An example of this is the EXTRANOTES
variable, where we initially mentioned leaving a key with the concierge if the tenant is not available, but what if the tenant's apartment building doesn't have a concierge? Likewise, while the sender of the letter will usually be a property manager, some property managers may have assistants and the company could have a mixture of managers with Senior Property Manager job titles, so it's best to allow the sender's job title to change.
The same Creodocs variable ID can be used within the LaTeX code multiple times. This is powerful when we need to output the same piece of information in multiple places in the resulting document. An example of this is theTENANTNAME
variable which is used at the top of the letter with the tenant's address and for addressing the letter to the tenant withDear TENANTNAME,
.
Looking through our letter again, we can see that the tenant's address is split across 3 variables. What if we need to enter a suburb on a 4th line or we want to write the apartment number inline with the street number so the address only takes up 2 lines? For this, we can use variable multi-groups.
Variable multi-groups allow you to specify that some LaTeX code containing one or more variable IDs can be inserted into the document multiple times. Multi-groups are enclosed in 3 pipe characters (|||
) and must contain one or more variable IDs specified as usual within square brackets, e.g.|||[[[TENANTADDR]]]|||
. Groups can span multiple lines of LaTeX code and contain any other LaTeX code. If more than one set of data is submitted by a user for a multi-group, all code within the multi-group specification is duplicated one after another prior to document creation.
Let's make it so the users of our template on Creodocs can specify any number of lines for the tenant's address by replacing the 3 tenant address variables with 1 and putting it into a multi-group (change in bold):
\documentclass{letter}
\usepackage{palatino}
\signature{[[[SENDERNAME]]] \\ \textit{[[[SENDERJOBTITLE]]]} \\ Impact Real Estate}
\address{[[[TENANTNAME]]] |||\\ [[[TENANTADDR]]]|||}
\date{}
\begin{document}
\begin{letter}{Impact Real Estate \\ 72 Queen Street \\ Auckland 1010}
\opening{{\Large\textbf{Notice of Inspection}} \\\\ Dear [[[TENANTNAME]]],}
This letter is to notify you that I will be conducting a routine inspection of your apartment on \textbf{[[[INSPECTIONTIME]]]}. The previous inspection was carried out on [[[PREVINSPECTIONTIME]]] and as per your tenancy contract, biannual inspections must be carried out to continue your tenancy.
I will be checking for the following:
\begin{enumerate}
\item{Damage to the property}
\item{Functionality of smoke detectors}
\item{Carpet cleanliness}
\item{Any other maintenance issues}
\end{enumerate}
[[[EXTRANOTES]]] Please note that I may need to take photographs of any damage found for documentation purposes.
Should you have any questions or concerns, please contact me directly [[[SENDERCONTACTINFO]]].
\closing{Yours sincerely,}
\end{letter}
\end{document}
Notice how the multi-group contains \\
before the variable ID. This is because Creodocs duplicates all code inside the group delimiters and in this case we want each line of the address to be output on a new line, so we need to include the code that will do this inside the group. Creating groups can be tricky as it requires thinking about what will happen to the code you enclose in the group once it is duplicated. For example, in this case we could have naively specified the group as \address{[[[TENANTNAME]]] \\ |||[[[TENANTADDR]]] \\|||}
and this would compile fine, but there would always be an extra newline at the end of the tenant's address block which is not what we intended with the design.
Step 3. Defining Template User Interaction on Creodocs
We have now created our LaTeX document and decided which parts of it we will expose on Creodocs for users to populate. All that remains is to describe our document to Creodocs by specifying template, variable and group information in a format that it will understand. This will allow it to display the template and variables to users in a clean and helpful way, and restrict the types and amounts of information that can be submitted for each variable. This definition is done in a creodocs.json file that should be in the same directory as the LaTeX code.
All Creodocs templates must contain a creodocs.json file. This file specifies template information, acts as the key for variables in the LaTeX code and groups variables for display to users on Creodocs. The data within the file is in JSON format.
It's a good idea to familiarise yourself with the JSON format if you haven't come across it before. Broadly, it's a hierarchical format of keys and values that supports named and unnamed lists (or arrays) of information. The creodocs.json file is composed of 3 top-level sections. The first contains information about the whole template, the second defines each variable and the third specifies how variables should be grouped for display on Creodocs. Let's take a look at a basic creodocs.json file with 2 variables and groups:
{
"template": {
"name": "Template Name",
"description": "Template Description",
"engine": "pdflatex",
"version": "1.0.0",
"contact": "email@company.com"
},
"variables": {
"VARNAME": {
"name": "Variable Name",
"description": "What does this variable do in the document?",
"type": "string",
"max_length": 50,
"demo_value": "VARNAME",
"default_value": "Testing",
"required": true
},
"NUMBER": {
"name": "Number Variable",
"description": "What does this variable do in the document?",
"type": "integer",
"max_length": 4,
"demo_value": "NUMBER",
"default_value": "100",
"required": false
}
},
"groups": {
"Group Name": {
"variables": [ "VARNAME" ],
"multi": true,
"required": true
},
"Another Group":
"variables": [ "NUMBER" ],
"multi": false,
"required": true
}
}
}
Within each of the top-level sections, there are one or more levels of keys and values that define the information required to add the template to Creodocs. The first template
section contains overall information about the template such as its name and description which will appear in the Workshop, but also what TeX engine should be used to compile it, the current version of the template and who users should contact for changes and support. The variables
section contains a list of variables where the keys are the variable IDs used in the LaTeX code. Within each variable ID is information for how users will interact with the variable and includes how it should be displayed (name
and description
), what kind of data it can take (type
), how much data can it take (max_length
), do users have to specify it (required
) and is there a default value that should be used in different situations (demo_value
and default_value
). Finally, the groups
section combines variables into logical groups so they can be displayed together and specifies whether the variables in each group can be added by users once or many times. For a full description of the structure of this file and all the options available, please refer to the Complete Template Specifications section.
We can now follow the format of the example creodocs.json file and refer to the advanced documentation to create a creodocs.json file for our letter template:
{
"template": {
"name": "Notice of Inspection Letter",
"description": "For notifying tenants of an upcoming property inspection",
"engine": "pdflatex",
"version": "1.0.0",
"contact": "arthur@impactrealestate.nz"
},
"variables": {
"SENDERNAME": {
"name": "Sender Name",
"description": "The name of the property manager or the person sending the letter on their behalf.",
"type": "string",
"max_length": 100,
"demo_value": "SENDERNAME",
"default_value": "",
"required": true
},
"SENDERJOBTITLE": {
"name": "Sender Job Title",
"description": "The job title of the person sending the letter.",
"type": "string",
"max_length": 50,
"demo_value": "SENDERJOBTITLE",
"default_value": "Property Manager",
"required": true
},
"TENANTNAME": {
"name": "Tenant Name",
"description": "",
"type": "string",
"max_length": 100,
"demo_value": "TENANTNAME",
"default_value": "",
"required": true
},
"TENANTADDR": {
"name": "Tenant Address",
"description": "The mailing address of the tenant.",
"type": "string",
"max_length": 100,
"demo_value": "TENANTADDR",
"default_value": "",
"required": true
},
"INSPECTIONTIME": {
"name": "Inspection Time",
"description": "The day/time when the inspection will take place.",
"type": "string",
"max_length": 100,
"demo_value": "INSPECTIONTIME",
"default_value": "",
"required": true
},
"PREVINSPECTIONTIME": {
"name": "Previous Inspection Date",
"description": "The date of the last inspection of the property.",
"type": "string",
"max_length": 50,
"demo_value": "PREVINSPECTIONTIME",
"default_value": "",
"required": true
},
"EXTRANOTES": {
"name": "Extra Notes",
"description": "Any other notes or requirements for the inspection, such as where to leave the key if the tenant isn't home.",
"type": "string",
"max_length": 500,
"demo_value": "EXTRANOTES",
"default_value": "If you are unavailable on the date listed, please leave a key with the concierge in my name and I will carry out the inspection alone.",
"required": false
},
"SENDERCONTACTINFO": {
"name": "Sender Contact Information",
"description": "How the tenant should contact you with questions or concerns. Should start with 'by ...' or 'on ...' as the text in the letter prior to this is 'please contact me directly '.",
"type": "string",
"max_length": 200,
"demo_value": "SENDERCONTACTINFO",
"default_value": "",
"required": true
}
},
"groups": {
"Sender Information": {
"variables": [ "SENDERNAME", "SENDERJOBTITLE", "SENDERCONTACTINFO" ],
"multi": false,
"required": true
},
"Tenant Name": {
"variables": [ "TENANTNAME" ],
"multi": false,
"required": true
},
"Tenant Address": {
"variables": [ "TENANTADDR" ],
"multi": true,
"required": true
},
"Inspection Information": {
"variables": [ "INSPECTIONTIME", "PREVINSPECTIONTIME", "EXTRANOTES" ],
"multi": false,
"required": true
}
}
}
Let's step through the three sections of the completed creodocs.json file as there are multiple nuances to note.
The template
section contains the template name and description as they will be shown on the Workshop page. We have written our LaTeX code to be compiled with pdflatex so this is the specified engine, but if we needed to use a custom font then xelatex would be a better choice. The version of the template can be specified in any format, but it is advised to stick to the semantic X.Y.Z
versioning system where X
is iterated for major changes, Y
for minor changes and Z
for bug fixes, e.g. 1.5.12. Finally, we list a fictional Arthur at Impact Real Estate and the contact person if there are any issues with the template.
In the variables
section, all of the variable IDs in the LaTeX code must be defined. The order of the variable IDs doesn't matter, that is, it doesn't need to correspond to the order they appear in the LaTeX code. For each variable, we first have a name
attribute for the friendly name to be displayed to users on Creodocs. The description
provides further explanation of the variable's function to users. The type of content variables can accept from users is specified in the type
attribute. In our example, all variables have a value of string
, which means they can hold any text content. Alternative options include integer
(whole numbers), float
(numbers with decimals or whole numbers) and boolean
(true or false). The max_length
attribute specifies the maximum number of individual letters, numbers or symbols a user can enter for the variable. This is a difficult specification to get right, since you need to set it large enough to refrain from restricting users unnecessarily, but small enough that the location of the variable in the document can accommodate the maximum number of characters. The demo_value
is used for making sure the template works and these values are used in the preview image for the template. A few of the variables have a default_value
, which is automatically populated in the manual entry form. Users still have the option to modify these, but the idea is that the default value represents the most common value the variable will contain. Finally, whether variables are required
is also an important attribute. Optional variables can be left blank by users and the document will be produced without them, but variables marked as required must have content entered. In our case, most of our variables are required because they represent pieces of information that are needed in the letter for it to make sense.
In the groups
section, group names each contain a number of key-value pairs with variable IDs specified as a list under a variables
attribute. Each variable ID must be present in only one group. The group names will be displayed to users, so they should be clear and concise. The order in which they appear will be their order on Creodocs. The idea is to group variables in a logical fashion so like is with like. For example, in our letter, we have 3 variables related to the person sending the letter: sender name, sender job title and sender contact information. These are logically grouped into the Sender Information
group to be displayed together. The multi
attribute specifies whether the variables in the group can be added multiple times by template users. If multi
is true, all variables in the group must be in the same variable multi-group in the LaTeX code (i.e. enclosed in |||
). In our letter, only the TENANTADDR
variable ID can be entered multiple times for each line of the tenant's address, so it must be in its own group in the groups
specification. Finally, the required
attribute allows overriding the required
attribute of individual variables in the group. If required
is false for the group, all variables can have no content submitted for them by the template user, even if they are required individually. However, if any variable does have content submitted for it, then the normal per-variable required
values will apply.
Closing Remarks
We have finished making our template! All that remains is to package the two files we have created into a zip file so they can be uploaded to Creodocs together. For convenience, you can download this file here:
All Creodocs templates must be uploaded as zip files containing at minimum a main.tex file and a creodocs.json file. Other files can be included if needed, such as additional .tex files, images or fonts.
Hopefully you are now equipped to create your own templates. When doing so, it is recommended that you refer to the Complete Template Specifications section for additional information and options, as this guide intentionally glossed over details in favour of simplicity.
The next step is to add our template to Creodocs which is covered in the Adding a Template section.
Complete Template Specifications
This page contains a complete reference of all requirements and options for creating Creodocs templates. The creation of a template requires you to first implement your document in LaTeX, then to define your document in a creodocs.json file in a way that allows Creodocs to display it and accept user inputs. As such, this page is divided into the following sections:
LaTeX Code Specifications
Creodocs uses TeX Live for typesetting templates and the two typesetting engines available are pdflatex and xelatex. There are no restrictions on what you can do in your LaTeX code; in general, if it compiles using TeX Live, it will compile on Creodocs. This means you are free to use packages that are part of TeX Live without including them as files with your template, unless you need a specific version of a package or it is not included with TeX Live. Other inclusions such as images, fonts and additional .tex files are allowed and can be housed in separate directories or alongside the template code.
The template you upload to Creodocs must be packaged as a zip file and must contain a main.tex file at the top (root) level. This is the file that will be compiled by Creodocs but you can include additional LaTeX files from within it using the standard LaTeX \input{}
command.
Each location in the LaTeX code where Creodocs users can supply information is called a variable. Variables are added inline to the LaTeX code and have the syntax of [[[VARNAME]]]
. The text within the square brackets is the variable identifier (ID) and can only contain upper case letters and numbers with a length of 1 to 30 characters. This is an example of using a variable inside a LaTeX document: Hello world, my name is \textbf{[[[NAME]]]}!
. Variables can be used any number of times in the LaTeX code.
By default, variables accept one value from users, but it is sometimes useful to allow one or more variables to accept multiple sets of content, this is called a multi-group. For example, in an invoice document, each invoiced item works well as a multi-group of several variables, one for the date, description, count and rate. Multi-groups are enclosed in 3 pipe characters (|||
) in the LaTeX code and must contain one or more variable IDs specified as usual within square brackets, e.g. |||[[[VARNAME]]]|||
. Groups can span multiple lines of LaTeX code and contain any other LaTeX code, but they cannot contain other groups. If more than one set of data is submitted by a user for a multi-group, all code and text within the multi-group specification is duplicated for each set prior to typesetting.
creodocs.json Specifications
A creodocs.json file must be included with every template at the top (root) level of the packaged template, alongside the LaTeX code. It is formatted using JSON syntax and describes the template to Creodocs in a standard format. This enables Creodocs to display the template and variables to users in a clean and helpful way, and restrict the types and amounts of information that can be submitted for each variable.
The creodocs.json file must contain template
, variables
and groups
top level sections. You will find each of these described under their corresponding titles below. Please take careful note of the attributes required within each section and the allowed values. The order of attributes within each top level section does not matter in your creodocs.json file. Attributes that are listed as not required in the specifications must be present, but their values can be left blank as empty strings (e.g. "name:" ""
).
template
Specification
This top level section contains information that applies to the entire template.
Attribute | Description | Required | Allowed Values |
---|---|---|---|
name |
The name of the template as it will be displayed to users | Yes | 1-50 letters, numbers, spaces or any of _-:,./'" |
engine |
The TeX engine to be used for typesetting the template | Yes | pdflatex or xelatex |
version |
The version of the template, used for keeping track of updates to templates; the recommended syntax is semantic versioning (X.Y.Z; e.g. 1.4.12) | Yes | 1-10 letters, numbers, spaces or any of _-:.,/() |
description |
A description of the template displayed in the Workshop to provide additional information about the template's purpose to users | No | 0-250 letters, numbers, spaces or any of _-:,./'" |
contact |
Contact details of the person responsible for the template, typically an email address | No | 0-50 letters, numbers, spaces or any of @_-:.,/() |
Example:
"template": {
"name": "Company Design Invoice",
"description": "Use for invoicing clients for design work",
"engine": "pdflatex",
"version": "1.0.0",
"contact": "rob@company.com"
}
variables
Specification
This top level section defines each variable ID used in the LaTeX code for display to users of the template and restricts the type and amount of content each variable can take.
Variable IDs
Under the variables
top level section should be a list of all variable IDs used in the LaTeX code. Their order does not need to correspond to the order in which they are used in the code. Variable IDs must be 1-30 characters in length and contain only uppercase letters and numbers.
For Each Variable ID
Attribute | Description | Required | Allowed Values |
---|---|---|---|
name |
The name of the variable as it will be displayed to users | Yes | 1-40 letters, numbers, spaces or any of _-:.,/' |
type |
The type of content the variable can accept from users | Yes | string , integer , float or boolean |
required |
Whether users must enter content for the variable or if it can be empty | Yes | true or false |
max_length |
Maximum number of characters that can be submitted for the variable | Yes | Whole number between 1-5000 A value of >300 will show multi-line input fields in the manual data submission form |
demo_value |
A value to be used for testing the template works and in the image preview of the template | Yes (if variable required ) |
Must adhere to type and max_length of the variable Can be an array of values if variable is in a multi-group (all other variables in the group must have the same number of array elements) |
default_value |
Pre-filled value for the variable, useful when there is an obvious default value | No | Must adhere to type and max_length of the variable |
description |
Additional information about the variable or usage instructions, displayed in a tooltip to users | No | 0-50 letters, numbers, spaces or any of _-:.,?/()'"; |
Example
"variables": {
"INVITEE": {
"name": "Invitee Name",
"description": "",
"type": "string",
"demo_value": "John Smith",
"default_value": "",
"max_length": 100,
"required": true
},
"GUESTS": {
"name": "Additional Guests",
"description": "The number of additional guests the invitee can bring.",
"type": "integer",
"demo_value": "1",
"default_value": "1",
"max_length": 2,
"required": false
}
}
groups
Specification
This top level section groups variable IDs in logical categories for display to users. A variable ID cannot be in multiple groups and all variable IDs must be grouped.
Group Names
Under the groups
top level section should be a list of all group names to display to users of the template. Their order corresponds to the order in which they will be displayed. Group names must be 1-50 characters in length and contain only letters, numbers, spaces and any of _-:,./'()
.
For Each Group Name
Attribute | Description | Required | Allowed Values |
---|---|---|---|
variables |
A list of variable IDs that belong in the group | Yes | One or more variable IDs in a list, each variable ID must be identical to one of the variable IDs present in the variables top level specification; variables will appear in the order they are listed |
multi |
Whether users can submit multiple sets of data for the group's variables | Yes | true or false |
required |
false if all variables can be submitted empty, even if they are required individually |
Yes | true or false |
Example
"groups": {
"Invitees": {
"variables": [ "INVITEENAME", "INVITEEPARTNERNAME" ],
"multi": false,
"required": true
},
"Invitee Address":
"variables": [ "ADDRESSLINE" ],
"multi": true,
"required": true
}
}
Example Template Downloads
Template Ownership and Sharing
Creodocs provides a number of global templates that can be used by anyone with an account. These are owned and managed by Creodocs, but any user can submit their own template(s) which are private by default. Private templates can be owned by and shared with other users, such as within a company. This page covers the ways in which a user can have access to a private template, known as access levels, then describes how template sharing is managed.
Access Levels
Any number of users can have access to a private template. When a template is first added, the user who added it becomes the first owner and can then invite other users to have access. There are three access levels a user can have to a private template: owner, administrator or user. These access levels allow fine-grained control over how much power a given user has over the template. In a commercial team-based environment, this allows differentiating between people who simply need to use the template to create documents and those who are also able to make changes to it.
The table below lists all possible template actions, split by access level. Use this as a reference for deciding the access level to grant additional users of your template.
User | Administrator | Owner | |
---|---|---|---|
Create documents | |||
View the access level of everyone with access | |||
Update template with new versions | |||
Switch to a previous template version | |||
Delete inactive template version | |||
Grant and remove user access | |||
Grant and remove administrator access | |||
Grant and remove owner access | |||
Delete template |
Template Sharing
Template sharing can be accessed for any private template in your Workshop by clicking the sharing icon ( ) under the template. This takes you to a page listing all users who have access to the template, split by their access level. If you have sufficient access, you can remove access to the template for a specific user by clicking 'Remove access' in their row. You can always remove your own access unless you are the sole owner, but removing another user's access requires a higher access level than them. Owners can remove anyone's access (including other owners), administrators can remove users and users can only remove their own access. Removing access is immediate and will delete any documents the user has recently created using the template.
To share the template with a new user, select the Share Template menu option on the Template Settings page. You will be able to enter an email address corresponding to the Creodocs user you wish to invite and select the access level you want to grant them.
If you are upgrading or downgrading a user who already has access to the template, remove their access first before sharing the template with them at the new access level.
What Is Document Data?
Most business documents that are produced repeatedly contain large sections of text and visual elements that are identical from document to document. This content is static and typically doesn't change very often, such as company contact information, or is informative and applied to all recipients, such as the terms and conditions in an invoice. The information that does change from document to document is dynamic and typically includes customer information, such as the addressee and item lines in an invoice. To produce each document, dynamic information needs to be placed in specific locations amongst the static content, which is exactly what Creodocs does to produce your documents. Document data is the dynamic information which you need to enter to produce a unique document from an existing template.
Variables
A single piece of dynamic information is called a variable. In the simplest case, a document can contain one variable that's used in one place, such as a letter notifying customers of an event that merely needs to use the customer's name in the "Dear [name]," greeting. A variable can be used in one or more places in the document but its content is always the same. This means it only needs to be specified once and can be styled as needed wherever it appears in the document.
Most documents will have need for more than one variable, and some of these variables may not need to have values. For example, a letter may contain not only the customer's name but also their address and phone number. The name and address are required for correctly addressing the letter, but the phone number is merely added under the address if it's available and without it the document is still complete. Variables are marked as required if they must have information entered for them, or not required (i.e. optional) if they can be empty. It is the template's job to correctly adjust the document when an optional variable is submitted without content.
In some situations, we may wish to specify the type of a variable to allow only specific kinds of information to be submitted for it. For example, if we have an invoice document where the number of hours and hourly rate are used to calculate the gross and total amounts due, these variables can only contain numbers or the calculations can't happen. In this case we specify the types of these variables as number
and a document will not be produced if submitted values contain anything but numbers.
Variables need not strictly store information that is output directly into the document. For example, a value of a variable can be used as an internal switch in the LaTeX code to alter the entire layout of a document without being written to the document.
Variable Groups
Documents typically contain many variables and natural groups arise based on the similarity of information stored in two or more variables. For example, a receipt is likely to have several variables for customer information and several others for the goods purchased, which form two natural groups. Variables that are grouped together can be used independently in different places in a document but are presented together for users entering their information. All variables must belong to a group but a group can contain a single variable if there are no other variables that are similar.
Multi-groups
So far we have seen that variables accept a single input value from the user and this value is substituted for the variable in one or more places in the document. However, sometimes it makes sense for a variable (or group of variables) to accept and output multiple sets of values. Consider the case of multiple items in an invoice. Each item has the same information: date, description and cost, but if each variable is only allowed one value, there need to be separate variables for each item, e.g. date1, description1, cost1, date2, description2, cost2, etc. This is cumbersome, repetitive to specify and supports only a fixed number of invoice items.
Multi-groups are a solution to this problem and strongly tie one or more variables together with surrounding static content and/or code. This means the entirety of the multi-group specification in the code is duplicated for each set of content supplied. Using our invoice items example, this means date, description and cost are specified as 3 variables in a multi-group and this allows users to enter multiple sets of content for them. Each set is then output to the document one after another, and any code that is required to create the line is also duplicated to ensure each item is on a separate line and styled correctly.
Submitting Document Data Manually
The easiest way to create documents on Creodocs is by manually entering document data into the website. To do this, click on the template you want to use in your Workshop and you will be presented with a manual entry form containing all the document's variables and fields for entering your content.
Manual Entry Form
The manual entry form contains sections for each variable group in the template selected. Inside each group section, all variables belonging to the group are displayed as rows, with the variable name on the left and the document data input on the right. If the variable name is bold, it must have data entered for it for the document to be produced; if the variable name is bold italic, the variable must have data entered for it only if any other variable in the group has data entered (i.e. all variables in the group can be empty). It is not always obvious what each variable corresponds to in the document, so if there is a small question mark () to the right of the variable name, mouse over it to see a description of what the variable does and how the value you enter may be automatically transformed.
If the group is a multi-group, the variables will appear with a box around them indicating that multiple sets of variables can be created in the group. Three tabs are present for each set of variables that let you manipulate the set. The green tab below is for creating a new blank set below the current set, the red tab to the right is for deleting the current set and the grey tab on the left is for moving the current set up or down in relation to other sets.
Variables can only accept content up to a maximum defined length of characters. Maximum lengths are necessary to constrain the impact that each variable can have on the document. For example, a main title at a font size of 80pt looks good if it contains a handful of words, but if a whole sentence is entered for the main title variable, it would quickly take up the entire page and have an adverse effect on the document. Each variable in the manual entry form shows the current number of characters entered and the maximum allowed under the input field as "X/Y characters remaining".
Variables can accept different types of data depending on what they are used for in the document. Broadly, variables can accept text, whole numbers, numbers with decimals or true/false values (see the Template Specifications section for more information). If a variable is defined as accepting only whole numbers, you will only be allowed to enter whole numbers in the input field for the variable, and the same goes for the other types listed. You can determine what type of data is allowed by looking at the remaining characters text underneath the input field, which will read "digits remaining" for number inputs or "characters remaining" when the input accepts any text. True/false inputs will appear as 2 radio buttons for true and false.
Once you submit your variable data for document creation, it will be checked for accuracy and if there are any errors you will be returned to the manual entry form where what you entered will be restored so you don't lose your progress.
Locked Variable Content
Beside each variable's data input field you will find a lock icon (), which can be toggled on (locked) or off (unlocked). This is a feature exclusive to the manual entry form and allows you to save variable data entered into the form for later re-use. To use this feature, simply enter data for any variable and once you are done, click the lock button to lock the variable content. When you submit the form to create a document, all variables you have locked will have their content saved and next time you return to the manual entry form for the document the values will be restored. This is a very useful feature for creating documents that change over time, such as invoices or curriculum vitaes, where you can save your personal information once and never have to re-enter it again.
Locking variables in a multi-group will lock them per set, in other words, all variables in the locked set are locked together. The order of locked sets in each multi-group is also saved.
Default Values
You may notice that some variables have pre-filled values even though they are unlocked, these are known as default values. Default values are specified in the template when there is a single variable value that is used the majority of the time, but it is allowed to be customised if required by the user. For example, an invoice template may have large lettering at the top saying Invoice, but some companies or jurisdictions require invoices to explictily say Tax Invoice for legal reasons. In this case, the template may expose this variable to the user to allow it to be changed, but specify Invoice as the default value since this will be used the majority of the time. If you would like to override a default value, simply replace it with your own and lock the value so it is saved. Likewise, if you want the value to always be blank, rather than use the default, just remove the default value and lock the empty variable.
Submitting Document Data via Database
Submitting document data via database lets you create multiple documents at once using the same template. This is useful if you need a large batch of documents created as a regular operation, such as producing monthly invoices for customers, or you need to produce a one off communication, such as notifying clients of an upcoming event in a letter.
To submit document data using a database, click on the template you want to use in your Workshop, then select the Upload a Database tab at the top. You will be presented with a form to upload your database for document creation.
Each document produced from a database of document data is charged to the billing group of the account making the request and costs the same number of credits as creating the document manually.
Database Structure Specification
The database you upload must be in a specific format for Creodocs to read it. Primarily, the database must be a *.tsv tab-delimited file where each column is an individual variable and each row contains the document data for a separate document. This structure means that each cell in the database contains the document data for a specific variable within a specific document, with tab characters separating variable content.
The first row (line) of the database must contain variable ID names for all variables in the template selected. Variable IDs are the internal identifiers for each variable and are not the friendly variable names seen in the manual entry form. For multi-groups where multiple sets of the same variables can be submitted per document, you can specify each set by entering the group's variable IDs next to each other multiple times. For example, VAR1 VAR2 VAR3 VAR1 VAR2 VAR3
can make up 6 columns of the database where these three variables are in a multi-group.
The table below is laid out in the format of an example database to illustrate the requirements written above. It uses the variables from the example letter template created in the Creating a Template section.
SENDERNAME | SENDERJOBTITLE | TENANTNAME | TENANTADDR | TENANTADDR | TENANTADDR | INSPECTIONTIME | PREVINSPECTIONTIME | EXTRANOTES | SENDERCONTACTINFO |
---|---|---|---|---|---|---|---|---|---|
Cindy Kim | Senior Property Manager | Martin Jones | 388 Pleasant Lane | City, State | July 21 at 1pm | January 18 | 021 123 4567 | ||
Cindy Kim | Senior Property Manager | Rebecca Smith | Apartment 221 | 5 West Street | City, State | July 22 at 10am | January 11 | 021 123 4567 | |
Cindy Kim | Senior Property Manager | Hinata Adachi | Apartment 638 | 5 West Street | City, State | July 22 at 10:30am | December 8 | 021 123 4567 |
Optional variables can be left blank in the database but must be present as columns. You can see this in the table above for the optional EXTRANOTES variable where all three document rows have no data for this variable.
Multi-group variable sets that are required can be left blank, but only if at least one set has been entered for the row. This is because other rows in the database have content, so additional columns are required to accomodate it. An example of this is the multi-group containing the required TENANTADDR variable in the table above, which is present as 3 sets (columns) because the second and third rows have 3 sets for this variable each. However, the first row only has 2 sets of data for this variable and the third set is blank. The general rule is that all empty sets for multi-groups will be ignored in databases, but otherwise normal rules apply.
Variable data in your database must adhere to the corresponding variable types and lengths. This means data entered for a variable that only accepts boolean data can only have values of 'true' or 'false', a variable that only accepts integer data can only have values of whole numbers and so on. Maximum lengths of variables must also be respected.
Downloading an Automatically Generated Empty Database
To make the process of creating a database easier, you can download an automatically generated database file for every template. To do this, click on the template you want to use in your Workshop, then select the Upload a Database tab at the top. You will find a link to download a database template on the resulting page which will provide you a TSV file ready for populating with document content.
The first row of the database template file contains all the variable IDs in the document template in the required format. The second row contains an indication of whether each variable is required (must have content entered for it), to aid you in entering your document content on subsequent rows. This second row should be removed before submitting your database.
Multi-grouped variables are output 3 times side by side in the example database template. This is to indicate how to submit multiple sets only, you can increase or decrease the number of sets for each group as required.
Downloading Documents Produced Using a Database
Documents produced using a database are downloaded the same way as those produced using the manual entry form. The key difference is that the download itself will be a zip file containing all the documents produced instead of a single PDF file.
Submitting Document Data via API
The Creodocs API allows you to submit document data for a template and returns a URL to the document PDF when it is successful. This means you don't need to interact with the Creodocs website to create documents. This method is primarily useful for software developers who need to automatically create documents as part of another product or service.
All API requests are charged to the billing group of the account making the request and cost the same number of credits as creating the document manually.
API Specifications
The API uses the JSON format to structure requests and responses. To verify your identity when making an API request, you will need to generate an API key as described on the API Keys Support page. Creating a document requires you to send your Creodocs user ID (yours is ), the template ID of the document you'd like to create, your API key and the document data for each variable. API requests must be made via POST to https://www.creodocs.com/api/create under a data
key.
The table below details each of the required components of an API request and provides details on their expected values.
Attribute | Description | Allowed Values |
---|---|---|
user_id |
Your Creodocs user ID number | Must be a number |
template_id |
The template ID number you would like to use to create the document | Must be a number |
key |
Your secret API key | The key provided to you by Creodocs |
document_data |
Document data for all variables in the template | An object of keys and values where keys are template variable IDs and values are arrays of document data. Unless the variable is in a multi-group, the array must contain one element. All variables in each multi-group must contain the same number of elements. |
Example:
{
"user_id": 12,
"template_id": 52,
"key": "b70b53f2c9e09fa836410bed18126c38b497b660cd7fcc72a6",
"document_data": {
"NAME": [
"John Smith"
],
"DATE": [
"20/04/2020"
],
"PARAGRAPHS": [
"First paragraph text.",
"Second paragraph text."
],
"OPTIONALSIGNATURE": [
""
]
}
}
You can find an automatically populated template for making API requests for a given template under the Submit via API section of the Add Document Content page for the template.
Additional Document Data Specification Information
- All template variables must be included in the API request, even if they are not required and no data is being provided for them. In this case, the variable data should just be an empty string (i.e.
""
). - Only multi-grouped variables can have more than one set of content supplied. In this case, all other variables in the same group must have the same number of content sets supplied. For example,
VAR1
andVAR2
are in a group that allows multiple sets of content but onlyVAR1
is required. If you specify four sets of content forVAR1
, you must also specify four sets forVAR2
, even if they are empty strings. - All rules that normally apply to variable content (such as maximum length, type, disallowed characters, whether multiple sets of content are allowed, etc) apply for in API request. If document data submitted for any variable does not match the variable's requirements, your request will fail.
API Return Values
The API will return a JSON string containing three keys.
request_outcome
— will have a value of eithersuccess
orfailure
document_url
— if the request was asuccess
, the value will contain a URL to the created document, otherwise it will be an empty stringrequest_description
— if the request was afailure
, the value will contain the reason why, otherwise it will be an empty string
Example:
{
"request_outcome": "failure",
"request_description": "missing_input",
"document_url": ""
}
Try Submitting to the API
Test API requests can be made using dedicated software for this purpose, but if you would like to make a quick test request you can use the form below. Paste the entire JSON request object and press Submit to send your request.