Freigeben über


Konvertieren eines Dokuments aus einem Textverarbeitungsprogramm vom DOCM- in das DOCX-Dateiformat

In diesem Thema wird gezeigt, wie Sie die Klassen im Open XML SDK für Office verwenden, um ein Microsoft Word 2010- oder Microsoft Word 2013-Dokument, das VBA-Code enthält (und über eine DOCM-Erweiterung verfügt) programmgesteuert in ein Standarddokument (mit einer .docx-Erweiterung) zu konvertieren. Es enthält eine ConvertDOCMtoDOCX -Beispielmethode, um diese Aufgabe zu veranschaulichen.

ConvertDOCMtoDOCX-Methode

Mit der ConvertDOCMtoDOCX -Beispielmethode kann ein Word 2010- oder Word 2013-Dokument, das VBA-Code enthält (und eine DOCM-Erweiterung aufweist), in ein Standarddokument (mit einer DOCX-Erweiterung) konvertiert werden. Verwenden Sie diese Methode, um die Makros und den vbaProject-Teil, in dem sie enthalten sind, aus einem im DOCM-Dateiformat gespeicherten Dokument zu entfernen. Die Methode akzeptiert einen einzigen Parameter, der den Dateinamen der zu konvertierenden Datei angibt.

    public static void ConvertDOCMtoDOCX(string fileName)

Den vollständigen Codeeintrag für die Methode finden Sie im Abschnitt Beispielcode.

Aufrufen der Beispielmethode

Zum Aufrufen der Beispielmethode übergeben Sie eine Zeichenfolge, die den Namen der zu konvertierenden Datei enthält. Der folgende Code zeigt ein Beispiel.

    string filename = @"C:\Users\Public\Documents\WithMacros.docm";
    ConvertDOCMtoDOCX(filename);

Teile und der vbaProject-Teil

Ein textverarbeitendes Dokumentenpaket wie z. B. eine Datei mit einer .docx- oder .docm-Erweiterung ist tatsächlich eine ZIP-Datei, die aus mehreren Teilen besteht. Sie können sich jeden Teil ähnlich wie eine externe Datei vorstellen. Ein Teil weist einen bestimmten Inhaltstyp auf und kann je nach Typ ähnliche Inhalte wie eine externe XML-Datei, eine Binärdatei, Bilddatei usw. enthalten. Der Standard, der definiert, wie Open XML-Dokumente in ZIP-Dateien gespeichert werden, wird als Open Packaging Convention bezeichnet. Weitere Informationen über die Open Packaging Conventions finden Sie unter ISO/IEC 29500-2.

Wenn Sie ein VBA-Makro in einem Dokument erstellen und speichern, wird von Word ein neuer binärer Teil mit dem Namen "vbaProject" hinzugefügt, der die interne Darstellung des Makroprojekts enthält. Die folgende Abbildung aus dem Explorer im Open XML SDK Productivity Tool für Microsoft Office zeigt die Dokumentteile in einem Beispieldokument, das ein Makro enthält. Der vbaProject-Teil ist hervorgehoben.

Abbildung 1: Der vbaProject-Teil

vbaProject-Teil im dokument-Explorer Die Aufgabe, ein Makro aktiviertes Dokument in ein Dokument zu konvertieren, das nicht makrofähig ist, besteht daher größtenteils darin, den vbaProject-Teil aus dem Dokumentpaket zu entfernen.

Funktionsweise des Codes

Der Beispielcode bearbeitet das von Ihnen angegebene Dokument, überprüft, ob das Dokument einen vbaProject-Teil enthält, und löscht den Teil. Nachdem der Code den Teil gelöscht hat, ändert er den Dokumenttyp intern und benennt das Dokument so um, dass die DOCX-Erweiterung verwendet wird.

Der Code beginnt, das Dokument mithilfe der Open -Methode zu öffnen, und gibt an, dass das Dokument für Lese-/Schreibzugriff (der letzte Parameter "true") geöffnet werden soll. Der Code ruft dann mithilfe der MainDocumentPart-Eigenschaft des Textverarbeitungsdokuments einen Verweis auf den Document-Teil ab.

    using (WordprocessingDocument document = 
        WordprocessingDocument.Open(fileName, true))
    {
        // Get access to the main document part.
        var docPart = document.MainDocumentPart;
        // Code removed here…
    }

Der Beispielcode überprüft dann, ob der vbaProject-Teil vorhanden ist, löscht den Teil und speichert das Dokument. Der Code hat keine Auswirkungen, wenn die zu konvertierende Datei keinen vbaProject-Teil enthält. Um den Teil zu suchen, ruft der Beispielcode die VbaProjectPart -Eigenschaft des Dokuments ab. Sie ruft die DeletePart-Methode auf, um den Teil zu löschen, und ruft dann die Save-Methode des Dokuments auf, um die Änderungen zu speichern.

    // 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.
    }

Es reicht nicht aus, den Teil aus dem Dokument zu löschen. Sie müssen den Dokumenttyp auch intern konvertieren. Das Open XML SDK bietet eine Möglichkeit, diese Aufgabe auszuführen: Sie können die ChangeDocumentType-Methode des Dokuments aufrufen und den neuen Dokumenttyp angeben (in diesem Fall geben Sie den Aufzählungswert WordProcessingDocumentType.Document an).

Sie müssen die Datei auch umbenennen. Dies ist jedoch nicht möglich, während die Datei geöffnet ist. Der using-Block schließt die Datei am Ende des Blocks. Daher müssen Sie über eine Möglichkeit verfügen, um den Code nach dem Block darauf hinzuweisen, dass Sie die Datei geändert haben: Die boolesche FileChanged-Variable verfolgt diese Informationen für Sie nach.

    // Change the document type to
    // not macro-enabled.
    document.ChangeDocumentType(
        WordprocessingDocumentType.Document);

    // Track that the document has been changed.
    fileChanged = true;

Der Code benennt dann das neu geänderte Dokument um. Dazu erstellt der Code einen neuen Dateinamen, indem er die Erweiterung ändert. überprüft, ob die Ausgabedatei vorhanden ist und löscht sie und verschiebt die Datei schließlich vom alten Dateinamen in den neuen Dateinamen.

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

Beispielcode

Es folgt ein vollständiges ConvertDOCMtoDOCX-Codebeispiel in C# und 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);
    }
}