Compartir a través de


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 método de ejemplo ReplaceStyles para ilustrar esta tarea, así como los ReplaceStylesPart métodos auxiliares 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 Microsoft Word 2010 contiene una sola parte de estilos. versiones posteriores de Microsoft Word agregar 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.

Elementos de estilo en un documento de procesamiento de texto

Con el fin de proporcionar "ida y vuelta" un documento de Word 2013+ a Word 2010 y posteriores, Word 2013+ mantiene tanto la parte de estilos original como la nueva parte de estilos. (La especificación Formatos de archivo Open XML de Office requiere que Microsoft Word ignore las partes que no reconozca; Word 2010 no observa 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 ReplaceStyles método de ejemplo para reemplazar los estilos de un documento de procesamiento de texto por los estilos de otro documento de procesamiento de texto. El ReplaceStyles método acepta dos parámetros: el primer parámetro contiene una cadena que indica la ruta de acceso del archivo que contiene los estilos que se van 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.

static void ReplaceStyles(string fromDoc, string toDoc)

La lista de código completa para el ReplaceStyles método y sus métodos auxiliares se puede encontrar 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.

string fromDoc = args[0];
string toDoc = args[1];

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 ExtractStylesPart método tiene el trabajo de extraer el contenido de la parte styles o stylesWithEffects y colocarlo en un XDocument objeto . El ReplaceStylesPart método toma el objeto creado por ExtractStylesPart y usa su contenido para reemplazar la parte styles o stylesWithEffects del documento de destino.

// Extract and replace the styles part.
XDocument? node = ExtractStylesPart(fromDoc, false);

if (node is not null)
{
    ReplaceStylesPart(toDoc, node, false);
}

El parámetro final de la firma para el ExtractStylesPart método o ReplaceStylesPart determina si se emplea la parte styles o la parte 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 2010 to Word 2007, you should 
// replace this part, as well.
node = ExtractStylesPart(fromDoc);

if (node is not null)
{
    ReplaceStylesPart(toDoc, node);
}

return;

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


Método ReplaceStylesPart

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

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

Funcionamiento del código ReplaceStylesPart

El ReplaceStylesPart método examina el documento que especifique, buscando la parte styles o stylesWithEffects. Si el elemento solicitado existe, el método guarda el proporcionado XDocument en la parte seleccionada.

El código comienza abriendo el documento mediante el Open método e indicando que el documento debe estar abierto para el acceso de lectura y escritura (el parámetro final true ). Dado el documento abierto, el código usa la MainDocumentPart propiedad 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))
{
    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;

Buscar el elemento Estilos correcto

A continuación, el código recupera una referencia a la parte de estilos solicitada mediante el setStylesWithEffectsPart parámetro Boolean. 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 existe la parte solicitada, el código debe guardar todo el contenido del XDocument objeto pasado al método en la parte. Cada parte proporciona un GetStream() método , que devuelve un Stream. El código pasa la instancia de Stream al constructor de la StreamWriter(Stream) clase , creando un sistema de escritura de secuencias alrededor de la secuencia del elemento. Por último, el código llama al Save(Stream) método de XDocument, guardando su contenido en la parte styles.

// 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)));
}

Código de ejemplo

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

// 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.
    XDocument? 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)
        {
            throw new ArgumentNullException("MainDocumentPart is null.");
        }

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

        if (getStylesWithEffectsPart && docPart.StylesWithEffectsPart is not null)
        {
            stylesPart = docPart.StylesWithEffectsPart;
        }
        else if (docPart.StyleDefinitionsPart is not null)
        {
            stylesPart = docPart.StyleDefinitionsPart;
        }
        else
        {
            throw new ArgumentNullException("StyleWithEffectsPart and StyleDefinitionsPart are undefined");
        }

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

Recursos adicionales