First running version

This commit is contained in:
elapouya 2015-03-13 11:59:50 +01:00
parent d8a33febe0
commit e9b9a8bf3f
8 changed files with 98 additions and 1 deletions

17
.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>python-docx-template</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>

5
.pydevproject Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
</pydev_project>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding//docxtpl/__init__.py=utf-8

View File

@ -7,10 +7,64 @@ Created : 2015-03-12
__version__ = '0.1.1'
from lxml import etree
from docx import Document
from jinja2 import Template
import copy
import re
class DocxTemplate(object):
""" Class for managing docx files as they were jinja2 templates """
pass
def __init__(self, docx):
self.docx = Document(docx)
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)
with open('/tmp/docx1.xml','w') as fh:
fh.write(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):
return re.sub('</w:t>.*?(<w:t>|<w:t [^>]*>)','',m.group(0),flags=re.DOTALL)
src_xml = re.sub(r'{%(?:(?!%}).)*|{{(?:(?!}}).)*',striptags,src_xml,flags=re.DOTALL)
# manage table cell background color
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)
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)
# 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)
with open('/tmp/docx2.xml','w') as fh:
fh.write(src_xml)
template = Template(src_xml)
dst_xml = template.render(context)
return dst_xml
def map_xml(self,xml):
root = self.docx._element
body = root.body
root.replace(body,etree.fromstring(xml))
def render(self,context):
xml = self.build_xml(context)
self.map_xml(xml)
class Subdoc(object):
""" Class for subdocumentation insertion into master document """

0
tests/__init__.py Normal file
View File

19
tests/order.py Normal file
View File

@ -0,0 +1,19 @@
from docxtpl import DocxTemplate
tpl=DocxTemplate('test_files/order_tpl.docx')
context = {
'customer_name' : 'Eric',
'items' : [
{'desc' : 'Python interpreters', 'qty' : 2, 'price' : 'FREE' },
{'desc' : 'Django projects', 'qty' : 5403, 'price' : 'FREE' },
{'desc' : 'Guido', 'qty' : 1, 'price' : '100,000,000.00' },
],
'in_europe' : True,
'is_paid': False,
'company_name' : 'The World Wide company',
'total_price' : '100,000,000.00'
}
tpl.render(context)
tpl.save('test_files/order.docx')

BIN
tests/test_files/order.docx Normal file

Binary file not shown.

Binary file not shown.