Live-Forum - Die aktuellen Beiträge
Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender

Forumthread: Timer-Funktion zum Schließen einer Excel-Datei

Timer-Funktion zum Schließen einer Excel-Datei
06.01.2020 08:36:22
Ann
Hallo,
seit der Umstellung auf Windows 10 (64 Bit-Version) funktioniert die Timer-Funktion nicht mehr korrekt. Eigentlich soll 5 Minuten nach dem öffnen der Excel-Datei ein Fenster (frmExpire) geöffnet werden in der ein 20 Sekunden-Countdown abläuft. Nach Ablauf der 20 Sekunden soll sich die Excel-Datei automatisch schließen. Wenn im Countdown-Fenster "Schließen" angeklickt wird, sollen die 5 Minuten bis sich das Fenster erneut öffnet wieder gestartet werden. Anstatt die UserForm (frmExpire) zu öffnen, erhalte ich nach Ablauf der 5 Minuten den Fehler "Fehler beim Kompiulieren: Typen unverträglich". Beim Debuggen wird mir im Formular-Code von frmExpire im Private Sub UserForm_Activate() "hwnd = GetActiveWindow" markiert.
Die Beispieldatei findet ihr hier:
https://www.herber.de/bbs/user/134192.xlsm
Vielen Dank für eure Hilfe
Ann
Anzeige

7
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Timer-Funktion zum Schließen einer Excel-Datei
06.01.2020 08:43:46
volti
Hallo Ann,
auch die Callback-Funktion muss auf 64 Bit umgestellt werden, nicht nur die Declares.
Public Sub TimerCallback( _
    ByVal hwndptr As LongPtr, ByVal uMsg As Long, _
        ByVal idEvent As LongPtr, ByVal dwTime As Long)
    RaiseEvent Tick
End Sub

viele Grüße
Karl-Heinz

Anzeige
AW: Timer-Funktion zum Schließen einer Excel-Datei
06.01.2020 09:14:55
volti
Hallo Ann,
da war mir ein kleiner Fehler reingeraten:
Public Sub TimerCallback( _
ByVal hwnd As LongPtr, ByVal uMsg As Long, _
ByVal idEvent As LongPtr, ByVal dwTime As Long)
RaiseEvent Tick
End Sub
Aber Deine Datei muss grundsätzlich überarbeitet werden, da die Declares teilweise nicht stimmen und auch nicht überall die Handle angepasst wurden.
Ein Beispiel:
Public Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Public Declare PtrSafe Function SetWindowPos Lib "user32" ( _
       ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, _
       ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
       ByVal cy As Long, ByVal wFlags As Long) As Long
Public Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hwnd As LongPtr) As Long
Public Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" ( _
       ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Public Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" ( _
       ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
Public Declare PtrSafe Function GetWindowRect Lib "user32" (ByVal hwnd As LongPtr, lpRect As Rect) As Long

I m Moment habe ich keine Zeit dafür, aber vielleicht hat ja jemand anderes Idee und Zeit.
viele Grüße
Karl-Heinz
Anzeige
AW: Timer-Funktion zum Schließen einer Excel-Datei
06.01.2020 13:21:13
Nepumuk
Hallo,
ich gebe zu, ich war schlampig. Jetzt sollte es passen:
https://www.herber.de/bbs/user/134198.xlsm
Gruß
Nepumuk
Anzeige
AW: Timer-Funktion zum Schließen einer Excel-Datei
06.01.2020 19:28:04
Nepumuk
Hallo,
jetzt hab ich doch noch eine nicht angepasste Prozedur gefunden. Der neue Code für die Klasse clsTimer:
Option Explicit

Private Declare PtrSafe Function SetTimer Lib "user32.dll" ( _
    ByVal hwnd As LongPtr, _
    ByVal nIDEvent As LongPtr, _
    ByVal uElapse As Long, _
    ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32.dll" ( _
    ByVal hwnd As LongPtr, _
    ByVal nIDEvent As LongPtr) As Long
Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32.dll" ( _
    ByRef Destination As Any, _
    ByRef Source As Any, _
    ByVal Length As LongPtr)
Private Declare PtrSafe Function VirtualAlloc Lib "kernel32.dll" ( _
    ByRef lpAddress As Any, _
    ByVal dwSize As LongPtr, _
    ByVal flAllocationType As Long, _
    ByVal flProtect As Long) As LongPtr
Private Declare PtrSafe Function VirtualFree Lib "kernel32.dll" ( _
    ByRef lpAddress As Any, _
    ByVal dwSize As LongPtr, _
    ByVal dwFreeType As Long) As Long

Private Const MEM_COMMIT As Long = &H1000&
Private Const MEM_DECOMMIT As Long = &H4000&

Private Const PAGE_EXECUTE As Long = &H10&
Private Const PAGE_EXECUTE_READ As Long = &H20&
Private Const PAGE_EXECUTE_READWRITE As Long = &H40&

Private Const ASM_SIZE As LongPtr = &HFF&

Private m_ptrCallback As LongPtr
Private m_hdlTimer As LongPtr
Private m_blnEnabled As Boolean
Private m_lngInterval As Long

Public Event Tick()

Public Sub TimerCallback(ByVal hwnd As LongPtr, ByVal uMsg As Long, _
        ByVal idEvent As LongPtr, ByVal dwTime As Long)

    RaiseEvent Tick
End Sub

Public Property Get Enabled() As Boolean
    Enabled = m_blnEnabled
End Property

Public Property Let Enabled(ByVal blnValue As Boolean)
    If blnValue <> m_blnEnabled Then
        If blnValue Then
            m_hdlTimer = SetTimer(0, 0, Interval, m_ptrCallback)
        Else
            Call KillTimer(0, m_hdlTimer)
        End If
        m_blnEnabled = blnValue
    End If
End Property

Public Property Get Interval() As Long
    Interval = m_lngInterval
End Property

Public Property Let Interval(ByVal lngMs As Long)
    m_lngInterval = lngMs
    
    If Enabled Then
        Enabled = False
        Enabled = True
    End If
End Property

Private Function GetFirstPublicMethod(ByVal obj As Object) As LongPtr
    Dim pObj As LongPtr
    Dim pVtbl As LongPtr
    Call RtlMoveMemory(pObj, ByVal ObjPtr(obj), 4)
    Call RtlMoveMemory(pVtbl, ByVal pObj + &H1C, 4)
    GetFirstPublicMethod = pVtbl
End Function

Private Sub FreeCallback(ByVal ptr As LongPtr)
    Call VirtualFree(ByVal ptr, ASM_SIZE, MEM_DECOMMIT)
End Sub

Private Function CreateCallback(ByVal obj As Object, _
        ByVal addr As LongPtr, ByVal params As Long) As LongPtr

    Dim ptrMem As LongPtr
    Dim ptrItr As LongPtr
    Dim ptrNewAddr As LongPtr
    Dim i As Long
    ptrMem = VirtualAlloc(ByVal 0&, ASM_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
    If ptrMem = 0 Then
        Call Err.Raise(vbObjectError, , "VirtualAlloc fehlgeschlagen!")
    End If
    ptrItr = ptrMem
    For i = 1 To params
        Call RtlMoveMemory(ByVal ptrItr + 0, &H2474FF, 3)
        Call RtlMoveMemory(ByVal ptrItr + 3, params * 4, 1)
        ptrItr = ptrItr + 4
    Next
    Call RtlMoveMemory(ByVal ptrItr + 0, &H68, 1)
    Call RtlMoveMemory(ByVal ptrItr + 1, ObjPtr(obj), 4)
    ptrItr = ptrItr + 5
    ptrNewAddr = addr - ptrItr - 5
    Call RtlMoveMemory(ByVal ptrItr + 0, &HE8, 1)
    Call RtlMoveMemory(ByVal ptrItr + 1, ptrNewAddr, 4)
    ptrItr = ptrItr + 5
    Call RtlMoveMemory(ByVal ptrItr + 0, &HC2, 1)
    Call RtlMoveMemory(ByVal ptrItr + 1, params * 4, 2)
    CreateCallback = ptrMem
End Function

Private Sub Class_Initialize()
    m_ptrCallback = CreateCallback(Me, GetFirstPublicMethod(Me), 4)
End Sub

Private Sub Class_Terminate()
    If Enabled Then Enabled = False
    Call FreeCallback(m_ptrCallback)
End Sub

Gruß
Nepumuk
Anzeige
AW: Timer-Funktion zum Schließen einer Excel-Datei
09.01.2020 13:01:13
Ann
Hallo Nepomuk,
erst durch deinen Beitrag im anderen Forum habe ich bemerkt, dass ich hier überhaupt eine Antwort erhalten hatte. Aus irgendeinen Grund habe ich keine Benachrichtigung per E-Mail bekommen.
Erstmal vielen Dank für deine Mühe.
Wenn ich dienen Code übernehme stürzt nach den 5 Minuten Excel einfach ab und will die Datei im Anschluss erneut öffnen :-(
Gruß Ann
Anzeige
;
Anzeige
Anzeige

Infobox / Tutorial

Timer-Funktion zum Schließen einer Excel-Datei


Schritt-für-Schritt-Anleitung

Um einen Excel Timer zu erstellen, der eine Excel-Datei automatisch schließt, befolge diese Schritte:

  1. Öffne Excel und drücke ALT + F11, um den Visual Basic for Applications (VBA) Editor zu öffnen.

  2. Füge eine neue UserForm hinzu, die als Countdown-Anzeige dient. Nenne sie frmExpire.

  3. Füge ein Label hinzu, um den Countdown anzuzeigen, und einen Button mit der Beschriftung "Schließen".

  4. Erstelle die folgenden Variablen in einem Modul:

    Dim WithEvents Timer As clsTimer
    Dim StartTime As Double
  5. Füge den Code für die Timer-Funktion in das Modul ein:

    Private Sub Workbook_Open()
        Set Timer = New clsTimer
        Timer.Interval = 300000 ' 5 Minuten
        Timer.Enabled = True
    End Sub
  6. In der UserForm frmExpire, füge den Code für den Countdown und die Schließfunktion hinzu:

    Private Sub UserForm_Activate()
        Dim countdown As Integer
        countdown = 20 ' 20 Sekunden Countdown
        For i = countdown To 1 Step -1
            Label1.Caption = i
            DoEvents
            Application.Wait Now + TimeValue("00:00:01")
        Next i
        ThisWorkbook.Close SaveChanges:=False
    End Sub
    
    Private Sub CommandButton1_Click()
        Timer.Enabled = False
        Unload Me
    End Sub
  7. Speichere die Datei als Makro-fähige Datei (xlsm).


Häufige Fehler und Lösungen

  • Fehler beim Kompilieren: Typen unverträglich: Stelle sicher, dass alle Variablen und Funktionen korrekt deklariert sind, insbesondere bei der Verwendung von LongPtr in 64-Bit-Versionen.
  • Excel stürzt ab: Überprüfe, ob alle Timer-Funktionen ordnungsgemäß implementiert sind und keine Endlosschleifen auftreten.

Alternative Methoden

Falls du keine UserForm verwenden möchtest, kannst du auch mit einem einfachen Application.OnTime arbeiten, um einen Excel Countdown Timer zu erstellen:

Sub StartTimer()
    Application.OnTime Now + TimeValue("00:05:00"), "ShowCountdown"
End Sub

Sub ShowCountdown()
    MsgBox "Die Datei wird in 20 Sekunden geschlossen!"
    Application.Wait Now + TimeValue("00:00:20")
    ThisWorkbook.Close SaveChanges:=False
End Sub

Praktische Beispiele

Hier sind einige Beispiele für Excel Timer, die du nutzen kannst:

  1. Countdown Timer: Verwende die oben genannten Codes, um einen Countdown zu erstellen, der nach 5 Minuten eine UserForm öffnet.
  2. Automatisches Schließen: Implementiere den Application.OnTime-Befehl, um die Datei nach einer festgelegten Zeit automatisch zu schließen.

Tipps für Profis

  • Nutze Application.OnTime für eine einfachere Timer-Implementierung, wenn du keinen komplexen Timer benötigst.
  • Achte darauf, dass der Timer nicht in einer Endlosschleife hängt, um Abstürze zu vermeiden.
  • Teste den Timer in einer Testdatei, bevor du ihn in produktiven Dokumenten verwendest.

FAQ: Häufige Fragen

1. Wie kann ich den Timer anpassen?
Du kannst die Intervalle in den Timer-Variablen im VBA-Code ändern, um die gewünschte Zeit für den Countdown festzulegen.

2. Funktioniert dieser Timer auch in Excel 2016?
Ja, der Code sollte auch in Excel 2016 und anderen neueren Versionen funktionieren, solange die VBA-Umgebung korrekt konfiguriert ist.

3. Kann ich den Timer auch für andere Zwecke nutzen?
Ja, der Timer kann angepasst werden, um verschiedene Aktionen nach einer festgelegten Zeit auszuführen, z. B. das Senden von E-Mails oder das Auslösen von Makros.

4. Was muss ich tun, wenn Excel nicht reagiert?
Überprüfe den Code auf Fehler und stelle sicher, dass alle Timer-Funktionen korrekt implementiert sind. Vermeide lange Wartezeiten in Schleifen, die Excel blockieren könnten.

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Entdecke mehr
Finde genau, was du suchst

Die erweiterte Suchfunktion hilft dir, gezielt die besten Antworten zu finden

Suche nach den besten Antworten
Unsere beliebtesten Threads

Entdecke unsere meistgeklickten Beiträge in der Google Suche

Top 100 Threads jetzt ansehen
Anzeige