9

明らかな何かが欠けているかどうかはわかりませんが、文書内の特定の場所に Word 要素 (表など) を挿入する方法について文書化されたものは見つかりませんでしたか?

以下を使用して、既存の MS Word .docx ドキュメントを読み込んでいます。

my_document = Document('some/path/to/my/document.docx')

私の使用例は、ドキュメント内のブックマークまたはセクションの「位置」を取得し、そのポイントの下にテーブルを挿入することです。

これらの線に沿って何かを実行できるようにする API について考えています。

insertion_point = my_document.bookmarks['bookmark_name'].position
my_document.add_table(rows=10, cols=3, position=insertion_point+1)

MS Word API の「範囲」オブジェクトに似たものを実装する計画があることを知りました。これにより、その問題が効果的に解決されます。documentそれまでの間、新しい要素を挿入する場所をオブジェクト メソッドに指示する方法はありますか?

たぶん、lxml コードを接着してノードを見つけ、それをこれらの python-docx メソッドに渡すことができますか? この件に関する助けをいただければ幸いです。ありがとう。

4

5 に答える 5

14

「ソースを使え、ルーク!」という古い格言を思い出し、それを理解することができました。git プロジェクト ページの python-docx 所有者からの投稿もヒントを与えてくれました: https://github.com/python-openxml/python-docx/issues/7

_document_part._element完全な XML ドキュメント モデルには、そのプロパティを使用してアクセスできます。これは、lxml etree 要素とまったく同じように動作します。そこから、すべてが可能になります。

特定の挿入ポイントの問題を解決するために、生成されたコンテンツを保存するために使用する一時的な docx.Document オブジェクトを作成しました。

import docx
from docx.oxml.shared import qn
tmp_doc = docx.Document()

# Generate content in tmp_doc document
tmp_doc.add_heading('New heading', 1)
# more content generation using docx API.
# ...

# Reference the tmp_doc XML content
tmp_doc_body = tmp_doc._document_part._element.body
# You could pretty print it by using:
#print(docx.oxml.xmlchemy.serialize_for_reading(tmp_doc_body))

次に、docx テンプレート (「insertion_point」という名前のブックマークを含む) を 2 つ目の docx.Document オブジェクトに読み込みました。

doc = docx.Document('/some/path/example.docx')
doc_body = doc._document_part._element.body
#print(docx.oxml.xmlchemy.serialize_for_reading(doc_body))

次のステップは、doc XML を解析して、挿入ポイントのインデックスを見つけることです。目前のタスクのために、名前付きブックマークの親段落要素を返す小さな関数を定義しました。

def get_bookmark_par_element(document, bookmark_name):
"""
Return the named bookmark parent paragraph element. If no matching
bookmark is found, the result is '1'. If an error is encountered, '2'
is returned.
"""
doc_element = document._document_part._element
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
for bookmark in bookmarks_list:
    name = bookmark.get(qn('w:name'))
    if name == bookmark_name:
        par = bookmark.getparent()
        if not isinstance(par, docx.oxml.CT_P): 
            return 2
        else:
            return par
return 1

新しく定義された関数は、ブックマーク 'insertion_point' の親段落を取得するために使用されました。エラー制御は読者に任されています。

bookmark_par = get_bookmark_par_element(doc, 'insertion_point')

これで、bookmark_par の etree インデックスを使用して、tmp_doc で生成されたコンテンツを適切な場所に挿入できます。

bookmark_par_parent = bookmark_par.getparent()
index = bookmark_par_parent.index(bookmark_par) + 1
for child in tmp_doc_body:
    bookmark_par_parent.insert(index, child)
    index = index + 1
bookmark_par_parent.remove(bookmark_par)

ドキュメントが完成し、生成されたコンテンツが既存の Word ドキュメントのブックマークの場所に挿入されました。

# Save result
# print(docx.oxml.xmlchemy.serialize_for_reading(doc_body))
doc.save('/some/path/generated_doc.docx')

これに関するドキュメントはまだ作成されていないため、これが誰かの助けになることを願っています。

于 2014-07-29T15:40:49.583 に答える
3

[image] をテンプレート ドキュメントにトークンとして配置します。

for paragraph in document.paragraphs:
    if "[image]" in paragraph.text:
        paragraph.text = paragraph.text.strip().replace("[image]", "")

        run = paragraph.add_run()
        run.add_picture(image_path, width=Inches(3))

表のセルにも段落があります。セルを見つけて、上記のようにします。

于 2015-02-06T01:17:39.413 に答える
0

このすべてを説明するために時間を割いていただきありがとうございます。

私は多かれ少なかれ同じ問題を経験していました。私の具体的なポイントは、最後に 2 つ以上の docx ドキュメントをマージする方法でした。

それはあなたの問題に対する正確な解決策ではありませんが、ここに私が持ってきた機能があります:

def combinate_word(main_file, files, output):   
    main_doc = Document(main_file)
    for file in files:
        sub_doc = Document(file)

        for element in sub_doc._document_part.body._element:
            main_doc._document_part.body._element.append(element)

    main_doc.save(output)

残念ながら、python-docx で画像をコピーすることはまだ不可能であり、簡単でもありません。私はwin32comに戻ります...

于 2014-08-07T14:20:55.883 に答える