Makro anhalten bis Benutzer ESC-Taste drückt

  • Word

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von tamaleus.

    Makro anhalten bis Benutzer ESC-Taste drückt

    Hallo allerseits!

    Brauche wieder mal etwas Hilfe: In einem schon recht komplexen Word-Makro (VBA) werden Text-Dateien ein Stück weit automatisch bearbeitet. Dann soll das Makro eine Pause machen, bis der User - in meinem Fall und vorzugsweise - die ESC-Taste (Escape) drückt. Danach soll das Makro seine Arbeit wieder aufnehmen und die Verarbeitung fortsetzen.

    Nachfolgend gleich die Lösung, die ich mittlerweile habe. Dabei gibt es aber div. Probleme: Z.B. blinkt der Cursor nicht (was bei dieser Textbearbeitung für den User halt sehr wichtig wäre) während der User den Text in Word bearbeitet, ferner verschindet der Cursor zeitweilig ganz und zusätzlich muss zum Ausführen eines Makros (mit AutoHotKey!) manchmal noch eine weitere Taste gedrückt werden, bis das (AutoHotKey-)Makro vollständig ausgeführt wird.

    Quellcode

    1. Sub Hauptprogramm
    2. ...
    3. ruft diverse Subs und Funktionen auf
    4. ...
    5. und soll dann hier (innerhalb einer Schlaufe der Hauptroutine)
    6. auf die Eingaben (Text-Änderungen) warten und die Verarbeitung
    7. an dieser Stelle erst fortsetzen, wenn der User hier die ESC-Taste drückt.
    8. ...
    9. dann werden weitere Subs aufgerufen
    10. ...


    Ich habe folgende Deklarationen

    Quellcode

    1. ' Das Abgreifen der Tasten-Drucke wird aus dieser Lib ermöglicht
    2. Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
    3. ' Das Warten mit 'Sleep' wird aus dieser Lib ermöglicht
    4. Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    5. ' Die Esc-Taste wird als Konstante deklariert
    6. Public Const VK_ESCAPE = &H1B


    Die eigentliche WARTE-Routine sieht bei mir wie folgt aus:

    Quellcode

    1. Sub WarteAufEscapeTaste()
    2. 'Dim intSekundenZaehler As Long
    3. Application.StatusBar = "Warte auf ESC-Taste"
    4. bolESCTaste = ESCTaste()
    5. While Not bolESCTaste
    6. DoEvents ' Das System andere Events/Tasks ausführen lassen
    7. Sleep (50) ' Stehenbleiben länger
    8. 'Application.StatusBar = "Warte auf ESC-Taste (" + CStr(intSekundenZaehler / 10) + ") Sekunden."
    9. 'Application.StatusBar = "Warte auf ESC-Taste"
    10. bolESCTaste = ESCTaste()
    11. 'intSekundenZaehler = intSekundenZaehler + 1
    12. Wend
    13. Application.StatusBar = ""
    14. If bolESCTaste Then
    15. ' Hier die Verarbeitung sauber abschliessen
    16. DoEvents
    17. End If
    18. Sleep (500)
    19. End Sub


    und dann noch die ESCAPE-Funktion wie folgt:

    Quellcode

    1. Function ESCTaste() As Boolean
    2. Dim intAKS As Integer
    3. intAKS = GetAsyncKeyState(VK_ESCAPE)
    4. ESCTaste = (intAKS And 2 ^ 16)
    5. End Function


    Hoffe sehr, dass mir jemand weiterhelfen kann und danke im Voraus für jeglichen Beitrag.

    Beste Grüsse
    Hallo peterfido

    Danke für Deinen Input. Leider verstehe ich nicht, was mir das sagen soll und hilft mir leider noch nicht, mein geschildertes Problem - CURSOR reagiert nicht wie sonst üblich beim Bearbeiten eines Word-Dokumentes, bzw. Mauszeiger blinkt nicht, bzw. ist teilweise überhaupt nicht sichtbar und Shortcuts werden nur teilweise richtig ausgeführt (der Rest wird erst geschrieben, wenn nochmals eine Taste gedrückt wird), was so denke ich, eben an der

    Quellcode

    1. WarteAufEscapeTaste
    , bzw. an der

    Quellcode

    1. Function ESCTaste
    liegt.
    Der Ansatz das Makro als Main-Stream zu betrachten und in den Bearbeitungspausen Word zwischendrin mal kurz freizuschalten, deckt sich nicht so richtig mit dem Grundgedanken der Word-Entwickler.

    Die haben nämlich die Textbearbeitung an sich als Haupt-Thread angedacht.

    Wenn ich dein Problem lösen müsste, würde ich im Hintergrund einen Timer laufen lassen, der immer mal wieder schaut, ob der Benutzer (noch) aktiv ist.
    Und wenn der Benutzer mal Pause hat, startet der Timer die Hintergrundverarbeitung.
    Wenn der Benutzer wieder mit Tippen loslegt, kannst du die Hintergrundverarbeitung stoppen.
    Setzt voraus, dass die Hintergrundbearbeitung schön granular ist und/oder mit Checkpoints durchzogen.

    Wenn du allerdings eine Methode suchst, auf eine Benutzereingabe zu warten, um die Hintergrundverarbeitung zu starten:
    Warum nimmst du nicht einfach ein Makro, das den Background-Code startet und ordnest dieses Makro einer Taste zu.

    ESC geht nicht so einfach, aber z.B. F12

    Egal wie du's machst, mach's aus der Überlegung:
    Word ist das Hauptprogramm und das Makro ist die Hintergrundverarbeitung. Nicht umgekehrt.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Danke auch für diesen Input.

    Wenngleich ich zugeben muss, dass ich nicht ganz alles verstehe. Vielleicht habe ich mein Problem auch zu wenig klar umschrieben. Drum hier nochmals der gewünschte Ablauf.

    Makro wird gestartet. Dieses zeigt dem User eine erste (von insgesamt 7) sog. Tagesdatei(en) an, nachdem das Makro schon gewisse Textbearbeitungen (automatisch) gemacht hat. DANN soll es eben diese "Pause" dem User ermöglichen, weitere, manuelle Bearbeitungen an diesem ersten Dokument vorzunehmen. Wenn der User dann mit seinen Änderungen am Dokument fertig ist, soll er - so war es angedacht - mit z.B. ESC (oder BREAK) das Makro "weiterlaufen" lassen, welches wiederum nochmals einige automatische Textänderungen an diesem Dokument vornimmt und es dann speichert.
    Dann fängt das Ganze wieder von vorne an, diesmal aber mit der nächsten "Tagesdatei". So soll der Prozess durchlaufen werden, bis alle Dateien "Montag" bis "Sonntag" abgearbeitet sind.

    Soweit klappt ja auch alles prima und ist den Anfoderungen entsprechend erfüllt. BLOSS das mit dieser "Pause" (siehe "WarteAufEscapeTaste") funktioniert nicht vollständig korrekt (Cursor beim manuell Bearbeiten teilweise oder ganz nicht sichtbar, Cursor blinkt nicht und Shortcuts (mit AutoHotKey) funktioniert erst dann richtig, wenn nochmals eine Taste gedrückt wird.

    Ich habe auch das Ganze ("WarteAufEscapeTaste") mit der BREAK- anstatt der ESC-Taste versucht, leider mit gleichem Ergebnis.

    Wer kann mir hier mit einem Stück Code weiterhelfen, sodass diese "Bearbeitungspause" möglich ist, ohne, dass der Cursor spinnt?
    Dir ist schon klar, dass du mit

    Visual Basic-Quellcode

    1. Sleep (50)
    20 mal pro Sekunde den VBA-Code ausführst und dabei die Word-Bearbeitung unterbrichst.
    Da würde ich als Cursor auch den Dienst verweigern.
    Auf der anderen Seite benötigst du das DoEvent so häufig, damit der User ansprechbare Responsezeiten bekommt.

    Deshalb würde ich, wie oben beschreiben, den Makro-Code beenden (vorher den Bearbeitungsstand merken) und den User unbehindern arbeiten lassen und danach mit Tastendruck (z.B. F12) den Code wieder starten lassen.
    Wieso willst du mit Gewalt permanent abfragen, ob der User eine Taste drückt, wenn du ihn genausogut per Tastendruck aktiv die Weiterverarbeitung starten lassen kannst?
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Danke. Auch für den Hinweis wegen "SLEEP"; das ist noch von Tests stehengeblieben und hätte hier gar nicht mit rein sollen.

    Hab wohl ein Brett vorm Kopf, aber verstehe leider nicht recht, wie ich Deinen Rat umsetzen kann. Mir ist z.B. nicht klar, wie das mit dem "vorher den Bearbeitungsstand merken" gehen, bzw. als Code-Schnippsel aussehen könnte. Und wie gelange ich dann wieder zu der Stelle, wo der User das ursprüngliche Makro beendet, bzw. unterbrochen hat? Falls das den Rahmen sprengt, bitte ich höflich um Entschuldigung. Bin da wohl etwas zu naiv an das Ganze rangegangen. :S
    Ich würde mit mehreren Makros arbeiten.
    Der User wird selbst am besten wissen, wann er fertig ist mit
    seiner Bearbeitung. Dann kann er einen Hotkey drücken, oder
    du machst ihm ein Icon in der Iconleiste. Dieser Hotkey/Icon
    startet nun das zweite Makro.

    Da das Hauptprogramm immer noch läuft bleiben globale
    Variablen die ganze Zeit auf ihrem Wert, bis du sie änderst.

    Ein Makro mitten im Lauf zu stoppen finde ich sehr problematisch
    bzw. unnötig. Du willst doch, dass das Makro eine Aufgabe erledigt.


    Also das erste Makro erledigt seine Arbeit. Wenn es fertig ist meldet es dem
    User per MessageBox, dass dieser nun weitermachen soll.
    Wenn der User fertig ist, dann soll er ein Icon anklicken, bzw. einen Hotkey
    drücken. Dadurch startet das zweite Makro. Wenn dieses fertig ist, startet
    das zweite Makro wieder das erste Makro, und alles beginnt von Vorne.

    Der Zähler, der sich durch die Dateien hangelt, muss z.B. eine globale
    Variable sein, damit das erste Makro beim zweiten Aufruf weiß, wo es
    weiter machen soll.