Convertir un documento de procesamiento de texto del formato de archivo DOCM a DOCX
En este tema se muestra cómo usar las clases del SDK de Open XML para Office para convertir mediante programación un documento Microsoft Word 2010 o Microsoft Word 2013 que contiene código VBA (y tiene una extensión .docm) en un documento estándar (con una extensión .docx). Contiene un ejemplo del método ConvertDOCMtoDOCX para ilustrar esta tarea.
Método ConvertDOCMtoDOCX
El método de ejemplo ConvertDOCMtoDOCX se puede usar para convertir un documento de Word 2010 o Word 2013 que contenga código VBA (y tenga extensión .docm) en un documento estándar (con extensión .docx). Use este método para quitar las macros y la parte vbaProject que los contenga de un documento almacenado en formato de archivo .docm. El método acepta un único parámetro que indica el nombre del archivo que desea convertir.
public static void ConvertDOCMtoDOCX(string fileName)
Encontrará el listado completo de códigos para el método en la sección Código de ejemplo.
Llamar al método de ejemplo
Para llamar al método de ejemplo, pase una cadena que contenga el nombre del archivo que desea convertir. El código de ejemplo siguiente muestra un ejemplo.
string filename = @"C:\Users\Public\Documents\WithMacros.docm";
ConvertDOCMtoDOCX(filename);
Partes y la parte vbaProject
Un paquete de documento de procesamiento de texto como, por ejemplo, un archivo con extensión .docx o .docm, 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 equivalente a 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.
Al crear y guardar una macro VBA en un documento, Word agrega una nueva parte binaria llamada vbaProject que contiene la representación interna de su proyecto de macro. 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 de documento de un documento de ejemplo que contiene una macro. La parte vbaProject esta resaltada.
Figura 1. La parte vbaProject
Por lo tanto, la tarea de convertir un documento habilitado para macros en uno que no está habilitado para macros consiste en gran medida en quitar la parte vbaProject del paquete de documentos.
Funcionamiento del código
El código de ejemplo modifica el documento que especifique, con lo que se comprueba que el documento contenga una parte vbaProject y se elimina la parte. Una vez que el código elimine la parte, cambia el tipo de documento internamente y le cambia el nombre de modo que usa la extensión .docx.
El código empieza abriendo el documento mediante el método Open e indicando que el documento debe abrirse al acceso de lectura/escritura (el parámetro verdadero final). A continuación, el código recupera una referencia al elemento Document mediante la propiedad MainDocumentPart del documento de procesamiento de texto.
using (WordprocessingDocument document =
WordprocessingDocument.Open(fileName, true))
{
// Get access to the main document part.
var docPart = document.MainDocumentPart;
// Code removed here…
}
A continuación, el código de ejemplo comprueba que exista la parte vbaProject, elimina la parte y guarda el documento. El código no tiene ningún efecto si el archivo que desea convertir no contiene una parte vbaProject. Para buscar la parte, el código de ejemplo recupera la propiedad VbaProjectPart del documento. Llama al método DeletePart para eliminar el elemento y, a continuación, llama al método Save del documento para guardar los cambios.
// Look for the vbaProject part. If it is there, delete it.
var vbaPart = docPart.VbaProjectPart;
if (vbaPart != null)
{
// Delete the vbaProject part and then save the document.
docPart.DeletePart(vbaPart);
docPart.Document.Save();
// Code removed here.
}
No basta con eliminar la parte del documento. También debe convertir el tipo de documento internamente. El SDK de Open XML proporciona una manera de realizar esta tarea: puede llamar al método ChangeDocumentType del documento e indicar el nuevo tipo de documento (en este caso, proporcionar el valor enumerado WordProcessingDocumentType.Document ).
También debe cambiar el nombre del archivo. Sin embargo, no puede hacerlo mientras el archivo esté abierto. El bloque de uso cierra el archivo al final del bloque. Por lo tanto, debe tener algún modo de indicar al código después del bloque que ha modificado el archivo: la variable booleana fileChanged realiza un seguimiento de esta información para el usuario.
// Change the document type to
// not macro-enabled.
document.ChangeDocumentType(
WordprocessingDocumentType.Document);
// Track that the document has been changed.
fileChanged = true;
A continuación, el código cambia el nombre del documento recién modificado. Para ello, el código crea un nombre de archivo nuevo cambiando la extensión; comprueba que existe el archivo de salida y lo elimina, y por último, traslada el archivo del nombre de archivo anterior al nombre de archivo nuevo.
// If anything goes wrong in this file handling,
// the code will raise an exception back to the caller.
if (fileChanged)
{
// Create the new .docx filename.
var newFileName = Path.ChangeExtension(fileName, ".docx");
// If it already exists, it will be deleted!
if (File.Exists(newFileName))
{
File.Delete(newFileName);
}
// Rename the file.
File.Move(fileName, newFileName);
}
Código de ejemplo
A continuación, se incluye el código de ejemplo completo ConvertDOCMtoDOCX en C# y Visual Basic.
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using System;
using System.IO;
ConvertDOCMtoDOCX(args[0]);
// Given a .docm file (with macro storage), remove the VBA
// project, reset the document type, and save the document with a new name.
static void ConvertDOCMtoDOCX(string fileName)
{
bool fileChanged = false;
using (WordprocessingDocument document = WordprocessingDocument.Open(fileName, true))
{
// Access the main document part.
var docPart = document.MainDocumentPart ?? throw new ArgumentNullException("MainDocumentPart is null.");
// Look for the vbaProject part. If it is there, delete it.
var vbaPart = docPart.VbaProjectPart;
if (vbaPart is not null)
{
// Delete the vbaProject part and then save the document.
docPart.DeletePart(vbaPart);
docPart.Document.Save();
// Change the document type to
// not macro-enabled.
document.ChangeDocumentType(
WordprocessingDocumentType.Document);
// Track that the document has been changed.
fileChanged = true;
}
}
// If anything goes wrong in this file handling,
// the code will raise an exception back to the caller.
if (fileChanged)
{
// Create the new .docx filename.
var newFileName = Path.ChangeExtension(fileName, ".docx");
// If it already exists, it will be deleted!
if (File.Exists(newFileName))
{
File.Delete(newFileName);
}
// Rename the file.
File.Move(fileName, newFileName);
}
}