Как использовать python-docx для замены текста в документе Word и сохранения

модуль oodocx, упомянутый на той же странице, ссылается на папку /examples, которой, похоже, там нет.
Я прочитал документацию python-docx 0.7.2, плюс все, что я мог найти в Stackoverflow по этому вопросу, поэтому, пожалуйста, поверьте, что я сделал свою "домашнюю работу".

Python-единственный язык, который я знаю (начинающий+, возможно, промежуточный), поэтому, пожалуйста, не предполагайте никаких знаний о C, Unix, xml и т. д.

задача: откройте ms-word 2007+ документ с одной строкой текста в нем (чтобы все было просто) и заменить любое "ключевое" слово в словаре, которое встречается в этой строке текста, его словарным значением. Затем закройте документ, сохраняя все остальное таким же.

строка текста (например) " мы задержимся в морских покоях."

from docx import Document

document = Document('/Users/umityalcin/Desktop/Test.docx')

Dictionary = {‘sea’: “ocean”}

sections = document.sections
for section in sections:
    print(section.start_type)

#Now, I would like to navigate, focus on, get to, whatever to the section that has my
#single line of text and execute a find/replace using the dictionary above.
#then save the document in the usual way.

document.save('/Users/umityalcin/Desktop/Test.docx')

Я не вижу ничего в документации, которая позволяет мне это сделать-может быть, это есть, но я не понимаю, потому что все не прописано на моем уровень.

Я следил за другими предложениями на этом сайте и пытался использовать более ранние версии модуля (https://github.com/mikemaccana/python-docx), который должен иметь "методы, такие как replace, advReplace" следующим образом: я открываю исходный код в интерпретаторе python и добавляю следующее В конце (это во избежание столкновений с уже установленной версией 0.7.2):

document = opendocx('/Users/umityalcin/Desktop/Test.docx')
words = document.xpath('//w:r', namespaces=document.nsmap)
for word in words:
    if word in Dictionary.keys():
        print "found it", Dictionary[word]
        document = replace(document, word, Dictionary[word])
savedocx(document, coreprops, appprops, contenttypes, websettings,
    wordrelationships, output, imagefiledict=None) 

запуск этого приводит к следующей ошибке сообщение:

NameError: имя 'coreprops' не определено

Если это имеет значение, я использую 64-битную версию Canopy Enthought на OSX 10.9.3

4 ответов


текущая версия python-docx не имеет . Они запрашиваются довольно часто, но реализация для общего случая довольно сложна, и она еще не поднялась на вершину отставания.

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

for paragraph in document.paragraphs:
    if 'sea' in paragraph.text:
        print paragraph.text
        paragraph.text = 'new text containing ocean'

для поиска в таблицах также, вам нужно будет использовать что-то вроде:

for table in document.tables:
    for cell in table.cells:
        for paragraph in cell.paragraphs:
            if 'sea' in paragraph.text:
               ...

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

кстати, код из ответа @wnnmaw предназначен для устаревшей версии python-docx и не будет работать вообще с версиями после 0.3.0.


мне нужно было что-то заменить регулярные выражения в docx. Я принял ответ скэнниса. Для обработки стиля я использовал ответ от: Python docx заменяет строку в абзаце, сохраняя при этом стиль добавлен рекурсивный вызов для обработки вложенных таблиц. и придумал что-то вроде этого:--5-->

import re
from docx import Document

def docx_replace_regex(doc_obj, regex , replace):

    for p in doc_obj.paragraphs:
        if regex.search(p.text):
            inline = p.runs
            # Loop added to work with runs (strings with same style)
            for i in range(len(inline)):
                if regex.search(inline[i].text):
                    text = regex.sub(replace, inline[i].text)
                    inline[i].text = text

    for table in doc_obj.tables:
        for row in table.rows:
            for cell in row.cells:
                docx_replace_regex(cell, regex , replace)



regex1 = re.compile(r"your regex")
replace1 = r"your replace string"
filename = "test.docx"
doc = Document(filename)
docx_replace_regex(doc, regex1 , replace1)
doc.save('result1.docx')

для перебора по словарю:

for word, replacement in dictionary.items():
    word_re=re.compile(word)
    docx_replace_regex(doc, word_re , replacement)

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

также, если текст отредактированный после сохранения того же стиля текст может быть в отдельных запусках. Например, если вы открываете документ, который имеет строку" testabcd", и вы меняете его на" test1abcd "и сохраняете, даже тесто в том же стиле есть 3 отдельных запуска" test"," 1 "и" abcd", в этом случае замена test1 не будет работать.

Это для отслеживания изменений в документе. Чтобы Мардж это один раз, в Word вам нужно перейти в "Параметры", "Центр доверия " и в" параметры конфиденциальности "unthick" хранить случайные числа для улучшения объединить точность " и сохранить документ.


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

relationships = docx.relationshiplist()
title = "Document Title"
subject = "Document Subject"
creator = "Document Creator"
keywords = []

coreprops = docx.coreproperties(title=title, subject=subject, creator=creator,
                       keywords=keywords)
app = docx.appproperties()
content = docx.contenttypes()
web = docx.websettings()
word = docx.wordrelationships(relationships)
output = r"path\to\where\you\want\to\save"

в Центре разработки Office есть запись, в которой разработчик опубликовал (MIT лицензируется в это время) описание нескольких алгоритмов, которые, как представляется, предлагают решение для этого (хотя и на C#, и требуют переноса):" MS Dev Centre posting