将字处理文档从 DOCM 转换为 DOCX 文件格式

本主题演示如何使用 Open XML SDK for Office 中的类以编程方式将包含 VBA 代码 (且具有 .docm 扩展名) 的Microsoft Word文档转换为具有 .docx 扩展名) 的标准文档 (。 它包含演示此任务的示例 ConvertDOCMtoDOCX 方法。

ConvertDOCMtoDOCX 方法

示例ConvertDOCMtoDOCX方法可用于将包含 VBA 代码 (且具有 .docm 扩展名的 Word 文档) 转换为具有 .docx 扩展名) 的标准文档 (。 使用该方法可从以 .docm 文件格式存储的包含宏和 vbaProject 部件的文档中移除这些宏和部件。 该方法接受一个指示要转换的文件的文件名的参数。

static void ConvertDOCMtoDOCX(string fileName)

该方法的完整代码列表位于示例代码部分。

调用示例方法

若要调用示例方法,请传递包含要转换的文件的名称的字符串。 以下示例代码演示了一个示例。

ConvertDOCMtoDOCX(args[0]);

部件和 vbaProject 部件

字处理文档包(如扩展名为 .docx 或 .docm 的文件)实际上是一个 .zip 文件,由几个部件 组成。 您可将每个部件视为与外部文件类似。 每个部件具有特定的内容类型,并且可能包含与外部 XML 文件、二进制文件、图像文件等相同的内容,具体取决于类型。 定义 Open XML 文件在 .zip 文件中如何存储的标准称为"开放打包约定"。 有关开放打包约定的详细信息,请参阅 ISO/IEC 29500-2:2021

当创建 VBA 宏并将其保存在文档中时,Word 会添加一个名为 vbaProject 的新二进制部分,其中包含您的宏项目的内部表示形式。 Microsoft Office Open XML SDK Productivity Tool 中文档资源管理器中的下图显示了包含宏的示例文档中的文档部件。 其中突出显示了 vbaProject 部件。

图 1. vbaProject 部件

文档资源管理器中显示的 vbaProject 部件

因此,将启用宏的文档转换为未启用宏的文档的任务基本上由从文档包中移除 vbaProject 部件的任务组成。

代码的工作方式

该示例代码将修改您指定的文档,验证该文档是否包含 vbaProject 部件,并删除该部件。 该代码在删除此部分后,将在内部更改文档类型并重命名该文档,以便它使用 .docx 扩展名。

代码首先使用 Open 方法打开文档,并指示应打开文档以 (最终 true 参数) 进行读/写访问。 然后,代码使用 MainDocumentPart 字处理文档的 属性检索对 Document 部件的引用。

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.");

从文档中删除部件是不够的。 还必须在内部转换文档类型。 Open XML SDK 提供了一种执行此任务的方法:可以调用 document ChangeDocumentType 方法并指示在这种情况下 (的新文档类型,) 提供 WordprocessingDocumentType.Document 枚举值。

您还必须重命名文件。 但您无法在文件处于打开状态时执行此操作。 using 块在该块末尾关闭文件。 因此,必须通过某种方式向代码指示你修改了该文件的块之后的代码: fileChanged 布尔变量会为你跟踪此信息。

// Look for the vbaProject part. If it is there, delete it.
var vbaPart = docPart.VbaProjectPart;
if (vbaPart is not null)
{
    // Delete the vbaProject part.
    docPart.DeletePart(vbaPart);

之后,该代码将重命名新修改的文档。 为此,该代码将通过更改扩展名来创建新文件名;验证输出文件是否存在并将其删除,最后,该代码会将文件从旧文件名移动到新文件名。

// 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# 和 Visual Basic 中的完整 ConvertDOCMtoDOCX 代码示例。

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.
            docPart.DeletePart(vbaPart);

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

另请参阅