📄 DocumentPlaceholder
Automatically fill Word templates using YAML configs, expressions, and SQL.
Generate invoices, reports, statements, and any other documents with a single command.
Features • Installation • Quick Start • Configuration • Functions • GUI
🚀 Features
DocumentPlaceholder turns .docx templates into ready-to-use documents based on YAML configs with a powerful expression language.
- 📝 Word templates — placeholders like
{KEY}in text, tables, and headers/footers. - ⚡ Expression language — arithmetic, comparisons, nested function calls, and template strings.
- 🛢 SQLite out of the box — run database queries directly inside configs for counters, lookups, and client data.
- 📅 59 built-in functions — date/time, strings, math, logic, and conditions.
- 📤 PDF export — automatic conversion through LibreOffice.
- 🖥 GUI with syntax highlighting — config editor, live preview, SQL manager.
- 🔌 Extensible — add your own functions with a single decorator.
📦 Installation
pip install document-placeholder
Optional extras:
| Extra | Includes |
|---|---|
document-placeholder[gui] |
GUI interface (CustomTkinter) |
document-placeholder[dev] |
Development tools (pytest) |
document-placeholder[all] |
Everything |
⚡ Quick Start
1. Create a Word template (template.docx)
Insert placeholders into the document:
Invoice #{INVOICE_NUM}
Date: {DAY_NUM}.{MONTH_STR}.{YEAR_NUM}
Amount: ${PRICE}
{DESCRIPTION}
2. Write a config (template.yaml)
ON_START:
- SQL('CREATE TABLE IF NOT EXISTS doc (num INTEGER DEFAULT 0)')
- SQL('INSERT OR IGNORE INTO doc (rowid, num) VALUES (1, 0)')
INVOICE_NUM:
SQL('SELECT num FROM doc WHERE rowid = 1') + 1
MONTH_STR:
CURRENT_DATE_STR(month)
DAY_NUM:
CURRENT_DATE_NUM(day)
YEAR_NUM:
CURRENT_DATE_NUM(year)
PRICE:
500
DESCRIPTION:
"Software Development Services
(Period: {CURRENT_DATE_NUM(day, month, year) - DAYS(7)} — {CURRENT_DATE_NUM(day, month, year)})"
OUTPUT_NAME:
"Invoice-{INVOICE_NUM}"
OUTPUT_FORMAT:
- docx
- pdf
ON_END:
SQL('UPDATE doc SET num = num + 1 WHERE rowid = 1')
3. Run
docplaceholder -c template.yaml -t template.docx
INVOICE_NUM = 2026-2-5
MONTH_STR = February
DAY_NUM = 16
YEAR_NUM = 2026
PRICE = 500
DESCRIPTION = Software Development Services (Period: 09.02.2026 — 16.02.2026)
Output: Invoice-2026-2-5 [docx, pdf]
-> Invoice-2026-2-5.docx
-> Invoice-2026-2-5.pdf
🎨 Expression Language
A config is not just key-value mapping. Every value is an expression that gets evaluated.
Arithmetic and comparisons
TAX: ROUND(PRICE * 0.2, 2)
TOTAL: PRICE + TAX
IS_PREMIUM: TOTAL > 1000
Template strings
Inside "...", expressions like {expr} are interpolated into the final string:
PERIOD: "{CURRENT_DATE_NUM(day, month, year) - DAYS(30)} — {CURRENT_DATE_NUM(day, month, year)}"
Nested calls
INVOICE_NUM:
"{CURRENT_DATE_NUM(year)}-{SQL('SELECT num FROM doc WHERE rowid = 1') + 1}"
Conditional logic
STATUS: IF(TOTAL > 1000, 'Premium', 'Standard')
DISCOUNT: IF(TOTAL >= 500, TOTAL * 0.1, 0)
LABEL: SWITCH(STATUS, 'Premium', '⭐ Premium', 'Standard', '📋 Standard')
Supported operators: + - * / % > < >= <= == != ()
⚙️ Configuration
CLI arguments
docplaceholder [-c CONFIG] [-t TEMPLATE] [-o OUTPUT] [--db DATABASE]
| Argument | Default | Description |
|---|---|---|
-c, --config |
template.yaml |
Path to YAML config |
-t, --template |
template.docx |
Path to Word template |
-o, --output |
output.docx |
Path to output file |
--db |
data.db |
Path to SQLite database |
-V, --version |
Print program version |
Special YAML keys
| Key | Description |
|---|---|
ON_START |
Expressions executed before processing (table creation, initialization) |
ON_END |
Expressions executed after processing (increment counters, cleanup) |
OUTPUT_NAME |
Output filename template: "Invoice-{INVOICE_NUM}" |
OUTPUT_FORMAT |
List of output formats: [docx, pdf] |
All other keys are treated as placeholders and replaced in the document.
🧰 Built-in Functions
59 functions in 5 categories. Full reference: FUNCTIONS.md
📅 Date and time
TODAY: TODAY() # 16.02.2026
YEAR: CURRENT_DATE_NUM(year) # 2026
MONTH: CURRENT_DATE_STR(month) # February
CUSTOM: DATE_FORMAT(DATE(2026, 3, 8), '%d %B %Y') # 08 March 2026
WEEK_AGO: "{TODAY() - DAYS(7)}" # 09.02.2026
DIFF: DAYS_BETWEEN(DATE(2026, 1, 1), TODAY()) # 46
🔤 Strings
UPPER('hello') # HELLO
TITLE('john doe') # John Doe
PAD_LEFT('42', 6, '0') # 000042
JOIN(', ', 'a', 'b', 'c') # a, b, c
REPLACE('foo bar', 'bar', 'baz') # foo baz
SPLIT('user@mail.com', '@', 1) # mail.com
🔢 Math
ROUND(19.956, 2) # 19.96
FORMAT_NUM(1234567, 2) # 1,234,567.00
MIN(3, 1, 4, 1, 5) # 1
AVG(10, 20, 30) # 20.0
SQRT(144) # 12.0
🧠 Logic
IF(PRICE > 1000, 'expensive', 'cheap')
COALESCE(SQL('SELECT name FROM clients'), 'Unknown')
DEFAULT(value, 'N/A')
SWITCH(status, 'draft', 'Draft', 'sent', 'Sent', 'Unknown')
🛢 SQL
SQL('SELECT count(*) FROM orders WHERE user_id = 1')
SQL('INSERT INTO log (event) VALUES ("generated")')
🖥 Graphical Interface
pip install document-placeholder[gui]
docplaceholder-gui
The GUI includes:
- Config editor with YAML and custom syntax highlighting (
SQL(...),{expressions}) - Live preview of evaluated values
- SQL manager for running queries and viewing tables/schema
- Keyboard shortcuts —
Ctrl+Ssave,Ctrl+Fsearch,F5refresh
🔌 Extending Functions
Add a custom function with a single decorator:
from document_placeholder.functions import FunctionRegistry
@FunctionRegistry.register("MY_FUNC")
def my_func(arg1, arg2):
"""Your custom logic."""
return f"{arg1}-{arg2}"
After importing the module, the function becomes available in config expressions:
VALUE: MY_FUNC('hello', 'world') # hello-world
📁 Library Usage
from document_placeholder.config import Config
from document_placeholder.evaluator import Evaluator
from document_placeholder.processor import DocumentProcessor
config = Config.from_string("""
NAME: UPPER('john doe')
DATE: TODAY()
""")
evaluator = Evaluator()
values = {k: evaluator.evaluate_value(v) for k, v in config.placeholders.items()}
# {'NAME': 'JOHN DOE', 'DATE': DateValue(2026-02-16)}
processor = DocumentProcessor("template.docx")
processor.replace_placeholders(values)
processor.save("output.docx")
🧪 Testing
pip install document-placeholder[dev]
pytest
295 passed in 0.36s
🤝 Contributing
- Fork the repository
- Create a feature branch
- Commit your changes
- Open a Pull Request
Bugs and feature requests → Issues
📄 License
This project is released under the MIT license. See LICENSE for details.
Developed with ❤️ by FlacSy
Metadata
Release files for document-placeholder 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| document_placeholder-1.1.0.tar.gz | 53.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| document_placeholder-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 86.0 kB
Release files / document_placeholder-1.1.0.tar.gz
| Download URL | document_placeholder-1.1.0.tar.gz |
|---|---|
| Size | 53.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
affc1e099a46a5126834f87dfc5525231184262394cff392f6825ee8a6048c3c
|
|
BLAKE2b-256 checksum How to use checksums |
e5d6c80a7366b7ca9e9009705ad080eb2caf372f554710d6bb3bedd2608382c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 3, 2026.
Transparency logRelease files / document_placeholder-1.1.0-py3-none-any.whl
| Download URL | document_placeholder-1.1.0-py3-none-any.whl |
|---|---|
| Size | 32.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fb2d9ea93af49167c9ec9b735f62146d870fd9510ab7d9949af6710f9915fce5
|
|
BLAKE2b-256 checksum How to use checksums |
4782051c791661c5710113b066fdf7abfa78174d512de08b5a68059605760340
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 3, 2026.
Transparency log