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).
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).
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).
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).
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.
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: