Add horizontal merge '{% hm %}' tag support
This commit is contained in:
parent
8b351236f7
commit
9aa6019d25
@ -252,11 +252,15 @@ And in your template, use the {{r notation::
|
||||
Tables
|
||||
------
|
||||
|
||||
You can span table cells in two ways, horizontally (see tests/dynamic_table.py) by using::
|
||||
You can span table cells horizontally in two ways, by using ``colspan`` tag (see tests/dynamic_table.py)::
|
||||
|
||||
{% colspan <number of column to span> %}
|
||||
|
||||
or vertically within a for loop (see tests/vertical_merge.py)::
|
||||
or within a for loop (see tests/horizontal_merge.py)::
|
||||
|
||||
{% hm %}
|
||||
|
||||
You can also merge cells vertically within a for loop (see tests/vertical_merge.py)::
|
||||
|
||||
{% vm %}
|
||||
|
||||
|
||||
@ -98,8 +98,8 @@ class DocxTemplate(object):
|
||||
|
||||
# add vMerge
|
||||
# use {% vm %} to make this table cell and its copies be vertically merged within a {% for %}
|
||||
def tc(m):
|
||||
def vMerge(m1):
|
||||
def v_merge_tc(m):
|
||||
def v_merge(m1):
|
||||
return (
|
||||
'<w:vMerge w:val="{% if loop.first %}restart{% else %}continue{% endif %}"/>' +
|
||||
m1.group(1) + # Everything between ``</w:tcPr>`` and ``<w:t>``.
|
||||
@ -111,11 +111,61 @@ class DocxTemplate(object):
|
||||
)
|
||||
return re.sub(
|
||||
r'(</w:tcPr[ >].*?<w:t(?:.*?)>)(.*?)(?:{%\s*vm\s*%})(.*?)(</w:t>)',
|
||||
vMerge,
|
||||
v_merge,
|
||||
m.group(), # Everything between ``</w:tc>`` and ``</w:tc>`` with ``{% vm %}`` inside.
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
src_xml = re.sub(r'<w:tc[ >](?:(?!<w:tc[ >]).)*?{%\s*vm\s*%}.*?</w:tc[ >]', tc, src_xml, flags=re.DOTALL)
|
||||
src_xml = re.sub(r'<w:tc[ >](?:(?!<w:tc[ >]).)*?{%\s*vm\s*%}.*?</w:tc[ >]', v_merge_tc, src_xml, flags=re.DOTALL)
|
||||
|
||||
# Use ``{% hm %}`` to make table cell become horizontally merged within
|
||||
# a ``{% for %}``.
|
||||
def h_merge_tc(m):
|
||||
xml_to_patch = m.group() # Everything between ``</w:tc>`` and ``</w:tc>`` with ``{% hm %}`` inside.
|
||||
|
||||
def with_gridspan(m1):
|
||||
return (
|
||||
m1.group(1) + # ``w:gridSpan w:val="``.
|
||||
'{{ ' + m1.group(2) + ' * loop.length }}' + # Content of ``w:val``, multiplied by loop length.
|
||||
m1.group(3) # Closing quotation mark.
|
||||
)
|
||||
|
||||
def without_gridspan(m2):
|
||||
return (
|
||||
'<w:gridSpan w:val="{{ loop.length }}"/>' +
|
||||
m2.group(1) + # Everything between ``</w:tcPr>`` and ``<w:t>``.
|
||||
m2.group(2) + # Everything before ``{% hm %}``.
|
||||
m2.group(3) + # Everything after ``{% hm %}``.
|
||||
m2.group(4) # ``</w:t>``.
|
||||
)
|
||||
|
||||
if re.search(r'w:gridSpan', xml_to_patch):
|
||||
# Simple case, there's already ``gridSpan``, multiply its value.
|
||||
|
||||
xml = re.sub(
|
||||
r'(w:gridSpan w:val=")(\d+)(")',
|
||||
with_gridspan,
|
||||
xml_to_patch,
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
xml = re.sub(
|
||||
r'{%\s*hm\s*%}',
|
||||
'',
|
||||
xml, # Patched xml.
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
else:
|
||||
# There're no ``gridSpan``, add one.
|
||||
xml = re.sub(
|
||||
r'(</w:tcPr[ >].*?<w:t(?:.*?)>)(.*?)(?:{%\s*hm\s*%})(.*?)(</w:t>)',
|
||||
without_gridspan,
|
||||
xml_to_patch,
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
|
||||
# Discard every other cell generated in loop.
|
||||
return "{% if loop.first %}" + xml + "{% endif %}"
|
||||
|
||||
src_xml = re.sub(r'<w:tc[ >](?:(?!<w:tc[ >]).)*?{%\s*hm\s*%}.*?</w:tc[ >]', h_merge_tc, src_xml, flags=re.DOTALL)
|
||||
|
||||
def clean_tags(m):
|
||||
return m.group(0).replace(r"‘","'").replace('<','<').replace('>','>')
|
||||
|
||||
7
tests/horizontal_merge.py
Normal file
7
tests/horizontal_merge.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from docxtpl import DocxTemplate
|
||||
|
||||
tpl = DocxTemplate('test_files/horizontal_merge_tpl.docx')
|
||||
tpl.render({})
|
||||
tpl.save('test_files/horizontal_merge.docx')
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/test_files/horizontal_merge.docx
Normal file
BIN
tests/test_files/horizontal_merge.docx
Normal file
Binary file not shown.
BIN
tests/test_files/horizontal_merge_tpl.docx
Normal file
BIN
tests/test_files/horizontal_merge_tpl.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user