Lotemplate
LOTemplate is document generator used to create documents programatically (ODT, DOCX, PDF) from a template (DOCX or ODT) and a json file using LibreOffice in headless mode
Install / Use
/learn @Probesys/LotemplateREADME
LOTemplate (for Libre Office Template)
Warning : This readme is for the version 2.x of LoTemplate. There are breaking changes between versions 1.x and 2.x. See UPGRADE.md documentation. You can also see the CHANGELOG.md for the versions.
<a name="principles"></a>Principles
LOTemplate is document generator used to create documents programatically (ODT, DOCX,ODS, XLSX, PDF) from an office template and a json file.
---
title: Word / Writer document
---
flowchart LR
template["Word Template<br/>(DOCX or ODT)"]
json["Data<br/>(JSON)"]
lotemplate["LO Template<br/>(accessible by API or CLI)"]
generatedFile["Generated File<br/>(PDF, DOCX, ODT, RTF,...)"]
template --> lotemplate
json --> lotemplate
lotemplate --> generatedFile
---
title: Excel / Calc document
---
flowchart LR
calc_template["Excel Template<br/>(ODS or XLSX)"]
calc_json["Data<br/>(JSON)"]
calc_lotemplate["LO Template<br/>(accessible by API or CLI)"]
calc_generatedFile["Generated File<br/>(ODS, XLSX, PDF, csv,...)"]
calc_template --> calc_lotemplate
calc_json --> calc_lotemplate
calc_lotemplate --> calc_generatedFile
What makes this tool different from others are the following features :
- The templates are in office format (ods,odt, docx, xlsx, ... ) format
- Word Template can have complex structures (variables, loop, conditions, counters, html,...)
- The tool can scan the template to extract the variables sheet
- The tool can be called by an API, a CLI or a python module.
- The tool uses a real LibreOffice headless to fill the templates. Then the output formats are all the LibreOffice supported formats (docx, xlsx, pdf, odt, ods, text, rtf, html, ...)
The tool is written in Python and use a real LibreOffice headless to fill the templates.
Table of content
- Principles
- Quick Start
- API and CLI Usage
- DOCX and ODT Template syntax and examples
- XLSX and ODS Template syntax and examples
- Add watermark when output in pdf
- Supported formats
- Doc for developpers of lotemplate
- Unsolvable problems
- Installation without Docker
- External documentations
<a name="quick_start"></a>Quick start
Run the project with docker compose
Use the docker-compose.yml at the root of the project. Configure the .env file
run the service
docker-compose up -d
Use the API
# creation of a directory
curl -X PUT -H 'secretkey: lopassword' -H 'directory: test_dir1' http://localhost:8000/
# {"directory":"test_dir1","message":"Successfully created"}
Let's imagine we have an file basic_test.odt (created by libreoffice) like this :
Test document
let’s see if the tag $my_tag is replaced and this $other_tag is detected.
[if $my_tag == foo]My tag is foo[endif]
[if $my_tag != foo]My tag is not foo[endif]
Upload this file to lotemplate
# upload a template
curl -X PUT -H 'secretkey: lopassword' -F file=@/tmp/basic_test.odt http://localhost:8000/test_dir1
# {"file":"basic_test.odt","message":"Successfully uploaded","variables":{"my_tag":{"type":"text","value":""},"other_tag":{"type":"text","value":""}}}
# generate a file titi.odt from a template and a json content
curl -X POST \
-H 'secretkey: lopassword' \
-H 'Content-Type: application/json' \
-d '{"name":"my_file.odt","variables":{"my_tag":{"type":"text","value":"foo"},"other_tag":{"type":"text","value":"bar"}}}' \
--output titi.odt http://localhost:8000/test_dir1/basic_test.odt
After the operation, you get the file titi.odt with this content :
Test document
let’s see if the tag foo is replaced and this bar is detected.
My tag is foo
<a name="api-and-cli-usage"></a>API and CLI Usage
With the API
Examples of curl requests
# creation of a directory
curl -X PUT -H 'secretkey: my_secret_key' -H 'directory: test_dir1' http://lotemplate:8000/
# {"directory":"test_dir1","message":"Successfully created"}
curl -X PUT -H 'secretkey: my_secret_key' -H 'directory: test_dir2' http://lotemplate:8000/
# {"directory":"test_dir2","message":"Successfully created"}
# look at the created directories
curl -X GET -H 'secretkey: my_secret_key' http://lotemplate:8000/
# ["test_dir2","test_dir1"]
# delete a directory (and it's content
curl -X DELETE -H 'secretkey: my_secret_key' http://lotemplate:8000/test_dir2
# {"directory":"test_dir2","message":"The directory and all his content has been deleted"}
# look at the directories
curl -X GET -H 'secretkey: my_secret_key' http://lotemplate:8000/
# ["test_dir1"]
Let's imagine we have an odt file (created by libreoffice) like this :
Test document
let’s see if the tag $my_tag is replaced and this $other_tag is detected.
Upload this file to lotemplate
# upload a template
curl -X PUT -H 'secretkey: my_secret_key' -F file=@/tmp/basic_test.odt http://lotemplate:8000/test_dir1
{"file":"basic_test.odt","message":"Successfully uploaded","variables":{"my_tag":{"type":"text","value":""},"other_tag":{"type":"text","value":""}}}
# analyse an existing file and get variables
curl -X GET -H 'secretkey: my_secret_key' http://lotemplate:8000/test_dir1/basic_test.odt
# {"file":"basic_test.odt","message":"Successfully scanned","variables":{"my_tag":{"type":"text","value":""},"other_tag":{"type":"text","value":""}}}
# generate a file titi.odt from a template and a json content
curl -X POST -H 'secretkey: my_secret_key' -H 'Content-Type: application/json' -d '{"name":"my_file.odt","variables":{"my_tag":{"type":"text","value":"foo"},"other_tag":{"type":"text","value":"bar"}}}' --output titi.odt http://lotemplate:8000/test_dir1/basic_test.odt
After the operation, you get the file titi.odt with this content :
Test document
let’s see if the tag foo is replaced and this bar is detected.
API reference
Then use the following routes :
all routes take a secret key in the header, key secretkey, that correspond to the secret key configured in the
.env file. If no secret key is configured, the secret key isn't required at request.
-
/PUT: take a directory name in the headers, key 'directory'. Creates a directory with the specified nameGET: returns the list of existing directories
-
/<directory>: directory correspond to an existing directoryGET: returns a list of existing templates within the directory, with their scanned variablesPUT: take a file in the body, key 'file'. Uploads the given file in the directory, and returns the saved file name and its scanned variablesDELETE: deletes the specified directory, and all its contentsPATCH: take a name in the headers, key 'name'. Rename the directory with the specified name.
-
/<directory>/<file>: directory correspond to an existing directory, and file to an existing file within the directoryGET: returns the file and the scanned variables of the fileDELETE: deletes the specified filePATCH: take a file in the body, key 'file'. replace the existing file with the given file. returns the file and the scanned variables of the filePOST: take a json in the raw body. fills the template with the values given in the json. returns the filled document(s).
-
/<directory>/<file>/download: directory correspond to an existing directory, and file to an existing file within the directoryGET: returns the original template file, as it was sent
you may wish to deploy the API on your server. Here's how to do it - but don't forget that you should have soffice installed on the server
You can also change the flask options - like port and ip - in the .flaskenv file.
If you're deploying the app with Docker, port and ip are editable in the Dockerfile.
You can also specify the host and port used to run and connect to soffice as command line arguments,
or in a config file (config.yml/config.ini/config or specified via --config).
Execute and use the CLI
Run the script with the following arguments :
usage: lotemplate_cli.py [-h] [--json_file JSON_FILE [JSON_FILE ...]]
[--json JSON [JSON ...]] [--output OUTPUT]
[--config CONFIG] [--host HOST] [--port PORT]
[--scan] [--force_replacement] template_file
positional arguments:
template_file Template file to scan or fill
optional arguments:
-h, --help show this help message and exit
--json_file JSON_FILE , -jf JSON_FILE
Json files that must fill the template, if any
--json JSON , -j JSON
Json strings that must fill the template, if any
--json_watermark_file JSON_FILE, -jwf JSON_FILE
Json files to configure pdf watermark, if any
--json_watermark JSON , -jw JSON
Json strings to configure pdf watermark, if any
--output OUTPUT, -o OUTPUT
Names of the filled files, if the template should
be filled. supported formats: pdf, html, docx, png, odt
--config CONFIG, -c CONFIG
Configuration file path
--host HOST Host address to use for the libreoffice connection
--port PORT Port to use for the libreoffice connexion
--scan, -s
Related Skills
node-connect
344.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
99.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
344.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
344.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
