Текст-заменить в docx и сохранить измененный файл с помощью python-docx
Я пытаюсь использовать модуль python-docx чтобы заменить слово в файле и сохранить новый файл с оговоркой, что новый файл должен иметь точно такое же форматирование, как и старый файл, но с замененным словом. Как мне это сделать?
модуль docx имеет savedocx, который принимает 7 входов:
- документ
- coreprops
- appprops
- contenttypes
- websettings
- wordrelationships
- выход
Как сохранить все в исходном файле, за исключением замененного слова?
6 ответов
как кажется, Docx для Python не предназначен для хранения полного Docx с изображениями, заголовками, ... , но содержит только внутреннее содержание документа. Поэтому нет простого способа сделать это.
правда, вот как вы могли бы сделать это:
во-первых, посмотрите на тег docx wiki:
это объясняет, как файл docx может быть распакован: вот как выглядит типичный файл:
+--docProps
| + app.xml
| \ core.xml
+ res.log
+--word //this folder contains most of the files that control the content of the document
| + document.xml //Is the actual content of the document
| + endnotes.xml
| + fontTable.xml
| + footer1.xml //Containst the elements in the footer of the document
| + footnotes.xml
| +--media //This folder contains all images embedded in the word
| | \ image1.jpeg
| + settings.xml
| + styles.xml
| + stylesWithEffects.xml
| +--theme
| | \ theme1.xml
| + webSettings.xml
| \--_rels
| \ document.xml.rels //this document tells word where the images are situated
+ [Content_Types].xml
\--_rels
\ .rels
Docx получает только одну часть документа, в метод opendocx
def opendocx(file):
'''Open a docx file, return a document XML tree'''
mydoc = zipfile.ZipFile(file)
xmlcontent = mydoc.read('word/document.xml')
document = etree.fromstring(xmlcontent)
return document
он получает только документ.XML-файл.
что я рекомендую вам сделать следующее:
- получить содержимое документа с помощью * * opendocx*
- заменить документ.XML-файле с помощью тега advReplace метод
- откройте docx как zip и замените документ.содержимое xml по новому содержимому xml.
- закройте и выведите сжатый файл (переименовав его в выход.файлы DOCX)
Если у вас есть узел.JS установлен, сообщаю, что я работал над DocxGenJS который является шаблоном для docx документов, библиотека находится в активной разработке и будет выпущена в ближайшее время как модуль узла.
это сработало для меня:
def docx_replace(old_file,new_file,rep):
zin = zipfile.ZipFile (old_file, 'r')
zout = zipfile.ZipFile (new_file, 'w')
for item in zin.infolist():
buffer = zin.read(item.filename)
if (item.filename == 'word/document.xml'):
res = buffer.decode("utf-8")
for r in rep:
res = res.replace(r,rep[r])
buffer = res.encode("utf-8")
zout.writestr(item, buffer)
zout.close()
zin.close()
вы используете модуль docx от здесь?
Если да, то модуль docx уже предоставляет такие методы, как replace, advReplace и т. д., которые могут помочь вам достичь вашей задачи. Обратитесь к исходный код для получения более подробной информации о воздействии методов.
Я разветвил РЕПО python-docx здесь, который сохраняет все существующие данные в файле docx, включая форматирование. Надеюсь, это то, что вы ищете.
в дополнение к @ramil вам нужно избежать некоторых символов, прежде чем размещать их в качестве строковых значений в XML, поэтому это сработало для меня:
def escape(escapee):
escapee = escapee.replace("&", "&")
escapee = escapee.replace("<", "<")
escapee = escapee.replace(">", ">")
escapee = escapee.replace("\"", """)
escapee = escapee.replace("'", "'")
return escapee
from docx import Document
file_path = 'C:/tmp.docx'
document = Document(file_path)
def docx_replace(doc_obj, data: dict):
"""example: data=dict(order_id=123), result: {order_id} -> 123"""
for paragraph in doc_obj.paragraphs:
for key, val in data.items():
key_name = '{{{}}}'.format(key)
if key_name in paragraph.text:
paragraph.text = paragraph.text.replace(key_name, str(val))
for table in doc_obj.tables:
for row in table.rows:
for cell in row.cells:
docx_replace(cell, data)
docx_replace(document, dict(order_id=123, year=2018, payer_fio='payer_fio', payer_fio1='payer_fio1'))
document.save(file_path)