web-dev-qa-db-ja.com

python-docxを使用して、Word文書内のテキストを置き換えて保存する方法

同じページに記載されているoodocxモジュールは、存在しないように見える/ examplesフォルダーをユーザーに参照します。
python-docx 0.7.2のドキュメントに加えて、このテーマに関するStackoverflowで見つけることができるすべてのものを読んだので、「宿題」をしたと信じてください。

Pythonは私が知っている唯一の言語(初心者+、中級かもしれません)ですので、C、Unix、xmlなどの知識を前提としないでください。

タスク:1行のテキストを含むms-Word 2007+ドキュメントを開き(簡単にするため)、そのテキスト行で発生する辞書の「キー」Wordを辞書の値に置き換えます。次に、ドキュメントを閉じて、他のすべてを同じにします。

テキスト行(たとえば)「私たちは海の部屋にとどまります。」

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 )を使用しようとしました。次のように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'は定義されていません

できないことをしようとしているのかもしれませんが、簡単なものが足りない場合はご協力をお願いします。

これが問題になる場合、OSX 10.9.3でEnthoughtのCanopyの64ビットバージョンを使用しています。

19
user2738815

Python-docxの現在のバージョンには、search()関数またはreplace()関数がありません。これらはかなり頻繁に要求されますが、一般的なケースの実装は非常にトリッキーであり、まだバックログのトップに達していません。

しかし、既に存在する施設を使用して、何人かが成功し、必要なことを成し遂げました。以下に例を示します。ちなみにセクションとは関係ありません:)

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以降のバージョンではまったく機能しません。

30
scanny

Docxの正規表現を置き換えるものが必要でした。私はスカニーの答えを取りました。スタイルを処理するために、私はからの回答を使用しました: Python docxスタイルを維持しながら段落内の文字列を置換 ネストされたテーブルを処理するための再帰呼び出しを追加しました。そして次のようなものを思いつきました:

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」に変更して保存すると、同じスタイルの生地でさえ、この場合は「test」、「1」、「abcd」という3つの別々の実行がありますtest1の置換は機能しません。

これは、ドキュメント内の変更を追跡するためです。 1回の実行にマージするには、Wordで[オプション]、[セキュリティセンター]に移動し、[プライバシーオプション]で[結合精度を向上させるために乱数を保存]のチェックを外してドキュメントを保存します。

11
szum

Office Dev Centerには、開発者がこのソリューションを提案していると思われるいくつかのアルゴリズムの説明を公開しているエントリがあります(現時点ではMITライセンスが付与されています)(C#ではありますが、移植が必要です): MS Dev Centerの投稿

1
Soferio

2回目の試行での問題は、savedocxが必要とするパラメーターを定義していないことです。このようなことをする必要がありますbefore保存します:

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"
0
wnnmaw