Add subdoc support
This commit is contained in:
parent
80a10956ed
commit
028820f3dd
@ -1,2 +1,5 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
encoding//docxtpl/__init__.py=utf-8
|
encoding//docxtpl/__init__.py=utf-8
|
||||||
|
encoding//tests/cellbg.py=utf-8
|
||||||
|
encoding//tests/order.py=utf-8
|
||||||
|
encoding//tests/subdoc.py=utf-8
|
||||||
|
|||||||
@ -1,3 +1,8 @@
|
|||||||
0.1.2 (2015-03-13)
|
0.1.3 (2015-03-13)
|
||||||
|
------------------
|
||||||
|
- add subdoc support
|
||||||
|
- add some exemples in tests/
|
||||||
|
|
||||||
|
0.1.2 (2015-03-12)
|
||||||
------------------
|
------------------
|
||||||
- First running version
|
- First running version
|
||||||
@ -21,9 +21,17 @@ class DocxTemplate(object):
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self.docx, name)
|
return getattr(self.docx, name)
|
||||||
|
|
||||||
def build_xml(self,context):
|
def get_docx(self):
|
||||||
src_xml = etree.tostring(self.docx._element.body, pretty_print=True)
|
return self.docx
|
||||||
|
|
||||||
|
def get_xml(self):
|
||||||
|
return etree.tostring(self.docx._element.body, pretty_print=True)
|
||||||
|
|
||||||
|
def write_xml(self,filename):
|
||||||
|
with open(filename,'w') as fh:
|
||||||
|
fh.write(self.get_xml())
|
||||||
|
|
||||||
|
def patch_xml(self,src_xml):
|
||||||
# strip all xml tags inside {% %} and {{ }}
|
# strip all xml tags inside {% %} and {{ }}
|
||||||
# that Microsoft word can insert into xml code for this part of the document
|
# that Microsoft word can insert into xml code for this part of the document
|
||||||
def striptags(m):
|
def striptags(m):
|
||||||
@ -34,23 +42,29 @@ class DocxTemplate(object):
|
|||||||
def cellbg(m):
|
def cellbg(m):
|
||||||
cell_xml = m.group(1) + m.group(3)
|
cell_xml = m.group(1) + m.group(3)
|
||||||
cell_xml = re.sub(r'<w:r[ >](?:(?!<w:r[ >]).)*<w:t></w:t>.*?</w:r>','',cell_xml,flags=re.DOTALL)
|
cell_xml = re.sub(r'<w:r[ >](?:(?!<w:r[ >]).)*<w:t></w:t>.*?</w:r>','',cell_xml,flags=re.DOTALL)
|
||||||
return re.sub(r'(<w:shd[^/]*w:fill=")[^"]*("[^/]*/>)',r'\1{{ %s}}\2' % m.group(2), cell_xml)
|
cell_xml = re.sub(r'<w:shd[^/]*/>','', cell_xml, count=1)
|
||||||
|
return re.sub(r'(<w:tcPr[^>]*>)',r'\1<w:shd w:val="clear" w:color="auto" w:fill="{{%s}}"/>' % m.group(2), cell_xml)
|
||||||
src_xml = re.sub(r'(<w:tc[ >](?:(?!<w:tc[ >]).)*){%\s*cellbg\s+([^%]*)\s*%}(.*?</w:tc>)',cellbg,src_xml,flags=re.DOTALL)
|
src_xml = re.sub(r'(<w:tc[ >](?:(?!<w:tc[ >]).)*){%\s*cellbg\s+([^%]*)\s*%}(.*?</w:tc>)',cellbg,src_xml,flags=re.DOTALL)
|
||||||
|
|
||||||
# replace xml code corresponding to the paragraph containing {{{ xxx }}} by {{ xxx }}
|
for y in ['tr', 'p', 'r']:
|
||||||
src_xml = re.sub(r'<w:p[ >](?:(?!<w:p[ >]).)*{{{([^}]*)}}}.*?</w:p>',r'{{\1}}',src_xml,flags=re.DOTALL)
|
# replace into xml code the row containing {%y xxx %} or {{y xxx}} template tag
|
||||||
|
# by {% xxx %} or {{ xx }} without any surronding xml tags.
|
||||||
|
pat = r'<w:%(y)s[ >](?:(?!<w:%(y)s[ >]).)*({%%|{{)%(y)s ([^}%%]*(?:%%}|}})).*?</w:%(y)s>' % {'y':y}
|
||||||
|
src_xml = re.sub(pat, r'\1 \2',src_xml,flags=re.DOTALL)
|
||||||
|
|
||||||
# replace xml code corresponding to the row containing {% tr-xxx template tag by {% xxx template tag itself
|
return src_xml
|
||||||
src_xml = re.sub(r'<w:tr[ >](?:(?!<w:tr[ >]).)*{%\s*tr-([^%]*%}).*?</w:tr>',r'{% \1',src_xml,flags=re.DOTALL)
|
|
||||||
|
|
||||||
# replace xml code corresponding to the paragraph containing {% p-xxx template tag by {% xxx template tag itself
|
|
||||||
src_xml = re.sub(r'<w:p[ >](?:(?!<w:p[ >]).)*{%\s*p-([^%]*%}).*?</w:p>',r'{% \1',src_xml,flags=re.DOTALL)
|
|
||||||
|
|
||||||
|
def render_xml(self,src_xml,context):
|
||||||
template = Template(src_xml)
|
template = Template(src_xml)
|
||||||
dst_xml = template.render(context)
|
dst_xml = template.render(context)
|
||||||
|
|
||||||
return dst_xml
|
return dst_xml
|
||||||
|
|
||||||
|
def build_xml(self,context):
|
||||||
|
xml = self.get_xml()
|
||||||
|
xml = self.patch_xml(xml)
|
||||||
|
xml = self.render_xml(xml, context)
|
||||||
|
return xml
|
||||||
|
|
||||||
def map_xml(self,xml):
|
def map_xml(self,xml):
|
||||||
root = self.docx._element
|
root = self.docx._element
|
||||||
body = root.body
|
body = root.body
|
||||||
@ -60,9 +74,27 @@ class DocxTemplate(object):
|
|||||||
xml = self.build_xml(context)
|
xml = self.build_xml(context)
|
||||||
self.map_xml(xml)
|
self.map_xml(xml)
|
||||||
|
|
||||||
|
def new_subdoc(self):
|
||||||
|
return Subdoc(self)
|
||||||
|
|
||||||
class Subdoc(object):
|
class Subdoc(object):
|
||||||
""" Class for subdocumentation insertion into master document """
|
""" Class for subdocumentation insertion into master document """
|
||||||
pass
|
def __init__(self, tpl):
|
||||||
|
self.tpl = tpl
|
||||||
|
self.docx = tpl.get_docx()
|
||||||
|
self.subdocx = Document()
|
||||||
|
self.subdocx._part = self.docx._part
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self.subdocx, name)
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
xml = ''
|
||||||
|
for p in self.paragraphs:
|
||||||
|
xml += '<w:p>\n' + re.sub(r'^.*\n', '', etree.tostring(p._element,pretty_print=True))
|
||||||
|
return xml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Tpldoc(object):
|
class Tpldoc(object):
|
||||||
""" class to build documenation to be passed into template variables """
|
""" class to build documenation to be passed into template variables """
|
||||||
|
|||||||
2
setup.py
2
setup.py
@ -24,7 +24,7 @@ News
|
|||||||
""" % read('README', 'CHANGES')
|
""" % read('README', 'CHANGES')
|
||||||
|
|
||||||
setup(name='docxtpl',
|
setup(name='docxtpl',
|
||||||
version='0.1.2',
|
version='0.1.3',
|
||||||
description='Python docx template engine',
|
description='Python docx template engine',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
classifiers=[
|
classifiers=[
|
||||||
|
|||||||
22
tests/cellbg.py
Normal file
22
tests/cellbg.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
Created : 2015-03-12
|
||||||
|
|
||||||
|
@author: Eric Lapouyade
|
||||||
|
'''
|
||||||
|
|
||||||
|
from docxtpl import DocxTemplate
|
||||||
|
|
||||||
|
tpl=DocxTemplate('test_files/cellbg_tpl.docx')
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'alerts' : [
|
||||||
|
{'date' : '2015-03-10', 'desc' : 'Very critical alert', 'type' : 'CRITICAL', 'bg': 'FF0000' },
|
||||||
|
{'date' : '2015-03-11', 'desc' : 'Just a warning', 'type' : 'WARNING', 'bg': 'FFDD00' },
|
||||||
|
{'date' : '2015-03-12', 'desc' : 'Information', 'type' : 'INFO', 'bg': '8888FF' },
|
||||||
|
{'date' : '2015-03-13', 'desc' : 'Debug trace', 'type' : 'DEBUG', 'bg': 'FF00FF' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl.render(context)
|
||||||
|
tpl.save('test_files/cellbg.docx')
|
||||||
@ -1,3 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
Created : 2015-03-12
|
||||||
|
|
||||||
|
@author: Eric Lapouyade
|
||||||
|
'''
|
||||||
|
|
||||||
from docxtpl import DocxTemplate
|
from docxtpl import DocxTemplate
|
||||||
|
|
||||||
tpl=DocxTemplate('test_files/order_tpl.docx')
|
tpl=DocxTemplate('test_files/order_tpl.docx')
|
||||||
|
|||||||
25
tests/subdoc.py
Normal file
25
tests/subdoc.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
Created : 2015-03-12
|
||||||
|
|
||||||
|
@author: Eric Lapouyade
|
||||||
|
'''
|
||||||
|
|
||||||
|
from docxtpl import DocxTemplate
|
||||||
|
|
||||||
|
tpl=DocxTemplate('test_files/subdoc_tpl.docx')
|
||||||
|
|
||||||
|
sd = tpl.new_subdoc()
|
||||||
|
p = sd.add_paragraph('This is a sub-document inserted into a bigger one')
|
||||||
|
p = sd.add_paragraph('It has been ')
|
||||||
|
p.add_run('dynamically').style = 'dynamic'
|
||||||
|
p.add_run(' generated with python by using ')
|
||||||
|
p.add_run('python-docx').italic = True
|
||||||
|
p.add_run(' library')
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'mysubdoc' : sd,
|
||||||
|
}
|
||||||
|
|
||||||
|
tpl.render(context)
|
||||||
|
tpl.save('test_files/subdoc.docx')
|
||||||
BIN
tests/test_files/cellbg.docx
Normal file
BIN
tests/test_files/cellbg.docx
Normal file
Binary file not shown.
BIN
tests/test_files/cellbg_tpl.docx
Normal file
BIN
tests/test_files/cellbg_tpl.docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/test_files/subdoc.docx
Normal file
BIN
tests/test_files/subdoc.docx
Normal file
Binary file not shown.
BIN
tests/test_files/subdoc_tpl.docx
Normal file
BIN
tests/test_files/subdoc_tpl.docx
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user