Cómo usar python-docx para reemplazar texto en un documento de Word y guardar

El módulo oodocx mencionado en la misma página remite al usuario a una carpeta / examples que no parece estar allí.
He leído la documentación de python-docx 0.7.2, además de todo lo que pude encontrar en Stackoverflow sobre el tema, así que, por favor, crea que he hecho mi “tarea”.

Python es el único idioma que conozco (principiante +, tal vez intermedio), así que no asum ningún conocimiento de C, Unix, xml, etc.

Tarea: abra un documento ms-word 2007+ con una sola línea de texto (para simplificar las cosas) y reemplace cualquier palabra “clave” en el diccionario que aparezca en esa línea de texto con su valor de diccionario. Luego cierra el documento manteniendo todo lo demás igual.

Línea de texto (por ejemplo) “Nos detendremos en las cámaras del mar”.

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

No veo nada en la documentación que me permita hacer esto, tal vez esté allí, pero no lo entiendo porque todo no está explicado a mi nivel.

He seguido otras sugerencias en este sitio y he intentado usar versiones anteriores del módulo ( https://github.com/mikemaccana/python-docx ) que se supone que tiene “métodos como reemplazar, advReplace” de la siguiente manera: Abro el código fuente en el intérprete de python, y agregue lo siguiente al final (esto es para evitar choques con la versión ya instalada 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) 

Ejecutando esto produce el siguiente mensaje de error:

NameError: el nombre ‘coreprops’ no está definido

Tal vez estoy tratando de hacer algo que no se puede hacer, pero agradecería su ayuda si me falta algo simple.

Si esto es importante, estoy usando la versión de 64 bits de Enthought’s Canopy en OSX 10.9.3

La versión actual de python-docx no tiene una función de search() o una función de replace() . Estos se solicitan con bastante frecuencia, pero una implementación para el caso general es bastante complicada y aún no ha llegado a la cima del trabajo pendiente.

Sin embargo, varias personas han tenido éxito al hacer lo que necesitan, utilizando las instalaciones ya presentes. Aquí hay un ejemplo. No tiene nada que ver con las secciones por cierto 🙂

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

Para buscar en Tablas también, necesitarías usar algo como:

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

Si sigues este camino, probablemente descubrirás rápidamente cuáles son las complejidades. Si reemplaza todo el texto de un párrafo, se eliminará cualquier formato de nivel de carácter, como una palabra o frase en negrita o cursiva.

Por cierto, el código de la respuesta de @wnnmaw es para la versión heredada de python-docx y no funcionará en absoluto con las versiones posteriores a 0.3.0.

Necesitaba algo para reemplazar expresiones regulares en docx. Tomé la respuesta de Scannys. Para manejar el estilo, utilicé la respuesta de: Python docx Reemplace la cadena en el párrafo mientras mantengo el estilo de la llamada recursiva agregada para manejar las tablas anidadas. y se le ocurrió algo como esto:

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

Para iterar sobre el diccionario:

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

Tenga en cuenta que esta solución reemplazará las expresiones regulares solo si todas las expresiones regulares tienen el mismo estilo en el documento.

Además, si el texto se edita después de guardar el mismo estilo, el texto podría estar en ejecuciones separadas. Por ejemplo, si abre un documento que tiene la cadena “testabcd” y lo cambia a “test1abcd” y guarda, incluso en su masa del mismo estilo hay 3 ejecuciones separadas “test”, “1” y “abcd”, en este caso El reemplazo de test1 no funcionará.

Esto es para el seguimiento de los cambios en el documento. Para unirlo a una ejecución, en Word debe ir a “Opciones”, “Centro de confianza” y en “Opciones de privacidad” no “Almacenar números aleatorios para mejorar la precisión de la combinación” y guardar el documento.

El problema con su segundo bash es que no ha definido los parámetros que necesita savedocx . Debe hacer algo como esto antes de guardar:

 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" 

El Centro de desarrollo de Office tiene una entrada en la que un desarrollador ha publicado (MIT con licencia en este momento) una descripción de un par de algoritmos que parecen sugerir una solución para esto (aunque esté en C # y requiera portabilidad): ” Publicación del Centro de desarrollo de MS