| Senden von Tastenbefehlen | |
| SendKeys - AppActivate - Shell - ActivateMicrosoftApp |
Einleitung
Inhalt dieser Seite
Zweck von
Tastenbefehlen senden
Einsatzgebiete
Voraussetzungen für das Senden von
Tasten
1. Anwendung muss aktiv
sein
2. Anwendung
muss Taste verstehen können
3.
Anwendung muss Taste verarbeiten können
Die verschiedenen
Möglichkeiten zum Senden von Tastenfolgen
SendKeys
(VBA-Anweisung)
Application.SendKeys
(Objekt-Methode)
Application.DDEExecute
(Objekt-Methode)
Technische
Informationen zu SendKeys, Application.SendKeys und DDEExecute
SendKeys,
Application.SendKeys oder DDEExecute?
Unterschiede zwischen
SendKeys und Application.SendKeys
Ein kleiner Praxis-Test
Unterschiedliches
Verhalten je nach Windows-Version
Verwendung von DoEvents
Was
bewirkt der Wait-Parameter?
Wann muss der Wait-Parameter
auf True gesetzt werden?
So sendet man Tastenanschläge
Tastenfolgen zur
Steuerung einer Dialogmaske an Excel senden
Sonstige
Tastenfolgen an Excel senden
Tastenfolgen
an eine andere Anwendung senden
Einschränkungen und Grenzen von SendKeys
Nicht unterstützte
Tasten
Umgehungslösung
für nicht unterstützte Tasten
Bestimmen der
Ausführungsumgebung
Empfänger-Anwendung starten und
aktivieren
Eine
alltägliche Aufgabe: Anwendung starten, Fenster aktivieren, Tasten senden
Programm-Stabilität und -Fehlerfreiheit
Makro-Unterbrechung
verhindern
Makro-Abbruch verhindern
Unterbrochenes Makro
fortsetzen
Checkliste für die Programmierung
Auf dieser Seite finden Sie umfassende und ausführliche Informationen zum Thema "Senden von Tastenfolgen an eine Anwendung". Lesen Sie hier allerlei Interessantes zu diesen Dingen:
- warum und in welchen Situationen man Tastenfolgen senden
sollte
- was man grundsätzlich beachten muss
- welche Risiken und Gefahren existieren
- welche Probleme und Fehler bekannt sind
- was man bereits vor dem Programmieren beachten sollte
- was aus technischer Sicht beim Senden von Tastenfolgen vorgeht
- wie die in VBA zur Verfügung stehenden Anweisungen und Funktionen heissen
- wie man mit VBA Tastenfolgen sendet
- was man bei Auftreten eines Fehlers tun kann
- welche Tasten nicht an eine Anwendung gesendet werden können
- wie man Spezialtasten wie u.a. CapsLock aufrufen kann
- wie eine andere Anwendung gestartet wird
- welche Alternativen es zum Senden von Tastenbefehlen gibt
- wie man überprüfen kann, ob Tastenfolgen korrekt verarbeitet wurden
- welche geheime und undokumentierte Features existieren
- wie man SendKeys-Programmcode stabil und fehlerresistent macht
- wie die offiziellen Tastenbezeichnungen lauten
- wo man weitere themenbezogene Informationen erhält
Zweck von Tastenbefehlen senden
Das Senden von Tastenfolgen stellt eine einfache Lösung dar, eine beliebige Anwendung zu steuern, Funktionen dieser Anwendung auszuführen, Menübefehle aufzurufen, Daten zu übergeben bzw. zu übernehmen, und so weiter. Die Möglichkeiten sind praktisch unbegrenzt, wobei es ein paar wenige Einschränkungen gibt (siehe Kapitel Einschränkungen und Grenzen von SendKeys).
Üblicherweise werden Tastenfolgen an eine andere Anwendung gesendet. Man kann jedoch problemlos auch Tastenbefehle an die eigene Anwendung senden, sprich an diejenige Anwendung, die den Programmcode enthält und ausführt, und somit die aktive Anwendung darstellt.
In den meisten Fällen gibt es bessere Lösungen als das Senden von Tastenbefehlen, nämlich unter anderem die Steuerung der anderen Anwendung mittels Automation (auch Office Automation genannt, früher OLE Automation genannt), oder, wenn die eigene Anwendung gesteuert werden soll, die Verwendung der entsprechenden, standardmässig vorhandenen VBA-Anweisungen und Objekt-Methoden.
Alternative 1: Objekt-Methode
Anstelle das Senden der Tastenkombination Strg+X verwendet man
innerhalb Microsoft Excel zum Ausschneiden einer Zelle besser die Cut-Methode.
Mit der Codezeile "ActiveCell.Cut" wird beispielsweise die gerade aktive Zelle
ausgeschnitten.
Alternative 2: VBA-Anweisung
Zum Kopieren einer Datei muss man nicht den Windows Explorer mittels Shell-Funktion
starten, die gewünschte Datei selektieren und dann den Kopieren-Befehl des Bearbeiten-Menüs
anhand von gesendeten Tastenanschlägen aufrufen. Einfacher geht es mit der FileCopy-Anweisung
von VBA.
Alternative 3: Automation
Ein neues Word-Dokument kann aus einer anderen Anwendung heraus sehr einfach
mittels Office Automation angelegt werden. Man muss also nicht Microsoft Word mit VBA
(z.B. mit Shell oder ActivateMicrosoftApp) starten und dann anhand von
Tastenfolgen den Menübefehl Datei/Neu von Word aufrufen.
Der VBA-Programmcode dieser Automation-Lösung, welche Word starten, ein neues Dokument erstellt, das Dokument speichert und anschliessend Word beendet sieht folgendermassen aus:
Sub CreateNewDocument()
Dim appWord As Object
Set appWord = CreateObject("Word.Application")
appWord.Documents.Add.SaveAs "D:\NewDocument.doc"
appWord.Quit
Set appWord = Nothing
End Sub
Wenn es keine Alternative gibt
Wie gesagt funktioniert in den meisten Fällen mindestens eine der oben aufgeführten Alternativen. Es gibt jedoch ein paar Fälle, bei denen weder eine VBA-Anweisung, noch eine Objekt-Methode, noch eine Automation-Lösung in Frage kommt, und zwar ganz einfach aus dem Grund, weil es keine entsprechende Lösungsmöglichkeit gibt.
Verschiedene Aufgabenstellungen lassen sich ausschliesslich
durch das Senden von Tastenfolgen lösen. In Bezug auf Microsoft Excel kann man diese in
zwei Gruppen einteilen:
1. Dialogmasken und Fenster, die in Excel zwar aufgerufen werden können, aber
nicht mit VBA angesprochen werden können
2. Funktionen, Befehle und Optionen, die im Excel-Objektmodell nicht als Methoden
oder Eigenschaften existieren
Hier ein paar solcher Aufgaben:
| Aufgabe | Beschreibung | Beispiel |
| Drucker-Eigenschaften ändern | Die Drucker-Eigenschaften können nicht mit VBA eingestellt werden, da entsprechende Eigenschaften im Objektmodell fehlen. | - |
| Bearbeiten-Modus aktivieren | Der Zellbearbeitungsmodus wird in Excel mittels Doppelklick auf eine Zelle oder mit der Funktionstaste F2 aktiviert. Excel-VBA stellt keine entsprechende Methode zur Verfügung. | - |
| Bestimmter Datensatz in Datenmaske anzeigen | - | - |
| Optionen-Dialogfenster öffnen | - | - |
| Optionen des VBA-Editors ändern | - | - |
Voraussetzungen für das Senden von Tasten
Damit eine Taste an eine Anwendung gesendet und von dieser
verarbeitet werden kann, müssen insbesondere drei Bedingungen erfüllt sein:
1. Die Empfänger-Anwendung muss aktiv sein
2. Die Empfänger-Anwendung muss die an sie gesendete Taste interpretieren können
3. Die Empfänger-Anwendung muss die an sie gesendete Taste verarbeiten können
In den folgenden drei Abschnitten werden diese drei Bedingungen vorgestellt.
Gesendete Tastenfolgen werden immer von derjenigen Anwendung empfangen, die gerade aktiv ist. Die aktive Anwendung erkennt man daran, dass das Fenster dieser Anwendung aktiv ist, sprich den Fokus besitzt. Eine Anwendung, die kein Fenster besitzt oder nicht aktiviert werden kann, kann folglich auch keine Tastenbefehle empfangen (z.B. ein Systemprozess oder eine Anwendung mit einem ausgeblendeten Fenster).
2. Anwendung muss Taste verstehen können
Obwohl diese Voraussetzung an sich 'logisch' ist, darf man sie nicht vergessen und schon gar nicht als selbstverständlich betrachten.
Beispielsweise die an Microsoft Excel gesendete Tastenfolge "ALT+D, I" bewirkt, dass das Dialogfenster "Eigenschaften" geöffnet wird, weil mit ALT+D das Menü "Datei" geöffnet und mit der I-Taste der Menübefehl "Eigenschaften" ausgeführt wird. Es ist soweit eigentlich klar, dass Excel die Tastenfolge nur dann versteht, wenn es ein Menü "Datei" mit unterstrichenem Buchstabe D gibt und beim Menübefehl "Eigenschaften" der Buchstabe I unterstrichen ist. Gäbe es dies nicht, würde Excel die Tasten zwar ausführen, was jedoch zu einem unerwünschten oder gar keinem Resultat führen würde.
In diesem Zusammenhang wird oft vergessen, dass das Menü "Datei", um beim obigen Beispiel zu bleiben, nicht zwingend die Zugriffstaste ALT+D besitzt. Einerseits ist es für einen Excel-Anwender kein Problem, diesem Menü eine andere oder gar keine Zugriffstaste zu vergeben. Andererseits lautet das Menü nur in der deutschsprachigen Excelversion "Datei". In beispielsweise der englischen Version heisst dieses Menü "File" und wird mit der Tastenkombination ALT+F aufgerufen. Die Tastenfolge "ALT+D, I" wird somit bei der englischen Excelversion auf jeden Fall nicht das Dialogfenster "Eigenschaften" öffnen, sondern eine andere (oder gar keine) Aktion ausführen.
3. Anwendung muss Taste verarbeiten können
Es gibt Tasten, die von einer Anwendung nicht verarbeitet werden können. Es ist beispielsweise möglich, die Feststell-Taste (Caps Lock) mittels SendKeys zu senden (bzw. zu drücken):
SendKeys "{CAPSLOCK}"
Allerdings wird nichts passieren, wenn Sie diese Anweisung ausführen. Es liegt nicht etwa daran, weil der Tastencode "CAPSLOCK" falsch wäre (er existiert sehr wohl) oder weil die Feststell-Taste zwei Zustände Ein/Aus haben kann (auch die Druck-Taste funktioniert nicht). Der Grund ist ganz einfach, dass die aktive Anwendung mit der Feststell-Taste nichts anfangen und daher nicht verarbeiten kann. Nur das Betriebssystem - im Falle von VBA ist dies gewöhnlich Windows - kann diese Taste verarbeiten. Weil aber mit SendKeys Tasten immer an das aktive Anwendungsfenster gesendet werden und nie an Windows, funktioniert die obige VBA-Anweisung nicht.
Die verschiedenen Möglichkeiten zum Senden von Tastenfolgen
SendKeys sendet Tastenfolgen an die aktive Anwendung bzw. das aktive Fenster. Die Methode SendKeys des Application-Objektes von Excel (Application.SendKeys) besitzt grundsätzlich den gleichen Zweck, besitzt allerdings ein paar kleine Unterschiede. Mit DDEExecute kann man ebenfalls Tastenanschläge an eine andere Anwendung senden.
Syntax
SendKeys string[, wait]
Die Syntax der SendKeys-Anweisung verwendet die folgenden benannten Argumente:
Argument |
Beschreibung |
|---|---|
| string | Erforderlich. Ein Zeichenfolgenausdruck, der die zu sendende Tastenfolge angibt. |
| wait | Optional. Ein Wert vom Typ Boolean, der den Wartemodus angibt. Wenn der Wert False ist (Voreinstellung), setzt die Prozedur die Ausführung fort, unmittelbar nachdem die Tastenfolge gesendet wurde. Wenn der Wert True ist, muss die Tastenfolge verarbeitet werden, bevor die Prozedur die Ausführung fortsetzen kann. |
Bemerkungen
Jede Taste wird durch mindestens ein Zeichen repräsentiert. Ein einzelnes Zeichen
auf der Tastatur kann mit dem Zeichen selbst angegeben werden. "A"
für das Argument string repräsentiert beispielsweise den Buchstaben A. Sie geben
mehrere Zeichen an, indem Sie die Zeichen aneinanderhängen. "ABC"
für string repräsentiert zum Beispiel die Buchstaben A, B und C.
Das Pluszeichen (+), Caret-Zeichen (^),
Prozentzeichen (%), die Tilde (~) und die Klammern ( ) haben bei der
SendKeys-Anweisung eine spezielle Bedeutung. Sie müssen jedes dieser Zeichen in
geschweifte Klammern einschliessen ({}), um es verwenden zu können. Für das
Pluszeichen geben Sie beispielsweise {+} an. Eckige Klammern ([ ]) haben bei
der SendKeys-Anweisung zwar keine spezielle Bedeutung, müssen aber auch in geschweifte
Klammern eingeschlossen werden, da sie in anderen Anwendungen eine spezielle Bedeutung
haben, insbesondere im Zusammenhang mit dynamischem Datenaustausch (DDE). Die Zeichen für
die geschweiften Klammern legen Sie unter Verwendung von {{} und {}}
fest.
Für Zeichen, die beim Drücken einer Taste nicht angezeigt werden (z.B. die EINGABETASTE oder TAB-TASTE) und für bestimmte Aktionstasten können Sie die folgenden Codes verwenden:
Taste |
Code |
|---|---|
| RÜCKTASTE | {BACKSPACE}, {BS} oder {BKSP} |
| PAUSE | {BREAK} |
| FESTSTELLTASTE | {CAPSLOCK} |
| ENTF | {DELETE} oder {DEL} |
| NACH-UNTEN | {DOWN} |
| ENDE | {END} |
| EINGABETASTE | {ENTER} oder ~ |
| ESC | {ESC} |
| HILFE | {HELP} |
| POS 1 | {HOME} |
| EINFG | {INSERT} oder {INS} |
| NACH-LINKS | {LEFT} |
| NUM-FESTSTELL | {NUMLOCK} |
| BILD-AB | {PGDN} |
| BILD-AUF | {PGUP} |
| DRUCK | {PRTSC} |
| NACH-RECHTS | {RIGHT} |
| ROLLEN-FESTSTELL | {SCROLLLOCK} |
| TAB-TASTE | {TAB} |
| NACH-OBEN | {UP} |
| F1 | {F1} |
| F2 | {F2} |
| F3 | {F3} |
| F4 | {F4} |
| F5 | {F5} |
| F6 | {F6} |
| F7 | {F7} |
| F8 | {F8} |
| F9 | {F9} |
| F10 | {F10} |
| F11 | {F11} |
| F12 | {F12} |
| F13 | {F13} |
| F14 | {F14} |
| F15 | {F15} |
| F16 | {F16} |
Sie können Tastenkombinationen mit der UMSCHALTTASTE, STRG-TASTE oder ALT-TASTE angeben, indem Sie vor dem normalen Tasten-Code einen oder mehrere der folgenden Codes angeben:
Taste |
Code |
|---|---|
| UMSCHALT | + |
| STRG | ^ |
| ALT | % |
Wenn UMSCHALT, STRG und ALT gleichzeitig mit
anderen Tasten gedrückt werden müssen, schliessen Sie die Codes für die Tasten in
Klammern ein. Wenn zum Beispiel die UMSCHALTTASTE gleichzeitig mit den Tasten E und C
gedrückt werden soll, geben Sie "+(EC)" an. Wenn die UMSCHALTTASTE
zusammen mit E gedrückt werden soll und im Anschluss daran C ohne UMSCHALTTASTE, geben
Sie "+EC" an.
Tastenwiederholungen können Sie in der Form {Taste
Zahl} angeben. Das Leerzeichen zwischen Taste und Zahl ist
dabei zwingend erforderlich. {LEFT 42} wird zum Beispiel als 42-maliges
Drücken der NACH-LINKS-TASTE interpretiert, {h 10} als 10-maliges Drücken
der Taste H.
Anmerkung
SendKeys kann keine Tastenanschläge an Anwendungen senden, die nicht
unter Microsoft Windows oder auf dem Macintosh ausgeführt werden können. SendKeys
kann auch die DRUCK-TASTE {PRTSC} an keine Anwendung senden.
Application.SendKeys (Objekt-Methode)
Syntax
Ausdruck.SendKeys(Keys, Wait)
Ausdruck: Ein optionaler Ausdruck, der ein Application-Objekt zurückgibt.
Keys: Variant erforderlich. Die Taste oder Tastenkombination, die Sie als Zeichenfolge an die Anwendung senden möchten.
Wait: Variant optional. Falls True, wartet Microsoft Excel das Ende der Verarbeitung ab, bevor die Steuerung an das Makro zurückgegeben wird. False oder keine Angabe führt das Makro weiter aus, ohne auf einen Tastenkombination zu warten.
Anmerkungen
Diese Methode schreibt die Tastenkombination in einen Tastenpuffer. In einigen
Fällen müssen Sie diese Methode vor der Methode aufrufen, die die Tastenkombination
verarbeitet. Wenn Sie z.B. ein Kennwort an ein Dialogfeld senden möchten, müssen Sie
zuerst die SendKeys-Methode aufrufen, bevor Sie das Dialogfeld anzeigen.
Das Argument Keys kann eine einzelne Taste
oder eine Taste kombiniert mit einer oder mehreren der Tasten ALT, STRG oder UMSCHALT
sein. Jede Taste wird durch ein oder mehrere Zeichen dargestellt, wie z.B. "a"
für das Zeichen a oder "{EINGABE}" für die EINGABETASTE.
Wenn Sie Zeichen angeben möchten, die beim Drücken der entsprechenden Taste nicht angezeigt werden (z. B. EINGABE oder TAB), verwenden Sie die Codes aus der folgenden Tabelle. Jeder Code in der Tabelle steht für eine Taste auf der Tastatur.
Taste |
Code |
|---|---|
| RÜCKTASTE | {RÜCKTASTE} oder {RÜCK} |
| UNTBR oder BREAK | {UNTBR} |
| FESTSTELLTASTE | {FESTSTELLTASTE} |
| CLEAR oder LÖSCHTASTE | {SÄUBERN} |
| ENTF oder LÖSCH | {ENTF} oder {LÖSCH} |
| NACH-UNTEN | {UNTEN} |
| ENDE | {ENDE} |
| EINGABETASTE (Ziffernblock) | {EINGABE} |
| EINGABETASTE | ~ (Tilde) |
| RETURNTASTE | {EINGABE} |
| ESC | {ESCAPE} oder {ESC} |
| HILFE | {HILFE} |
| POS1 | {POS1} |
| EINFG | {EINFG} |
| NACH-LINKS | {LINKS} |
| NUM | {NUMFT} |
| BILD-AB | {BILDU} |
| BILD-AUF | {BILDO} |
| NACH-RECHTS | {RECHTS} |
| ROLLEN oder SCROLL | {UNTERBR} |
| TAB | {TAB} |
| NACH-OBEN | {OBEN} |
| F1 bis F15 | {F1} bis {F15} |
Sie können jede beliebige Tastenkombination mit UMSCHALT, STRG und ALT angeben. Kombinieren Sie eine Taste mit einer oder mehreren anderen Tasten entsprechend der folgenden Tabelle.
Kombinieren mit |
Vorangestelltes Zeichen |
|---|---|
| UMSCHALT | + (Pluszeichen) |
| STRG | ^ (Caret-Zeichen) |
| ALT | % (Prozentzeichen) |
Application.DEExecute (Objekt-Methode)
Syntax
Ausdruck.DDEExecute(Channel, String)
Ausdruck Optional. Ein
Ausdruck, der ein Application-Objekt zurückgibt.
Channel Long erforderlich. Die Kanalnummer, die von der DDEInitiate-Methode
zurückgegeben wird.
String String erforderlich. Die Nachricht, die in der
empfangenden Anwendung definiert wurde.
Anmerkungen
Die DDEExecute-Methode dient dazu, Befehle an eine andere Anwendung zu senden. Mit
Hilfe dieser Methode lassen sich auch Tastenanschläge an die andere Anwendung senden,
obwohl für diesen Zweck die SendKeys-Methode geeigneter ist. Das String-Argument
kann jede einzelne Taste angeben, die mit ALT, STRG oder UMSCHALT sowie jeder Kombination
dieser Tasten kombiniert wird. Jede Taste wird durch ein oder mehrere Zeichen
repräsentiert, etwa "a" für das Zeichen a, oder "{ENTER}"
für die EINGABETASTE.
Zur Angabe von Zeichen, die beim Drücken der entsprechenden Taste nicht angezeigt werden (z. B. EINGABE oder TAB), verwenden Sie die in der Tabelle unten angeführten Codes. Jeder Code in der Tabelle repräsentiert eine Taste auf Ihrer Tastatur.
Taste |
Code |
|---|---|
| RÜCKTASTE | {RÜCKTASTE} oder {RÜCK} |
| UNTBR | {UNTBR} |
| FESTSTELLTASTE | {FEST} |
| CLEAR oder LÖSCHTASTE | {SÄUBERN} |
| LÖSCH oder ENTF | {ENTF} oder {LÖSCH} |
| NACH-UNTEN | {UNTEN} |
| ENDE | {ENDE} |
| EINGABETASTE (Zehnertastatur) | {EINGABE} |
| EINGABETASTE | ~ (Tilde) |
| ESC | {ESCAPE} oder {ESC} |
| HILFE | {HILFE} |
| POS1 | {POS1} |
| EINFG | {EINFG} |
| NACH LINKS | {LINKS} |
| NUM | {NUMFT} |
| BILD-AB | {BILDU} |
| BILD-AUF | {BILDO} |
| RETURNTASTE (Macintosh) | {EINGABE} |
| NACH RECHTS | {RECHTS} |
| ROLLEN | {ROLLEN} |
| TAB | {TAB} |
| NACH OBEN | {OBEN} |
| F1 bis F15 | {F1} bis {F15} |
Sie können zudem Tasten angeben, die mit UMSCHALT und/oder STRG und/oder ALT kombiniert sind. Um eine Taste anzugeben, die mit einer oder mehreren der oben erwähnten Tasten kombiniert wird, verwenden Sie die folgende Tabelle.
Kombination mit |
Vorangestelltes Zeichen |
|---|---|
| UMSCHALT | + (Pluszeichen) |
| STRG oder CTRL | ^ (Caret-Zeichen) |
| ALT | % (Prozentzeichen) |
Technische Informationen zu SendKeys, Application.SendKeys und DDEExecute
SendKeys (VBA-Anweisung)
SendKeys ist eine Anweisung die zum Sprachumfang von VBA gehört. Die SendKeys-Anweisung ist allerdings keine Core-Anweisung von VBA (d.h. keine Anweisung, die zum Kernumfang der Sprache gehört) wie beispielsweise die Anweisungen "For...Next", "Exit" oder "End". SendKeys ist in der Objektbibliothek von VBA (genau wie Excel besitzt auch VBA eine Objektbibliothek) definiert, und zwar im Modul "Interaction" (Achtung: Interaction ist ein Modul und keine Klasse). Das Interaction-Modul enthält VBA-Anweisungen wie unter anderem "AppActivate", "CreateObject", "MsgBox" und "Shell", also alles Anweisungen, die eine Interaktion mit dem Benutzer oder mit einer Anwendung bezwecken.
Library
VBA
Path
D:\Programme\Gemeinsame Dateien\Microsoft Shared\VBA\VBA332.dll
Description
Visual Basic For Applications
Module
Interaction
Syntax
SendKeys(String As String, [Wait])
Samples
SendKeys
Interaction.SendKeys
VBA.Interaction.SendKeys
VBA.SendKeys
Application.SendKeys (Methode des Application-Objektes)
Application.SendKeys gehört zum Sprachumfang von Excel-VBA. Die SendKeys-Methode ist in der Objektbibliothek von Microsoft Excel definiert, und zwar in der Klasse Application.
Library
Excel
Path
D:\Programme\Microsoft Office\Office\EXCEL8.OLB
Description
Microsoft Excel 8.0 Object Library
Class
Application (Global)
Syntax
SendKeys(Keys, [Wait])
Samples
Application.SendKeys
Excel.Application.SendKeys
Excel.SendKeys
Excel.Global.SendKeys
Excel.Global.Application.SendKeys
SendKeys oder Application.SendKeys oder DDEExecute verwenden?
Unterschiede zwischen SendKeys und Application.SendKeys
Die SendKeys-Anweisung von VBA und die SendKeys-Methode des Application-Objektes von Excel sind an sich identisch. Allerdings können Sie SendKeys und Application.SendKeys in einem VBA-Programm nicht ohne weiteres austauschen. Ich habe unzählige Tests mit beiden Anweisungen durchgeführt und insbesondere drei markante Unterschiede festgestellt:
Die VBA-Anweisung SendKeys verwendet englische Bezeichnungen für die Tastencodes. Die SendKeys-Methode von Excel dagegen verwendet deutsche Abkürzungen.
Enter-Taste ist nicht gleich Enter-Taste. Wie in Punkt 1 erwähnt, werden deutsche oder englische Tastencodes verwendet. Der Code {ENTER} darf nicht mit {EINGABE} gleichgesetzt werden. Der Tastencode {EINGABE} steht für die Eingabetaste der Zehnertastatur. Auch wenn diese Eingabetaste in der Empfänger-Anwendung den genau gleichen Zweck wie die Eingabetaste der Alpha-Tastatur besitzt, verhält sie sich bei Application.SendKeys anders.
Ein auf True gestellter Wait-Parameter funktioniert bei Application.SendKeys je nach Windows-Version nur eingeschränkt oder sogar überhaupt nicht. Das Argument "Wait:=True" von SendKeys funktioniert dagegen in jeder Situation korrekt.
Damit man sich diese Unterschiede besser vorstellen kann, nachfolgend ein kleiner Praxis-Test mit ein paar VBA-Beispielen zu den obigen Punkten 1 und 2.
Testvorbereitung
1. Starten Sie zuerst den Windows Editor (Notepad.exe).
2. Geben Sie die Ziffern 0 bis 9 sowie einen Leerschlag ein, d.h. "0123456789 ". Lassen Sie nach der Eingabe den Textcursor einfach stehen, sodass er nach dem Leerzeichen blinkt. Drücken Sie nicht die Enter-Taste. Speichern Sie auch nicht (es ist wichtig, dass im Fenstertitel "Unbenannt" steht).

Schritt 1: Testen von SendKeys
Führen Sie das Makro NotepadSendKeysTest1 aus. Das Makro sendet diese Tastenfolgen insgesamt 10 mal: Menübefehl Bearbeiten/Alles markieren, Menübefehl Bearbeiten/Kopieren, Tasten Pfeil nach unten und Eingabe, Menübefehl Bearbeiten/Einfügen.
Sub NotepadSendKeysTest1()
Dim intCounter As Integer
AppActivate "Unbenannt", True
For intCounter = 1 To 10
SendKeys "%(BM)", True
SendKeys "%(BK)", True
SendKeys "{DOWN}{ENTER}", True
SendKeys "%(BE)", True
Next intCounter
End Sub
Sobald die Makroausführung beendet ist, sehen Sie im Editor den eingegebenen Text "0123456789 ", der mehrmals untereinander aufgelistet ist:

Schritt 2: Testen von Application.SendKeys
Löschen Sie den Inhalt des Notizblocks (Menübefehl Datei/Neu) und geben Sie den Text "0123456789 " erneut ein. Führen Sie jetzt das Makro NotepadSendKeysTest2 aus. Dieses Makro macht genau das gleiche wie das erste Makro, mit dem einzigen Unterschied, dass Application.SendKeys anstatt SendKeys benutzt wird.
Sub NotepadSendKeysTest2()
Dim intCounter As Integer
AppActivate "Unbenannt", True
For intCounter = 1 To 10
Application.SendKeys "%(BM)", True
Application.SendKeys "%(BK)", True
Application.SendKeys "{DOWN}{ENTER}", True
Application.SendKeys "%(BE)", True
Next intCounter
End Sub
Sobald die Makroausführung fertig ist, sehen Sie im Editor den eingegebenen Text "0123456789 ", der mehrmals nebeneinander steht:

Das zweite Makro führt zu einem anderen Ergebnis als das erste Makro. Und dies, obwohl lediglich Application.SendKeys anstelle von SendKeys benutzt wird.
Der Grund für das abweichende Ergebnis liegt an den verwendeten Tastencodes. Die SendKeys-Methode verwendet im Gegensatz zur SendKeys-Anweisung deutsche Abkürzungen. Mit den beiden Codes {DOWN} und {ENTER} kann sie nichts anfangen. Unschön finde ich, dass diese Tastencodes einfach übergangen werden, das heisst ohne eine Fehler- oder Hinweismeldung nicht verarbeitet werden. Zumindest ist jetzt klar, warum der Text nebeneinander und nicht untereinander erscheint: Das {ENTER} wurde nicht verarbeitet und folglich keine Zeilenschaltung eingefügt.
Schritt 3: Testen von Application.SendKeys (zweiter Versuch)
Löschen Sie wieder den Inhalt des Editors und erfassen den Text "0123456789 ". Starten Sie nun das Makro NotepadSendKeysTest3. Dieses Makro entspricht dem zweiten Makro. Lediglich die Tastencodes {DOWN} und {ENTER} wurden mit {UNTEN} bzw. {EINGABE} übersetzt.
Sub NotepadSendKeysTest3()
Dim intCounter As Integer
AppActivate "Unbenannt", True
For intCounter = 1 To 10
Application.SendKeys "%(BM)", True
Application.SendKeys "%(BK)", True
Application.SendKeys "{UNTEN}{EINGABE}", True
Application.SendKeys "%(BE)", True
Next intCounter
End Sub
Nach Ausführung des Makros sehen Sie dieses Bild im Editor:

Im Notizblock steht der Text wieder nebeneinander anstatt untereinander - obwohl deutschsprachige Tastencodes verwendet wurden. Wo liegt der Fehler? Nun, der Fehler liegt an der Übersetzung des englischen Tastencodes {ENTER}. Der Code {ENTER} steht sowohl für die Eingabetaste der alphanummerischen Tastatur als auch für die Eingabetaste der Zehnertastatur. Der deutsche Code {EINGABE} dagegen bezeichnet nur die Eingabetaste der Zehnertastatur. Für die Eingabetaste der Alpha-Tastatur muss das "~"-Zeichen (Tilde) benutzt werden, und zwar ohne das geschweifte Klammernpaar "{}".
Schritt 4: Testen von Application.SendKeys (dritter Versuch)
Das korrekte Makro mit Application.SendKeys muss folgedessen so aussehen:
Sub NotepadSendKeysTest4()
Dim intCounter As Integer
AppActivate "Unbenannt", True
For intCounter = 1 To 10
Application.SendKeys "%(BM)", True
Application.SendKeys "%(BK)", True
Application.SendKeys "{UNTEN}~", True
Application.SendKeys "%(BE)", True
Next intCounter
End Sub
Wenn Sie dieses Makro ausführen, erhalten Sie das gleiche Ergebnis wie beim ersten Makro "NotepadSendKeysTest1", nämlich den untereinander aufgelisteten Text "0123456789 ".
Zusammenfassung
Wie man erkennen kann, ist das Austauschen von SendKeys durch Application.SendKeys nicht ganz so einfach wie es zuerst aussieht.
Unterschiedliches Verhalten je nach Windows-Version
Das Verhalten der beiden Befehle SendKeys und Application.SendKeys ist nicht immer gleich, da der - bei beiden Anweisungen existierende - Wait-Parameter je nach Betriebssystem (Windows-Version) unterschiedlich reagiert.
| Windows-Version | Empfohlene Anweisung | Wait-Parameter | Beispiel (Neuberechnung auslösen) |
| Windows 95 | SendKeys | True | SendKeys "%^{F9}", True |
| Windows 98 | SendKeys | True | SendKeys "%^{F9}", True |
| Windows ME | SendKeys | True | SendKeys "%^{F9}", True |
| Windows NT | Application.SendKeys | False | Application.SendKeys "%^{F9}":DoEvents |
| Windows 2000 | Application.SendKeys | False | Application.SendKeys "%^{F9}":DoEvents |
| Windows XP | Application.SendKeys | False | Application.SendKeys "%^{F9}":DoEvents |
DoEvents übergibt wie allgemein bekannt ist die Ablaufsteuerung an das Betriebssystem. Das Programm erhält erst dann die Steuerung wieder zurück, wenn das Betriebssystem alle wartenden Ereignisse verarbeitet hat und alle wartenden Tastenanschläge in der SendKeys-Warteschlange abgearbeitet sind.
In der VBA-Hilfe steht, dass der Wait-Parameter der SendKeys-Methode - wenn auf True gesetzt - die vollständige Verarbeitung der Tastenanschläge abwartet (d.h. Application.SendKeys "...", True). Das kann man vergessen. Ich hab's in Excel 97 unter Windows NT 4 getestet: Funktioniert nicht. Daher die obige Lösung mit dem DoEvents. Bei "Wait:=True" wird die Steuerung erst wieder an das Makro übergeben, wenn Excel mit der Verarbeitung fertig ist. Das klappt jedoch bei präemptiven Multitasking-System wie Windows NT 4, Windows 2000 und Windows XP nicht, da nicht der ausgeführte Task den Zeitpunkt der Rückgabe bestimmen kann. Das entscheided bei diesen Betriebssystemen ein spezieller Systemprozess (der sogenannte "Scheduler").
Was bewirkt der Wait-Parameter von SendKeys?
Mit dem Wait-Parameter wird gesteuert, wann der Programmcode weiter ausgeführt wird:
Wie im vorangegangenen Abschnitt über die Unterschiede bereits kurz erwähnt wurde, verhält sich der auf True eingestellte Wait-Parameter der beiden Anweisungen je nach Windows-Version nicht immer gleich. Während mit "SendKeys "<Taste>", True" die Verarbeitung der gesendeten Tasten korrekt abgewartet wird, wird bei "Application.SendKeys "<Taste>", True" das VBA-Programm zu früh fortgeführt bzw. keine Pause eingelegt.
Ein praktisches Beispiel
Anhand eines kleines VBA-Beispiels lässt sich Zweck des Wait-Parameters gut erkennen. Starten Sie zuerst den Windows Editor (Notepad) und führen dann dieses Makro im VBA-Editor aus:
Sub NotepadTest()
AppActivate "Unbenannt"
SendKeys "Hallo", True
End Sub
Als Resultat sollten Sie das geöffnete Notepad mit dem Wort "Hallo" auf dem Bildschirm sehen. Im Programm wurde der Wait-Parameter auf True gestellt. Das Makro wurde somit erst weiter ausgeführt, nachdem alle Tastenanschläge (d.h. alle fünf Buchstaben des Wortes "Hallo") verarbeitet wurden. Da nach der SendKeys-Anweisung das Makro zu Ende war, also keine weiteren Befehle ausser dem "End Sub" (der das Makroende kennzeichnet), blieb der Fokus beim Notepad-Anwendungsfenster.
Nun wird Wait auf False gesetzt und das Makro nochmals ausgeführt. Löschen Sie aber zuerst das "Hallo" aus dem Notepad, sodass Sie wieder eine leere Seite sehen.
Sub NotepadTest()
AppActivate "Unbenannt"
SendKeys "Hallo", False
End Sub
Nach diesem Makro sehen Sie anstelle des Notepads den VBA-Editor vor sich. Wenn Sie zum Notepad wechseln, werden Sie lediglich den Buchstaben "H" des Wortes "Hallo" im Textdokument vorfinden. Wegen dem auf False gestellten Wait-Parameter hat das Makro nicht gewartet, bis alle Buchstaben an das Notepad übermittelt wurden. Doch wo sind die restlichen vier Buchstaben "allo" geblieben? Nun, da nach Senden des ersten Buchstabens das Makro bereits wieder die Kontrolle übernahm, sprich den Fensterfokus zurückerhielt, hat das Makro die restlichen Buchstaben quasi sich selbst geschickt! Das gesuchte "allo" wurde in ein Fenster des VBA-Editors eingefüllt, und zwar genau an der Stelle, wo sich der Textcursor befand, als das Makro gestartet wurde.
Wann muss der Wait-Parameter auf True gesetzt werden?
Ob die Verarbeitung der gesendeten Tastenfolgen abgewartet werden muss oder nicht, was mit dem Wait-Parameter von SendKeys gesteuert wird, lässt sich anhand von Situationen aus der Praxis gut erkennen. Diese Situationen werden im nächsten Kapitel So sendet man Tastenanschläge anhand verschiedener Beispiele erläutert.
Tastenanschläge zur Steuerung einer Dialogmaske an Excel senden
| Aktion | VBA-Anweisung | SendKeys | Wait | Beispiel |
| Dialog wird mittels Dialogs-Auflistung geöffnet | Dialogs(...).Show | Vor Dialog-Aufruf | False | SendKeys "%z200" Application.Dialogs(xlDialogCalculation).Show |
| Dialog wird mit der speziellen, dafür zuständigen Methode geöffnet | Application.GetOpenFilename Application.GetSaveAsFilename Application.FindFile Worksheet.ShowDataForm Worksheet.CheckSpelling Range.FunctionWizard |
Vor Dialog-Aufruf | False | SendKeys "%s" &
strBegriff & "%t" Worksheet.ShowDataForm |
| Dialog wird durch Simulation eines Klicks auf eine Symbolleisten-Schaltfläche geöffnet | CommandBars.FindControl().Execute | Vor Dialog-Aufruf | False | SendKeys "%n" & strID
& "{TAB}" Application.CommandBars.FindControl _ (Id:=860).Execute |
| Dialog wird durch eine sonstige Methode geöffnet, die ihrerseits den Dialog einblendet | Workbooks.Open mit einer kennwortgeschützten Mappe | Vor Dialog-Aufruf | False | SendKeys "Heute" Workbooks.Open "D:\Kennwort.xls" |
| Dialog wird mit einer Funktionstaste oder Tastaturabkürzung geöffnet | SendKeys | - | True | SendKeys "{F5}", True |
| Dialog wird über einen Menübefehl geöffnet | SendKeys | - | True | SendKeys "%di", True |
Sonstige Tastenanschläge an Excel senden
| Aktion | Wait-Parameter | Bemerkung | Beispiel |
| Makro wird in der VBE gestartet | Immer True, egal ob weitere Codezeilen nach SendKeys folgen oder nicht | Excel muss immer zuerst mit AppActivate
aktiviert werden Wait muss immer True sein, egal ob nach SendKeys weitere Befehle folgen oder nicht |
Sub OpenNamesDialog() AppActivate "Microsoft Excel" SendKeys "^{F3}", True 'Evtl. weiterer Code... End Sub |
| Makro wird in Excel gestartet | False oder True, wenn Makro nach SendKeys beendet ist | - | Sub OpenNamesDialog() SendKeys "^{F3}" End Sub |
| Makro wird in Excel gestartet | False, wenn die Codezeilen nach SendKeys ausgeführt werden müssen | - | Sub OpenNamesDialog() SendKeys "^{F3}" Application.StatusBar = "Name wählen" End Sub |
| Makro wird in Excel gestartet | False, wenn die Codezeilen nach SendKeys ausgeführt werden dürfen | - | Sub OpenNamesDialog() SendKeys "^{F3}" intZahl = intZahl + 1 End Sub |
| Makro wird in Excel gestartet | True, wenn die Codezeilen nach SendKeys nicht ausgeführt werden dürfen | - | Sub OpenNamesDialog() SendKeys "^{F3}", True Application.StatusBar = "Name ok" End Sub |
Tastenfolgen an eine andere Anwendung senden
| Aktion | Wait | Bemerkung | Beispiel |
| Makro wird in der VBE mit F5 gestartet | True | Die Anwendung muss immer zuerst mit AppActivate aktiviert werden | Sub OpenNamesDialog() AppActivate "Explorer" SendKeys "a", True End Sub |
Einschränkungen und Grenzen von SendKeys
SendKeys besitzt ein paar Einschränkungen. Nicht alle auf einer PC- oder Mac-Tastatur angeordneten Tasten können mit SendKeys aufgerufen werden, sprich lassen sich an eine Anwendung senden.
Hier eine Liste der nicht unterstützten Tasten mit den Tastencodes:
Taste |
Code |
|---|---|
| FESTSTELLTASTE | {CAPSLOCK} |
| HILFE | {HELP} |
| NUM-FESTSTELL | {NUMLOCK} |
| DRUCK | {PRTSC} |
| ROLLEN-FESTSTELL | {SCROLLLOCK} |
Zudem können die Spezialtasten einer Tastatur, wie unter
anderem
- SysRq (System Request),
- Pause und
- die beiden Windows-Tasten (links und rechts der Leertaste),
nicht mit SendKeys angesprochen werden.
Umgehungslösung für nicht unterstützte Tasten
Mit dem nachfolgenden VBA-Programmcode kann beispielsweise die CapsLock-Taste umgeschaltet werden:
Private Const VER_PLATFORM_WIN32_NT = 2
Private Const VER_PLATFORM_WIN32_WINDOWS = 1
Private Const VK_CAPITAL = &H14
Private Const KEYEVENTF_EXTENDEDKEY = &H1
Private Const KEYEVENTF_KEYUP = &H2
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Private Declare Function GetVersionEx Lib
"kernel32" Alias "GetVersionExA" _
(lpVersionInformation As OSVERSIONINFO) As Long
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan _
As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As
Long
Private Declare Function SetKeyboardState Lib "user32" (lppbKeyState As Byte) As
Long
Public Sub ToggleCapsLock(TurnOn As Boolean)
'To turn Caps Lock on, set TurnOn to True
'To turn Caps Lock off, set TurnOn to False
Dim bytKeys(255) As Byte
Dim bCapsLockOn As Boolean
Dim typOS As OSVERSIONINFO
'Get state of the 256 virtual keys
GetKeyboardState bytKeys(0)
bCapsLockOn = bytKeys(VK_CAPITAL)
If bCapsLockOn <> TurnOn Then 'If current
state <> requested state
If typOS.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then '=== Win95/98
bytKeys(VK_CAPITAL) = 1
SetKeyboardState bytKeys(0)
Else '=== WinNT/2000
'Simulate Key Press
keybd_event VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or
0, 0
'Simulate Key Release
keybd_event VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or
KEYEVENTF_KEYUP, 0
End If
End If
End Sub
Public Sub PressAstericsKey()
Dim bytKeys(255) As Byte
Dim typOS As OSVERSIONINFO
If typOS.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then '=== Win95/98
bytKeys(VK_ASTERICS) = 1
SetKeyboardState bytKeys(0)
Else '=== WinNT/2000
keybd_event VK_ASTERICS, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
keybd_event VK_ASTERICS, &H45, KEYEVENTF_EXTENDEDKEY Or
KEYEVENTF_KEYUP, 0
End If
End Sub
Bestimmen der Ausführungsumgebung (Excel oder VBE)
Wie in einem Kapitel weiter oben bereits erwähnt wurde, kann ein Makro, welches mittels SendKeys Tastenfolgen an Microsoft Excel sendet, nicht so ohne weiteres im VBA-Editor bzw. aus dem VBA-Editor heraus gestartet werden. Das funktioniert aus zwei Gründen nicht:
Das Anwendungsfenster von Excel muss zuerst aktiviert werden, da ansonsten die Tastenfolgen von der VBE empfangen werden und nicht von Excel.
Nach Beendigung der Makroausführung wird automatisch zur VBE zurückgekehrt. Das darf erst erfolgen, nachdem alle Tastenfolgen von Excel verarbeitet wurden. Anderenfalls kann es passieren, dass zu früh zum VBA-Editor gewechselt wird und somit einzelne noch anstehende Tastenfolgen in der VBE verarbeitet werden.
Die beiden obigen Punkte bedeuten nichts anderes, als dass
die Anweisung AppActivate und die Parameter-Einstellung "Wait:=True"
verwendet werden müssen, wenn das Makro in der VBE gestartet wird. Damit ein und dasselbe
Makro sowohl aus der VBE als auch aus Excel heraus gleichermassen funktioniert, bedient
man sich am besten einer globalen Variablen, mit welcher man den Makroablauf komfortabel
steuern kann.
VBA-Programmcode
Hier der entsprechende VBA-Code zum Aktivieren des Office-Programmes:
Public RunInVBE as Boolean
Sub OpenNamesDialog()
If RunInVBE = True Then
AppActivate "Microsoft Excel"
End If
SendKeys "^{F3}", RunInVBE
End Sub
Die globale Variable RunInVBE steuert den einzuschlagenden Makroablauf. Wenn das Makro in der VBE ausgeführt wird, muss RunInVBE auf True gesetzt werden. Dadurch weiss das Makro, dass vor dem SendKeys die Anwendung Excel aktiviert (Codezeile mit der AppActivate-Anweisung) und auf die vollständige Abarbeitung der Tastenfolgen gewartet werden muss (der Wait-Parameter von SendKeys steht auf RunInVBE, wobei RunInVBE den Wert True besitzt).
Empfänger-Anwendung starten und aktivieren
Shell startet eine Anwendung asynchron und gibt die Task-ID der ausgeführten Anwendung zurück. Asynchron bedeutet, dass das VBA-Programm weiterläuft, während Windows die Anwendung startet. Es kommt häufig vor, dass in einer VBA-Codezeile eine Anwendung mittels Shell gestartet wird und unmittelbar danach, in der nächsten Codezeile, auf eben diese Anwendung zugegriffen werden soll (z.B. mit AppActivate, SendKeys oder dergleichen). Wenn die zu startende Anwendung sehr klein ist, oder die Anwendungsdatei (exe) auf einer lokalen Festplatte liegt, oder wenn sich die Anwendung noch im Arbeitsspeicher befindet, so startet sie sofort und ist folgedessen augenblicklich bereit, wenn die Codezeile nach der Shell-Funktion ausgeführt wird. Benötigt jedoch die Anwendung zum vollständigen Aufstarten etwas mehr Zeit, so ist sie noch nicht bereit, wenn die Codezeile nach der Shell-Funktion ausgeführt wird.
Anwendung aktivieren mit "AppActivate"
Die von Shell gelieferte Task-ID ist nützlich, wenn die Anwendung mit AppActivate aktiviert werden soll. Der AppActivate-Anweisung kann anstelle des Fenstertitels der Anwendung nämlich die Task-ID mitgegeben werden. Leider funktioniert die Aktivierung mittels Task-ID in der Praxis je nach Empfänger-Anwendung nicht in jeder Situation und nicht bei jeder Anwendung.
Die folgende Tabelle zeigt das Verhalten verschiedener Windows-Programme:
| Anwendung | Aktivierung mittels Task-ID | Codebeispiel |
| Calculator (Rechner) | Funktioniert korrekt | TaskID =
Shell("calc.exe", vbNormalFocus) AppActivate TaskID |
| Paint/Paint Brush | Funktioniert korrekt | TaskID =
Shell("mspaint.exe", vbNormalFocus) AppActivate TaskID |
| Registry Editor | Funktioniert korrekt bei der ersten
Aktivierung Funktioniert nicht korrekt bei allen weiteren Aktivierungen |
TaskID =
Shell("regedit.exe", vbNormalFocus) AppActivate TaskID |
| Explorer | Funktioniert nicht immer korrekt [* siehe Hinweis] | TaskID =
Shell("explorer.exe", vbNormalFocus) AppActivate TaskID |
| Notepad (Editor) | Funktioniert korrekt | TaskID =
Shell("notepad.exe", vbNormalFocus) AppActivate TaskID |
| WordPad | Funktioniert nicht korrekt | TaskID =
Shell("write.exe", vbNormalFocus) AppActivate TaskID |
| CD Player | Funktioniert korrekt bei der ersten
Aktivierung Funktioniert nicht korrekt bei allen weiteren Aktivierungen |
TaskID =
Shell("cdplayer.exe", vbNormalFocus) AppActivate TaskID |
| Clock (Uhr) | Funktioniert korrekt | TaskID =
Shell("clock.exe", vbNormalFocus) AppActivate TaskID |
| CharMap (Zeichentabelle) | Funktioniert korrekt | TaskID =
Shell("charmap.exe", vbNormalFocus) AppActivate TaskID |
| Event Viewer (Ereignisanzeige) | Funktioniert korrekt | TaskID =
Shell("eventvwr.exe", vbNormalFocus) AppActivate TaskID |
| User Manager (Benutzerverwaltung) | Funktioniert korrekt | TaskID =
Shell("musrmgr.exe", vbNormalFocus) AppActivate TaskID |
| Task Manager | Funktioniert korrekt bei der ersten
Aktivierung Funktioniert nicht korrekt bei allen weiteren Aktivierungen |
TaskID =
Shell("taskmgr.exe", vbNormalFocus) AppActivate TaskID |
*
Hinweis zum Starten des Windows Explorers
Beschreibung folgt...
Anwendung starten und aktivieren mit "ActivateMicrosoftApp"
Muss mit Excel-VBA eine andere Office-Anwendung gestartet werden, bedient man sich häufig der Shell-Funktion von VBA. Damit die Anwendung jedoch gestartet werden kann, muss der Shell-Funktion der genaue Pfad der ausführbaren Datei (.exe) mitgegeben werden. Solange die zu startende Anwendung aus der gleichen Office-Version wie Excel stammt, könnte man behelfsmässig den Pfad von Excel verwenden (d.h. Application.Path) und voraussetzen, dass die exe-Datei der anderen Anwendung im gleichen Verzeichnis wie Excel.exe steht. Sobald es sich um eine Anwendung einer anderen Office-Version handelt, weicht der Programmpfad sehr wahrscheinlich ab. Damit nicht ein (eher schwierig zu programmierender) Zugriff auf die Windows Registry vorgenommen werden muss, um den Pfad der gesuchten Anwendung herauszufinden, stellt Excel eine spezielle Methode zum Starten von Office-Anwendungen bereit: Die ActivateMicrosoftApp-Methode.
Der wohl grösste Vorteil von ActivateMicrosoftApp ist - verglichen mit der Shell-Funktion - das synchrone Starten der angegebenen Anwendung. Das VBA-Programm läuft somit erst dann weiter, wenn die andere Anwendung vollständig aufgestartet und bereit ist.
VBA-Syntax
Application.ActivateMicrosoftApp(Index As
XlMSApplication)
Konstanten für XlMSApplication
xlMicrosoftAccess (Wert 4)
xlMicrosoftFoxPro (5)
xlMicrosoftMail (3)
xlMicrosoftPowerPoint (2)
xlMicrosoftProject (6)
xlMicrosoftSchedulePlus (7)
xlMicrosoftWord (1)
Wenn die als Argument angegebene Office-Anwendung nicht auf der Arbeitsstation installiert ist, erscheint der Laufzeitfehler 1004 mit einem entsprechenden Fehlertext (Beispiel FoxPro for Windows):

Abbildung: Laufzeitfehler bei nicht auffindbarer Programmdatei
foxprow.exe
Das Geheimnis von ActivateMicrosoftApp
Übrigens besitzt ActivateMicrosoftApp ein gut verstecktes und höchst interessantes Geheimnis: Die beiden boolschen Werte True (Wahr bzw. -1) und False (Falsch bzw. 0) können nebst den XlMSApplication-Konstanten ebenfalls als Argument eingesetzt werden.
Mit der Programmzeile
Application.ActivateMicrosoftApp False
kann der Taschenrechner von Windows (calc.exe) gestartet werden.
Mit der Codezeile
Application.ActivateMicrosoftApp True
lässt sich das Kartenspiel Solitär von Windows (sol.exe) ausführen.
Handelt es sich um einen Zufall, dass für True bzw. False genau die beiden Programme Solitär bzw. Rechner gewählt wurden? Oder steht vielleicht etwa der Rechner für das "falsche" Programm (symbolisiert die Arbeit), während das Kartenspiel Solitär die "wahre" oder "richtige" Anwendung darstellt (symbolisiert das Spielen/den Spass)?
Der Parameterwert True bzw. -1 ist VBA-intern fix mit der ausführbaren Datei sol.exe des Kartenspiels Solitär verknüpft. Wenn sich weder im Windows- oder Windows System-Verzeichnis noch in den mit der Systemumgebungsvariable "Path" definierten Verzeichnissen eine Datei namens sol.exe befindet, tritt der Laufzeitfehler 1004 auf:

Abbildung: Laufzeitfehler bei nicht auffindbarer
Programmdatei sol.exe
Das gleiche gilt für den False bzw. 0; dieser Wert ist fest mit der Datei 'calc.exe' verbunden.
XL: Custom Button Images Start Solitaire or
Calculator
http://support.microsoft.com/default.aspx?scid=kb;en-us;112374
Eine alltägliche Aufgabe: Anwendung starten, Fenster aktivieren, Tasten senden
Diese versteckte Möglichkeit zum Starten von Solitär hat
mich auf eine Idee gebracht, wie man ein in der Praxis häufig anzutreffende schwierige
Aufgabe sehr einfach lösen könnte. Die Aufgabe, die schwierig zu lösen ist, definiert
sich wie folgt:
- Eine Nicht-Office-Anwendung soll von einem Server-Laufwerk gestartet werden
- Nach dem Start ist die Anwendung zu aktivieren, damit Tastenfolgen gesendet
werden können
Sie fragen sich jetzt vielleicht, wo denn das Problem liegt. Schliesslich muss man lediglich mit Shell die Anwendung starten und dann mit AppActivate den Fokus setzen. Der VBA-Code würde dann lediglich zwei Zeilen umfassen und ungefähr so aussehen:
Sub AnwendungAktivieren()
x = Shell("P:\Programme\FeuerwehrPlaner.exe", vbNormalFocus)
AppActivate "Feuerwehr-Planer 1.0 - Administrator"
End Sub
Grundsätzlich haben Sie recht, denn genau so würden viele
Programmierer diese Aufgabe lösen. Aber seien Sie auf der Hut! In der Praxis sieht das
Ganze nämlich gar nicht mehr so einfach aus. Bis der Programmcode - für diese eigentlich
simple Aufgabe - fehlerfrei und stabil läuft, müssen Sie noch ein paar ganz interessante
Probleme lösen:
- Woher kennen Sie den bei Shell erforderlichen Pfad zur Anwendung,
sprich zur Datei FeuerwehrPlaner.exe?
- Was machen Sie, wenn der Programmstart misslingt (fehlende Berechtigung, Pfad
falsch usw.)?
- Nach Shell wird das Makro weiter ausgeführt, ohne den vollständigen
Programmstart abzuwarten. AppActivate wird daher höchstwahrscheinlich
fehlschlagen. Was können Sie dagegen tun?
- Bei AppActivate ist im Anwendungstitel die Version der Anwendung
angegeben. Was tun Sie, wenn die Versionsnummer ändert?
- Bei AppActivate ist ebenfalls im Titel der angemeldete Benutzer mit
"Administrator" angegeben. Was machen Sie, damit die Aktivierung bei allen
Benutzern funktioniert?
ActivateMicrosoftApp für eigene Zwecke missbrauchen
Wie unter "Das Geheimnis von ActivateMicrosoftApp" zu lesen ist, können anstelle eines offiziellen Konstantenwertes auch die Werte True oder False als Argument verwendet werden.
- Nach Shell wird das Makro weiter ausgeführt, ohne den vollständigen Programmstart abzuwarten. AppActivate wird daher höchstwahrscheinlich fehlschlagen. Was
Application.ActivateMicrosoftApp True
AppActivate "Feuerwehr"
Aktivieren einer bereits laufenden Empfänger-Anwendung
Wenn die Empfänger-Anwendung bereits läuft, verfügt man über keine Task-ID (da die Shell-Funktion nicht verwendet wurde, welche die Task-ID liefern würde). In diesem Fall muss man die Anwendung aktiviert werden, indem man AppActivate einsetzt und als Argument den Titel des zu aktivierenden Anwendungsfensters übergibt.
VBA-Syntax
AppActivate Title [, Wait]
Die Syntax der AppActivate-Anweisung verwendet die folgenden benannten Argumente:
Argument |
Beschreibung |
|---|---|
| Title | Erforderlich. Ein Zeichenfolgenausdruck, der den Titel in der Titelleiste des zu aktivierenden Anwendungsfensters angibt. Die von der Shell-Funktion zurückgegebene Task-ID kann anstelle von title verwendet werden, um eine Anwendung zu aktivieren. |
| Wait | Optional. Ein Wert vom Typ Boolean, der angibt, ob die aufrufende Anwendung den Fokus hat, bevor sie eine andere Anwendung aktiviert. Beim Wert False (Voreinstellung) wird die angegebene Anwendung mit sofortiger Wirkung aktiviert, auch wenn die aufrufende Anwendung nicht den Fokus hat. Beim Wert True wartet die aufrufende Anwendung, bis sie den Fokus erhält, und aktiviert dann die angegebene Anwendung. |
Bemerkungen
Die AppActivate-Anweisung setzt den Fokus auf die angegebene Anwendung
oder das angegebene Fenster, hat aber keinen Einfluss darauf, ob diese maximiert oder
minimiert dargestellt werden. Das aktivierte Anwendungsfenster verliert den Fokus, wenn
der Benutzer das Fenster schliesst oder den Fokus auf ein anderes Fenster setzt. Verwenden
Sie die Shell-Funktion, wenn Sie eine Anwendung starten und den Fensterstil
festlegen möchten.
Welche Anwendung aktiviert werden soll, wird bestimmt, indem Title mit der Zeichenfolge des Titels jeder einzelnen momentan ausgeführten Anwendung verglichen wird. Wenn es keine genaue Übereinstimmung gibt, wird eine beliebige Anwendung, deren Zeichenfolge mit Title beginnt, aktiviert. Wenn mehr als eine Instanz dieser Anwendung mit Title bezeichnet ist, wird willkürlich eine dieser Instanzen aktiviert.
Der Wait-Parameter von AppActivate
Die AppActivate-Anweisung wird oft zusammen oder genauer gesagt nach der Shell-Funktion verwendet.
TaskID = Shell("Calc.exe", 1)
AppActivate TaskID, True
Programm-Stabilität und -Fehlerfreiheit
Makro-Unterbrechung verhindern
Wenn Sie mit SendKeys oder Application.SendKeys arbeiten, ist es wichtig, dass die Ausführung des Programmcodes möglichst nicht unterbrochen wird bzw. nicht unterbrochen werden kann. Insbesondere beim Senden von Tastenfolgen an eine andere Anwendung kann es - untertrieben ausgedrückt - sehr unangenehm sein, wenn das VBA-Programm aufgrund eines Fehlers oder einer Intervention durch den Benutzer irgendwo abbricht. Der Programmabbruch infolge eines Laufzeitfehlers kann man recht einfach abfangen, indem im Code eine Fehlerbehandlungsroutine hinzugefügt wird. Innerhalb des Error Handlers kann fehlerverursachende Situation bereinigt werden, sodass das Programm fortgesetzt werden kann.
Weil die zu steuernde Anwendung zum Empfangen von Tastenfolgen aktiviert sein muss, lässt sich die Ausführung eines unterbrochenen VBA-Makros nicht so einfach fortsetzen. Dies, weil man sich bei der weiteren Ausführung des Programmcodes im VBA-Editor befindet, und folgedessen nicht das Fenster der Empfänger-Anwendung aktiv ist sondern das Hauptfenster des VBA-Editors. Die für die korrekte Code-Fortführung benötigte Anweisung AppActivate muss somit zuerst ausgeführt werden.

Abbildung: Hinweismeldung "Ausführung des Codes wurde
unterbrochen"
Beschreibung folgt...
Anwendung kann nicht mit AppActivate aktiviert werden
-> Laufzeitfehler Nr. 5

Abbildung: Laufzeitfehler 5
Unterbrochenes Makro fortsetzen
Beschreibung folgt...
Checkliste für die Programmierung
Diese Checkliste hilft Ihnen bei der Programmierung von Anwendungen, mit denen Sie Tastenfolgen senden. Überprüfen Sie anhand der Fragen, ob allenfalls wichtige Punkte bei der Realisierung ungenügend beachtet oder sogar vergessen wurden.
| Nr. | Themenbereich | Frage | Wenn Antwort 'Nein' ist... |
| 1 | Programmabbruch verhindern | Besitzt die Prozedur einen Error Handler, damit bei Auftreten eines Laufzeitfehlers das Programm nicht abgebrochen wird bzw. abstürzt? | Fügen Sie in
die Prozedur die Anweisung "On Error Goto <ErrorHandler>" ein und fangen
Sie alle Laufzeitfehler ab. Muster siehe VBA Codebeispiele |
| 2 | Programmunterbrechung verhindern | Wurde die Tastenkombination Strg+Unterbrechen (Ctrl+Break) sowie die Escape-Taste (Esc) abgefangen, damit die Codeausführung nicht durch die Benutzer unterbrochen werden kann? | Leiten Sie mit
der Codezeile "Application.EnableCancelKey = xlErrorHandler" die
Codeunterbrechung an den Error Handler weiter. Muster siehe VBA Codebeispiele |
| 3 | VBE-Fehlerbehandlungsoptionen prüfen | Ist sichergestellt, dass die Fehlerbehandlungsoption "Bei jedem Fehler unterbrechen" nicht eingestellt ist? | Wenn Sie nicht
davon ausgehen können, dass die Optionen immer wie erwartet eingestellt sind, sollte dies
im Programm berücksichtigt werden. Anderenfalls bricht die Ausführung des VBA-Codes bei
einem Laufzeitfehler trotz korrekter Fehlerbehandlungsroutine ab. Muster siehe VBA Codebeispiele |
| 4 | Timing-Probleme berücksichtigen | Wurde im Code berücksichtigt, dass in bestimmten Situationen Timing-Probleme auftreten könnten, z.B. wenn die Empfänger-Anwendung sehr lange benötigt, bis sie vollständig gestartet und bereit zum Empfangen von Tastenfolgen ist? |
Die folgenden Testmakros rufen den Eigenschaften-Dialog über das Menü Datei auf und setzen die Texteinfügemarke in das Eingabefeld "Hyperlink-Basis". Wenn das Dialogfenster korrekt geöffnet wird, ohne dass die Meldung "Das war ..." erscheint, funktioniert die im Makro benutzte Lösungsvariante zum Senden von Tastenfolgen.
Sub SendKeysTest1()
SendKeys "%di{tab 8}", True
MsgBox "Das war SendKeys mit Wait=True."
End Sub
Sub SendKeysTest2()
SendKeys "%di{tab 8}"
DoEvents
MsgBox "Das war SendKeys mit Wait=False und DoEvents."
End Sub
Sub SendKeysTest3()
Application.SendKeys "%di{tab 8}", True
MsgBox "Das war Application.SendKeys mit Wait=True"
End Sub
Sub SendKeysTest4()
Application.SendKeys "%di{tab 8}"
DoEvents
MsgBox "Das war Application.SendKeys mit Wait=False und DoEvents."
End Sub
Beispiel aus der VBA-Hilfe
Dim Ergebnis, I
Ergebnis = Shell("CALC.EXE", 1) ' Rechner starten.
AppActivate Ergebnis
'
Rechner aktivieren.
For I = 1 To 100
' Zählschleife beginnen.
SendKeys I & "{+}", True
' Tastenanschläge senden, um die
Next I
' Werte von I zu addieren.
SendKeys "=", True
' Gesamtsumme abrufen.
SendKeys "%{F4}", True
' Rechner mit
ALT+F4 beenden.
Synchron
Asynchron
Task-ID
VBE
Präemptives Multitasking
Kooperatives Multitasking
In general, spell key names as they appear in the following list, whether the name appears in text or in a procedure. Use all caps unless otherwise noted.
Note This list applies to Microsoft and IBM-type keyboards unless otherwise noted. Differences with the Macintosh keyboard are noted.
| Key | Comment |
| ALT | - |
| ALT GR | - |
| Application key | Microsoft Natural Keyboard only |
| arrow keys | Not direction keys, directional keys, or movement keys. |
| BACKSPACE | - |
| BREAK | - |
| CAPS LOCK | - |
| CLEAR | - |
| COMMAND | Macintosh keyboard only. Use the bitmap to show this key whenever possible, because the key is not named on the keyboard. |
| CONTROL | Macintosh keyboard only. Does not always map to the CTRL key on the PC keyboard. Use correctly. |
| CTRL | - |
| DEL | Macintosh keyboard only. Use to refer to the forward delete key. |
| DELETE | Use to refer to the back delete key on the Macintosh keyboard. |
| DOWN ARROW | Use the and key with the arrow keys except in key combinations or key sequences. Always spell out. Do not use graphical arrows. |
| END | - |
| ENTER | On the Macintosh, use only when functionality requires it. |
| ESC | Always use ESC, not ESCAPE or Escape, especially on the Macintosh. |
| F1F12 | - |
| HELP | Macintosh keyboard only. Always use "the HELP key" to avoid confusion with the Help button. |
| HOME | - |
| INSERT | - |
| LEFT ARROW | Use the and key with the arrow keys except in key combinations or key sequences. |
| NUM LOCK | - |
| OPTION | Macintosh keyboard only. |
| PAGE DOWN | - |
| PAGE UP | - |
| PAUSE | - |
| PRINT SCREEN | - |
| RESET | - |
| RETURN | Macintosh keyboard only. |
| RIGHT ARROW | Use the and key with the arrow keys except in key combinations or key sequences. |
| SCROLL LOCK | - |
| SELECT | - |
| SHIFT | - |
| SPACEBAR | Precede with the except in procedures, key combinations, or key sequences. |
| SYS RQ | - |
| TAB | Use the and key except in key combinations or key sequences. |
| UP ARROW | Use the and key with the arrow keys except in key combinations or key sequences. |
| Windows logo key | Microsoft Natural Keyboard only. |
Zuletzt aktualisiert am 27.01.2006 / 21:00 Uhr
© 2002-2006 by Philipp von Wartburg, CH-8916 Jonen
Alle Rechte vorbehalten