Share via


Reemplazar las partes de estilos de un documento de procesamiento de texto

En este tema se muestra cómo usar las clases del SDK de Open XML para Office para reemplazar mediante programación los estilos de un documento de procesamiento de texto por los estilos de otro documento de procesamiento de texto. Contiene un ejemplo del método ReplaceStyles para ilustrar esta tarea, así como los métodos de apoyo ReplaceStylesPart y ExtractStylesPart.


Acerca del almacenamiento de estilos

Un paquete de documento de procesamiento de texto como, por ejemplo, un archivo con extensión .docx, es de hecho un archivo .zip formado por varias partes. Puede concebir cada parte como algo parecido a un archivo externo. Una parte tiene un tipo de contenido determinado y puede incluir contenido igual al de un archivo XML externo, archivo binario, archivo de imagen, etc., en función del tipo. El estándar que define cómo se almacenan los documentos Open XML en archivos .zip se llama Open Packaging Conventions (Convenciones de empaquetado abierto). Para obtener más información acerca de Open Packaging Conventions, consulte ISO/IEC 29500-2.

Los estilos se almacenan en elementos dedicados dentro de un paquete de documentos de procesamiento de texto. Un documento de Microsoft Word 2010 contiene un elemento de estilos simple. Microsoft Word 2013 agrega una segunda parte stylesWithEffects. En la siguiente imagen del Explorador de documentos de la Herramienta de productividad del SDK de Open XML para Microsoft Office se muestran los elementos del documento de un ejemplo Word documento de 2013 que contiene estilos.

Figura 1. Elementos de estilo en un documento de procesamiento de texto.

Estilos de partes en un documento de procesamiento de texto. Con el fin de proporcionar para "ida y vuelta" un documento de Word 2013 a Word 2010 y posteriores, Word 2013 mantiene tanto la parte de estilos original como la parte de estilos nuevos. (La especificación de formatos de archivo de Office Open XML requiere que Microsoft Word ignore cualquier elemento que no reconozca; Word 2010 no advierte la parte stylesWithEffects que Word 2013 agrega al documento.)

El ejemplo de código proporcionado en este tema se puede usar para reemplazar estos elementos styles.


Método ReplaceStyles

Puede usar el método de ejemplo ReplaceStyles para reemplazar los estilos en un documento de procesamiento de texto por los estilos de otro documento de procesamiento de texto. El método ReplaceStyles acepta dos parámetros: el primer parámetro contiene una cadena que indica la ruta de acceso al archivo que contiene la parte styles que se va a extraer. El segundo parámetro contiene una cadena que indica la ruta de acceso al archivo en que se va a copiar la parte styles, con lo que se reemplaza de manera completamente eficaz la parte styles.

    public static void ReplaceStyles(string fromDoc, string toDoc)

Encontrará el listado completo de códigos para el método ReplaceStyles y sus métodos de apoyo en la sección Código de ejemplo.


Llamar al método de ejemplo

Para llamar al método de ejemplo, debe pasar una cadena para el primer parámetro que indica la ruta de acceso al archivo con la parte styles que va a extraer y una cadena para el segundo parámetro que representa la ruta de acceso al archivo en que se va a reemplazar la parte styles. El código de ejemplo siguiente muestra un ejemplo. Cuando el código termina de ejecutarse, se habrá reemplazado la parte styles en el documento de destino y, por lo tanto, el aspecto del texto del documento reflejará los nuevos estilos.

    const string fromDoc = @"C:\Users\Public\Documents\StylesFrom.docx";
    const string toDoc = @"C:\Users\Public\Documents\StylesTo.docx";
    ReplaceStyles(fromDoc, toDoc);

Funcionamiento del código

El código extrae y reemplaza primero la parte styles y, a continuación, la parte stylesWithEffects, y se basa en dos métodos de apoyo para realizar la mayor parte del trabajo. El método ExtractStylesPart tiene el trabajo de extraer el contenido de la parte styles o stylesWithEffects y colocarlo en un objeto XDocument . El método ReplaceStylesPart toma el objeto creado por ExtractStylesPart y usa su contenido para reemplazar la parte styles o stylesWithEffects en el documento de destino.

    // Extract and replace the styles part.
    var node = ExtractStylesPart(fromDoc, false);
    if (node != null)
        ReplaceStylesPart(toDoc, node, false);

El parámetro final de la firma para el método ExtractStylesPart o ReplaceStylesPart determina si se emplea la parte styles o stylesWithEffects. Un valor false indica que desea extraer y reemplazar la parte styles. La ausencia de un valor (el parámetro es opcional) o un valor true (el predeterminado), significa que desea extraer y reemplazar la parte stylesWithEffects.

    // Extract and replace the stylesWithEffects part. To fully support 
    // round-tripping from Word 2013 to Word 2010, you should 
    // replace this part, as well.
    node = ExtractStylesPart(fromDoc);
    if (node != null)
        ReplaceStylesPart(toDoc, node);
    return;

Para obtener más información sobre el método ExtractStylesPart , vea el ejemplo asociado. La siguiente sección explica el método ReplaceStylesPart.


Método ReplaceStylesPart

El método ReplaceStylesPart se puede usar para reemplazar la parte styles o styleWithEffects en un documento, teniendo una instancia de XDocument que contiene la misma parte para un documento Word 2010 o Word 2013 (tal como se muestra en el código de ejemplo de este tema, el método ExtractStylesPart se puede usar para obtener dicha instancia). El método ReplaceStylesPart acepta tres parámetros: el primer parámetro contiene una cadena que indica la ruta de acceso al archivo que contiene la parte styles que se va a extraer. El segundo parámetro contiene un objeto XDocument que contiene la parte styles o stylesWithEffect de otro documento de procesamiento de texto, y el tercero indica si desea reemplazar la parte styles o la parte stylesWithEffects (tal como se muestra en el código de ejemplo anterior de este tema, deberá llamar a este procedimiento dos veces para documentos Word 2013, con lo que se reemplazará cada parte por la parte correspondiente de un documento origen).

    public static void ReplaceStylesPart(string fileName, XDocument newStyles,
      bool setStylesWithEffectsPart = true)

Funcionamiento del código ReplaceStylesPart

El método ReplaceStylesPart examina el documento que especifica y busca la parte styles o stylesWithEffects. Si existe la parte solicitada, el método guarda el XDocument suministrado en la parte seleccionada.

El código comienza abriendo el documento mediante el método Open e indicando que el documento debe estar abierto para el acceso de lectura y escritura (el parámetro true final). Dado el documento abierto, el código usa la propiedad MainDocumentPart para navegar a la parte principal del documento y, a continuación, prepara una variable denominada stylesPart para contener una referencia a la parte styles.

    // Open the document for write access and get a reference.
    using (var document = 
        WordprocessingDocument.Open(fileName, true))
    {
        // Get a reference to the main document part.
        var docPart = document.MainDocumentPart;

        // Assign a reference to the appropriate part to the
        // stylesPart variable.
        StylesPart stylesPart = null;

Buscar el elemento Estilos correcto

El código, a continuación, recupera una referencia a la parte styles solicitada mediante el parámetro booleano setStylesWithEffectsPart. Basándose en este valor, el código recupera una referencia a la parte styles solicitada y la almacena en la variable stylesPart.

    if (setStylesWithEffectsPart)
        stylesPart = docPart.StylesWithEffectsPart;
    else
        stylesPart = docPart.StyleDefinitionsPart;

Guardar el contenido del elemento

Suponiendo que exista el elemento solicitado, el código debe guardar todo el contenido del XDocument que se haya pasado al método para el elemento. Cada elemento proporciona un método GetStream , que devuelve un objeto Stream. El código pasa la instancia de Stream al constructor de la clase StreamWriter , creando un sistema de escritura de secuencias alrededor de la secuencia del elemento. Por último, el código llama al método Save de XDocument, guardando su contenido en la parte styles.

    // If the part exists, populate it with the new styles.
    if (stylesPart != null)
    {
        newStyles.Save(new StreamWriter(stylesPart.GetStream(
          FileMode.Create, FileAccess.Write)));
    }

Código de ejemplo

A continuación, se incluyen los métodos completos ReplaceStyles, ReplaceStylesPart y ExtractStylesPart en C# y Visual Basic.

using DocumentFormat.OpenXml.Packaging;
using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;

ReplaceStyles(args[0], args[1]);

// Replace the styles in the "to" document with the styles in
// the "from" document.
static void ReplaceStyles(string fromDoc, string toDoc)
{
    // Extract and replace the styles part.
    var node = ExtractStylesPart(fromDoc, false);
    if (node is not null)
        ReplaceStylesPart(toDoc, node, false);

    // Extract and replace the stylesWithEffects part. To fully support 
    // round-tripping from Word 2010 to Word 2007, you should 
    // replace this part, as well.
    node = ExtractStylesPart(fromDoc);
    if (node is not null)
        ReplaceStylesPart(toDoc, node);
    return;
}

// Given a file and an XDocument instance that contains the content of 
// a styles or stylesWithEffects part, replace the styles in the file 
// with the styles in the XDocument.
static void ReplaceStylesPart(string fileName, XDocument newStyles, bool setStylesWithEffectsPart = true)
{
    // Open the document for write access and get a reference.
    using (var document = WordprocessingDocument.Open(fileName, true))
    {
        if (document.MainDocumentPart is null || document.MainDocumentPart.StyleDefinitionsPart is null || document.MainDocumentPart.StylesWithEffectsPart is null)
        {
            throw new ArgumentNullException("MainDocumentPart and/or one or both of the Styles parts is null.");
        }

        // Get a reference to the main document part.
        var docPart = document.MainDocumentPart;

        // Assign a reference to the appropriate part to the
        // stylesPart variable.
        StylesPart? stylesPart = null;
        if (setStylesWithEffectsPart)
            stylesPart = docPart.StylesWithEffectsPart;
        else
            stylesPart = docPart.StyleDefinitionsPart;

        // If the part exists, populate it with the new styles.
        if (stylesPart is not null)
        {
            newStyles.Save(new StreamWriter(stylesPart.GetStream(
              FileMode.Create, FileAccess.Write)));
        }
    }
}

// Extract the styles or stylesWithEffects part from a 
// word processing document as an XDocument instance.
static XDocument ExtractStylesPart(string fileName, bool getStylesWithEffectsPart = true)
{
    // Declare a variable to hold the XDocument.
    XDocument? styles = null;

    // Open the document for read access and get a reference.
    using (var document = WordprocessingDocument.Open(fileName, false))
    {
        // Get a reference to the main document part.
        var docPart = document.MainDocumentPart;

        if (docPart is null || docPart.StyleDefinitionsPart is null || docPart.StylesWithEffectsPart is null)
        {
            throw new ArgumentNullException("MainDocumentPart and/or one or both of the Styles parts is null.");
        }

        // Assign a reference to the appropriate part to the
        // stylesPart variable.
        StylesPart? stylesPart = null;
        if (getStylesWithEffectsPart)
            stylesPart = docPart.StylesWithEffectsPart;
        else
            stylesPart = docPart.StyleDefinitionsPart;

        using (var reader = XmlNodeReader.Create(
          stylesPart.GetStream(FileMode.Open, FileAccess.Read)))
        {
            // Create the XDocument.
            styles = XDocument.Load(reader);
        }
    }
    // Return the XDocument instance.
    return styles;
}

Vea también