Skip to content
This repository has been archived by the owner on Apr 16, 2022. It is now read-only.

rewrite to support formatting and nesting fields #103

Open
wants to merge 89 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
8d6aa2e
reimplemented the base docx-mailmerge functionality, support for form…
iulica Mar 4, 2022
245c659
removed IF MergeElement and only update the inner MERGEFIELDS
iulica Mar 5, 2022
f11752a
added support for updateFields setting
iulica Mar 6, 2022
bb9c90c
cleaned up the code, removed support for IF, added implemented auto_u…
iulica Mar 6, 2022
fbcc2bc
more verbose error messages
iulica Mar 7, 2022
3dca645
fixed the complex fields when span over multiple paragraphs
iulica Mar 7, 2022
e7cfef4
complete tests, added a workaround to make tests happy for section ty…
iulica Mar 8, 2022
dd3f592
make more tests happy
iulica Mar 8, 2022
68b1327
make all tests happy
iulica Mar 8, 2022
256cf22
make tests happy
iulica Mar 8, 2022
59f2040
test_merge_template_with_rows
iulica Mar 8, 2022
f3fac1f
formatting tests and framework for easier testing
iulica Mar 8, 2022
783d28c
fixes for nested simple Fields and tests for nested fields
iulica Mar 8, 2022
076e191
added tests for auto fields udpate flag
iulica Mar 8, 2022
78c4f90
test for warnings (removing the warnings from the unittest run), impl…
iulica Mar 9, 2022
e0c9604
changed the documentation to reflect the changes
iulica Mar 9, 2022
a0ca1f6
Update README.rst
iulica Mar 13, 2022
e07d5d3
Update README.rst
iulica Mar 14, 2022
0d10293
Update README.rst
iulica Mar 22, 2022
914f811
Create auto_assign-issues.yml
iulica Mar 22, 2022
53b1b66
publish workflow
iulica Apr 1, 2022
af1a967
Update setup.py for version 0.6.0
iulica Apr 1, 2022
b32bf3b
Updated the package name and removed travis CI
iulica Apr 1, 2022
2e3ad7f
fix install command to docx-mailmerge2
iulica Apr 1, 2022
446c70c
Fixed number formatting when value is None
iulica Apr 5, 2022
c226d9f
refactoring to prepare the NEXT and NEXTIF fields implementation
iulica Apr 5, 2022
d30435d
gitignore
iulica Apr 6, 2022
5d33d00
(failed) test for issue #4
iulica Apr 6, 2022
5c4a5c9
add support for fixing the id duplicates issue #4
iulica Apr 6, 2022
443725b
Wish list update
iulica Apr 8, 2022
e53c4cc
added support for test output docx instead of temporary file for debu…
iulica Apr 15, 2022
f8e699c
added an workaround for IF fields containing text values with spaces …
iulica Apr 15, 2022
b12c7c0
added support for apostrophes for currency thousand separators with t…
iulica Apr 15, 2022
4f1190d
implemented date formatting support
iulica Apr 15, 2022
3740614
Release 0.6.2. Added support for Date formatting. Issues #5 #57
iulica Apr 16, 2022
e0c8e9a
implemented NEXT field #4
iulica Apr 16, 2022
bd7175c
fixed NEXT field #4
iulica Apr 18, 2022
55ce8ca
Update TODO list
iulica Apr 20, 2022
6b80124
Update README.rst
iulica Dec 18, 2022
5b1b69a
prepare release 0.6.3
iulica Oct 12, 2023
4945f33
added footnotes+xml to content_types_part
402Martin Oct 16, 2023
7939ebe
Merge pull request #13 from 402Martin/master
iulica Oct 16, 2023
3e45bf0
Revert "Added content type footnotes+xml so mail merge fields are sup…
iulica Oct 16, 2023
edbbac3
Merge pull request #14 from iulica/revert-13-master
iulica Oct 16, 2023
1e6fc8a
Adds test for merge footnotes
iulica Oct 24, 2023
1e256e0
adding support for endnotes and macro enabled documents
iulica Oct 24, 2023
4a313a0
Refactored MergeField class.
iulica Oct 26, 2023
3cbc7f2
Added support for keeping fields in the document.
iulica Oct 27, 2023
a57da5c
prepare release 0.7.0
iulica Oct 27, 2023
22dc108
Refactor duplicate_id_map to its own class UniqueIdsManager
iulica Nov 9, 2023
4ddc603
Added support for header/footer for merge_templates #17
iulica Nov 10, 2023
dae81c3
prepare v0.8.0
iulica Jan 16, 2024
9fb68e5
Update README.rst
iulica Jan 18, 2024
dc42458
Update README.rst
iulica Jan 23, 2024
42dc54d
ruffed
iulica Jul 19, 2024
7338d79
Added failed test for multiple tables with the same anchor
iulica Jul 19, 2024
544680b
Fix case where multiple table contain the same anchor. Issue #24
iulica Jul 19, 2024
f02a517
setup version 0.8.1
iulica Jul 19, 2024
1d2ad75
fix for empty fields, #25
iulica Sep 19, 2024
51a8db7
add test for empty field #25
iulica Sep 19, 2024
02cf82e
setup version 0.8.2
iulica Sep 19, 2024
d7206dc
fix for python 3.7
iulica Sep 27, 2024
f2f2a82
setup version 0.8.3
iulica Sep 27, 2024
823e9b0
Moved to pyproject.toml
iulica Dec 26, 2024
bd36953
Ruffed all code
iulica Dec 26, 2024
b72a012
Make pylance happy, with older version of lxml
iulica Dec 26, 2024
09e06ca
Ruff and flake8 warnings fixed
iulica Dec 26, 2024
3a96325
fix
iulica Dec 26, 2024
4260f68
make tox happy and include ruff
iulica Dec 26, 2024
cb15c66
ruffed
iulica Dec 26, 2024
475becf
Moved mailmerge to src-layout
iulica Dec 26, 2024
96e8568
Refactor: move classes to own files
iulica Dec 26, 2024
457b785
Refactor: move parts and relations to own file
iulica Dec 26, 2024
2455546
Refactor: move new_parts from tuple to Class
iulica Dec 26, 2024
8de1112
fix test with new parts
iulica Dec 26, 2024
c6662ce
various fixes
iulica Dec 26, 2024
c147259
refactor remove_empty_tables attribute
iulica Dec 26, 2024
528f6ca
Refactor: move the settings to their own class and deprecate setting …
iulica Dec 26, 2024
87ab891
Refactor: moved parsing fields into Part class, docx operations into …
iulica Dec 26, 2024
df461c6
commit
iulica Dec 26, 2024
bfa3683
make ruff happy in vscode
iulica Dec 26, 2024
38ffc2a
make ruff happy in vscode
iulica Dec 26, 2024
9c9de21
Fix cases where the before and/or after switches have paragraphs. #29
iulica Dec 27, 2024
268046f
Added test (expected failure) for the case where there is a nested fi…
iulica Dec 28, 2024
ce1ba0f
Enable nested fields. Change <br> to <cr> for the right new paragraph…
iulica Dec 28, 2024
ec7db7b
Add experimental support for IF fields and support for SKIPIF and NEX…
iulica Dec 29, 2024
b6b38e1
update the README
iulica Dec 29, 2024
6bd9eda
Version 0.9.0
iulica Dec 29, 2024
3b16162
Update README.rst
iulica Dec 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/auto_assign-issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# If enabled, auto-assigns users when a new issue is created
# Defaults to true, allows you to install the app globally, and disable on a per-repo basis
addAssignees: true

# The list of users to assign to new issues.
# If empty or not provided, the repository owner is assigned
assignees:
- iulica
36 changes: 36 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI

on:
release:
types: [published]

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
.env
/.tox/
*.pyc
*.egg-info
dist
*.code-workspace
.DS_Store
/tests/old
/tests/output
3 changes: 2 additions & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Copyright (C) 2012 Bouke Haarsma
Copyright (C) 2012 Bouke Haarsma, https://github.com/Bouke
Copyright (C) 2023 Iulian Ciorascu, https://github.com/iulica

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
123 changes: 106 additions & 17 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
docx Mail Merge
===============

.. image:: https://travis-ci.org/Bouke/docx-mailmerge.png?branch=master
:alt: Build Status
:target: https://travis-ci.org/Bouke/docx-mailmerge

.. image:: https://badge.fury.io/py/docx-mailmerge.png
.. image:: https://badge.fury.io/py/docx-mailmerge2.png
:alt: PyPI
:target: https://pypi.python.org/pypi/docx-mailmerge
:target: https://pypi.python.org/pypi/docx-mailmerge2

Performs a Mail Merge on Office Open XML (docx) files. Can be used on any
system without having to install Microsoft Office Word. Supports Python 2.7,
Expand All @@ -20,7 +16,7 @@ Installation
Installation with ``pip``:
::

$ pip install docx-mailmerge
$ pip install docx-mailmerge2


Usage
Expand All @@ -30,14 +26,18 @@ Open the file.
::

from mailmerge import MailMerge
with MailMerge('input.docx') as document:
with MailMerge('input.docx',
remove_empty_tables=False,
auto_update_fields_on_open="no",
keep_fields="none",
enable_experimnetal=False) as document:
...


List all merge fields.
::

print document.get_merge_fields()
print(document.get_merge_fields())


Merge fields, supplied as kwargs.
Expand All @@ -50,6 +50,9 @@ Merge table rows. In your template, add a MergeField to the row you would like
to designate as template. Supply the name of this MergeField as ``anchor``
parameter. The second parameter contains the rows with key-value pairs for
the MergeField replacements.

If the tables are empty and you want them removed, set remove_empty_tables=True
in constructor.
::

document.merge_rows('col1',
Expand All @@ -72,11 +75,8 @@ single call to `merge`.
Starting in version 0.2.0 there's also the feature for template merging.
This creates a copy of the template for each item in the list, does a merge,
and separates them by page or section breaks (see function documentation).

When using this feature, make sure you don't use comments, footnotes,
bookmarks, etc. This is because these elements have an id attribute, which
must be unique. This library does not handle this, resulting in invalid
documents.
Starting in version 0.8.0 you can also use fields in the headers/footers/footnotes
with the merge_templates method.
::

document.merge_templates([
Expand All @@ -85,20 +85,105 @@ documents.
], separator='page_break')


Starting in version 0.6.0 the fields formatting is respected when compatible.
Numeric, Text, Conditional and Date fields (0.6.2) are implemented.
For Date fields a compatible datetime, date or time objects must be provided.
If locale support is needed, make sure to call the setlocale before merging
::

import locale
locale.setlocale(locale.LC_TIME, '') # for system locale

document.merge_templates([
{'datefield': datetime.date('2022-04-15')},
], separator='page_break')

The {NEXT} fields are supported (0.6.3).

You can also use the merge fields inside other fields, for example to insert
pictures in the docx {INCLUDEPICTURE} or for conditional texts {IF}.
Microsoft Word is needed to update the values of those fields.
::

{ INCLUDEPICTURE "{ MERGEFIELD path }/{ MERGEFIELD image }" }
{ IF "{ MERGEFIELD reason }" <> "" "Reason: { MERGEFIELD reason }" }

Always enclose the fields with double quotes, as the MERGE fields will be first
filled in with data and then the other fields will be computed through Word.

If the fields are nested inside other fields, the outer fields need to be
updated in Word. This can be done by selecting everything (CTRL-a) and then
update the fields (F9). There is a way to force the Word to update fields
automatically when opening the document. docx-mailmerge can set this
setting when saving the document. You can configure this feature by using
the *auto_update_fields_on_open* parameter. The value *always* will set the
setting regardless if needed or not and the value *auto* will only set it
when necessary (when nested fields exist). The default value *no* will not
activate this setting.

The {NEXTIF} and {SKIPIF} fields are supported (0.9.0).
The {IF} fields are supported (0.9.0) only if the enable_experimnetal=True is
set.
The condition can use nested fields. Spaces are *MANDATORY* before and after
the operator (<, <>, >, <=, >=, =). The values are better enclosed in double
quotes. For <> and = operators, the Microsoft-style regular expressions are
supported (?, \*).

Write document to file. This should be a new file, as ``ZipFile`` cannot modify
existing zip files.
::

document.write('output.docx')

By default, all MERGEFIELD fields are replaced with their value. If a value is
not given, it is replaced with an empty string.
If you want to keep the existing MERGEFIELD fields (with their current value)
you can specify the keep_fields="some" parameter in the constructor.
::

from mailmerge import MailMerge
with MailMerge('keep_unchanged_fields.docx',
keep_fields="some") as document:
...

If you want to only update the value of the MERGEFIELD fields but keep the
fields themselves, you can specify the keep_fields="all" parameter in the
constructor. This way, you can change the document and update the fields again
later.
::

from mailmerge import MailMerge
with MailMerge('keep_all_fields.docx',
keep_fields="all") as document:
...


See also the unit tests and this nice write-up `Populating MS Word Templates
with Python`_ on Practical Business Python for more information and examples.

Inserting Dynamic Images
========================

To include dynamic images in a docx template document you can use the
{ INCLUDEPICTURE "...." } field. For the path you can use MERGEFIELD dynamic
fields. See example above.

The problem is to actually include the images in the word document after the
mailmerge. This can be done by opening the merged docx in Microsoft Word,
selecting all the text and pressing the F9 to update all fields. Unfortunately
this method needs Microsoft Word installed and it is known to cause a lot of
problems.

Another solution would be to use the `docx-mergefields`_ package to replace the
INCLUDEPICTURE fields with the actual image. This method also works with images
loaded from a database in base64 data-uri format, as well as URLs and local images.

See the documentation of `docx-mergefields`_ for examples.

Todo / Wish List
================

* Image merging.

* Better support for the IF fields and conditions

Contributing
============
Expand All @@ -119,7 +204,11 @@ unit test that demonstrates it. Run the test suite::
Credits
=======

This library was written by `Bouke Haarsma`_ and contributors.
| This library was `originally`_ written by `Bouke Haarsma`_ and contributors.
| This repository is maintained by `Iulian Ciorăscu`_.

.. _Bouke Haarsma: https://twitter.com/BoukeHaarsma
.. _Populating MS Word Templates with Python: http://pbpython.com/python-word-template.html
.. _originally: https://github.com/Bouke/docx-mailmerge
.. _Iulian Ciorăscu: https://github.com/iulica/
.. _docx-mergefields: https://github.com/iulica/docx-mergefields
Loading