Найти и заменить текст в файле .docx - Python

Я много искал метод поиска и замены текста в файле docx с небольшой удачей. Я пробовал модуль docx и не мог заставить это работать. В конце концов я разработал метод, описанный ниже, используя модуль zipfile и заменив файл document.xml в архиве docx. Для этого вам нужен документ-шаблон (docx) с текстом, который вы хотите заменить, как уникальные строки, которые не могли бы соответствовать любому другому существующему или будущему тексту в документе (например, "Встреча с XXXCLIENTNAMEXXX на XXXMEETDATEXXX прошла очень хорошо." ).

import zipfile

replaceText = {"XXXCLIENTNAMEXXX" : "Joe Bob", "XXXMEETDATEXXX" : "May 31, 2013"}
templateDocx = zipfile.ZipFile("C:/Template.docx")
newDocx = zipfile.ZipFile("C:/NewDocument.docx", "a")

with open(templateDocx.extract("word/document.xml", "C:/")) as tempXmlFile:
    tempXmlStr = tempXmlFile.read()

for key in replaceText.keys():
    tempXmlStr = tempXmlStr.replace(str(key), str(replaceText.get(key)))

with open("C:/temp.xml", "w+") as tempXmlFile:
    tempXmlFile.write(tempXmlStr)

for file in templateDocx.filelist:
    if not file.filename == "word/document.xml":
        newDocx.writestr(file.filename, templateDocx.read(file))

newDocx.write("C:/temp.xml", "word/document.xml")

templateDocx.close()
newDocx.close()

Мой вопрос в том, что не так с этим методом? Я новичок в этом, поэтому я чувствую, что кто-то еще должен был это понять. Это заставляет меня думать, что с этим подходом что-то очень не так. Но это работает! Что мне здесь не хватает?

.

Вот прохождение моего процесса мышления для всех, кто пытается изучить этот материал:

Шаг 1) Подготовьте словарь Python для текстовых строк, которые вы хотите заменить как клавиши, и новый текст как элементы (например, { "XXXCLIENTNAMEXXX": "Joe Bob", "XXXMEETDATEXXX": "31 мая 2013 года" }).

Шаг 2) Откройте файл docx шаблона с помощью zipfile-модуля.

Шаг 3) Откройте новый файл docx с режимом доступа append.

Шаг 4) Извлеките document.xml(где весь текст живет) из файла docx шаблона и прочитайте xml для текстовой строковой переменной.

Шаг 5) Используйте цикл for, чтобы заменить весь текст, определенный в словаре, в текстовой строке xml новым текстом.

Шаг 6) Запишите текстовую строку xml в новый временный XML файл.

Шаг 7) Используйте цикл for и модуль zipfile для копирования всех файлов в архиве docx шаблона в новый архив docx. ИСКЛЮЧИТЕ файл word/document.xml.

Шаг 8) Запишите временный файл xml с замененным текстом в новый архив docx как новый файл word/document.xml.

Шаг 9) Закройте свой шаблон и новые архивы docx.

Шаг 10) Откройте новый документ docx и наслаждайтесь замененным текстом!

- Изменить - Отсутствуют закрывающиеся круглые скобки ')' в строках 7 и 11

Ответ 1

Иногда слово делает странные вещи. Вы должны попытаться удалить текст и переписать его одним махом, например, без редактирования текста в середине

Ваш документ сохраняется в XML файле (обычно в word/document.xml для docx, afer unzipping). Иногда возможно, что ваш текст будет не одним ударом: возможно, что где-то в документе, это XXXCLIENT, а где-то еще NAMEXXX.

Что-то вроде этого:

<w:t> XXXCLIENT </w:t> ... <w:t> NAMEXXX </w:t>

Это происходит довольно часто из-за языковой поддержки: слово разбивает слова, когда он думает, что одно слово имеет один конкретный язык и может делать это между словами, которые будут разделять слова на несколько тегов.

Единственная проблема с вашим решением заключается в том, что вы должны писать все одним движением, что не является самым удобным для пользователя.

Я создал JS-библиотеку, которая использует усы как теги: {clientName} https://github.com/edi9999/docxgenjs

Он работает в глобальном масштабе так же, как и ваш алгоритм, но не будет разбиваться, если содержимое не в один такт (при написании {clientName} в Word текст обычно будет разделен: {, clientName,} в документе.

Ответ 2

Вы можете попробовать обходной путь. Используйте Word search/replace, чтобы получить текст за один такт.

Например, найдите "XXXCLIENTNAMEXXX" и снова замените его на "XXXCLIENTNAMEXXX".