435 Aufrufe
Gefragt in Windows 10 von pclaus
Ich erstelle ein kleines "Programm" im Excel mit VBA, das am Monitor ein Farbfeld generiert, dem auf der Tastatur ein zugeordnetes Zeichen entspricht, das möglichst schnell eingegeben werden soll.
Die Zeit vom Erscheinen des Farbfeldes bis zur Eingabe wird dabei gemessen. Dafür kann ich aber nicht das zusätzliche Drücken der Enter-Taste brauchen.
Die Lösung des Problems hab ich bisher auf 3 Ebenen gesucht, leider ohne Erfolg.
1) In den Optionen von Excel.
2) Auf der Tastatur selbst und
3) über Makros.
Hier müsste mein bestehendes Makro an einer bestimmten Stelle der Ausführung automatisch unterbrochen werden, um das Zeichen (ohne Entertaste) manuell eingeben zu können. Unmittelbar danach sollte das Makro (ohne manuelle Aktivierung) weiterlaufen, denn da wäre ja dann das Enter drinnen.
Die kurze Dauer der Makro-Ausführung wäre für die Zeitmessung vernachlässigbar, sodass nur die tatsächliche Zeit bis zur Eingabe des Zeichens gemessen würde.
Wichtig: Keine zeitabhängige Unterbrechung, denn dann würde entweder nichts gemessen (Zeit zu kurz) oder immer nur die Dauer der Unterbrechung (Zeit ausreichend oder zu lang).
Ich habe es schon mit If-Codes versucht, aber dann ging gar nix mehr.
Bitte um Eure Hilfe!
LG PClaus

24 Antworten

0 Punkte
Beantwortet von
Hallo PCLaus, Hier ein paar Anmerkungen dazu.

[quote]Was mir derzeit fehlt, ist ein Code, der es ermöglicht, dass die VBA-Ausführung bei Erscheinen des Farbfeldes so lange unterbrochen wird, bis der Nutzer eine Taste drückt (ohne Enter!)
[/quote]
Genau das ist der Problemteil. Das geht leider nur über eine Dauerschleife wie Do Loop die sich solange wiederholt bis KeyPressed = True ist. Um den Tastendruck abzufragen ist die Declare-Zeile von essentieller Wichtigkeit. Du kannst alternativ auch ein Userform verwenden. Das macht aber nur Sinn, wenn du auch die Ausgabe (z.B. Messzeiten) im Formular darstellst. Dann sollten es aber nicht zu viele Messzeiten sein.

[quote]Nein, ich warte schon bis das Excel sagt Keine Rückmeldung und alles blass wird.[/quote]
Das kann auch vorkommen wenn eine Dauerschleife wie Do Loop ausgeführt wird. Wie gesagt müsste in meinem obigen Beispiel dann je nach Farbe einfach nur die Taste A S oder D gedrückt werden. Aber das hast du sicher bereits ausprobiert.

[quote]Ich habe ja viele Schritte, die du in VBA programmiert hast (Farbauswahl, Zuordnung zu Buchstaben, Zeitrechnung etc.) schon im Excel "programmiert"[/quote]
Und wo genau? Bis jetzt sehe ich in deinem Code nur, dass du bestimmte Werte in die jeweils nächste Spalte bzw. Zeile kopierst. Wo entsteht hier das Farbfeld?

Vielleicht hab ich dein Projekt ja auch falsch verstanden. Beschreib doch nochmal genau was, wann, wo und wie passieren soll. Was möchtest du mit dem Tastendruck erreichen? Soll eine bestimmte Taste gedrückt werden oder nur irgendeine beliebige?

Gruß Mr. K.
0 Punkte
Beantwortet von pclaus
Hallo xlKing!
Danke für deine Antwort und Infos! Habe daraus wieder viel gelernt.
Du hast recht, ich habe dir meine Berechnungen im Excel nicht gezeigt.
Also:
In Zelle B5 wird eine Zufallszahl generiert (=ZUFALLSBEREICH(1;9)).
In D5 wird der Zufallszahl ein Buchstabe zugeordnet mit =SVERWEIS auf eine Tabelle, in der Zahlen Buchstaben zugeordnet sind.
Dieser Buchstabe wird nach E5 kopiert und damit fixiert. (Makro)
In F5 wird die aktuelle Uhrzeit angegeben mit =JETZT().
Diese Uhrzeit wird nach G5 kopiert, um die Startzeit zu fixieren. (Makro)
Gleichzeitig wird über "Bedingte Formatierung" von A10:A12 ein Farbfeld gemalt, das dem generierten Buchstaben entspricht.
In G8 wird mit =JETZT() die aktuelle Uhrzeit angegeben, die der letzten Eingabe entspricht (könnte man verbessern durch ein weiteres Kopieren direkt nach der Eingabe des Buchstaben, fällt mir gerade auf).
Nun wird die Zelle D18 aktiviert. (Makro) Das ist die Zelle, in die die manuelle Eingabe des Buchstaben erfolgen soll.
Daher sollte hier die Ausführung des Makros unterbrochen werden bis unmittelbar nach der Eingabe.
Dann wird die Zelle D18 wieder aktiviert (entspricht dzt. dem Enter). (Makro)
Nun wird D18 nach D19 kopiert, um die Eingabe für die Auswertung (Wahr oder Falsch etc.) zu fixieren. (Makro)
Gleichzeitig wird im Excel auch die Dauer vom Erscheinen des Farbfeldes bis zur manuellen Eingabe des entsprechenden Buchstaben gemessen durch =G8-G5.
Als letzter Schritt wird wieder die Zelle D18 aktiviert und Inhalt entfernt (Makro) und wäre so wieder bereit für die nächste Eingabe.

Noch nicht berücksichtigt dabei ist eine Wiederholung des prozesses, dafür würde ich zur Not das Makro kopieren und dranhängen, auch 40mal.
Eventuell gewünschte Pausen zwischen Schritten würde ich dann mit "Application.OnTime Now + TimeValue("0:00:5")" für 5 s versuchen, wäre das ok?

Ich hoffe, ich konnte es verständlich erklären.
LG PClaus
0 Punkte
Beantwortet von
Hallo PClaus, OK lag ich also zumindest nicht ganz so falsch.

Grundsätzlich ist erstmal alles OK, was funktioniert und in einer Weise geschrieben ist, die du verstehst. Ob der Code dann auch
elegant ist, ist eine ganz andere Frage. Da dieser sich aber im Hintergrund befindet, wo er nicht auffällt ist das eher
nebensächlich.

Eine (!) der eleganteren Varianten hab ich bereits in Antwort1 gepostet. Warum die bei dir nicht funktioniert - Keine Ahnung. Es
geht aber auch anders. In deinem Fall kannst du auch direkt Application.Onkey verwenden. Dazu musst du den Code in mehrere
Teilmakros unterteilen und in einem allgemeinen Modul (z.B. Modul1) ablegen.

[code]Const wdh = 20
Dim akt As Integer

Sub Start()
'
' Start Makro
'
Application.OnKey "a", "TasteA"
Application.OnKey "b", "TasteB"
Application.OnKey "c", "TasteC"
Application.OnKey "d", "TasteD"
Application.OnKey "e", "TasteE"
Application.OnKey "f", "TasteF"
Application.OnKey "g", "TasteG"
Application.OnKey "h", "TasteH"
Application.OnKey "i", "TasteI"

Range("D5").Copy
Range("E5").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("F5").Copy
Range("G5").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("D18").Select
Application.CutCopyMode = False
End Sub
Sub TasteA()
  Range("D18").Value = "A"
  Weiter
End Sub
Sub TasteB()
  Range("D18").Value = "B"
  Weiter
End Sub
Sub TasteC()
  Range("D18").Value = "C"
  Weiter
End Sub
Sub TasteD()
  Range("D18").Value = "D"
  Weiter
End Sub
Sub TasteE()
  Range("D18").Value = "E"
  Weiter
End Sub
Sub TasteF()
  Range("D18").Value = "F"
  Weiter
End Sub
Sub TasteG()
  Range("D18").Value = "G"
  Weiter
End Sub
Sub TasteH()
  Range("D18").Value = "H"
  Weiter
End Sub
Sub TasteI()
  Range("D18").Value = "I"
  Weiter
End Sub

Sub Weiter()
Range("D18").Copy
Range("D19").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Range("D18").Select
Selection.ClearContents
akt = akt + 1 'zum nächsten Level hochschalten

If akt < wdh Then
  Start 'wenn Anzahl nochn nicht erreich dann neuer Start
Else
  'Tasten wieder für normale Nutzung freigeben
  Application.OnKey "a"
  Application.OnKey "b"
  Application.OnKey "c"
  Application.OnKey "d"
  Application.OnKey "e"
  Application.OnKey "f"
  Application.OnKey "g"
  Application.OnKey "h"
  Application.OnKey "i"
  End
End If

End Sub[/code]Wie gesagt: Elegant ist das nicht, sollte aber auch gehen. Hab hier bewusst nur wenig verändert. Probiers mal
aus.
0 Punkte
Beantwortet von pclaus
Danke! Sieht gut aus!
Probiers aber erst morgen, bin heute schon zu müd.
LG PClaus
0 Punkte
Beantwortet von pclaus
Hallo xlKing!
Danke vielmals!
Code und Eingabe des Buchstaben funktioniert ohne Enter! Auch die Wiederholungen funktionieren!
Was aber leider noch nicht funktioniert:
Bei Eingabe des Buchstaben generiert mein Excel Befehl Zufallsbereich sofort eine neue Zahl und damit ein neues Farbfeld.
Und Excel vergleicht jetzt den eingegebenen Buchstaben mit dem neuen Farbfeld, was natürlich selten stimmt.
Auch die dauer wird nur am Ende des Ablaufes gemessen und dazwischen nur die Zeiten, die der PC zur Berechnung braucht, also 1/100stel Sekunden.
Ich arbeite seit Stunden daran, leider bisher ohne Erfolg.
Jetzt mach ich eine Pause und arbeite dann weiter.
Danke und LG PClaus
0 Punkte
Beantwortet von
Hallo PClaus.

Klar tut es das. Eine Formel wie Zufallsbereich wird immer neu berechnet, sobald irgendwo eine Eintragung gemacht wird. Deshalb kopierst du ja den Buchstaben per Makro von D5 nach E5. Um ihn zu sichern. Durch das Kopieren entsteht schon ein neuer Buchstabe. Ein weiterer entsteht durch Kopieren von F5 nach G5 und ein Dritter durch die Eintragung des Tastendrucks in D18. Vergleiche also D18 mit E5 bzw. beziehe die Bedingte Formatierung auf E5 und alles ist gut.

Wenn dich die zwischendurch entstehenden Buchstaben verständlicherweise verwirren, kannst du die Berechnung auch kurzfristig abschalten. Schreibe dazu in das Startmakro nach dem letzten OnKey Befehl:

[i]Application.Calculate
Application.Calculation = xlCalculationMa[/i]nual

sowie in das Weiter Makro ebenfalls nach dem letzten OnKey Befehl aber vor die Zeile End den Befehl: [i]Application.Calculation = xlCalculationAutomatic[/i]

Damit stehen in D5 und E5 die gleichen Buchstaben drin. Alternativ kannst du auch auf die Formel verzichten und die Zahl direkt im Makro generieren. Dafür brauchst du wie in Antwort 1 gezeigt die Zeile [i]Randomize Timer[/i] zum Initialisieren des Zufallsgenerators sowie die Zeile [i]Range("E5") = Int(Rnd * 9) + 1[/i] um eine Zahl zwischen 1 und 9 zu generieren.

Mit der Dauer ist es ähnlich. Eine Formel wie Jetzt() gibt halt immer die Zeit zum Berechnungszeitpunkt (also nach Zelleintrag) aus.
Alternativ kannst du im Makro Weiter gleich als erste Zeile unter der Sub einen Befehl wie [i]Range("G9") = ["=Now()"] - Range("G5")[/i] einbauen. Aber Achtung: Die Zielzelle (hier G9) muss das richtige Zahlenformat "s,000" haben um Sekunden und Millisekunden korrekt anzuzeigen.

Gruß Mr. K.
0 Punkte
Beantwortet von pclaus
Hallo xlKing!
Danke für deine neuen Vorschläge!!
Ich werde das alles durchprobieren und melde mich dann wieder.
LG PClaus
0 Punkte
Beantwortet von
Kleine Korrektur: der Letzte Teil war Quatsch. So wärs richtig:
Range("G9") = ["=Now()-G5"]
0 Punkte
Beantwortet von pclaus
Danke, alles klar.
Aber ich kämpfe immer noch mit dem Ergebnis der Eingabe.
Du schreibst: "Vergleiche also D18 mit E5 bzw. beziehe die Bedingte Formatierung auf E5 und alles ist gut."
Beides hatte ich schon vorher, das Problem ist aber, dass die Eingabe nicht mit dem vorher generierten Buchstaben verglichen wird sondern mit dem neuen, der bei der Eingabe selbst generiert wird. Das System überholt sich sozusagen selbst, deshalb hilft auch mein Kopieren von D5 nach E5 nix, weil der Code auch das mit dem neuen Buchstaben macht.
Verstehst du, was ich meine? Ist nicht leicht zu erklären.
Ich versuchs einmal mit einem Beispiel:
Nach dem Start erscheint auf E5 ein Buchstabe mit rotem Farbfeld.
In dem Augenblick, wenn ich den richtigen Buchstaben drücke, wechselt E5 auf einen neuen Buchstaben mit gelbem Farbfeld.
Nun wird mein Buchstabe für rot mit dem von gelb verglichen, das hat noch gar nix mit der Auswertung zu tun, das System "weiß gar nichts mehr von rot".

LG PClaus
0 Punkte
Beantwortet von
Hattest du nicht geschrieben, du generierst den Buchstaben in D5 und kopierst ihn dann als Wert nach E5? Wie kann er sich dann
zwischendurch ändern?

Frage: Wie startest du das Makro eigentlich? Vielleicht über ein Ereignis wie z.B. Worksheet Change? Das wäre für mich im Moment
die logischste Erklärung für das von dir beschriebene Verhalten. In diesem Fall ruft sich das Ereignis durch Makro-Eingabe in die
Zelle selbst wieder auf. Das kannst du aber über Application.EnableEvents = False abschalten.
...