ne kombination aus deinen beiden lösungsansätzen wäre ideal
Dafür hab ich eigentlich 2 Abfragen eingebaut, damit das nicht passiert. Hast du Antwort 11 umgesetzt?
ne kombination aus deinen beiden lösungsansätzen wäre ideal
Entweder alle Zahlen kommen gleich oft vor, oder alle Zahlen kommen unterschiedlich oft vor.
Hab den Code jetzt mal so umgebaut, dass für die ersten 3 Durchgänge die bisherige Variante 2 genutzt
wird und im 4. Durchgang, wenn nur noch 12 Zellen frei sind auf die Variante 1 geswitcht wird, damit nicht
nur die niedrigsten genommen werden, sondern eine Auswahl getroffen wird.
Du brauchst jetzt nur noch einmal starten um alle Zellen zu füllen!
Sub ZahlenVerteilen()
Werte = Array(2, 6, 8, 12, 16, 20, 26, 28, 30, 32, 34, 40, 42, 44)
Set Zielbereich = Range("B4:D21")
If Zielbereich.Cells.Count < UBound(Werte) Then
MsgBox "Zielbereich ist zu klein um alle Werte zu verteilen"
Exit Sub
End If
Randomize Timer
For x = 1 To Int(Zielbereich.Count / (UBound(Werte) + 1))
For w = 0 To UBound(Werte)
startzeit = Timer
timeout = False
Do
setzen = True
z = Int(Rnd * Zielbereich.Rows.Count) + 1 'Zeile berechnen
s = Int(Rnd * Zielbereich.Columns.Count) + 1 'Spalte Berechnen
If Application.WorksheetFunction.Count(Zielbereich) _
= Zielbereich.Count Then Exit Sub 'Prüfung ob noch freie Zellen vorh.
Select Case z
Case 1 To 5 'nicht 0-9 bzw. 0-9|10-19, 0-9|20-29 usw.
If Int(Werte(w) / 10) = 0 Or Int(Werte(w) / 10) = z - 1 Then setzen = False
Case 6 To 9 'nicht 10-19 bzw. 10-19|20-29, 10-19|30-39 usw.
If Int(Werte(w) / 10) = 1 Or Int(Werte(w) / 10) = z - 5 Then setzen = False
Case 10 To 12 'nicht 20-29 bzw. 20-29|30-39, 20-29|40-45
If Int(Werte(w) / 10) = 2 Or Int(Werte(w) / 10) = z - 8 Then setzen = False
Case 13 To 14 'nicht 30-39 bzw. 30-39|40-45
If Int(Werte(w) / 10) = 3 Or Int(Werte(w) / 10) = z - 10 Then setzen = False
Case 15 'nicht 40-45
If Int(Werte(w) / 10) = 4 Then setzen = False
End Select
If Application.CountIf(Zielbereich.Rows(z), Werte(w)) > 0 Then setzen = False
'wenn für 5 sek keine der gefundenen Zellen für den Wert in Frage kommt Abbruch:
If Timer >= startzeit + 5 Then timeout = True
Loop Until Zielbereich.Cells(z, s) = "" And setzen = True Or timeout
Zielbereich(z, s) = Werte(w)
Next w
Next x
Set Zielbereich2 = Zielbereich.SpecialCells(xlCellTypeBlanks)
For Each c In Zielbereich2.Cells
z = c.Row - Zielbereich.Row + 1
s = c.Column - Zielbereich.Column + 1
startzeit = Timer
timeout = False
Do
setzen = True
w = Int(Rnd * UBound(Werte))
Select Case z
Case 1 To 5 'nicht 0-9 bzw. 0-9|10-19, 0-9|20-29 usw.
If Int(Werte(w) / 10) = 0 Or Int(Werte(w) / 10) = z - 1 Then setzen = False
Case 6 To 9 'nicht 10-19 bzw. 10-19|20-29, 10-19|30-39 usw.
If Int(Werte(w) / 10) = 1 Or Int(Werte(w) / 10) = z - 5 Then setzen = False
Case 10 To 12 'nicht 20-29 bzw. 20-29|30-39, 20-29|40-45
If Int(Werte(w) / 10) = 2 Or Int(Werte(w) / 10) = z - 8 Then setzen = False
Case 13 To 14 'nicht 30-39 bzw. 30-39|40-45
If Int(Werte(w) / 10) = 3 Or Int(Werte(w) / 10) = z - 10 Then setzen = False
Case 15 'nicht 40-45
If Int(Werte(w) / 10) = 4 Then setzen = False
End Select
If Application.CountIf(Zielbereich.Rows(z), Werte(w)) > 0 Then setzen = False
'wenn für 5 sek kein gültiger Wert gefunden wurde dann Abbruch
If Timer >= startzeit + 5 Then timeout = True
Loop Until setzen = True Or timeout
Zielbereich(z, s) = Werte(w)
Next c
End Sub
Um Alles nach Variante 1 zu füllen und gleichzeitig eine nur annähernd gleiche Verteilung zu erreichen, hast
du nicht genügend Zellen zur Verfügung. Würdest du jedoch tausende von Zeilen füllen, würdest du eine
gewisse Regelmäßigkeit in der Zahlenwiederholung feststellen, die sich aus der gleichmäßigen Taktrate
deiner Windows-Uhr (Timer) begründet. Leider fehlt mir das Wissen um den Code eine Gaußsche
Normalverteilung beizubringen. Ich war zwar nie schlecht in Mathe, aber studiert hab ich das Fach nicht.
Kannst ja trotzdem mal nach Variante 1 probieren.
Sub ZahlenVerteilen_Var1()
Werte = Array(2, 6, 8, 12, 16, 20, 26, 28, 30, 32, 34, 40, 42, 44)
Set Zielbereich = Range("B4:D21")
If Zielbereich.Cells.Count < UBound(Werte) Then
MsgBox "Zielbereich ist zu klein um alle Werte zu verteilen"
Exit Sub
End If
Randomize Timer
For Each c In Zielbereich.Cells
z = c.Row - Zielbereich.Row + 1
s = c.Column - Zielbereich.Column + 1
startzeit = Timer
timeout = False
Do
setzen = True
w = Int(Rnd * UBound(Werte))
Select Case z
Case 1 To 5 'nicht 0-9 bzw. 0-9|10-19, 0-9|20-29 usw.
If Int(Werte(w) / 10) = 0 Or Int(Werte(w) / 10) = z - 1 Then setzen = False
Case 6 To 9 'nicht 10-19 bzw. 10-19|20-29, 10-19|30-39 usw.
If Int(Werte(w) / 10) = 1 Or Int(Werte(w) / 10) = z - 5 Then setzen = False
Case 10 To 12 'nicht 20-29 bzw. 20-29|30-39, 20-29|40-45
If Int(Werte(w) / 10) = 2 Or Int(Werte(w) / 10) = z - 8 Then setzen = False
Case 13 To 14 'nicht 30-39 bzw. 30-39|40-45
If Int(Werte(w) / 10) = 3 Or Int(Werte(w) / 10) = z - 10 Then setzen = False
Case 15 'nicht 40-45
If Int(Werte(w) / 10) = 4 Then setzen = False
End Select
If Application.CountIf(Zielbereich.Rows(z), Werte(w)) > 0 Then setzen = False
'wenn für 5 sek kein gültiger Wert gefunden wurde dann Abbruch
If Timer >= startzeit + 5 Then timeout = True
Loop Until setzen = True Or timeout
Zielbereich(z, s) = Werte(w)
Next c
End Sub
Gruß Mr. K.