Wie kann ich zwischen 6 und 15 Zufallszahlen zwischen 1 und 49 generieren? Die Zahlen sollen auf dem Blatt Tab1 in der Zeile 1 ab A1 stehen. Keine Zahl darf sich wiederholen.
Dazu gibt es verschiedene Möglichkeiten.
Direkt in Zellen eintragen
In der ersten Variante erfolgt die Arbeit direkt an den Zellen, weil hier die Funktionen Finden und Sortieren von Excel genutzt werden. Funktionen, die Excel zur Verfügung stellt, sind i. d. R. recht schnell, so dass das in diesem Fall sicher die kürzere und schnellere Variante ist:
Sub Zufall()
Dim intWert As Integer, varWieviele, intI As Integer
Dim bolVorhanden As Boolean, rngGef As Range
varWieviele = InputBox("Wieviele Zahlen sollen erzeugt werden?", "Anzahl", 6)
If Not IsNumeric(varWieviele) Then Exit Sub
If varWieviele > 15 Then Exit Sub
Sheets("Tab1").Range("A1:O1").ClearContents
For intI = 1 To varWieviele
intWert = Int((49 * Rnd) + 1)
If intI = 1 Then
Sheets("Tab1").Cells(1, intI) = intWert
Else
Do
bolVorhanden = False
Set rngGef = Range(Cells(1, 1), Cells(1, intI - 1)).Find(intWert)
If Not rngGef Is Nothing Then
bolVorhanden = True
intWert = Int((49 * Rnd) + 1)
End If
Loop While bolVorhanden = True
Sheets("Tab1").Cells(1, intI) = intWert
End If
Next
Sheets("Tab1").Range("A1:O1").Sort Key1:=Sheets("Tab1").Range("A1"), Order1:=xlAscending, Orientation:=xlLeftToRight
End Sub
Kern des Codes ist eine Schleife, die so lange läuft, wie eine Zufallszahl nicht mehr in den bisherigen Zufallszahlen gefunden wird. Erst dann wird sie als neue Zufallszahl verwendet.
Weiteres Beispiel - Schleife statt Find:
Sub Zufall()
Dim intAnzahl As Integer, intMax As Integer, intMin As Integer
Dim intWert As Integer, intI As Integer, intN As Integer
Dim bolVorhanden As Boolean
intAnzahl = 10
intMax = 49
intMin = 1
'alte Zahlen löschen
Range(Cells(1, 2), Cells(intAnzahl, 2)).ClearContents
Cells(1, 2) = Int((intMax * Rnd) + intMin) '1. Zahl erzeugen
For intI = 2 To intAnzahl 'nächste Zahlen erzeugen
Do
bolVorhanden = False
intWert = Int((intMax * Rnd) + intMin)
For intN = 1 To intI 'Kontrolle ob schon vorhanden
If Cells(intN, 2) = intWert Then
bolVorhanden = True
Exit For
End If
Next
Loop While bolVorhanden = True
Cells(intI, 2) = intWert 'Zahl eintragen
Next
End Sub
Erst Array, zum Schluss in Zellen
Manchmal kann die Arbeit mit Zellen aber auch von Nachteil sein. Deshalb ist hier der Vollständigkeit halber noch ein Beispiel, in dem Herangehensweisen mit einem Array aufgezeigt werden:
Sub Zufall1()
Dim intWert As Integer, intI As Integer, intN As Integer, varWieviele
Dim bolVorhanden As Boolean, bolSortiert As Boolean
Dim arrZahlen()
varWieviele = InputBox("Wieviele Zahlen sollen erzeugt werden?", "Anzahl", 6)
If Not IsNumeric(varWieviele) Then Exit Sub
If varWieviele > 15 Then Exit Sub
ReDim Preserve arrZahlen(varWieviele)
For intN = 0 To varWieviele - 1
intWert = Int((49 * Rnd) + 1)
If intN = 0 Then
arrZahlen(intN) = intWert
Else
Do
bolVorhanden = False
For intI = 0 To intN
If arrZahlen(intI) = intWert Then
bolVorhanden = True
intWert = Int((49 * Rnd) + 1)
Exit For
End If
Next
Loop While bolVorhanden = True
arrZahlen(intN) = intWert
End If
Next
Do
bolSortiert = True
For intN = 0 To varWieviele - 2
If arrZahlen(intN + 1) < arrZahlen(intN) Then
bolSortiert = False
intWert = arrZahlen(intN + 1)
arrZahlen(intN + 1) = arrZahlen(intN)
arrZahlen(intN) = intWert
End If
Next
Loop While bolSortiert = False
Sheets("Tab1").Range("A1:O1").ClearContents
For intN = 0 To varWieviele - 1
Sheets("Tab1").Cells(1, intN + 1) = arrZahlen(intN)
Next
End Sub
Das gesamte Erstellen der Zufallszahlen - bis hin zum Sortieren - erfolgt zunächst in einem Array. Auch hier erfolgt die Prüfung auf Doppelungen. Aber es ist zu sehen, dass dafür eine weitere Schleife eingebaut ist. Eine Funktion wie in PHP in_array() wäre da natürlich günstiger.
Auch zum Sortieren wird die innere Schleife so lange durchlaufen, bis im Array das nächste Element nicht kleiner als das gerade durchlaufene Element ist.
Erst ganz zum Schluss wird der fertige Array in die Zellen übernommen.
Die zweite Variante hat den Vorteil, dass sie beliebig - und unabhängig von Zellen - eingesetzt werden kann. Sie kann auch als eigenständige Funktion erstellt werden, die dann den Array mit den Zufallszahlen zurückgibt. So könnte die Funktion von überall aufgerufen werden; in die Zellen würde dann das Ergebnis eingetragen.
Oft stö�t man bei Schleifen, die Zellen lesen und schreiben, auf das Problem, dass die Laufzeit enorm steigt. Deshalb sollte zumindest in Betracht gezogen werden, das Ganze mit Arrays zu erledigen und die Zellzugriffe auf ein Minimum zu beschränken.
Dynamische Arrayformel mit Matrixfunktion (ab Excel 365)
Natürlich kann das auch als Matrixfunktion für eine dynamische Arrayformel erstellt werden. Die Funktion erstellt einen Array mit eindeutigen Zahlen. Zum Schluss wird mit der Arrayfunktion SORTIEREN() sortiert und der Array ausgegeben.
Function Zufallszahlen_Eindeutig(ByVal intAnzahl As Integer, ByVal intMin As Integer, ByVal intMax As Integer)
Dim intWert As Integer, intI As Integer, intN As Integer
Dim bolVorhanden As Boolean, arrZahlen()
Application.Volatile
ReDim Preserve arrZahlen(1 To intAnzahl)
For intN = 1 To intAnzahl
intWert = Int((intMax * Rnd) + intMin)
If intN = 1 Then
arrZahlen(intN) = intWert
Else
Do
bolVorhanden = False
For intI = 1 To intN
If arrZahlen(intI) = intWert Then
bolVorhanden = True
intWert = Int((intMax * Rnd) + intMin)
Exit For
End If
Next
Loop While bolVorhanden = True
arrZahlen(intN) = intWert
End If
Next
Zufallszahlen_Eindeutig = Application.WorksheetFunction.Sort(arrZahlen, 1, 1, 1)
End Function
In die Zelle kommt einfach:
=Zufallszahlen_Eindeutig(Anzahl;Minimum;Maximum)
=Zufallszahlen_Eindeutig(5;1;49)
Sollen die Zahlen untereinander erscheinen, kann die Funktion in MTRANS() gesetzt werden:
=MTRANS(Zufallszahlen_Eindeutig(5;1;49))
Die Funktion ZUFALLSMATRIX() klingt danach, als ob sie die Aufgabe auch erfüllen könnte. Jedoch hat sie bei dieser Aufgabenstellung den gro�en Nachteil, dass sie sehr häufig mehrfach vorhandene Zahlen erzeugt. Das hei�t, dass man so oft berechnen lassen müsste, bis jede Zahl eindeutig ist - und das kann etwas dauern.
Apropos eindeutig: Mit der Funktion EINDEUTIG() könnte natürlich geprüft werden, ob eindeutige Zufallszahlen vorliegen. Allerdings ist die Funktion manchmal schneller als die Sortieren-Funktion, so dass letztere Funktion noch rechnet, wenn EINDEUTIG() schon fertig ist. Das führt dann zum bekannten Fehler �BERLAUF.