Hallo.
Wahrscheinlich bin ich mit meiner Frage hier falsch, aber da hier im Forum doch einige IT-Experten anzutreffen sind, hat der eine oder andere sicherlich eine Idee.
In meiner Access-Anwendung werden unter anderem 2 Datenbanken erstellt. Auf diese greife ich mit einem externen Programm zu.
Dazu muss ich in diesem externen Programm:
- ein Icon anklicken
- ein "*" in der Suchmaske eingeben
- ein Häkchen bei der "Automatischen Suche" setzen (oder Schaltfläche "Suchen anklicken)
- eine weitere Schaltfläche betätigen
- und zuletzt auf "OK" klicken.
Da kam mir die Idee, ob es nicht so eine Art "Makro-Recorder" gibt, wo ich diesen Prozess aufzeichen - und diesen dann von Access aus aufrufen könnte nachdem ich diese externe Anwendung gestartet habe.
Im Internet gibt es das einiges zu finden. Da war dann auch zu lesen, das man da einen Script-Editor mit Aufzeichnung benötigt.
Kennt sich da zufälligt jemand mit aus? Oder gibt es für so einen Fall noch andere Möglichkeiten?
Gruß trebuh
Hallo,
irgendwie ist der Kontext unklar...
ZitatIn meiner Access-Anwendung werden unter anderem 2 Datenbanken erstellt
Wirklich? Oder enthält diese Datenbank(-Datei) lediglich irgendwelche schon erzeugte Tabellen mit Dateninhalt?
Zitat..greife ich mit einem externen Programm zu.
Was für ein Programm ist das denn? Eine Access-Anwendung oder irgendeine exe-Datei?
Zitatwo ich diesen Prozess aufzeichen - und diesen dann von Access aus aufrufen könnte nachdem ich diese externe Anwendung gestartet habe.
Soll was heißen? Soll das externe Programm von Access ( von einer Access-Anwendung ) aus ferngesteuert werden?
Einen wie auch immer gearteten "Makrorecorder" gibt es in Access nicht. Allenfalls könnte in einer Access-Anwendung mit einem Makro(-befehl) oder als VBA-Code-Schnippsel die "Sendkeys"-Anweisung für das Senden der Tastenanschläge an das externe Programm herangezogen werden.
Hallo,
Also das Programm ist eine exe-Datei (Ein Viewer auf dem Topographische Karten angesehen werden können). Dieses Programm bietet die Möglichkeit auf Mdb-Datenbanken zuzugreifen welche nach einer bestimmten Tabellenstruktur aufgebaut sein müssen. Somit kann man sich dann z.B. diese Objekte anzeigen lassen.
Um sich z.B. alle Objekte anzeigen zu lassen, muss wie schon beschrieben folgende Actionen gemacht werden:
- ein Icon anklicken (Suchen nach Objekten)
- ein "*" in der Suchmaske "Name" eingeben (Die auszuwählende Datenbank ist voreingestellt)
- ein Häkchen bei der "Automatischen Suche" setzen (oder Schaltfläche "Suchen anklicken)
- eine weitere Schaltfläche betätigen
- und zuletzt auf "OK" klicken.
Dies ist an einem Standart-PC schnell erledigt.
An einem Rechner der ausschließlich über Touch-Screen betätigt wird, muss dann unter anderem die visuelle Tastatur eingeblendet werden. Somit ist es schon ein wenig aufwendiger.
Daher war mein gedanke, dass wenn das Programm (aus Access) gestartet wird, vielleicht zusätzlich ein Makro gestartet werden kann, welches die oben genannten Actionen ausführt. Dass ein solches Makro nicht aus Access gemacht werden kann ist mir klar.Auch der Viewer bietet keine Makroaufzeichnung an. Aber es gibt ja solche Makro-Rekorder (exe) bzw. Skript-Editoren mit Aufzeichnung. Angeblich müsste ich letzteres haben, da ein reiner Makro-Recorder die Mausposition speichert. Wenn nun z.b. das Fenster eine andere Position hat, funktioniert es schon nicht mehr (Was sich an einer Demoanwendung schon bestätigt hat).
Habe schon versucht, die Programmier des Viewers zu kontaktieren, um vielleicht ein Tool zu bekommen, was mir diverse Actionen ermöglicht. Leider wurde der Support eingestellt.
Habe noch die Möglichkeit, bei einer anderen Softwareentwicklungs-Firma anzufragen. Diese bieten auch eine Software an, welche auf Topographische Kartenwerke zugreift. Möchte da mal fragen, wie sie es gelöst haben (sofern ich dazu überhaupt Auskunft bekomme).
Gruß
Hubert
Hi,
als Denkanstoß:
Mit Routinen, wie auf http://www.vbarchiv.net/tipps/tipp_447-alle-laufenden-programme-ermitteln.html beschrieben, lassen sich aus access heraus Fenster-Handler ermitteln und Programme steuern (weiteres Stichwort click-yes für eigene Recherchen).
Ist nach meiner Einschätzung allerdings etwas tricky.
Ob sich der Aufwand für Dich lohnt, Dich in das Thema einzuarbeiten, um dann anschließend als Lohn einen vereinfachten Programm-Ablauf zu haben, kannst nur Du beantworten.
Harald
Hallo Harald,
Deinen Denkanstoß verstehe ich jetzt nicht ganz.
Das mit dem Fensterhandle nutze ich in meiner Anwendung um den Viewer zu öffnen, bzw. wieder in den Vordergrund zu bringen. Aber dass ich jetzt mit diesem Fensterhandle Programme fernsteuern kann, sprich in einer geöffneten exe-Anwendung bestimmte Prozesse auslösen??? Wie soll das den gehen?
Was meinst Du mit "(weiteres Stichwort click-yes für eigene Recherchen)."
Gruß Hubert
Hallo Hubert
Zitat von: trebuh am Juni 21, 2015, 23:22:00
Was meinst Du mit "(weiteres Stichwort click-yes für eigene Recherchen)."
z.B. mit http://www.freevbcode.com/ShowCode.asp?ID=6654 sind aus Access heraus nervige Outlook-Bestätigungsmeldungen zu vermeiden.
Harald
Hallo,
Du brauchst das Fenster-Handle, um dem ext. Programm den Fokus zu verleihen und dann darauf, wie vorher gesagt , mit dem Sendkeys-Befehl die Tastatureingabe zu simulieren.
Hallo,
da arbeitet man schon so lange schon mit einer exe-Anwendung, aber das da Tastenkombinationen möglich sind, geschweige dies im Hilfemenü steht. Da hätte ich ja schon früher drauf kommen müssen. :o
Das mit dem Sendkeys funktioniert teilweise.
Von daher habe ich schon die nächste Frage. Die Sendkeys (Welche ich in Access programmiert habe) funktionieren bis einschließlich den Befehl Sendkeys"{Return}".
Alle danach programmierte Sendkeys funktionieren nicht.
Muss ich da erst wieder mit dem Fensterhandle das Fenster aus Access aktivieren, weil evtl. durch das Return die exe-Anwendung den Fokus hat (bzw. Access nicht mehr aktiv ist)?
Oder was kann sonst die Ursache sein?
Hallo,
Sendkeys ist immer tricky, weil komplett asynchron und eben auf das im Moment aktive Fenster/Input-Element abzielt. Vermutlich ist zum Zeitpunkt des entspr. Sendkeys-Befehl kein Input-Element "aktiv".... Evtl. helfen ein paar Warte(milli)Sekunden...
Hallo Franz,
Danke für den Tipp.
Jetzt verstehe ich auch, warum im allgemeinen immer behauptet wird, dass "Sendkeys" immer etwas "Tricky" sind.
Kaum hat man ein Problem beseitigt, dann kommt das nächste.
Jetzt habe ich das Problem mit der deaktivierten NumLock-Taste.
Wenn man googlet, so findet man ja schon einiges zu dem Thema Probleme mit Sendkeys.
Habe auch schon das mit der alternative zu Sendkeys versucht.
Aber da komme ich auch nicht so recht weiter. Wie kann ich mit der SendKeyEx-Funktion z.B. die Funktion Alt-Taste und Buchstaben "B","O","S" realisieren? Wie soll da die Schreibweise sein?
SendKeysEx "{%}BOS" (das geht zumindest nicht)?
Bei Sendkeys geht das ja mit: SendKeys "%BOS", True
Mit den normalen Buchstabeneingabe (z.B in ein Textfeld) gibt es mit SendKeyEx hingegen keine Probleme.
Dann ließt man, dass man meistens auch auf SendKeys verzichten kann, ja sogar sollte. Es geht auch anders. Nur Wie?
Wäre das kein Thema für "Tipps & Tricks", damit man (insbesondere der Laie) sich nicht alles zusammensuchen und probieren muß? Oder es zumindest an Beispielen erklärt wird.
Gruß und nochmals Danke für die Tipps
Hubert
Hi,
Zitatdass "Sendkeys" immer etwas "Tricky" sind.
man könnte es auch "buggy" nennen. ;-)
ZitatJetzt habe ich das Problem mit der deaktivierten NumLock-Taste.
Ich habe dazu früher mal folgendes eingesetzt:
' nach dem Aufruf von Sendkeys:
If CBool(GetKeyState(vbKeyNumlock) And 1) = False Then _
Call SetKeyState(vbKeyNumlock, 1)
' Tastaturbefehle - Reaktivieren der NumLock-Taste nach SendKeys
' (aus FAQ 7.8 )
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As _
Long) As Integer
Public Declare Function GetKeyboardState Lib "user32" (pbKeyState As _
Byte) As Long
Public Declare Function SetKeyboardState Lib "user32" (lppbKeyState As _
Byte) As Long
Vielleicht hilft's ja auch bei dir.
Nachtrag:
Sub SetKeyState(intKey As Integer, fTurnOn As Boolean)
'
' Tastatur-Eigenschaft NumLock zurücksetzen
Dim abytBuffer(0 To 255) As Byte
GetKeyboardState abytBuffer(0)
abytBuffer(intKey) = CByte(Abs(fTurnOn))
SetKeyboardState abytBuffer(0)
End Sub
{Edit: fehlende Prozedur hinzugefügt}
Hallo MaggieMay,
kann es sein, das der Code nicht vollständig ist? Fehlt da nicht eine Function() oder Sub()?
SetKeyState ( Call SetKeyState(vbKeyNumlock, 1)) ist nirgends deklariert.
Gruß und vorab Danke für die Hilfe
Hubert
Zitat von: trebuh am Juni 23, 2015, 20:59:53
SetKeyState ( Call SetKeyState(vbKeyNumlock, 1)) ist nirgends deklariert.
Die im zweiten Code-Auszug gezeigten Zeilen gehören in ein allgemeines Modul.
Was fehlt dir da noch?
Hallo MaggieMay,
Ja den Code:
' Tastaturbefehle - Reaktivieren der NumLock-Taste nach SendKeys
' (aus FAQ 7.8 )
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As _
Long) As Integer
Public Declare Function GetKeyboardState Lib "user32" (pbKeyState As _
Byte) As Long
Public Declare Function SetKeyboardState Lib "user32" (lppbKeyState As _
Byte) As Long
habe ich in einem Modul.
Den Code:
' nach dem Aufruf von Sendkeys:
If CBool(GetKeyState(vbKeyNumlock) And 1) = False Then _
Call SetKeyState(vbKeyNumlock, 1)
habe ich nach dem letzten Sendkeys-Befehl gesetzt.
Bekomme aber dann die Fehlermeldung:
Fehler beim Kompilieren:
Sub oder Function nicht definiert
Es ist dann im VBA-Editor der Text:
Call SetKeyState Blau hinterlegt.
Gruß Hubert
Hi,
deklariert ist: GetKeyboardState
Also sollte das aufgerufen werden:
If CBool(GetKeyBoardState(vbKeyNumlock)
Gleiches für die folgenden Anweisung.
Harald
Hallo Harald,
wenn das mit dem Sendkeys so weiter geht, dann habe ich bald keine Haare mehr auf dem Kopf;-)
Der Code:
If CBool(GetKeyboardState(vbKeyNumlock) And 1) = False Then _
Call SetKeyboardState(vbKeyNumlock, 1)bringt mir die Fehlermeldung:
Fehler beim Kompilieren:
Falsche Anzahl an Argumenten oder ungültige Zuweisung zu einer Eigenschaft
Gruß Hubert
Hi Hubert,
was passiert bei: Call SetKeyboardState(vbKeyNumlock)?
Harald
Hallo Harald,
wie darf ich die Frage jetzt verstehen?
- Fragst Du mich, was bei dem Befehl passieren sollte? oder
- Was bei mir genau passiert?
Hi,
streich ",1" weg und berichte, was passiert.
Harald
Nichts gutes.
Zuerst dachte ich jetzt gehts (Zumindest wird mein Code abgearbeitet, d.h. Exe- Anwendung geöffnet und die Sendkey-Befehle werden ausgeführt.)
Dann hängt sich Access auf und es erscheint das zu guter letzt die Fehlermeldung (siehe im Anhang)
Hi,
Zitat von: trebuh am Juni 24, 2015, 13:12:11
... dann habe ich bald keine Haare mehr auf dem Kopf
Diesen Zustand habe ich schon erreicht. ;)
Das folgende ohne Garantie (deswegen auch in meinem ersten Beitrag das Wort "tricky"). Bei dem Kommando gibt es einen optionalen Parameter
SendKeys string[, wait].
Also
SendKeys Bitte hier Dein Kommando eintragen, True
Hi,
dann laufen jetzt 2 Männer mit herausgerissenen Haaren herum:-)))
das ",True" habe ich bereits drin.
Wie ist es eigentlich mit dem Link 7.8 bei Donkarl. Da ist ja folgender Code:
' Declare Type for API call:
Private Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128 ' Maintenance string for PSS usage
End Type
' API declarations:
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
' Constant declarations:
Const VK_NUMLOCK = &H90
Const VK_SCROLL = &H91
Const VK_CAPITAL = &H14
Const KEYEVENTF_EXTENDEDKEY = &H1
Const KEYEVENTF_KEYUP = &H2
Const VER_PLATFORM_WIN32_NT = 2
Const VER_PLATFORM_WIN32_WINDOWS = 1
Function IsCapsLockOn() As Boolean
Dim o As OSVERSIONINFO
o.dwOSVersionInfoSize = Len(o)
GetVersionEx o
Dim keys(0 To 255) As Byte
GetKeyboardState keys(0)
IsCapsLockOn = keys(VK_CAPITAL)
End Function
Sub ToggleCapsLock()
Dim o As OSVERSIONINFO
o.dwOSVersionInfoSize = Len(o)
GetVersionEx o
Dim keys(0 To 255) As Byte
GetKeyboardState keys(0)
If o.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then '=====Win95
'Toggle capslock
keys(VK_CAPITAL) = Abs(Not keys(VK_CAPITAL))
SetKeyboardState keys(0)
ElseIf o.dwPlatformId = VER_PLATFORM_WIN32_NT Then '=====WinNT
'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 Sub
Function IsNumLockOn() As Boolean
Dim o As OSVERSIONINFO
o.dwOSVersionInfoSize = Len(o)
GetVersionEx o
Dim keys(0 To 255) As Byte
GetKeyboardState keys(0)
IsNumLockOn = keys(VK_NUMLOCK)
End Function
Sub ToggleNumLock()
Dim o As OSVERSIONINFO
o.dwOSVersionInfoSize = Len(o)
GetVersionEx o
Dim keys(0 To 255) As Byte
GetKeyboardState keys(0)
If o.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then '=====Win95
keys(VK_NUMLOCK) = Abs(Not keys(VK_NUMLOCK))
SetKeyboardState keys(0)
ElseIf o.dwPlatformId = VER_PLATFORM_WIN32_NT Then '=====WinNT
'Simulate Key Press
keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
'Simulate Key Release
keybd_event VK_NUMLOCK, &H45, KEYEVENTF_EXTENDEDKEY _
Or KEYEVENTF_KEYUP, 0
End If
End Sub
Function IsScrollLockOn()
Dim o As OSVERSIONINFO
o.dwOSVersionInfoSize = Len(o)
GetVersionEx o
Dim keys(0 To 255) As Byte
GetKeyboardState keys(0)
IsScrollLockOn = keys(VK_SCROLL)
End Function
Sub ToggleScrollLock()
Dim o As OSVERSIONINFO
o.dwOSVersionInfoSize = Len(o)
GetVersionEx o
Dim keys(0 To 255) As Byte
GetKeyboardState keys(0)
If o.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then '=====Win95
keys(VK_SCROLL) = Abs(Not keys(VK_SCROLL))
SetKeyboardState keys(0)
ElseIf o.dwPlatformId = VER_PLATFORM_WIN32_NT Then '=====WinNT
'Simulate Key Press
keybd_event VK_SCROLL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0
'Simulate Key Release
keybd_event VK_SCROLL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0
End If
End Sub
Sub mySendKeys(sKeys As String, Optional bWait As Boolean = False)
Dim bNumLockState As Boolean
Dim bCapsLockState As Boolean
Dim bScrollLockState As Boolean
bNumLockState = IsNumLockOn()
bCapsLockState = IsCapsLockOn()
bScrollLockState = IsScrollLockOn()
SendKeys sKeys, bWait
If IsNumLockOn() <> bNumLockState Then
ToggleNumLock
End If
If IsCapsLockOn() <> bCapsLockState Then
ToggleCapsLock
End If
If IsScrollLockOn() <> bScrollLockState Then
ToggleScrollLock
End If
End Sub
Function fSendKeys(sKeys As String, Optional bWait As Boolean = False)
' Function to make it callable from macros
mySendKeys sKeys, bWait
End Function
Nur welche funktion muss ich da aufrufen? Die Funktion "mySendKeys"? und wie?
Wirklich tricky und buggy.
Hi Hubert,
es scheint jetzt immer mehr "tricky" zu werden. ;)
Vielleicht ist es hilfreich, erst einmal eine vereinfachte Version zu probieren, um einzukreisen, wo der Absturz ausgelöst wird.
Deshalb die Frage:
Funktionieren Deine Routinen ohne access-Programm-Absturz mit dem normalen SendKeys ohne die "numlock-Anweisungen"?
Das im obigen Link verwendete mysendkeys ersetzt den normalen sendkeys-Befehl und hat den Vorteil, dass Du nicht bei jedem aufruf an numlock, capslock und dergl denken mußt.
Harald
Hi,
Zitates scheint jetzt immer mehr "tricky" zu werden.
Ja das stimmt! Mittlerweile muss ich darüber lachen.
Also mein Code funkioniert jetzt in soweit, dass ich am Schluß jetzt einfach
SendKeys "{NumLock}", Truesetze.
Nach dem Code-Tipp von Maggie-May kommt die Fehlermeldung:
Fehler beim Kompilieren:
Sub oder Function nicht definiertUnd nachdem ich das
If CBool(GetKeyboardState(vbKeyNumlock) And 1) = False Then _
Call SetKeyboardState(vbKeyNumlock, 1)in
If CBool(GetKeyboardState(vbKeyNumlock) And 1) = False Then _
Call SetKeyboardState(vbKeyNumlock)umgeändert habe, hängt Access sich auf.
Andere Frage (zu den mysendkeys):
Heißt das, ich setze den Code in ein Modul und schreibe dann statt
SendKeys "%(O)", True ganz einfach
mysendkeys "%(O)", True? Und das wäre alles? (Ich probiers einfach mal. Es kann ja nur ein Fehler kommen ;D)
Gruß Hubert
Zitat von: trebuh am Juni 24, 2015, 16:57:31Nach dem Code-Tipp von Maggie-May kommt die Fehlermeldung:
Fehler beim Kompilieren:
Sub oder Function nicht definiert
Sorry, das hatte ich übersehen, dies ist die fehlende Prozedur:
Sub SetKeyState(intKey As Integer, fTurnOn As Boolean)
'
' Tastatur-Eigenschaft NumLock zurücksetzen
Dim abytBuffer(0 To 255) As Byte
GetKeyboardState abytBuffer(0)
abytBuffer(intKey) = CByte(Abs(fTurnOn))
SetKeyboardState abytBuffer(0)
End Sub