Substituir as partes de estilos em um documento de processamento de texto
Este tópico mostra como utilizar as classes no SDK Open XML para o Office para substituir programaticamente os estilos num documento de processamento de palavras pelos estilos de outro documento de processamento de palavras. Contém um método de exemplo ReplaceStyles
para ilustrar esta tarefa, bem como os ReplaceStylesPart
métodos de suporte e ExtractStylesPart
.
Acerca do Armazenamento de Estilos
Um pacote de documentos de processamento de palavras, como um ficheiro que tem uma extensão .docx, é, de facto, um ficheiro .zip que consiste em várias partes. Pode considerar cada parte semelhante a um ficheiro externo. Uma parte tem um tipo de conteúdo específico e pode conter conteúdo igual ao conteúdo de um ficheiro XML externo, ficheiro binário, ficheiro de imagem, etc., consoante o tipo. A norma que define a forma como os documentos Open XML são armazenados em ficheiros .zip é denominada Convenções de Empacotamento Aberto. Para obter mais informações sobre as Convenções de Embalagem Abertas, consulte ISO/IEC 29500-2.
Os estilos são armazenados em partes dedicadas num pacote de documentos de processamento de palavras. Um Microsoft Word 2010 documento contém uma única parte de estilos. versões posteriores do Microsoft Word adicionar uma segunda parte stylesWithEffects. A imagem seguinte do documento Explorer na Open XML SDK Productivity Tool for Microsoft Office (Ferramenta de Produtividade do SDK Open XML para Microsoft Office) mostra as partes do documento num documento de exemplo Word 2013 ou superior que contém estilos.
Figura 1. Estilos de partes num documento de processamento de palavras
Para fornecer um documento "round-tripping" de Word 2013+ para Word 2010 e posterior, Word 2013+ mantém a parte dos estilos originais e a parte dos novos estilos. (A especificação Formatos de Ficheiro Open XML do Office requer que o Microsoft Word ignorar quaisquer partes que não reconheça; Word 2010 não repara na parte stylesWithEffects que Word 2013+ adiciona ao documento.)
O exemplo de código fornecido neste tópico pode ser utilizado para substituir estas partes de estilos.
Método ReplaceStyles
Pode utilizar o ReplaceStyles
método de exemplo para substituir os estilos num documento de processamento de palavras pelos estilos noutro documento de processamento de palavras. O ReplaceStyles
método aceita dois parâmetros: o primeiro parâmetro contém uma cadeia que indica o caminho do ficheiro que contém os estilos a extrair. O segundo parâmetro contém uma cadeia que indica o caminho do ficheiro para o qual copiar os estilos, substituindo efetivamente completamente os estilos.
static void ReplaceStyles(string fromDoc, string toDoc)
A listagem de código completa para o método e os ReplaceStyles
respetivos métodos de suporte pode ser encontrada na secção Código de Exemplo .
Chamar o Método de Exemplo
Para chamar o método de exemplo, transmita uma cadeia para o primeiro parâmetro que indica o caminho do ficheiro com os estilos a extrair e uma cadeia para o segundo parâmetro que representa o caminho para o ficheiro no qual pretende substituir os estilos. O código de exemplo seguinte mostra um exemplo. Quando o código terminar de ser executado, os estilos no documento de destino terão sido substituídos e, consequentemente, o aspeto do texto no documento irá refletir os novos estilos.
string fromDoc = args[0];
string toDoc = args[1];
ReplaceStyles(fromDoc, toDoc);
Como Funciona o Código
O código extrai e substitui os estilos em primeiro lugar e, em seguida, os estilosWithEffects parte segundo e baseia-se em dois métodos de suporte para fazer a maior parte do trabalho. O ExtractStylesPart
método tem a tarefa de extrair o conteúdo da parte estilos ou estilosWithEffects e colocá-lo num XDocument objeto. O ReplaceStylesPart
método utiliza o objeto criado por ExtractStylesPart
e utiliza o respetivo conteúdo para substituir a parte estilos ou estilosWithEffects no documento de destino.
// Extract and replace the styles part.
XDocument? node = ExtractStylesPart(fromDoc, false);
if (node is not null)
{
ReplaceStylesPart(toDoc, node, false);
}
O parâmetro final na assinatura do ExtractStylesPart
método ou ReplaceStylesPart
determina se a parte de estilos ou a parte stylesWithEffects está empregue. Um valor falso indica que pretende extrair e substituir a parte de estilos. A ausência de um valor (o parâmetro é opcional) ou um valor verdadeiro (a predefinição) significa que pretende extrair e substituir a 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 obter mais informações sobre o ExtractStylesPart
método, veja o exemplo associado. A secção seguinte explica o ReplaceStylesPart
método .
Método ReplaceStylesPart
O ReplaceStylesPart
método pode ser utilizado para substituir a parte estilos ou estilosWithEffects num documento, dada uma XDocument
instância que contém a mesma parte para um documento Word 2010 ou Word 2013+ (conforme mostrado no código de exemplo anterior neste tópico, o ExtractStylesPart
método pode ser utilizado para obter essa instância). O ReplaceStylesPart
método aceita três parâmetros: o primeiro parâmetro contém uma cadeia que indica o caminho para o ficheiro que pretende modificar. O segundo parâmetro contém um XDocument
objeto que contém os estilos ou estilosA parteWithEffect de outro documento de processamento de palavras e o terceiro indica se pretende substituir a parte de estilos ou a parte stylesWithEffects (conforme mostrado no código de exemplo anteriormente neste tópico, terá de chamar este procedimento duas vezes para documentos Word 2013 e superior, substituindo cada parte pela parte correspondente de um documento de origem).
static void ReplaceStylesPart(string fileName, XDocument newStyles, bool setStylesWithEffectsPart = true)
Como funciona o Código ReplaceStylesPart
O ReplaceStylesPart
método examina o documento que especificar, procurando a parte estilos ou estilosWithEffects.
Se a peça pedida existir, o método guarda o fornecido XDocument
na parte selecionada.
O código começa por abrir o documento com o Open método e indicando que o documento deve estar aberto para acesso de leitura/escrita (o parâmetro final true
). Dado o documento aberto, o código utiliza a MainDocumentPart propriedade para navegar para a parte main documento e, em seguida, prepara uma variável com o nome stylesPart
para conter uma referência à parte estilos.
// 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;
Localizar a Peça Estilos Corretos
Em seguida, o código obtém uma referência à parte de estilos pedidos com o parâmetro Booleano setStylesWithEffectsPart
. Com base neste valor, o código obtém uma referência à parte de estilos pedidos e armazena-a na stylesPart
variável .
if (setStylesWithEffectsPart)
{
stylesPart = docPart.StylesWithEffectsPart;
}
else
{
stylesPart = docPart.StyleDefinitionsPart;
}
Guardar o Conteúdo da Peça
Partindo do princípio de que a peça pedida existe, o código tem de guardar todo o conteúdo do XDocument
transmitido para o método para a peça. Cada parte fornece um GetStream() método, que devolve um Stream.
O código transmite a instância Stream ao construtor da StreamWriter(Stream) classe, criando um escritor de fluxo em torno do fluxo da peça. Por fim, o código chama o Save(Stream) método do XDocument, guardando os respetivos conteúdos na parte de estilos.
// 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 exemplo
Seguem-se os métodos completos ReplaceStyles
, ReplaceStylesPart
e ExtractStylesPart
em C# e 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;
}