Trojanische Kontextmenüs am Beispiel Excel

Die guten alten Trojaner lassen uns nicht in Ruhe – auch wenn das trojanische Pferd eigentlich gar kein trojanisches, sondern ein griechisches Pferd war: Der Begriff des Trojaners verfolgt uns sogar bis ins Computerzeitalter. Der vorliegende Beitrag beschäftigt sich auch mit diesem Thema, allerdings geht es hier um ein trojanisches Kontextmenü, mit dem Sie von Access aus Funktionen in andere Office-Anwendungen einschleusen. Dreht der Autor jetzt völlig durch Sie werden sehen: Vielleicht schicken ja auch Sie schon bald einen Trojaner in Richtung Word, Excel oder Outlook …

Ein praxisnahes Beispiel für ein trojanisches Kontextmenü liefert der Beitrag Ferngesteuerter Seriendruck mit Access und Word (www.access-im-unternehmen.de/714). Dort geht es um eine Access-Anwendung, die Seriendruckdokumente auf Basis beliebiger Datenherkünfte erzeugen soll. Dabei öffnet der Benutzer von Access aus eine Word-Instanz mit einem vorhandenen oder auch neuen Dokument, um dieses mit den für diese Anwendung notwendigen Platzhaltern auszustatten. Der Clou dabei: Die Platzhalter, die den Feldern der zuvor in Access ausgewählten Tabelle entsprechen, werden so im Kontextmenü von Word angeboten, dass man die Textmarke nach dem Positionieren der Einfügemarke per Kontextmenü in das Word-Dokument einfügen kann. Außerdem schließt der Benutzer die Bearbeitung des Word-Dokuments ebenfalls mit einer Kontextmenüschaltfläche ab.

Natürlich ist diese Vorgehensweise nicht ganz trivial (sonst würde es ja jeder machen): Die VBA-Funktion, die für das Einfügen der Textmarke im Word-Dokument sorgt, steckt nämlich in einem Modul der Access-Anwendung. Und auch wenn es noch relativ einfach ist, ein Kontextmenü der Word-Anwendung mit eigenen Befehlen zu bestücken oder diese anderweitig zu manipulieren, so reicht es längst nicht aus, einfach die VBA-Funktion des Access-Moduls für die OnAction-Eigenschaft des Kontextmenüeintrags anzugeben: Word wiegelt diesen Versuch mit einer humorlosen Meldung ab, dass die Funktion nicht gefunen werden könne.

Beispiel: Excel

Ein Beispiel für den Einsatz eines trojanischen Kontextmenüs in Word finden Sie in der Beispieldatenbank zum oben genannten Beitrag, daher beschäftigen wir uns hier mit einer praktischen Excel-Anwendung. Dabei möchten wir von Access aus eine Excel-Instanz mit einem zuvor ausgewählten Dokument öffnen, einen Bereich dieses Dokuments referenzieren und dann irgendetwas mit diesem Bereich veranstalten – was, bleibt Ihrer Fantasie überlassen.

Excel-Instanz holen

Bevor wir von Access aus irgendwelche Anpassungen am Menü von Excel durchführen können, müssen wir zunächst eine Excel-Instanz erstellen und einen Verweis darauf in einer Objekt-Variablen speichern. Für mehr Komfort bei der Entwicklung setzen wir zunächst einen Verweis auf die Bibliothek Microsoft Excel x.0 Object Library (VBA-Editor, Menü Extras|Verweise). Falls Sie eine andere Anwendung, wie etwa Word oder Outlook, infiltrieren möchten, binden Sie natürlich den entsprechenden Verweis ein. Und da wir exzessiv mit dem CommandBars-Objektmodell arbeiten werden, kann natürlich auch ein Verweis auf die Bibliothek Microsoft Office x.0 Object Library nicht schaden.

Den Verweis auf die Excel-Instanz und auf das darin erzeugte Excel-Dokument speichern Sie in entsprechenden Objektvariablen, die Sie in einem neuen Standardmodul namens mdlExcel anlegen:

Public objExcel As Excel.Application
Public objWorkbook As Excel.Workbook

Wenn Sie später auf Late Binding umstellen und die Verweise aus dem Projekt entfernen möchten, ändern Sie diese beiden Zeilen wie folgt:

Dim objExcel As Object
Dim objWorkbook As Object

Nachdem objExcel und objWorkbook global verfügbar sind, können wir uns für das Öffnen und Schließen dieser Elemente eigene Prozeduren gönnen. Die erste erzeugt zunächst eine Excel-Instanz und erstellt ein neues Workbook:

Public Sub ExcelStarten()
    Set objExcel = CreateObject("Excel.Application")
    Set objWorkbook = objExcel.Workbooks.Add()
End Sub

Die nächste Routine schließt das Dokument, ohne es zu speichern, und beendet auch die Excel-Instanz:

Public Sub ExcelBeenden()
    objWorkbook.Close False
    Set objWorkbook = Nothing
    objExcel.Quit
    Set objExcel = Nothing
End Sub

Wenn Sie beide hintereinander aufrufen, geschieht gar nichts Sichtbares – was auch logisch ist: Wir haben die Excel-Instanz nicht sichtbar gemacht. Das geschieht mit dieser Anweisung, die Sie nach Ausführen von ExcelStarten im Direktfenster ausprobieren können:

objExcel.Visible = True

Vorerst wollen wir Excel aber gar nicht sichtbar machen. Erstmal statten wir das entsprechende Kontextmenü von Excel mit einem neuen Eintrag aus, der die aktuelle Auswahl zur weiteren Bearbeitung an Access übergibt. In der Prozedur, die diese Aufgabe erledigt, brauchen wir zwei Objektvariablen. Die erste referenziert die Kontextmenüleiste, der wir einen Eintrag hinzufügen möchten, die zweite den neuen Eintrag selbst:

Dim cbr As Commandbar
Dim cbc As CommandBarControl

Bevor wir das neue Steuerelement hinzufügen können, müssen wir herausfinden, welches Kontextmenü überhaupt erscheint, wenn wir mit der rechten Maustaste auf einen Bereich im Excel-Worksheet klicken. Dies bekommen wir leicht heraus. Dazu öffnen wir Excel und ein Workbook mit der Prozedur ExcelStarten und rufen die folgende Routine auf:

Public Sub KontextmenueIdentifizieren()
    Dim cbr As Commandbar
    Dim cbc As CommandBarControl
    For Each cbr In objExcel.CommandBars
        If cbr.Type = msoBarTypePopup Then
            Set cbc = cbr.Controls.Add(1, , , , True)
            cbc.Caption = "Name des Kontextmenüs: " & cbr.Name
        End If
    Next cbr
End Sub

Damit fügen Sie jedem Kontextmenü der gesamten Anwendung einen Eintrag hinzu, der sich am Beispiel des Kontextmenüs einer Zelle wie in Abb. 1 auswirkt und einen Eintrag mit der Angabe des Namens der Kontextmenüleiste hinzufügt.

pic001.png

Abb. 1: Ermitteln des Namens eines Kontextmenüs

Das Kontextmenü Cell wird auch aufgerufen, wenn Sie einen Bereich aus mehreren Zellen markieren, wir brauchen uns also offensichtlich nur um dieses eine Kontextmenü zu kümmern. Gehen wir also in die Vollen und legen unseren Kontextmenüeintrag an:

Public Sub TrojanermenueAnlegen()
    Dim cbr As Commandbar
    Dim cbc As CommandBarButton
    Set cbr = objExcel.CommandBars("Cell")
    Set cbc = cbr.Controls.Add(1, , , , True)
    With cbc
        .Caption = "Auswahl nach Access übernehmen"
        .BeginGroup = True
        .OnAction = "=AuswahlUebernehmen()"
    End With
End Sub

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

Workplace

Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar