Frage von AntwortHunter, 64

MS Excel Makro Pausieren ohne Excel komplett zu pausieren?

Hi, Ich arbeite an einer art "Schiffe Versenken" für MS Excel und arbeite grade daran, dass man auf Zeit Spielen kann. dafür brauche ich logischerweise nen Timer, der die eingestellte Zeit Herunterzählt und das Spiel Beendet. Das war kein Großes Problem für mich, bis auf eine Sache: Das Makro funktioniert zwar, aber ich habe keinen Befehl gefunden der es zulässt, dass man, während der Timer läuft, noch das Spielfeld benutzen kann, da auch Excel pausiert wird und keine Änderung an den Zellen zulässt. Kennt einer von euch einen Befehl, bei dem nur das Makro angehalten wird und nicht das komplette Programm? Mein Makro sieht bis jetzt so aus:

Sub Schaltfläche1_Klicken()

Dim SE As Integer

Dim MN As Integer

Dim I As Integer

I = 0

Do While I = 0

I = 0

SE = Sheets("Eigene Flotte").Range("O26").Value

MN = Sheets("Eigene Flotte").Range("N26").Value

If SE > 0 Then

SE = SE - 1

Sheets("Eigene Flotte").Range("O26").Value = SE

Else

If MN > 0 Then

MN = MN - 1

SE = 59

(hier soll der Befehl zum Pausieren hin)

Sheets("Eigene Flotte").Range("O28").Value = SE

Sheets("Eigene Flotte").Range("N26").Value = MN

Else

Range("A1:L30").Value = ""

I = 1

End If

End If

Loop

End Sub

Hilfreichste Antwort - ausgezeichnet vom Fragesteller
von daCypher, 23

Ich hab mir mal deine Prozedur genommen und sie ein bisschen umgebaut. (Achtung, du musst die Zellbezüge wieder richtig einstellen). Die While-Schleife ist jetzt weg, dafür ist die Methode "Application.OnTime" jetzt drin. Die sorgt dafür, dass die Funktion jede Sekunde einmal aufgerufen wird, wodurch der Zähler runtergezählt wird. Es kann sein, dass ab und zu eine Sekunde übersprungen wird, deshalb sollte man vielleicht anstatt mit den Variablen "SE" und "MN" mit einer Date-Variable arbeiten, die beim ersten Start gefüllt wird und die echte Zeitdifferenz seit dem Programmstart anzeigt.

Sub Schaltfläche1_Klicken()
Dim SE As Integer
Dim MN As Integer

SE = Sheets(1).Range("B1").Value
MN = Sheets(1).Range("A1").Value

If SE > 0 Then
SE = SE - 1
Sheets(1).Range("B1").Value = SE
Application.OnTime DateAdd("s", 1, Now), "Schaltfläche1_Klicken"
Else
If MN > 0 Then
MN = MN - 1
SE = 59
Sheets(1).Range("B1").Value = SE
Sheets(1).Range("A1").Value = MN
Application.OnTime DateAdd("s", 1, Now), "Schaltfläche1_Klicken"
Else
Range("A1:L30").Value = ""
End If
End If

End Sub
Kommentar von daCypher ,

Andere Variante, die für dich aber wahrscheinlich eher uninteressant sein wird:

Ich hab mir irgendwann mal den Spaß gemacht, und Snake in Excel programmiert. Leider finde ich die xls nicht mehr. Jedenfalls hab ich da soweit ich weiß diese beiden Libs verwendet:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds as Long)

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Integer) As Integer

Mit Sleep kannst du angeben, wieviele Millisekunden die Anwendung pausieren soll. Mit GetAsyncKeyState kannst du einzelne Tasten abfragen, ob sie grade gedrückt sind. Bei meinem Snake-Programm hab ich damit halt die Cursor-Tasten und die ESC-Taste abgefragt. Alles andere war zur Laufzeit nicht bedienbar.

Kommentar von AntwortHunter ,

DANKE!

Mein Makro sieht jetzt so aus(das mit dem kernal32 hab ich schon mal im Internet gesehen und habs ausprobiert. Konnte nichts verändern damit)

Sub Schaltfläche1_Klicken()

Dim SE As Integer
Dim MN As Integer

SE = Sheets("Eigene Flotte").Range("O26").Value
MN = Sheets("Eigene Flotte").Range("N26").Value
If SE > 0 Then
SE = SE - 1
Sheets("Eigene Flotte").Range("O26").Value = SE
Else
If MN > 0 Then
MN = MN - 1
SE = 59
Sheets("Eigene Flotte").Range("O28").Value = SE
Sheets("Eigene Flotte").Range("N26").Value = MN
Else
Sheets("Eigene Flotte").Select
Range("A1:L30").Value = ""
Exit Sub
End If
End If
Application.OnTime Now + TimeValue("00:00:1"), "Schaltfläche1_Klicken"
End Sub
Kommentar von daCypher ,

Bitte :)

Bei deiner Version könnte es Probleme geben, weil die Funktion auch nach Ablauf der Zeit immer wieder neu aufgerufen wird. Ansonsten sieht das aber gut aus.

Kommentar von AntwortHunter ,

Nein, nachdem das Spielfeld geleert wurde wird doch Exit Sub aufgerufen und beendet das Makro.

Kommentar von daCypher ,

Achso, das ist mir gar nicht aufgefallen. Ja, dann passt es.

Expertenantwort
von Suboptimierer, Community-Experte für Excel, 8

Das einfachste wäre es, beim Start des Spiels die Uhrzeit festzuhalten und nach jeder (relevanten) Aktion zu prüfen, ob die neue, aktuelle Uhrzeit über dem Limit liegt.

Der Vorteil ist, dass kein paralleler Thread laufen muss (Ich bin mir nicht einmal sicher, ob VBA das überhaupt kann).
Eventuell kommt doch das OnTimer-Ereignis, welches IamIam vorgeschlagen hat, für dich infrage. Wenn Spielzeit rum, wird der Timer ausgelöst.

Der Nachteil meines Vorschlags ist, dass eben nicht automatisch eine Meldung kommt, wenn die Zeit rum ist, sondern erst, wenn man probiert, die nächste Aktion durchzuführen.

Expertenantwort
von Iamiam, Community-Experte für Excel, 35

Es gibt zwar den Befehl

NeuZeit = Now + Frequenz
Application.OnTime NeuZeit, "xBlinkmakro"

Wobei Frequenz die Wartezeit ist und xBlinkmakro der Ort, in dem der Befehl steht, so dass es sich im Abstand von Frequenz selber immer wieder aufruft, aber das blockiert xl -wenn auch nicht völlig, so doch-unverschämt stark.

Besser ist es wohl, Du schreibst den aktuellen Wert Now immer wieder neben die Aktionszelle, wo Du auch die Auswahl für die Ziele tätigst (vermutlich ja als fortlaufende Liste, zur Vereinfachung Spieler A und B in der gleichen Zeile. Du kannst dann in einer weiteren Spalte immer wieder die Differenz zur Eingabe von Mitspieler (also Deine verbrauchte Bedenkzeit) bilden und die von einer Zwischensummenzelle sofort abziehen - soviel als allgemeine Anweisung, ich mag jetzt Deine speziellen Gegebenheiten nicht nachvollziehen.

Sowas kannst Du sowohl auf Deinem wie auch auf dem Blatt des Mitspielers anlegen oder auf einem gemeinsamen dritten Blattl, so dass keiner die Schiffe des anderen sieht.

Frag ggf zurück!

Kommentar von AntwortHunter ,

Sorry, ich kapier nicht ganz, wie du das meinst. Ich habe ein Spielfeld mit den Schiffen von Zelle A1 bis L30. Dort platziert man seine eigenen Schiffe indem man die zugehörige Nummer einträgt. Danach Wechselt der erste Spieler auf ein anderes Arbeitsblatt, in dem er einträgt, ob in der Zelle, auf die er feuert ein Schiff war oder nicht. Wenn ein Schiff getroffen wurde, muss der Gegenüber das entsprechende Schiff gegen ein x austauschen. Der Timer soll dafür sorgen, dass das Komplette Spiel z.B. 10 Minuten dauern soll. Danach soll er die eigene Flotte löschen und auf das Blatt der Feindlichen Flotte wechseln, wo man schauen kann, ob man mehr Schiffe als der Gegner versenkt hat. Die Zeit stellt man über die beiden Zellen ein, die vom makro ausgelesen werden.

Kommentar von Iamiam ,

Ah, ich dachte, JEDER hat eine begrenzte Zeit -so wie beim Blitzschach- wäre das nicht sinnvoller? Aber eine Gesamtzeit vereinfacht wahrscheinlich das Verfahren!

Ausserdem bin ich davon ausgegangen, dass jeder im eigenen Blatt eine Liste seiner eigenen Schüsse und auch eine Liste der Schüsse seines Gegners hat, zusätzlich zum x im Feld.

Muss ich nochmal nachdenken (aber erst heit nacht oder morgen), ich glaube, ich hatte da schon mal was!

Kommentar von AntwortHunter ,

Ok, danke schon mal für die Hilfe :)

Kommentar von Iamiam ,

ich hab das jetzt zwar gefuden, muss es aber aus einem anderen Kontext
herauslösen und selbst erst wieder verstehen! (sind für mich keine
Standardbefehle!)
Hab die Vorlage dafür gda gefunden:

erstellt von HajoZiplies@web.de *
'* http://Hajo-Excel.de/

-falls ich das nicht in Kürze hinkriege!

Kommentar von Iamiam ,

sehe gerade, dass daCypher Dein Problem schon gelöst hat

Expertenantwort
von Ninombre, Community-Experte für Excel, 35

auf was soll das Makro warten? Wenn es nach einer Eingabe erst weitergehen soll, dann kannst Du das Makro nach dem SE=59 beenden und den restlichen Ablauf mit einem worksheet_change o.ä. starten.

Kommentar von AntwortHunter ,

Danke für die schnelle antwort. Das makro soll einfach herunterzählen im Sekundentakt und nachdem MN und SE beide 0 erreicht haben einfach das Spielfeld der Eigenen Flotte leeren, weil es zählt, wie viele teile von Schiffen versenkt wurden. Das trägt man auf nem anderen Arbeitsblatt ein.

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten