Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1444to1448
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Idle_Timer bei aktiver Zelle

Idle_Timer bei aktiver Zelle
09.09.2015 15:17:25
Marcus
Hallo zusammen,
ich setze folgenden Idle Timer bei mir ein:

Function IdleTime() As Single
Dim a As LASTINPUTINFO
a.cbSize = LenB(a)
GetLastInputInfo a
IdleTime = (GetTickCount - a.dwTime) / 1000 'Idletime in Sekunden
End Function
Sub Idle_Timer()
If IdleTime >= Time_To_Idle Then 'Vergleich Idletime mit Zeitvorgabe in Sekunden
Call CloseIt
End If
Application.OnTime Now + TimeValue("0:0:1"), "Idle_Timer2" 'Wiederholungsprüfung nach 1 Sekunde
End Sub
Sub Idle_Timer2()
If IdleTime >= Time_To_Idle Then 'Vergleich Idletime mit Zeitvorgabe in Sekunden
Call CloseIt
End If
Application.OnTime Now + TimeValue("0:0:1"), "Idle_Timer" 'Wiederholungsprüfung nach 1 Sekunde
End Sub

Dies funktioniert soweit auch ganz gut, jedoch ist mir aufgefallen, dass eine angewählte Zelle in der der Cursor steht(blinkt) diesen Mechanismus außer Kraft setzt.
Hat jemand eine Idee, wie das umgangen werden kann?
Danke im Voraus
Marcus

18
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Idle_Timer bei aktiver Zelle
09.09.2015 15:31:13
fcs
Hallo Marcos,
keine Chance dies zu umgehen.
Anstehende OnTime-Ereignisse werden erst ausgeführt, wenn die Zellbearbeitung oder geöffnete Menüs/Dialoge beendet werden.
Gruß
Franz

AW: Idle_Timer bei aktiver Zelle
09.09.2015 15:46:37
Marcus
Hallo Franz,
siehst Du eine andere Möglichkeit die sekündliche Wiederholung zu realisieren?
Gruß Marcus

AW: Idle_Timer bei aktiver Zelle
09.09.2015 16:27:56
Nepumuk
Hallo,
das geht schon, per API-Timer. Welche Aktion löst denn dein Timer bisher aus? Wenn du nämlich im Editiermodus bist und du willst per Timer in eine andere Zelle schreiben dann stürzt dir Excel ab.
Gruß
Nepumuk

AW: Idle_Timer bei aktiver Zelle
09.09.2015 16:48:21
Marcus
Hallo ausglöst wird der Timer durch Workbook_Open und über dann alle 1000ms ihn toggled , so der Plan.
Ich habe jetzt Folgendes gefunden und im Modul1 implementiert:
Option Explicit
'=============================================================================================== _
'=============================================================================================== _
'=============================================================================================== _
Private Const Time_To_Idle As Single = 60 ' Zeit nach der ausgeloggt werden soll in Sekunden
'=============================================================================================== _
'=============================================================================================== _
'=============================================================================================== _
Private Type LASTINPUTINFO
cbSize As Long
dwTime As Long
End Type
Private Declare PtrSafe Sub GetLastInputInfo Lib "user32" (ByRef plii As LASTINPUTINFO)
Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
Public Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long,  _
ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As  _
Long
Public TimerID As Long
Public TimerSeconds As Single
'Sekundentakt starten
Sub StartTimer()
TimerSeconds = 1
TimerID = SetTimer(0&, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
End Sub
'Sekundentakt beenden
Sub EndTimer()
On Error Resume Next
KillTimer 0&, TimerID
End Sub
'Inaktivität prüfen aufrufen im Sekundentakt
Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, ByVal nIDEvent As Long, ByVal dwTimer As  _
Long)
'Inaktivität prüfen aufrufen
Call Idle_Timer
End Sub
Function IdleTime() As Single
Dim a As LASTINPUTINFO
a.cbSize = LenB(a)
GetLastInputInfo a
IdleTime = (GetTickCount - a.dwTime) / 1000 'Idletime in Sekunden
End Function
Sub Idle_Timer()
If IdleTime >= Time_To_Idle Then 'Vergleich Idletime mit Zeitvorgabe in Sekunden
'Sekundentakt beenden
Call EndTimer
'Arbeitsmappe speichern und schließen
ActiveWorkbook.Close savechanges:=True
End If
End Sub
Aufgerufen wird der Timer in "DieseArbeitsmappe" mit:
Option Explicit
Private Sub Workbook_Open()
'Sekundentakt starten
Call StartTimer
End Sub
Das funktioniert soweit auch, es resultiert jedoch ein Fehler von Excel mit diefferenzierendem Fehlercode.

Anzeige
AW: Idle_Timer bei aktiver Zelle
09.09.2015 16:55:08
Nepumuk
Hallo,
du musst den Timer zwingend an die Application binden. Also:
TimerID = SetTimer(Application.hWnd, 0&, TimerSeconds * 1000&, AddressOf TimerProc)
KillTimer Application.hWnd, TimerID
Gruß
Nepumuk

AW: Idle_Timer bei aktiver Zelle
09.09.2015 17:03:04
Marcus
Auch dies führt leider immer noch zur Arbeitsverweigerung von Excel nach speichern und schließen der Datei. :-(

AW: Idle_Timer bei aktiver Zelle
09.09.2015 18:08:42
Nepumuk
Hallo,
kannst du eine Mustermappe hochladen?
Gruß
Nepumuk

AW: Idle_Timer bei aktiver Zelle
10.09.2015 08:22:19
Marcus
Hallo Nepumuk,
habe es leider gestern nicht mehr geschafft, hier jetzt aber die Mustermappe:

Die Datei https://www.herber.de/bbs/user/100110.xlsm wurde aus Datenschutzgründen gelöscht


Gruß
Marcus

Anzeige
AW: Idle_Timer bei aktiver Zelle
10.09.2015 11:55:42
Marcus
Also ich habe mittlerweile herausgefunden, dass der Fehler dadurch verursacht wird, dass der Timer nicht beendet wird.
Mir ist jedoch nicht klar, warum er nicht beendet wird.
Option Explicit
'=============================================================================================== _
_
'=============================================================================================== _
_
'=============================================================================================== _
_
Private Const Time_To_Idle As Single = 10 ' Zeit nach der ausgeloggt werden soll in Sekunden
'=============================================================================================== _
_
'=============================================================================================== _
_
'=============================================================================================== _
_
Private Type LASTINPUTINFO
cbSize As Long
dwTime As Long
End Type
Private Declare PtrSafe Sub GetLastInputInfo Lib "user32" (ByRef plii As LASTINPUTINFO)
Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
Public Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long,  _
ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As  _
Long
Public TimerID As Long
Public Initial As Boolean
'Sekundentakt starten
Sub StartTimer()
TimerID = SetTimer(0&, 0&, 1000&, AddressOf TimerProc)
End Sub
'Sekundentakt beenden
Sub EndTimer()
KillTimer 0&, TimerID
End Sub
'Inaktivität prüfen aufrufen im Sekundentakt
Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, ByVal nIDEvent As Long, ByVal dwTimer As  _
Long)
'Inaktivität prüfen aufrufen
If IdleTime >= Time_To_Idle Then 'Vergleich Idletime mit Zeitvorgabe in Sekunden
'Sekundentakt beenden
MsgBox "Erfüllt" & vbCr & IdleTime & vbCr & Time_To_Idle
Call EndTimer
'Arbeitsmappe speichern und schließen
'        ActiveWorkbook.Close savechanges:=True
End If
End Sub
Function IdleTime() As Single
Dim a As LASTINPUTINFO
a.cbSize = LenB(a)
GetLastInputInfo a
IdleTime = (GetTickCount - a.dwTime) / 1000 'Idletime in Sekunden
End Function
Die hervorgehobene Stelle sollte dies eigentlich bewriken, tut es aber nicht.
Stoße ich Endtimer über einen Button an, funktioniert es.

Anzeige
AW: Idle_Timer bei aktiver Zelle
10.09.2015 12:53:07
Nepumuk
Hallo,
ich hab jetzt alles mögliche versucht, aber es klappt nicht.
Sorry !!!
Gruß
Nepumuk

AW: Idle_Timer bei aktiver Zelle
10.09.2015 15:13:55
Marcus
Also das Problem liegt defintiv bei
ActiveWorkbook.Close
wobei savechanges hier keinen Unterschied macht.
Aber erklären kann ich es mir auch nicht.

AW: Idle_Timer bei aktiver Zelle
10.09.2015 15:28:21
EtoPHG
Hallo Marcus,
Was willst du den mit diesem Timer erreichen?
Wenn ich so zwischen den Zeilen lese und dazu fantasiere:
Du willst vermutlich die Arbeitsmappe schliessen, wenn eine bestimmte Zeit keine User-Aktion erfolgte.
Das könnte man mit anderen Mitteln erreichen.
Wenn ich mit meiner Annahme falsch liege, vergiss meinen Beitrag einfach. Ansonsten, erkläre bitte genau, was der Zweck des 'Timings' sein soll.
Gruess Hansueli

Anzeige
AW: Idle_Timer bei aktiver Zelle
10.09.2015 15:51:52
Marcus
Hallo Hansueli,
Du hast das Ziel genau richtig erkannt.
Die Arbeitsmappe soll nach einer definierten Zeit der Inaktivität gespeichert und geschlossen werden.
Bitte keine Grundsatzdikussion über die Sinnhaftigkeit, diese habe ich bereits ausführlich intern diskutiert, es ist jedoch so gewünscht.
Sollte deine Lösung auf Application.ontime abzielen, so möchte ich gleich vorweg nehmen, dass hier das Problem der Nichtbearbeitung bei angewählter Zelle besteht.
Ansonsten bin ich sehr gespannt.
Gruß Marcus

AW: Idle_Timer bei aktiver Zelle
10.09.2015 17:13:13
EtoPHG
Hallo Marcus,
Zitat:
Sollte deine Lösung auf Application.Ontime abzielen, so möchte ich gleich vorweg nehmen, dass hier das Problem der Nichtbearbeitung bei angewählter Zelle besteht.
Was für ein Problem genau? Wenn sich Excel im Editiermodus befindet, so ist die Application gesperrt, bis dieser Modus wieder verlassen wird. Da helfen keine Externen API / Timer oder VBA Code. Aber schliesslich hat der Anwender diesen Modus bewusst initiiert.
Immerhin würde die Datei automatisch geschlossen, sobald er den Editiermodus verlässt, was aber in ,meinen Augen wiederum eine Benutzeraktion ist, die den Timer auf 0 zurückstellen müsste, da er ja vielleicht eine weitere Aktion ausführen will.
Ja meine Idee war die Mouse-Koordinaten im Sekundentakt zu kontrollieren und wenn diese sich innerhalb dem definierten Zeitfenster nicht verändern, das OntimeMakro für das (sofortige) Schliessen der Datei zu initieren.
Gruess Hansueli

Anzeige
AW: Idle_Timer bei aktiver Zelle
10.09.2015 19:07:47
Marcus
Hallo Hanueli,
das Problem besteht darin, dass das Makro bei aktivierter Zelle, also im Editiermodus, nicht abgearbeitet wird.
Ich Muss Dir leider gleich doppelt widersprechen, zum einen werden Makros auf API-Timer-Basis sehr wohl ausgeführt und zum anderen wird ein gestopptes ontime-Makro nicht direkt nach Verlassen des Editiermodus zu Ende geführt.
Dies wäre nur der Fall würde man genau den Moment der ontime-Toggelung treffen.
Zudem sehe ich es wie Du, dass das Verlassen des Editiermodus sehr wohl eine weitere Handlung des Bedieners ist und das speichern und schließen verhindern und nicht auslösen sollte.
Es geht eigentlich auch schon nicht mehr um die Art und Weise der Timer-Ausführung, sondern um die Frage warum Excel bei automatisiertem Aufruf des Makros "Endtimer" abstürzt, bei jeder Art händischen Aufrufes jedoch nicht.
Vielleicht sollte ich dazu einen neuen Thread eröffnen, denn dies hat ja eigentlich schon nichts mehr mit der eigentlichen Fragestellung zu tun.
Gruß
Marcus

Anzeige
widerspreche deinen Widersprüchen...
11.09.2015 09:34:58
EtoPHG
Hallo Marcus,
Zitat: zum einen werden Makros auf API-Timer-Basis ... ist Quatsch. Natürlich können Prozesses asynchron zum VBA Code ablaufen, die über API-Schnittstellen vor dem Starten des Editiermodus in XL abgesetzt wurden. Keinesfalls wird aber irgendwelcher VBA-Code, ob mit oder ohne OnTime-Methode gestartet oder ausgeführt. Die Möglichkeit für XL weiteren VBA-Code auszuführen ist erst nach dem Verlassen des Editiermodus wieder gegeben.
Zitat: ...Ontime Schedule=False...Dies wäre nur der Fall würde man genau den Moment der ontime-Toggelung treffen. auch das ist Quatsch. Die OnTime-Methode macht nichts anderes als eine Queue zu füllen. Die Queue-Kontrolle läuft Asynchron zu XL. Entscheidend ist: Die Ausführung kann nur dann gestartet werden, wenn XL für die VBA-Kontrolle bereit ist, also sicher nicht im Editiermodus! Das kann in der XL Hilfe zur OnTime Methode nachgelesen werden:
XL Hilfe:EarliestTime : Die Zeit, zu der diese Prozedur ausgeführt werden soll.
Man beachte: werden soll, nicht wird! D.h. die Prozedur wird nach diesem definierten Zeitpunkt ausgeführt, sobald XL in der Lage ist VBA-Code auszuführen. Also z.B. nach der Aufhebung des Editiermodus!
XL Hilfe:LatestTime : Der späteste Zeitpunkt zum Ausführen der Prozedur. Wenn beispielsweise LatestTime auf EarliestTime + 30 festgelegt wird und Microsoft Excel sich nicht für EarliestTime im Modus Ready, Copy, Cut oder Find befindet, da eine andere Prozedur ausgeführt wird, wird in Microsoft Excel 30 Sekunden auf das Beenden der ersten Prozedur gewartet. Wenn sich Microsoft Excel innerhalb von 30 Sekunden nicht im Modus Ready befindet, wird die Prozedur nicht ausgeführt. Wenn dieses Argument nicht angegeben wird, wartet Microsoft Excel, bis die Prozedur ausgeführt werden kann.
Fazit: Ein Aufheben des Editiermodus von XL, könnte ggf. durch ein komplett entkoppeltes externes Programm ausgeführt werden, indem dieses die Zeit überwacht, in der sich XL in diesem Modus befindet und es durch einen SendKey {ESCAPE} veranlasst diesen zu verlassen und damit wieder in der Lage ist VBA-Code auszuführen.
Eine ziemlich aufwändiges Projekt, dass IMHO für den 'Editierfall' aufwandmässig nicht vertretbar ist.
Gruess Hansueli

Anzeige
AW: widerspreche deinen Widersprüchen...
11.09.2015 09:45:37
Marcus
Hallo Hanueli,
dann verstehe ich das Verhalten der angehänten Excel-Datei erst recht nicht mehr.
Bitte tue mir den Gefallen und öffne die Mappe, beschreibe eine Zelle und lasse sie angewählt.
Nach deiner Ausführung dürfte nach 10 Sekunden Inaktivität nichts passieren.
Datei mit API-Timer: https://www.herber.de/bbs/user/100126.xlsm
Bitte versuche es wegen mir auch mit dem folgenden Code und Du wirst sehen, dass OnTime-Makro wird nicht wie von dir beschrieben reagieren.
                Function IdleTime() As Single
Dim a As LASTINPUTINFO
a.cbSize = LenB(a)
GetLastInputInfo a
IdleTime = (GetTickCount - a.dwTime) / 1000 'Idletime in Sekunden
End Function
Sub Idle_Timer()
If IdleTime >= Time_To_Idle Then 'Vergleich Idletime mit Zeitvorgabe in  _
Sekunden
msgbox "OnTime ausgeführt"
End If
Application.OnTime Now + TimeValue("0:0:1"), "Idle_Timer2" 'Wiederholungsprü _
fung nach 1 Sekunde
End Sub
Sub Idle_Timer2()
If IdleTime >= Time_To_Idle Then 'Vergleich Idletime mit Zeitvorgabe in  _
Sekunden
msgbox "OnTime ausgeführt"
End If
Application.OnTime Now + TimeValue("0:0:1"), "Idle_Timer" 'Wiederholungsprüfung  _
nach 1 Sekunde
End Sub
Gruß
Marcus

Anzeige
AW: widerspreche deinen Widersprüchen...
11.09.2015 10:06:56
EtoPHG
Hallo Marcus,
Deine Beispielmappe verhält sich bei mir so:
a) Öffnen - nichts tun - Die Mappe schliesst sich automatisch nach 10 Sekunden ohne irgendwelche Meldungen.
b) Öffne - innerhalb von 10 Sekunden in den Editiermodus gehen - Mind. 10 Sekunden im Editiermodus bleiben - Editiermodus verlassen - Die Mappe schliesst sich automatisch 10 Sekunden nach Verlassen des Editiermodus ohne irgendwelche Meldungen.
Das ist alles. Zu deinem 'Irrsinns-Code' des 2ten Vorschlags äussere ich mich nicht weiter, weil ich nicht verstehe, was du damit zeigen willst. Lies nochmals die Hilfe zur OnTime-Methode und beachte, dass zu einem 'OnTime-Start' (Schedule=True) immer auch ein 'OnTime-Ende' ) (Schedule=False) gehört!
Gruess Hansueli
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige