Product Page | Docs | Demos | API Reference | Blog | Free Support | Temporary License
GroupDocs.Assembly for Python via .NET is a document automation and report generation API. It fills templates - ordinary Word, Excel, PowerPoint, OpenDocument, email, HTML, Markdown and text documents with tags such as <<[customer.Name]>> and <<foreach [o in orders]>> - with data from Python dicts and lists, JSON, XML and CSV files, or the tables of other documents, and saves the report in the template's format or another one, such as PDF. No Microsoft Office or other software is needed.
Get Started
pip install groupdocs-assembly-net
Every release's wheels are also on releases.groupdocs.com, for installing offline: download the one for your platform and run pip install on the file.
from groupdocs.assembly import DataSourceInfo, DocumentAssembler
# hello-world.docx holds the tags <<[customer.Name]>> and <<[customer.Product]>>
customer = {"Name": "Quayside Bistro", "Product": "Harbor Blend whole bean coffee"}
DocumentAssembler().assemble_document("hello-world.docx", "hello-world-report.docx", DataSourceInfo(customer, "customer"))
How It Works
The package is a self-contained Python wheel (about 80 MB) that bundles the embedded .NET runtime and everything needed to read templates and write reports: just pip install and start. On Linux the system also needs ICU, and libgdiplus for presentations; on macOS, mono-libgdiplus for presentations (see System Requirements below). The wheel works across Python 3.5-3.14 on Windows, Linux, and macOS 12 or newer (Intel + Apple Silicon).
A template is a document you write in Word, Excel, PowerPoint or a text editor. Its tags name the data sources you pass, each in a DataSourceInfo with a name: <<[customer.Name]>> reads the "Name" key of the dict passed as "customer". The report is saved in the format of its file extension. The first call into the engine takes about a second; on Windows, applying a license makes the first call take 15-30 seconds, once per process (the engine's license check, in plain .NET too).
Features
- Python data as it is: dicts and lists, with their numbers, strings,
datetime,date,Decimaland bool values, reach the template as typed objects:o.OrderDate.Month,GroupBy(o => o.Customer),<<if [c.Vip]>>work as in the .NET templates. - Data files and documents:
JsonDataSource,XmlDataSourceandCsvDataSource, and the tables of Word, Excel and PowerPoint documents asDocumentTable/DocumentTableSet. - Template syntax: expressions, formatting (
:"0.00",:"d MMMM yyyy",:upper), conditions, variables, andSum,Count,Where,OrderBy,GroupByand other sequence operations in the template. - Every kind of report: tables (with totals, grouping, master-detail, highlighted rows, merged cells), bulleted and numbered lists, pie, bubble, scatter and column charts, images, barcodes, hyperlinks, bookmarks, check boxes and inserted documents.
- Email: MSG and EML templates whose sender, recipients, subject and body come from data.
- Any output format: a Word template saved as PDF, HTML, XPS, TIFF, Markdown and more; a spreadsheet or presentation as PDF, HTML or XPS.
- Assembly options: update fields and formulas, remove empty paragraphs, write template errors into the report instead of raising, keep spreadsheet values typed.
- Cross-Platform: Windows x64, Linux x64, macOS x64/ARM64.
Common Tasks
- Generate invoices, contracts and letters from one Word template per document type
- Build table, list and chart reports of sales or orders from a list of dicts or a JSON file
- Turn a Word template filled with data straight into a PDF
- Send an email per customer, with its recipients, subject and body from data
- Use the table of an Excel or Word document as the data of another report
- Fill a template from database rows (as dicts)
Supported File Formats
For the complete list, see supported document formats.
| Category | Templates and reports | Reports also as |
|---|---|---|
| Word Processing | DOC, DOCX, DOCM, DOT, DOTX, DOTM, RTF, ODT, OTT, TXT, MD | PDF, XPS, OXPS, TIFF, SVG, PS, PCL, XAML, EPUB, HTML, MHTML |
| Spreadsheets | XLS, XLSX, XLSM, XLSB, XLT, XLTX, XLTM, ODS | PDF, XPS, TIFF, PCL, HTML, MHTML |
| Presentations | PPT, PPTX, PPTM, PPS, PPSX, PPSM, POT, POTX, POTM, ODP, OTP | PDF, XPS, TIFF, HTML |
| MSG, EML, EMLX | PDF, MHTML, TIFF, SVG, PS, PCL | |
| Web | HTML, MHTML | as Word Processing |
Examples
Fill a Word table from a list of dicts
from groupdocs.assembly import DataSourceInfo, DocumentAssembler
orders = [
{"Number": 10001, "Product": "Harbor Blend whole bean coffee", "Quantity": 30, "Price": 552.0},
{"Number": 10004, "Product": "Aged harbour cheddar", "Quantity": 8, "Price": 132.0},
]
# order-table.docx: a table whose row <<foreach [o in orders]>><<[o.Number]>> ... <</foreach>> repeats per order
assembler = DocumentAssembler()
assembler.assemble_document("order-table.docx", "order-table-report.docx", [
DataSourceInfo("Quayside Bistro", "customer"),
DataSourceInfo(orders, "orders"),
])
A JSON file to a PDF report
import json
from datetime import datetime
from groupdocs.assembly import DataSourceInfo, DocumentAssembler
def parse_dates(item):
# JSON has no dates: the template formats ShippingDate as a date
for key in ("OrderDate", "ShippingDate"):
if key in item:
item[key] = datetime.strptime(item[key], "%Y-%m-%dT%H:%M:%S")
return item
with open("customers.json", encoding="utf-8") as f:
customers = json.load(f, object_hook=parse_dates)
# A Word template, a PDF report: the report's extension picks the format
DocumentAssembler().assemble_document("orders-by-customer.docx", "orders-by-customer.pdf", DataSourceInfo(customers, "customers"))
XML and CSV data sources
from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import CsvDataLoadOptions, CsvDataSource, XmlDataSource
assembler = DocumentAssembler()
assembler.assemble_document("data-destination-with-nested-elements.docx", "managers-report.docx",
DataSourceInfo(XmlDataSource("managers.xml"), "managers"))
# The first line of the CSV file holds the column names
persons = CsvDataSource("persons.csv", CsvDataLoadOptions(True))
assembler.assemble_document("data-destination-with-nested-elements.txt", "persons-report.txt", DataSourceInfo(persons, "persons"))
The table of another document as the data
from groupdocs.assembly import DataSourceInfo, DocumentAssembler
from groupdocs.assembly.data import DocumentTable, DocumentTableOptions
options = DocumentTableOptions()
options.first_row_contains_column_names = True
contracts = DocumentTable("contracts.xlsx", 0, options) # the first table of the workbook
DocumentAssembler().assemble_document("table-row.docx", "table-row-report.docx", DataSourceInfo(contracts, "contracts"))
An email message
import json
from groupdocs.assembly import DataSourceInfo, DocumentAssembler
with open("customers.json", encoding="utf-8") as f:
customers = json.load(f)
DocumentAssembler().assemble_document("in-table-list.msg", "in-table-list-report.msg", [
DataSourceInfo(customers, "customers"),
DataSourceInfo("Harbor Lane Provisions <orders@harborlane.example>", "sender"),
DataSourceInfo(["Quayside Bistro <orders@quaysidebistro.example>"], "recipients"),
DataSourceInfo("amara.osei@harborlane.example", "cc"),
DataSourceInfo("Orders by customer", "subject"),
])
Assembly options
from groupdocs.assembly import DataSourceInfo, DocumentAssembler, DocumentAssemblyOptions
assembler = DocumentAssembler()
# Remove the paragraphs left empty, and write template errors into the report instead of raising
assembler.options = DocumentAssemblyOptions.REMOVE_EMPTY_PARAGRAPHS | DocumentAssemblyOptions.INLINE_ERROR_MESSAGES
customer = {"Name": "Quayside Bistro", "Product": "Harbor Blend whole bean coffee"}
ok = assembler.assemble_document("hello-world.docx", "hello-world-report.docx", DataSourceInfo(customer, "customer"))
print("Template parsed without errors:", ok)
AI Agent & LLM Friendly
This package is designed for seamless integration with AI agents, LLMs, and automated code generation tools.
AGENTS.mdin the package - AI coding assistants (Claude Code, Cursor, GitHub Copilot) auto-discover the API surface, usage patterns, and troubleshooting tips from the installed package. Setup per tool: AI agents and LLM integration- MCP server - connect your AI tool to GroupDocs documentation for on-demand API lookups:
{ "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } }
- Machine-readable docs - full documentation available as plain text for RAG and LLM context:
- Single file:
https://docs.groupdocs.com/assembly/python-net/llms-full.txt - Per page: append
.mdto any docs URL
- Single file:
Evaluation Mode
The API works without a license in evaluation mode, with these limitations:
- Word processing, spreadsheet, presentation and email reports carry an "Evaluation Only" mark; an XLSX report gets an extra "Evaluation Warning" worksheet. HTML and text reports carry none.
- A word-processing report stops after about 200 paragraphs: the rest of the template is not written.
assemble_documentstill returnsTrue.
To remove these limitations, apply a license or request a temporary license:
from groupdocs.assembly import License
License().set_license("path/to/license.lic")
Or set the environment variable, which is applied at the first call into the engine:
export GROUPDOCS_LIC_PATH="path/to/license.lic"
A license that cannot be applied raises LicenseError from that first call on, rather than falling back to evaluation mode.
Troubleshooting
| Issue | Platform | Fix |
|---|---|---|
The process aborts with Couldn't find a valid ICU package, or DOTNET_SYSTEM_GLOBALIZATION_INVARIANT errors |
Linux | Install ICU (apt-get install libicu-dev) and do NOT set this variable |
is not a supported wheel on this platform or No matching distribution found for groupdocs-assembly-net |
Linux/macOS | The OS is older than the wheel needs (glibc 2.27, macOS 12), or pip is older than 20.3: python -m pip install --upgrade pip. On an Intel Mac, a Python built against an old SDK reports macOS 10.16 - use pip 24.1+ or SYSTEM_VERSION_COMPAT=0 pip install groupdocs-assembly-net |
The type initializer for 'Gdip' threw an exception for a presentation template |
Linux/macOS | Install libgdiplus: apt-get install libgdiplus / brew install mono-libgdiplus |
Value cannot be null. (Parameter 'trueTypeFont') for a QR code |
Linux, or any system without the font | Install the font the QR code is drawn with, under that name: in a Word document, the document's default font (often Times New Roman); in a workbook, the font of the text box that holds the tag (Calibri in the .NET examples' Barcode.xlsx), not the Normal style. No other font stands in, not even DejaVu, Liberation or Carlito. Code 128, EAN-13 and Codabar need no particular font |
Can not get the value of member 'Month' on type 'System.Nullable...' |
All | A JsonDataSource, XmlDataSource or CsvDataSource value is nullable: write <<[o.OrderDate.Value.Month]>>, or load the JSON with json.load and pass the dicts |
Can not get the value of member 'X' on type 'System.Object' |
All | The data has an empty list and nothing says what its items are: give it one item, or set DocumentAssemblyOptions.ALLOW_MISSING_MEMBERS |
| "Café" shows as "Caf?" in a text or HTML report | All | Save the template with a UTF-8 byte order mark: without one the report is written in the Windows-1252 code page |
| The first call takes 15-30 seconds when a license is applied | Windows | The engine's license check, once per process (measured in plain .NET too). Reuse the process for many reports |
AttributeError: 'LoadSaveOptions' object has no attribute ... with a "Did you mean" hint |
All | The property name is misspelled; assigning it would have had no effect on the engine |
| "Evaluation Only" in the report, or a report that stops early | All | Evaluation mode: apply a license (above) |
System Requirements
- Python 3.5 - 3.14, pip 20.3 or newer
- Windows x64, Linux x64, macOS x64/ARM64 - 64-bit Python only; there is no 32-bit Windows wheel
- Linux: glibc 2.27 or newer (e.g. Ubuntu 18.04+, Debian 10+, RHEL 8+), plus ICU, libgdiplus and the fonts your templates use (
apt-get install libicu-dev libgdiplus fontconfig ttf-mscorefonts-installer) - macOS 12 or newer, Intel or Apple Silicon, plus
brew install mono-libgdiplus - libgdiplus serves presentations: without it a presentation template cannot be filled. Word processing, spreadsheet, email, HTML and text templates do not need it.
Upgrading from 25.5
- Linux and macOS wheels are new; Windows has a 64-bit wheel only (25.5 also had a 32-bit one).
- Python 3.5 to 3.14 (25.5: up to 3.13).
- A Python dict or list is a data source as it is:
DataSourceInfo(customer, "customer"). - One
DataSourceInfoor a list:assemble_document(src, dst, DataSourceInfo(...))andassemble_document(src, dst, [info1, info2])both work. - Two spellings changed:
BarcodeSettings.x_resolutionandy_resolutionarexresolutionandyresolution, and the old names raiseAttributeErrorwith a "Did you mean" hint;DocumentAssembler.set_use_reflection_optimization(False)isDocumentAssembler.use_reflection_optimization = False. Otherwise code written for 25.5 runs as it is: the 11 examples of the 25.5 examples repository that run without metered keys write the same reports with 26.11. - Exceptions: a template error or a member the data lacks raises
RuntimeError, with the engine's message naming the tag; a missing template or data file raisesFileNotFoundError; other engine errors raiseGroupDocsAssemblyException; a license that cannot be applied raisesLicenseError. The last two are importable fromgroupdocs.assembly.
More Resources
Also available for other platforms: .NET | Java | Node.js
Product Page | Docs | Demos | API Reference | Blog | Free Support | Temporary License
Metadata
Release files for groupdocs-assembly-net 26.11.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| groupdocs_assembly_net-26.11.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details for groupdocs_assembly_net-26.11.0-py3-none-win_amd64.whl |
| groupdocs_assembly_net-26.11.0-py3-none-manylinux_2_27_x86_64.whl | Python 3 | none | Linux glibc 2.27+ x86-64 | Details for groupdocs_assembly_net-26.11.0-py3-none-manylinux_2_27_x86_64.whl |
| groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_x86_64.whl | Python 3 | none | macOS 12.0+ x86-64 | Details for groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_x86_64.whl |
| groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_arm64.whl | Python 3 | none | macOS 12.0+ ARM64 | Details for groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_arm64.whl |
Total release size: 325.4 MB
Release files / groupdocs_assembly_net-26.11.0-py3-none-win_amd64.whl
| Download URL | groupdocs_assembly_net-26.11.0-py3-none-win_amd64.whl |
|---|---|
| Size | 81.3 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
dc2be3b61c3176367738b01ecf7bcb39851fd335e52b2779a2fcecd36aa3fe38
|
|
BLAKE2b-256 checksum How to use checksums |
0292e744bae62070e93920af491a9ea9cd4d29e6936c4f1071ae1af93a753791
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / groupdocs_assembly_net-26.11.0-py3-none-manylinux_2_27_x86_64.whl
| Download URL | groupdocs_assembly_net-26.11.0-py3-none-manylinux_2_27_x86_64.whl |
|---|---|
| Size | 81.2 MB |
| Tags | Linux glibc 2.27+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
e587c55b46b83e56f46218a2a006ad385875f9c6fb9ad20660a2210637f3bd1a
|
|
BLAKE2b-256 checksum How to use checksums |
1ae9c2b5150eb36886f6788a1422d2aafd4466db37015e3de378231c96177502
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_x86_64.whl
| Download URL | groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_x86_64.whl |
|---|---|
| Size | 82.6 MB |
| Tags | Python 3 macOS 12.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
a2be354bb4e48c180cb3e5cef6949ac822b01f709c21cb3f9203f4cea483fd5a
|
|
BLAKE2b-256 checksum How to use checksums |
004f407de00361836a9c1487c53e5faa9f2ed465592201dfd8708d61bba82cc6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_arm64.whl
| Download URL | groupdocs_assembly_net-26.11.0-py3-none-macosx_12_0_arm64.whl |
|---|---|
| Size | 80.3 MB |
| Tags | Python 3 macOS 12.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ee4cb44669fa8b38f29329139456f7ef3efa5a752292fe99c07005f4413f13d4
|
|
BLAKE2b-256 checksum How to use checksums |
871d0d1e6274ce70c188cff220f05e608593014223946496882ee97c0d3e2806
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Security for groupdocs-assembly-net 26.11.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.