2009-07-17 22 views
6

estoy usando Palabra y OpenXml para proporcionar funcionalidad de combinación de correspondencia en una aplicación Web ASP.NET en C#:documento Duplicación Word utilizando OpenXml y C#

1) Un documento se carga con un número de cadenas predefinidas para la sustitución .

2) Utilizo OpenXML SDK 2.0 Abro el documento de Word, obtengo mainDocumentPart como una cadena y realizo la sustitución utilizando Regex.

3) Luego creo un nuevo documento usando OpenXML, agrego un nuevo mainDocumentPart e inserto el string resultante de la sustitución en este mainDocumentPart.

Sin embargo, todos los formatos/estilos, etc. se pierden en el nuevo documento.

Supongo que puedo copiar y agregar el estilo, las definiciones, las partes de comentarios, etc. individualmente para imitar el documento original.

Sin embargo, ¿hay algún método que utilice Open XML para duplicar un documento que me permita realizar las sustituciones en la nueva copia?

Gracias.

Respuesta

-1

Cuando mira un documento openxml cambiando la extensión a zip y abriéndolo, ve que esa subcarpeta de palabras contiene una carpeta _rels donde se enumeran todas las relaciones. Estas relaciones apuntan a las partes que mencionaste (estilo ...). En realidad, necesita estas partes porque contienen la definición del formato. Por lo tanto, si no los copia, el nuevo documento utilizará el formato definido en el archivo normal.dot y no el definido en el documento original. Entonces creo que tienes que copiarlos.

+0

realmente no responde la pregunta. Lea sobre cómo hacerlo antes de responder. –

2

He hecho algunas cosas muy similares, pero en lugar de usar cadenas de sustitución de texto, uso Word Content Controls. He documentado algunos de los detalles en la siguiente publicación de blog, SharePoint and Open Xml. La técnica es no específica de SharePoint. Puede reutilizar el patrón en ASP.NET puro u otras aplicaciones.

Además, le recomiendo encarecidamente que consulte Eric White's Blog para consejos, trucos y técnicas relacionadas con Open Xml. Específicamente, echa un vistazo a las publicaciones in-memory manipulation of Open Xml post y Word content controls. Creo que encontrarás estos mucho más útiles a largo plazo.

Espero que esto ayude.

4

En segundo lugar el uso de la recomendación de Content Controls. Usarlas para marcar las áreas de su documento en las que desea realizar la sustitución es, de lejos, la manera más fácil de hacerlo.

En cuanto a la duplicación del documento (y retener el contenido del documento entero, estilos y todas) que es relativamente fácil:

string documentURL = "full URL to your document"; 
byte[] docAsArray = File.ReadAllBytes(documentURL); 

using (MemoryStream stream = new MemoryStream) 
{ 
    stream.Write(docAsArray, 0, docAsArray.Length); // THIS performs doc copy 
    using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true)) 
    { 
     // perform content control substitution here, making sure to call .Save() 
     // on any documents Part's changed. 
    } 
    File.WriteAllBytes("full URL of your new doc to save, including .docx", stream.ToArray()); 
} 

encontrar En realidad, los controles de contenido es un pedazo de pastel usando LINQ. El siguiente ejemplo busca todos los controles simples de contenido de texto (que se escriben como SdtRun):

using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true)) 
{      
    var mainDocument = doc.MainDocumentPart.Document; 
    var contentControls = from sdt in mainDocument.Descendants<SdtRun>() select sdt; 

    foreach (var cc in contentControls) 
    { 
     // drill down through the containment hierarchy to get to 
     // the contained <Text> object 
     cc.SdtContentRun.GetFirstChild<Run>().GetFirstChild<Text>().Text = "my replacement string"; 
    } 
} 

no pueden ya existir Las <Run> y <Text> elementos, pero la creación de ellos es tan simple como:

cc.SdtContentRun.Append(new Run(new Text("my replacement string"))); 

Esperanza eso ayuda a alguien: D

2

Como una adición a lo anterior; lo que quizás sea más útil es encontrar controles de contenido etiquetados (usando la palabra GUI). Recientemente escribí un software que incluía plantillas de documentos que contenían controles de contenido con etiquetas adjuntas. Para encontrarlos es simplemente una extensión de la consulta LINQ arriba:

var mainDocument = doc.MainDocumentPart.Document; 
var taggedContentControls = from sdt in mainDocument.Descendants<SdtElement>() 
          let sdtPr = sdt.GetFirstChild<SdtProperties>() 
          let tag = (sdtPr == null ? null : sdtPr.GetFirstChild<Tag>()) 
          where (tag != null) 
          select new 
          { 
           SdtElem = sdt, 
           TagName = tag.GetAttribute("val", W).Value 
          }; 

Tengo este código desde otro lugar, pero no pueden recordar donde por el momento; el crédito completo va a ellos.

La consulta solo crea un IEnumerable de un tipo anónimo que contiene el control de contenido y su etiqueta asociada como propiedades. ¡Práctico!

10

Este fragmento de código debe copiar todas las partes de un documento existente a uno nuevo.

using (var mainDoc = WordprocessingDocument.Open(@"c:\sourcedoc.docx", false)) 
using (var resultDoc = WordprocessingDocument.Create(@"c:\newdoc.docx", 
    WordprocessingDocumentType.Document)) 
{ 
    // copy parts from source document to new document 
    foreach (var part in mainDoc.Parts) 
    resultDoc.AddPart(part.OpenXmlPart, part.RelationshipId); 
    // perform replacements in resultDoc.MainDocumentPart 
    // ... 
} 
+1

He estado golpeando mi cabeza contra la pared durante horas jugando con ese negocio MemoryStream ... Esto funciona muy bien y es mucho más conciso. ¡Muchas gracias! – lukiffer

+0

¿Hay alguna manera de hacer algo similar, la única diferencia es que el contenido en 'mainDoc' necesita ser anexado al final de un documento existente? –

+0

Sí, aunque es mucho más difícil, ya que es necesario fusionar muchos datos de partes de ambos documentos. Afortunadamente, [Eric White] (http://ericwhite.com/blog/) ha creado un conjunto de [PowerTools para OpenXML] (http://ericwhite.com/blog/category/open-xml/powertools/) que maneja esta tarea de otra manera desalentadora para ti. En particular, eche un vistazo al [DocumentBuilder] (http://openxmldeveloper.org/wiki/w/wiki/documentbuilder.aspx) que he utilizado para agregar un documento a otro en el pasado. ¡Trabajado como un encanto! – bernhof

Cuestiones relacionadas