So verwenden Sie Python-docx, um Text in einem Word-Dokument zu ersetzen und zu speichern

Lesezeit: 11 Minuten

So verwenden Sie Python docx um Text in einem Word Dokument zu
Benutzer2738815

Das auf derselben Seite erwähnte oodocx-Modul verweist den Benutzer auf einen /examples-Ordner, der nicht dort zu sein scheint.
Ich habe die Dokumentation von python-docx 0.7.2 gelesen, plus alles, was ich in Stackoverflow zu diesem Thema finden konnte, also glauben Sie bitte, dass ich meine „Hausaufgaben“ gemacht habe.

Python ist die einzige Sprache, die ich kenne (Anfänger +, vielleicht Mittelstufe), also bitte keine Kenntnisse in C, Unix, XML usw. voraussetzen.

Aufgabe : Öffnen Sie ein ms-word 2007+-Dokument mit einer einzelnen Textzeile (um die Dinge einfach zu halten) und ersetzen Sie jedes „Schlüsselwort“ im Wörterbuch, das in dieser Textzeile vorkommt, durch seinen Wörterbuchwert. Schließen Sie dann das Dokument, wobei alles andere gleich bleibt.

Textzeile (zum Beispiel) „Wir werden in den Kammern des Meeres verweilen.“

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')

Ich sehe in der Dokumentation nichts, was mir dies ermöglicht – vielleicht ist es da, aber ich verstehe es nicht, weil nicht alles auf meinem Niveau buchstabiert ist.

Ich bin anderen Vorschlägen auf dieser Site gefolgt und habe versucht, frühere Versionen des Moduls zu verwenden (https://github.com/mikemaccana/python-docx), die “Methoden wie replace, advReplace” wie folgt haben soll: Ich öffne den Quellcode im Python-Interpreter und füge am Ende Folgendes hinzu (um Konflikte mit der bereits installierten Version 0.7.2 zu vermeiden):

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) 

Wenn Sie dies ausführen, wird die folgende Fehlermeldung ausgegeben:

NameError: Name ‘coreprops’ ist nicht definiert

Vielleicht versuche ich, etwas zu tun, was nicht möglich ist – aber ich würde mich über Ihre Hilfe freuen, wenn mir etwas Einfaches fehlt.

Wenn dies wichtig ist, verwende ich die 64-Bit-Version von Enthought’s Canopy auf OSX 10.9.3

1641917927 500 So verwenden Sie Python docx um Text in einem Word Dokument zu
dürftig

AKTUALISIEREN: Es gibt ein paar Funktionen auf Absatzebene, die dies gut machen und auf der GitHub-Site für . zu finden sind python-docx.

  1. Dieser wird Ersetze einen Regex-Match durch einen Ersatz-Str. Die Ersetzungszeichenfolge wird genauso formatiert wie das erste Zeichen der übereinstimmenden Zeichenfolge angezeigt.
  2. Dieser wird isolieren ein Lauf so dass eine gewisse Formatierung auf dieses Wort oder diesen Satz angewendet werden kann, z.

Die aktuelle Version von python-docx hat kein a search() Funktion oder a replace() Funktion. Diese werden ziemlich häufig angefordert, aber eine Implementierung für den allgemeinen Fall ist ziemlich knifflig und sie ist noch nicht an die Spitze des Backlogs gestiegen.

Mehrere Leute hatten jedoch Erfolg, indem sie die bereits vorhandenen Einrichtungen nutzten, um das zu erledigen, was sie brauchten. Hier ist ein Beispiel. Das hat übrigens nichts mit Abschnitten zu tun 🙂

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

Um auch in Tabellen zu suchen, müssen Sie Folgendes verwenden:

for table in document.tables:
    for row in table.rows:
        for cell in row.cells:
            for paragraph in cell.paragraphs:
                if 'sea' in paragraph.text:
                    paragraph.text = paragraph.text.replace("sea", "ocean")

Wenn Sie diesen Weg gehen, werden Sie wahrscheinlich ziemlich schnell feststellen, was die Komplexität ist. Wenn Sie den gesamten Text eines Absatzes ersetzen, werden alle Formatierungen auf Zeichenebene entfernt, z. B. ein Wort oder eine Wortgruppe in Fett- oder Kursivschrift.

Übrigens ist der Code aus der Antwort von @wnnmaw für die Legacy-Version von python-docx und funktioniert mit Versionen nach 0.3.0 überhaupt nicht.

  • Danke für die Klarstellung; spart viel Zeit. Ich werde zu der Menge gehören, die darauf wartet, dass diese Funktionen an die Spitze der Liste gelangen, während ich versuche, mit der “alten” Version zu tun, was ich tun muss. Gibt es übrigens in der aktuellen Version etwas, das es mir ermöglicht, das Wort “Meer” im Absatz zu streichen und stattdessen ein anderes Wort einzufügen? Vermutlich nicht, denn wenn die vorhanden wären, könnte sogar ich eine “Ersetzen”-Funktion schreiben…Grüße

    – Benutzer2738815

    17. Juli ’14 um 23:04


  • Ganz richtig. Es wäre einfach, wenn dem so wäre. Das Problem entsteht, weil “Meer” in einem sein kann <w:t> Element für sich, aufgeteilt auf zwei oder sogar drei und kann sogar in verschiedenen Durchläufen erscheinen (<w:r> Elemente, Eltern des t-Elements). Um ein Wort zu ersetzen, müssen die Elemente, die es enthalten, neu zusammengesetzt werden. Es gibt viele mögliche Fälle und Regeln, die bestimmen, wie Sie es wieder zusammenbauen, ohne es zu vermasseln. Wenn der Fall einfach ist, können Sie mit einem einfachen Umschreiben des Textes auskommen, aber ansonsten ist es eine ziemlich große Aufgabe. Vergiss nicht abzustimmen und die Antwort zu akzeptieren, wenn du zufrieden bist 🙂

    – spärlich

    18. Juli ’14 um 5:43

  • Anscheinend kann ich nicht abstimmen, weil mir der “Ruf” fehlt, aber ich weiß Ihre Hilfe zu schätzen und habe die Antwort überprüft. Grüße

    – Benutzer2738815

    18. Juli ’14 um 13:58

  • Als Referenz – dies ist die aktuelle Diskussion auf Github zu diesem Thema: github.com/python-openxml/python-docx/issues/30

    – Grzegorz Oledzki

    12. Apr. ’15 um 13:16

1641917928 166 So verwenden Sie Python docx um Text in einem Word Dokument zu
szum

Ich brauchte etwas, um reguläre Ausdrücke in docx zu ersetzen. Ich nahm Scannys Antwort. Um den Stil zu behandeln, habe ich die Antwort von verwendet: Python docx Ersetzen Sie den String im Absatz, während Sie den hinzugefügten rekursiven Aufruf beibehalten, um verschachtelte Tabellen zu behandeln. und kam auf so etwas:

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')

So iterieren Sie über das Wörterbuch:

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

Beachten Sie, dass diese Lösung Regex nur dann ersetzt, wenn die gesamte Regex den gleichen Stil im Dokument hat.

Auch wenn Text nach dem Speichern desselben Stils bearbeitet wird, kann sich der Text in separaten Durchläufen befinden. Wenn Sie beispielsweise ein Dokument mit der Zeichenfolge “testabcd” öffnen und es in “test1abcd” ändern und speichern, gibt es in diesem Fall 3 separate Durchläufe “test”, “1” und “abcd”, selbst wenn es den gleichen Stil hat Ersetzen von test1 funktioniert nicht.

Dies dient zum Verfolgen von Änderungen im Dokument. Um es zu einem Lauf zu verbinden, müssen Sie in Word zu “Optionen”, “Trust Center” gehen und in “Datenschutzoptionen” das Häkchen bei “Zufallszahlen speichern, um die Genauigkeit der Kombination zu verbessern” deaktivieren und das Dokument speichern.

  • Dies funktioniert innerhalb der von Ihnen genannten Grenzen, und ich habe es positiv bewertet. Es wäre jedoch nützlich, Ihren Code zu bearbeiten, um zu zeigen, wie Sie ihm ein Wörterbuch übergeben können. Ich habe nachgeschaut; kann gemacht werden, muss aber mit der Regex herumgespielt werden. Ich möchte keine separate Antwort posten. Danke

    – Benutzer2738815

    23. März ’17 um 2:42

  • Aktualisiert mit Wörterbuchbeispiel und hinzugefügter Beschreibung, wie Bearbeitungen in einem Lauf zusammengefasst werden. Beifall.

    – szum

    24. März ’17 um 10:54


  • Danke schön. Ich verwende 2.7 und word_re = re.compile(word) wirft einen Fehler auf. Stattdessen, word_re = re.compile(str(word) funktioniert. Ich weiß nicht, ob es sich um einen versionsbedingten Unterschied handelt, da ich nicht weiß, wie Python 3 funktioniert.

    – Benutzer2738815

    25. März ’17 um 5:06

  • Danke @szum für Ihre Lösung, es funktioniert perfekt, aber ich stelle fest, dass Wordart-Text oder Text in Textfeldern ignoriert werden. Können Sie darauf aufbauen, um dies zu unterstützen.

    – Johnn Kaita

    16. Dezember ’20 um 12:45

  • Ich habe den folgenden Fehler: ~~~ Traceback (letzter Aufruf zuletzt): gen_docx(Eingabe, Wörterbuch, Ausgabe) docx_replace_regex(Dokument, Wort_Re, Ersetzung) Text = regex.sub(Ersetzen, Inline[i].text) template = _compile_repl(template, pattern) return sre_parse.parse_template(repl, pattern) s = Tokenizer(source) string = str(string, ‘latin1’) TypeError: Dekodierung in str: Brauche ein bytesähnliches Objekt, int gefunden ~~~ Weißt du, wie man das löst? Danke.

    – Steven Lee

    18. März ’21 um 6:18


So verwenden Sie Python docx um Text in einem Word Dokument zu
poin

Ich habe viel Hilfe von den Antworten von früher bekommen, aber für mich funktioniert der folgende Code wie die einfache Suchen- und Ersetzen-Funktion in Word. Hoffe das hilft.

#!pip install python-docx
#start from here if python-docx is installed
from docx import Document
#open the document
doc=Document('./test.docx')
Dictionary = {"sea": "ocean", "find_this_text":"new_text"}
for i in Dictionary:
    for p in doc.paragraphs:
        if p.text.find(i)>=0:
            p.text=p.text.replace(i,Dictionary[i])
#save changed document
doc.save('./test.docx')

Die obige Lösung hat Einschränkungen. 1) Der Absatz, der “find_this_text” enthält, wird zu Klartext ohne Format, 2) Kontextsteuerelemente, die sich im selben Absatz wie “find_this_text” befinden, werden gelöscht und 3) “find_this_text” in Kontextsteuerelementen oder Tabellen wird nicht geändert werden.

  • Das ist großartig!

    – Jem

    13. Juni ’20 um 19:14

  • Das ist perfekt 🙂 Vielen Dank.

    – Manthan_Admane

    9. Juli ’20 um 19:00


  • Oh maaan…. Genau das habe ich gebraucht… Danke alooooooottt….

    – Pragyan Choudhury

    5. August ’20 um 7:24

  • Dies ist beleuchtet. Danke mann. Dies funktioniert jedoch nicht auf dem Tisch

    – ausbessern3

    2. Februar ’21 um 4:21

  • Genau das, was ich brauchte. Danke!

    – Danny Blaker

    8. Juni ’21 um 11:44

Ein kleines Skript zu teilen, das ich geschrieben habe – hilft mir, rechtliches zu generieren .docx Verträge mit Variablen unter Beibehaltung des ursprünglichen Stils.

pip install python-docx

Beispiel:

from docx import Document
import os


def main():
    template_file_path="employment_agreement_template.docx"
    output_file_path="result.docx"

    variables = {
        "${EMPLOEE_NAME}": "Example Name",
        "${EMPLOEE_TITLE}": "Software Engineer",
        "${EMPLOEE_ID}": "302929393",
        "${EMPLOEE_ADDRESS}": "דרך השלום מנחם בגין דוגמא",
        "${EMPLOEE_PHONE}": "+972-5056000000",
        "${EMPLOEE_EMAIL}": "[email protected]",
        "${START_DATE}": "03 Jan, 2021",
        "${SALARY}": "10,000",
        "${SALARY_30}": "3,000",
        "${SALARY_70}": "7,000",
    }

    template_document = Document(template_file_path)

    for variable_key, variable_value in variables.items():
        for paragraph in template_document.paragraphs:
            replace_text_in_paragraph(paragraph, variable_key, variable_value)

        for table in template_document.tables:
            for col in table.columns:
                for cell in col.cells:
                    for paragraph in cell.paragraphs:
                        replace_text_in_paragraph(paragraph, variable_key, variable_value)

    template_document.save(output_file_path)


def replace_text_in_paragraph(paragraph, key, value):
    if key in paragraph.text:
        inline = paragraph.runs
        for item in inline:
            if key in item.text:
                item.text = item.text.replace(key, value)


if __name__ == '__main__':
    main()

Bildbeschreibung hier eingeben

Für den Tabellenfall musste ich die Antwort von @scanny ändern auf:

for table in doc.tables:
    for col in table.columns:
        for cell in col.cells:
            for p in cell.paragraphs:

damit es funktioniert. Tatsächlich scheint dies mit dem aktuellen Status der API nicht zu funktionieren:

for table in document.tables:
    for cell in table.cells:

Gleiches Problem mit dem Code von hier: https://github.com/python-openxml/python-docx/issues/30#issuecomment-38658149

So verwenden Sie Python docx um Text in einem Word Dokument zu
Soferio

Das Office Dev Center hat einen Eintrag, in dem ein Entwickler (derzeit mit MIT-Lizenz) eine Beschreibung einiger Algorithmen veröffentlicht hat, die eine Lösung dafür vorzuschlagen scheinen (wenn auch in C# und eine Portierung erfordern):” MS Dev Center-Posting

Das Problem bei Ihrem zweiten Versuch ist, dass Sie die Parameter nicht definiert haben, die savedocx braucht. Du musst so etwas machen Vor du sparst:

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"pathtowhereyouwanttosave"

  • Vielen Dank, dass Sie geantwortet haben. Ich habe Ihren Code sofort vor dem “Speichern” hinzugefügt und nur den Ausgabepfad in “/Users/umityalcin/Desktop/” geändert (ich gehe davon aus, dass es keine Rolle spielt, den Titel usw. Erstens, da ich das aktuelle docx-Modul (0.7.2) nicht importiert hatte, um Fehler zu vermeiden, hat der Interpreter das “docx” nicht erkannt. Präfix. Also habe ich das Modul importiert – jetzt bekomme ich das: AttributeError: ‘Modul’-Objekt hat kein Attribut ‘relationshiplist’. Danke für Ihre Zeit und Hilfe.

    – Benutzer2738815

    17. Juli ’14 um 14:33

  • Ah, richtig, gut, anscheinend ist Lesen nicht meine Stärke 😛 Wenn Sie alle Funktionen von haben docx im Rahmen Ihres Programms brauchen Sie die docx. Präfix, also versuche es zu entfernen

    – wnnmaw

    17. Juli ’14 um 14:51

  • Nun, zumindest ist Codieren nicht Ihre Schwachstelle; es scheint mir zu gehören 🙂 Nachdem ich Ihrem Vorschlag gefolgt bin, habe ich es immer noch geschafft, diesen Fehler zu erhalten: savedocx(document, coreprops, appprops, contenttypes, websettings, wordrelationships, output, imagefiledict) 1061 ) 1062 -> 1063 assert os.path.isdir (template_dir) 1064 docxfile = zipfile.ZipFile( 1065 Ausgabe, mode=’w’, compression=zipfile.ZIP_DEFLATED) AssertionError:

    – Benutzer2738815

    17. Juli ’14 um 22:57


.

370610cookie-checkSo verwenden Sie Python-docx, um Text in einem Word-Dokument zu ersetzen und zu speichern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy