Add replace_medias() utility (useful for header/footer images)
This commit is contained in:
parent
a4fa1b4f26
commit
b7947ca10c
@ -1,3 +1,7 @@
|
||||
0.4.0 (2017-09-03)
|
||||
------------------
|
||||
- Add replace_medias() utility (useful for header/footer images)
|
||||
|
||||
0.3.9 (2017-06-27)
|
||||
------------------
|
||||
- Fix exception in fix_table()
|
||||
|
||||
@ -165,6 +165,20 @@ in your python code ::
|
||||
in your docx template just use ``{{ mylisting }}``
|
||||
With ``Listing()``, you will keep the current character styling (except after a ``\a`` as you start a new paragraph).
|
||||
|
||||
Replace docx medias
|
||||
-------------------
|
||||
|
||||
It is not possible to dynamically add images in header/footer, but you can change them.
|
||||
The idea is to put a dummy picture in your template, render the template as usual, then replace the dummy picture with another one.
|
||||
You can do that for all medias at the same time.
|
||||
Note: for images, the aspect ratio will be the same as the replaced image
|
||||
Note2 : it is important to have the source media files as they are required to calculate their CRC to find them in the docx
|
||||
|
||||
Syntax to replace dummy_header_pic.jpg and dummy2.jpg in mydoc.docx::
|
||||
|
||||
replace_medias('mydoc.docx',[('dummy_header_pic.jpg','header_pic_i_want.jpg'),('dummy2.png','mycompany.png')])
|
||||
|
||||
|
||||
Jinja custom filters
|
||||
--------------------
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ Created : 2015-03-12
|
||||
@author: Eric Lapouyade
|
||||
'''
|
||||
|
||||
__version__ = '0.3.9'
|
||||
__version__ = '0.4.0'
|
||||
|
||||
from lxml import etree
|
||||
from docx import Document
|
||||
@ -14,6 +14,9 @@ from jinja2 import Template
|
||||
from cgi import escape
|
||||
import re
|
||||
import six
|
||||
import binascii
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
NEWLINE = '</w:t><w:br/><w:t xml:space="preserve">'
|
||||
NEWPARAGRAPH = '</w:t></w:r></w:p><w:p><w:r><w:t xml:space="preserve">'
|
||||
@ -297,6 +300,35 @@ class InlineImage(object):
|
||||
def __str__(self):
|
||||
return self.xml
|
||||
|
||||
def replace_medias(docx_filename,src_dst_lst):
|
||||
"""Utility function replace any media by another into a docx
|
||||
|
||||
This has been done mainly because it is not possible to add images in docx header/footer.
|
||||
With this function, put a dummy picture in your header/footer, then specify it with its replacement in this function
|
||||
|
||||
Syntax: replace_medias('mydoc.docx',[('dummy_header_pic.jpg','header_pic_i_want.jpg'),('dummy2.png','mycompany.png')])
|
||||
|
||||
Note: for images, the aspect ratio will be the same as the replaced image
|
||||
Note2 : it is important to have the source media files as they are required to calculate their CRC to find them in the docx
|
||||
"""
|
||||
crc_to_new_media = {}
|
||||
for src,dst in src_dst_lst:
|
||||
with open(src,'rb') as fh:
|
||||
buf = fh.read()
|
||||
crc = (binascii.crc32(buf) & 0xFFFFFFFF)
|
||||
with open(dst,'rb') as fh:
|
||||
crc_to_new_media[crc] = fh.read()
|
||||
|
||||
backup_filename = '%s_before_replace_medias' % docx_filename
|
||||
os.rename(docx_filename,backup_filename)
|
||||
|
||||
with zipfile.ZipFile(backup_filename) as zin:
|
||||
with zipfile.ZipFile(docx_filename, 'w') as zout:
|
||||
for item in zin.infolist():
|
||||
buf = zin.read(item.filename)
|
||||
if item.filename.startswith('word/media/') and item.CRC in crc_to_new_media:
|
||||
zout.writestr(item, crc_to_new_media[item.CRC])
|
||||
else:
|
||||
zout.writestr(item, buf)
|
||||
|
||||
os.remove(backup_filename)
|
||||
|
||||
20
tests/header_footer_image.py
Normal file
20
tests/header_footer_image.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Created : 2017-09-03
|
||||
|
||||
@author: Eric Lapouyade
|
||||
'''
|
||||
|
||||
from docxtpl import DocxTemplate, replace_medias
|
||||
|
||||
DEST_FILE = 'test_files/header_footer_image.docx'
|
||||
|
||||
tpl=DocxTemplate('test_files/header_footer_image_tpl.docx')
|
||||
|
||||
context = {
|
||||
'mycompany' : 'The World Wide company',
|
||||
}
|
||||
|
||||
tpl.render(context)
|
||||
tpl.save(DEST_FILE)
|
||||
replace_medias(DEST_FILE,[('test_files/dummy_pic_for_header.png','test_files/python.png')])
|
||||
@ -2,7 +2,7 @@ import subprocess
|
||||
import glob
|
||||
import six
|
||||
|
||||
tests = glob.glob('[A-Za-z]*.py')
|
||||
tests = sorted(glob.glob('[A-Za-z]*.py'))
|
||||
excludes = ['runtests.py']
|
||||
|
||||
for test in tests:
|
||||
|
||||
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