Add subdoc support
This commit is contained in:
parent
80a10956ed
commit
028820f3dd
@ -1,2 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
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
|
||||
@ -21,9 +21,17 @@ class DocxTemplate(object):
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.docx, name)
|
||||
|
||||
def build_xml(self,context):
|
||||
src_xml = etree.tostring(self.docx._element.body, pretty_print=True)
|
||||
def get_docx(self):
|
||||
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 {{ }}
|
||||
# that Microsoft word can insert into xml code for this part of the document
|
||||
def striptags(m):
|
||||
@ -34,23 +42,29 @@ class DocxTemplate(object):
|
||||
def cellbg(m):
|
||||
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)
|
||||
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)
|
||||
|
||||
# replace xml code corresponding to the paragraph containing {{{ xxx }}} by {{ xxx }}
|
||||
src_xml = re.sub(r'<w:p[ >](?:(?!<w:p[ >]).)*{{{([^}]*)}}}.*?</w:p>',r'{{\1}}',src_xml,flags=re.DOTALL)
|
||||
for y in ['tr', 'p', 'r']:
|
||||
# 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
|
||||
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)
|
||||
return src_xml
|
||||
|
||||
def render_xml(self,src_xml,context):
|
||||
template = Template(src_xml)
|
||||
dst_xml = template.render(context)
|
||||
|
||||
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):
|
||||
root = self.docx._element
|
||||
body = root.body
|
||||
@ -60,9 +74,27 @@ class DocxTemplate(object):
|
||||
xml = self.build_xml(context)
|
||||
self.map_xml(xml)
|
||||
|
||||
def new_subdoc(self):
|
||||
return Subdoc(self)
|
||||
|
||||
class Subdoc(object):
|
||||
""" 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 to build documenation to be passed into template variables """
|
||||
|
||||
2
setup.py
2
setup.py
@ -24,7 +24,7 @@ News
|
||||
""" % read('README', 'CHANGES')
|
||||
|
||||
setup(name='docxtpl',
|
||||
version='0.1.2',
|
||||
version='0.1.3',
|
||||
description='Python docx template engine',
|
||||
long_description=long_description,
|
||||
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
|
||||
|
||||
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