COM-Add-In zum Übersetzen von Word-Dokumenten

Das Internet bietet für beinahe jeden Zweck einen Service. Auch für das Übersetzen von Texten. Ein Anbieter heißt DeepL. Er bietet nicht nur eine Benutzeroberfläche, in die man Texte eingeben kann, die direkt übersetzt werden, sondern auch noch eine API. Dieser können wir programmgesteuert Texte übergeben und die Übersetzung entgegennehmen. Das ist sehr praktisch für diejenigen Bereiche der Programmierung, wo man Texte in einer anderen oder in mehreren Sprachen braucht. In diesem Artikel wollen wir uns jedoch ansehen, wie wir aus den Techniken, die wir in weiteren Artikeln vorgestellt haben, ein COM-Add-In bauen, das sich nahtlos in die Word-Benutzeroberfläche eingliedert und auf Knopfdruck komplette Dokumente oder auch nur markierte Bereiche in die gewünschte Sprache übersetzt.

Übersetzen mit DeepL

Die Artikel, in denen wir auf die Grundlagen zu DeepL eingehen, findest Du unter Excel: Übersetzungen mit DeepL (www.vbentwickler.de/325), Texte übersetzen mit DeepL (www.vbentwickler.de/322) und Übersetzen mit Word und DeepL (www.vbentwickler.de/346).

Da DeepL seine API für bis zu 500.000 Zeichen pro Monat kostenlos anbietet, nutzen wir es gern als Beispiel für den Zugriff auf eine REST API. Wenn Du mehr als diese Anzahl Zeichen übersetzen möchtest, kannst Du den kostenpflichten Pro-Account nutzen. Beide schließt Du unter folgendem Link ab:

https://www.deepl.com/de/pro#developer

twinBASIC

Auch das Tool, das wir zum Erstellen des COM-Add-Ins nutzen, ist zumindest in der Variante, die das Erstellen von 32-Bit-Dateien erlaubt, kostenlos. Du findest weitere Informationen dazu zum Beispiel in twinBASIC: Visual Basic für die Zukunft (www.vbentwickler.de/310), COM-Add-Ins mit twinBASIC (www.vbentwickler.de/311) und Ribbon-Signaturen für VBA, VB6 und twinBASIC (www.vbentwickler.de/314).

Ziel des Artikels

Bevor wir in die Programmierung einsteigen, schauen wir uns den Plan an. Das Ziel ist es, dass wir per Mausklick auf einen Ribbon-Eintrag einen Übersetzungsvorgang starten können. Dieser Vorgang soll entweder den aktuell markierten Text übersetzen oder, wenn keine Markierung vorhanden ist, den Absatz übersetzen, in dem sich aktuell die Einfügemarke befindet.

Neben dem Button für das eigentliche Übersetzen benötigen wir natürlich noch eine Möglichkeit, die Original- und die Zielsprache festzulegen. Dies wollen wir ebenfalls im Ribbon ermöglichen, indem wir die verfügbaren Sprachen dort zur Auswahl anbieten.

Anlegen eines twinBASIC-Projekts

Für das COM-Add-In benötigen wir ein twinBASIC-Projekt, welches wir nach dem Öffnen von twinBASIC auf Basis des Beispielprojekts Sample 5. MyCOMAddIn erstellen (siehe Bild 1).

Auswahl einer Vorlage

Bild 1: Auswahl einer Vorlage

Wir schauen uns nicht im Detail an, welche Änderungen wir an dem bestehenden Code vornehmen, sondern beschreiben im Anschluss den neuen Code des COM-Add-Ins.

Hinzufügen benötigter Verweise

Wir wollen das Add-In nutzen, um auf das Objektmodell von Word zuzugreifen und die darin markierten Elemente auslesen, um diese zu übersetzen.

Damit wir dabei nicht mit Late Binding arbeiten müssen, fügen wir einen Verweis auf die Bibliothek Microsoft Word 16.0 Object Library hinzu. Außerdem brauchen wir noch einen Verweis auf die Bibliothek Microsoft XML, v6.0.

Dieser liefert das Objekt ServerXMLHTTP60, das wir für den Zugriff auf die DeepL-REST-API benötigen.

Diese Verweise fügen wir in twinBASIC im Bereich Settings hinzu. Hier scrollen wir ein wenig nach unten und finden dort den Bereich COM Type Library / ActiveX References. In der unteren Liste namens ALL AVAILABLE COM REFERENCES können wir nach den Namen dieser beiden Bibliotheken suchen und sie durch Setzen eines Hakens zum Projekt hinzufügen (siehe Bild 2).

Hinzufügen von Verweisen

Bild 2: Hinzufügen von Verweisen

Weitere Projekteinstellungen anpassen

Bevor wir die Änderungen nach dem Hinzufügen der Verweise speichern, was vor dem Kompilieren unbedingt notwendig ist, stellen wir gleich noch ein paar weitere Eigenschaften ein. Dabei handelt es sich um den Projektnamen, die Projektbeschreibung und den Anwendungstitel. Alle drei stellen wir im oberen Bereich unter Settings ein (siehe Bild 3).

Ändern weiterer Projekteigenschaften

Bild 3: Ändern weiterer Projekteigenschaften

Danach speichern wir das Projekt und geben als Namen beispielsweise amvWordTranslator.twinproj an.

Modul mit DeepL-Funktionen einfügen

Bevor wir uns um die eigentliche Funktionalität kümmern, fügen wir noch ein neues Modul hinzu. Dazu klicken wir mit der rechten Maustaste auf den Eintrag Sources im Projekt-Explorer und wählen dort den Eintrag Add|Add Module aus (siehe Bild 4).

Hinzufügen eines neuen Moduls

Bild 4: Hinzufügen eines neuen Moduls

Das noch leere Modul nennen wir mdlDeepL und fügen diesem den Code hinzu, den wir im Artikel Texte übersetzen mit DeepL (www.vbentwickler.de/322) entworfen haben.

Code zum Registrieren und De-Registrieren anpassen

Das Beispielprojekt enthält normalerweise den Code, um das COM-Add-In für den Gebrauch in Excel und Access zu registrieren. Diesen müssen wir anpassen, denn wir wollen unser COM-Add-In in Word anzeigen. Dazu öffnen wir das Modul DLLRegistration. Dieses passen wir nun an beziehungsweise gestalten es neu. Das Ergebnis kannst Du Listing 1 entnehmen.

Module DllRegistration
     Const AddinProjectName As String = VBA.Compilation.CurrentProjectName
     Const AddinClassName As String = "amvWordTranslator"
     Const AddinQualifiedClassName As String = AddinProjectName & "." & AddinClassName
     Const RootRegistryFolder_WORD As String = "HKCU\SOFTWARE\Microsoft\Office\Word\Addins\" & AddinQualifiedClassName & "\"
     
     Public Function DllRegisterServer() As Boolean
         On Error GoTo RegError
         Dim wscript As Object = CreateObject("wscript.shell")
         wscript.RegWrite RootRegistryFolder_WORD & "FriendlyName", AddinProjectName, "REG_SZ"
         wscript.RegWrite RootRegistryFolder_WORD & "Description", AddinProjectName, "REG_SZ"
         wscript.RegWrite RootRegistryFolder_WORD & "LoadBehavior", 3, "REG_DWORD"
         Return True
     RegError:
         MsgBox "DllRegisterServer -- An error occured trying to write to the system registry:" & vbCrLf & _
                 Err.Description & " (" & Hex(Err.Number) & ")"
         Return False
     End Function
  
     Public Function DllUnregisterServer() As Boolean
         On Error GoTo RegError
         Dim wscript As Object = CreateObject("wscript.shell")
         wscript.RegDelete RootRegistryFolder_WORD & "FriendlyName"
         wscript.RegDelete RootRegistryFolder_WORD & "Description"
         wscript.RegDelete RootRegistryFolder_WORD & "LoadBehavior"
         wscript.RegDelete RootRegistryFolder_WORD
         Return True
     RegError:
         MsgBox "DllUnregisterServer -- An error occured trying to delete from the system registry:" & vbCrLf & _
                 Err.Description & " (" & Hex(Err.Number) & ")"
         Return False
     End Function
End Module

Listing 1: Das Modul mit dem Code zum Registrieren und De-Registrieren des COM-Add-Ins

Hier definieren wir zunächst einige Konstanten. Die erste enthält den Projektnamen. Diesen lesen wir aus VBA.Compilation.CurrentProjectName aus, den wir zuvor in den Einstellungen des Projekts festgelegt haben.

Den Klassennamen stellen wir auf amvWordTranslator ein. Diese Bezeichnung sollten wir gleich beim Gestalten des Hauptmoduls als Bezeichnung des Moduls als auch als Name der darin enthaltenen Klasse verwenden.

Schließlich stellen wir in AddinQualifiedClassName noch die Kombination aus AddinProjectName und AddinClassName zusammen – getrennt durch einen Punkt. Diese Bezeichnung verwenden wir für den Eintrag in der Registry.

Um die Einträge in der Registry an der richtigen Stelle anzulegen, erstellen wir in der Konstanten RootRegistryFolder_WORD den Pfad für den anzulegenden Basispfad.

Dieser lautet in unserem Fall:

HKCU\SOFTWARE\Microsoft\Office\Word\Addins\amvWordTranslator.amvWordTranslator\

Die folgende Prozedur DllRegisterServer führt mithilfe des Shell-Objekts die notwendigen Eintragungen in der Registry durch. Dazu erstellt sie zuerst ein Objekt des Typs wscript.shell und ruft dann mehrfach dessen Methode RegWrite auf. Dieser übergibt sie den Pfad, den Namen des Eintrags und den gewünschten Wert sowie den Datentyp. Ist dies erfolgreich, liefert die Funktion den Wert True zurück, anderenfalls erscheint eine entsprechende Fehlermeldung.

Der durch diese Funktion erstellte Eintrag in der Registry sieht beispielsweise wie in Bild 5 aus.

Registry-Einträge für das COM-Add-In

Bild 5: Registry-Einträge für das COM-Add-In

Die zweite Funktion namens DllUnregisterServer enthält die Anweisungen, um die soeben vorgenommenen Einträge in die Registry wieder zu entfernen. Sie nutzt das gleiche Objekt, aber diesmal die Methode RegDelete. Hier muss nur noch die Pfad zu den zu löschenden Registry-Einträgen angegeben werden.

Diese beiden Funktionen kann man übrigens auch direkt von twinBASIC aus aufrufen – wenn also einmal nur ein Registry-Eintrag nicht korrekt ist, braucht man das Projekt nicht neu zu erstellen.

Allerdings geht auch das Erstellen sehr schnell, sodass sich das separate Aufrufen der Funktionen in diesem Fall nicht lohnt. Lohnenswert ist dies allerdings, wenn man einmal das Schreiben oder Löschen der Registry-Werte debuggen möchte.

Die Klasse amvWordTranslator

Damit kommen wir zur der Hauptklasse der Anwendung, welche die eigentliche Funktionalität enthält. Das beginnt mit den Ereignissen, die beim Öffnen von Word ausgelöst werden und die dazu führen, dass das Add-In gestartet und das Ribbon der Anwendung in Word integriert wird. Außerdem enthält die Klasse die Methoden, die durch das Betätigen der Ribbonelemente des COM-Add-Ins ausgelöst werden. Die Klasse enthält wie alle COM-Add-Ins einen eindeutigen Bezeichner, der in eckigen Klammern im Kopf des Klassenmoduls angegeben wird:

[ ClassId ("F333F038-C5F7-4AA3-8684-09A024EC892C") ]

Direkt danach beginnt die Definition der Klasse und ihrer Elemente. Hier haben wir das Class-Schlüsselwort und zunächst zwei Implements-Anweisungen. Damit geben wir an, dass wir die Schnittstellen IDExtensibility2 und IRibbonExtensibility in dieser Klasse implementieren:

Class amvWordTranslator
     Implements IDTExtensibility2
     [ WithDispatchForwarding ]
     Implements IRibbonExtensibility

Das bedeutet für die aufrufende Anwendung, in diesem Fall Word, dass sie in dieser Klasse die Implementierungen der Methoden der angegebenen Schnittstellen findet und diese aufrufen soll. Im Falle von IDTExtensibility heißt das beispielsweise, dass beim Start von Word die Methode OnConnection aufgerufen werden soll – mehr dazu gleich im Anschluss.

Vorher sehen wir uns noch die drei Variablen an, die wir hier benötigen. Die erste ist eine Objektvariable zum Speichern des Verweises auf die Word-Instanz, welche das COM-Add-In initialisiert hat.

Diese Variable können wir, nachdem wir sie gleich zugewiesen haben, nutzen, um vom COM-Add-In auf die Word-Instanz und das darin enthaltene Dokument zuzugreifen:

     Private objWord As Word.Application

Außerdem legen wir noch zwei Variablen fest für die Originalsprache sowie die Zielsprache der Übersetzung. Diese erhalten als Datentyp die Enumerationen der beiden Auflistungen aus dem Modul mdlDeepL:

     Public intSourceLanguage As SourceLanguage
     Public intTargetLanguage As TargetLanguage
...
End Class

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Visual Basic Entwickler:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 200 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar