Ich bekomme das Coding von snb so schnell nicht zum laufen, da muss man wieder erst alles umbauen und deklarieren.
Probiere ich dann später noch einmal.
Der umgebaute Code von mir sollte aber bei Dir unbedingt funktionieren, denn dieser läuft bei mir in der von Dir oben geposteten Datei ohne Probleme durch. Und nochmal und nochmal und nochmal ...
Der entspricht genau Deinem Coding, nur etwas 'thematisch' getrennt.
Wenn das also ein wirkliches Projekt ist, dann würde ich eher objektorientiert vorgehen und eine Klasse dafür erstellen.
(Array geht zwar auch, ist aber aus meiner Sicht später nicht mehr so schön lesbar/änderbar/erweiterbar.)
Dann zuerst die Eigenschaften aller Buttons ermitteln/festlegen und in der Collection wegschreiben.
Zum Schluss in einem Rutsch die Button löschen und neu erstellen.
Der Vorteil wäre, dass alles lesbar ist der Code bis zum löschen und neu erstellen debugbar bleibt.
08.02.2018, 08:56 (Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2018, 08:56 von BoskoBiati.)
Hi Carsten,
ich habe es auf einem anderen Rechner laufen lassen, funktioniert. Was in Einzelfällen passiert ist, dass statt 9 auf einmal 10 blaue Felder erstellt werden, warum konnte ich noch nicht nachvollziehen.
Fehler gefunden:
Code:
Select Case InStr(myValues, Format(i, "00"))
Zitat:Wenn das also ein wirkliches Projekt ist, dann würde ich eher objektorientiert vorgehen und eine Klasse dafür erstellen.
Das übersteigt meine eher Anfängerkenntnisse.
Gruß
Edgar
Meine Antworten sind freiwillig und ohne Gewähr!
Über Rückmeldungen würde ich mich freuen.
08.02.2018, 09:07 (Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2018, 09:07 von snb.)
Da konnte noch etwas verbessert werden:
Code:
Private Sub worksheet_BeforeDoubleClick(ByVal Target As Range, cancel As Boolean)
If Target.Address <> "$M$2" Then Exit Sub
cancel = True
With Tabelle1
If .Shapes.Count = 0 Then
For j = 0 To 59
With .OLEObjects.Add("Forms.CommandButton.1")
.Name = "C_" & Format(jj, "00")
.Height = 60
.Width = 68.25
.Top = 30 + .Height * (j \ 6)
.Left = 259 + (j Mod 6) * (.Width + 0.75)
Tabelle1.Cells(1) = .Object.BackColor
End With
Next
End If
sn = Tabelle2.Cells(1).CurrentRegion
y = Abs(Int(6 * Rnd() - 0.01)) + 1
For j = 1 To UBound(sn)
If sn(j, y) = "" Then Exit For
Next
For jj = 0 To 59
With .OLEObjects("C_" & Format(jj, "00")).Object
.Caption = sn(Abs(Int((j - 2) * Rnd() - 0.01)) + 2, y)
.BackColor = RGB(200, 200, 200)
.ForeColor = RGB(0, 0, 0)
End With
Next
For j = 1 To 14
With .OLEObjects("C_" & Format(sp(j, 1), "00")).Object
.BackColor = IIf(sp(j, 1) < 27, RGB(0, 0, 255), IIf(sp(j, 1) < 38, RGB(200, 100, 0), RGB(100, 100, 100)))
If sp(j, 1) < 27 Then .ForeColor = RGB(255, 255, 255)
End With
Next
End With
End Sub
Eben nochmal geschaut:
Dies wird ja auch nirgendwo begrenzt. Es werden derzeit 14 Zufallszahlen zwischen 1 und 61 erzeugt.
Rein theoretisch könnte es im Moment auch 14 blaue geben, wenn alle 14 Zufallszahlen kleiner 27 sind.
Wenn man Deine Bedingungen kennen würde, dann könnte man die Erzeugung der Zufallszahlen auch etwas besser angehen.
Zum Beispiel könnte man prüfen, dass es nur maximal 9 Zahlen kleiner als 27 geben darf. Oder was auch immer
Ansonsten ist mir ein Fehler bei meinen Änderungen aufgefallen:
Bitte ersetze in der Sub CreateMyButton die Zeile Case 28 To 38 durch Case 27 To 37.
Dies entspricht Deinem ersten Coding, ändert aber am eben angesprochenem Problem nichts.
Ja, stimmt. Da habe ich verschlimmbessert.
Richtig wäre:
Code:
Select Case i
Frage:
Gibt es eine weitere Regel für die Anzahl der farbigen Button?
@snb:
Habe deine Datei angeschaut, interessantes Coding wie immer. ;)
Aber leider immer mit Laufzeitfehler 1004-Element nicht gefunden und falscher Aufbau.
08.02.2018, 09:57 (Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2018, 09:57 von BoskoBiati.)
Hi,
die Beschränkung ist da. Mit Instr wird ja nur die Stelle gesucht, an der die Zahl im Array steht. Es wird als der CB mit der aktuellen Nummer gefärbt, wenn diese im Array vorkommt. Problem war, dass Zahlen kleiner 10 durchaus in größeren Zahlen weiter vorne gefunden wurden. Die Änderung des Vergleichs hat das gelöst.
Das mit Case 27 hattee ich schon geändert.
Mit Split könnte man evtl. das Array aufdröseln und die CB´s direkt ansprechen. In meinem Originalcode war das das Array arrZahlen2().
Regeln für die Farben: 9 blaue u. 4 braune Felder sowie 1 graues Feld
Gruß
Edgar
Meine Antworten sind freiwillig und ohne Gewähr!
Über Rückmeldungen würde ich mich freuen.
08.02.2018, 10:09 (Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2018, 10:09 von DbSam.)
Nochmal nachgeschaut:
Mit dem arrZahlen2() hast Du aber nichts gemacht. Es wurde gefüllt und war dann nur noch 'sinnlos' vorhanden. Es wurde nie abgefragt, deshalb habe ich es entfernt.
Ok, könntest Du mal bitte Deinen aktuellen Code posten, damit wir auf der gleichen Basis sind?
Zu Deiner Bemerkung mit Deinen Kenntnissen:
Wenn Du möchtest, dass ich Dir eine kleine Vorgabe erstelle, dann solltest Du diese problemlos verstehen und erweitern können.
Vermute ich mal so ...
Einschränkung vorweg, obwohl interessant:
Ich habe aber heute nicht mehr sehr viel Zeit, erst am späten Abend wieder.
08.02.2018, 10:17 (Dieser Beitrag wurde zuletzt bearbeitet: 08.02.2018, 10:19 von snb.)
Es geht primär um die Programmierungvorstöße; nich um Exakte 'Lösung'.
- analyse von Programmierstufen
- 'richtige' bau der Code
- Vermeidung verbundener Zellen
- Minimierung der Arbeitsblattinteraktion (keine ExcelFormeln wo VBA reicht)
Man sollte fähig sein die Code nur ein wenig an zu passen an den exakte Bedingungen/Wünsche (wie lernt man anders ??).
Es scheint mir etwas aufwändig/doof immer die Oleobjects neu zu gestalten wenn die immer in identischen Stellen stehen sollten.
DoppelKlicke mal verschiedene Male in M2
Noch etwas näher zur 'Lösung':
Code:
Private Sub worksheet_BeforeDoubleClick(ByVal Target As Range, cancel As Boolean)
If Target.Address <> "$M$2" Then Exit Sub
cancel = True
With Tabelle1
If .Shapes.Count = 0 Then
sn = Array(0, 5, 11, 18, 26, 35, 43, 50, 56, 61, 70)
For j = 0 To 60
y = Application.Match(j, sn, 1) - 1
With .OLEObjects.Add("Forms.CommandButton.1")
.Name = "C_" & Format(j, "00")
.Height = 60
.Width = 68.25
.Top = 30 + .Height * y
.Left = 259 - IIf(y < 5, y, 8 - y) * (.Width + 0.75) / 2 + (j - sn(y)) * (.Width + 0.75)
End With
Next
End If
sn = Tabelle2.Cells(1).CurrentRegion
y = Abs(Int(6 * Rnd() - 0.01)) + 1
For j = 1 To UBound(sn)
If sn(j, y) = "" Then Exit For
Next
For jj = 0 To 60
With .OLEObjects("C_" & Format(jj, "00")).Object
.Caption = sn(Abs(Int((j - 2) * Rnd() - 0.01)) + 2, y)
.BackColor = RGB(200, 200, 200)
.ForeColor = RGB(0, 0, 0)
End With
Next
For j = 1 To 14
With .OLEObjects("C_" & Format(sp(j, 1), "00")).Object
.BackColor = IIf(sp(j, 1) < 27, RGB(0, 0, 255), IIf(sp(j, 1) < 38, RGB(200, 100, 0), RGB(100, 100, 100)))
If sp(j, 1) < 27 Then .ForeColor = RGB(255, 255, 255)
End With
Next
End With
End Sub
Du hast recht. Das stammte aus einem vorhergehenden Code, bei dem ich anders vorgegangen bin.
Aktuell sieht mein Code so aus:
Code:
Sub test()
Dim loA As Long
Dim loB As Long
Dim lozahl As Long
Dim loZahl2 As Long
Dim loC As Long
Dim CB(61)
Dim strB As String
Dim strName As String
Dim arrZahlen, arrZahlen2(13)
With Sheets("Tabelle2")
On Error Resume Next
Application.ScreenUpdating = False
.Shapes.SelectAll
Selection.Delete
On Error GoTo Fehler
Do
Randomize
loC = Application.WorksheetFunction.RandBetween(1, 61)
If InStr(arrZahlen, loC) = 0 Then
arrZahlen = Format(loC, "00") & "," & arrZahlen 'Zufallszahlen in ein mit Leerzeichen getrennt in ein Array schreiben
arrZahlen2(loB) = loC
loB = loB + 1
End If
Loop While loB < 14
.Cells(1, 2).FormulaLocal = "=INDEX(Liste!1:1;ZUFALLSBEREICH(0;5)*2+1)"
.Cells(1, 2).Value = .Cells(1, 2).Value
For loA = 1 To 61
.Cells(1, 1).FormulaLocal = "=SVERWEIS(ZUFALLSBEREICH(1;200);INDEX(Liste!$1:$1;VERGLEICH($B$1;Liste!$1:$1;0)):INDEX(Liste!$26:$26;VERGLEICH($b$1;Liste!$1:$1;0)+1);2;1)"
strName = .Cells(1, 1)
Set CB(loA) = .OLEObjects.Add("Forms.CommandButton.1") 'Button einfügen
CB(loA).Object.Caption = strName
CB(loA).Height = 60
CB(loA).Width = 68.25
strB = Format(loA, "00")
If InStr(arrZahlen, strB) <> 0 Then
'----------------------
If InStr(arrZahlen, Format(loA, "00")) < 26 Then
CB(loA).Object.BackColor = RGB(0, 0, 255)
CB(loA).Object.ForeColor = RGB(255, 255, 255)
ElseIf InStr(arrZahlen, Format(loA, "00")) < 38 And InStr(arrZahlen, loA) > 27 Then
CB(loA).Object.BackColor = RGB(200, 100, 0)
Else
CB(loA).Object.BackColor = RGB(100, 100, 100)
End If
End If
' -------------------------------
If loA < 6 Then
CB(loA).Top = 30
CB(loA).Left = 259 + (loA - 1) * 69
ElseIf loA < 12 Then
CB(loA).Top = 90
CB(loA).Left = 259 + (loA - 6) * 69 - 34
ElseIf loA < 19 Then
CB(loA).Top = 150
CB(loA).Left = 259 + (loA - 13) * 69
ElseIf loA < 27 Then
CB(loA).Top = 210
CB(loA).Left = 259 + (loA - 20) * 69
ElseIf loA < 36 Then
CB(loA).Top = 270
CB(loA).Left = 259 + (loA - 29) * 69
ElseIf loA < 44 Then
CB(loA).Top = 330
CB(loA).Left = 259 + (loA - 37) * 69 - 34
ElseIf loA < 51 Then
CB(loA).Top = 390
CB(loA).Left = 259 + (loA - 45) * 69
ElseIf loA < 57 Then
CB(loA).Top = 450
CB(loA).Left = 259 + (loA - 51) * 68.25 - 34
Else
CB(loA).Top = 510
CB(loA).Left = 259 + (loA - 57) * 68.25
End If
Next
.Range("a1").Clear
.Range("B2") = "Doppelklick hier!"
End With
Application.ScreenUpdating = True
Exit Sub
Fehler: MsgBox (Err.Number & " " & Err.Description & "--> Button " & loA & " " & strName & " " & arrZahlen)
End Sub
Und bei Deinen habe ich die beiden bearbeitet:
Code:
Private Function CreateMyValues() As String
On Error GoTo Er
Dim i As Integer
Dim loC As Long
Dim myValues As String
Do
Randomize
loC = Application.WorksheetFunction.RandBetween(1, 61)
If InStr(myValues, loC) = 0 Then
myValues = Format(loC, "00") & "," & myValues
i = i + 1
End If
Loop While i < 14
CreateMyValues = myValues
Ex:
Exit Function
Er:
MsgBox Err.Number & vbNewLine & Err.Description, vbCritical, "Sub CreateMyValues"
Resume Ex
End Function
Private Sub CreateMyButton(ByVal sh As Worksheet, ByVal strCaption As String, ByVal myValues As String, ByVal i As Integer)
On Error GoTo Er
Dim o As Object
Set o = sh.OLEObjects.Add(ClassType:="Forms.Commandbutton.1", Width:=68.25, Height:=60)
If o Is Nothing Then Exit Sub
With o
.Object.Caption = strCaption
If InStr(myValues, Format(i, "00")) <> 0 Then
Select Case InStr(myValues, Format(i, "00"))
Case Is < 27
.Object.BackColor = RGB(0, 0, 255)
.Object.ForeColor = RGB(255, 255, 255)
Case 27 To 38
.Object.BackColor = RGB(200, 100, 0)
Case Else
.Object.BackColor = RGB(100, 100, 100)
End Select
End If
End With
ArrangeMyObject o, i
Ex:
Set o = Nothing
Exit Sub
Er:
MsgBox Err.Number & vbNewLine & Err.Description, vbCritical, "Sub CreateMyButton"
Resume Ex
End Sub
Was meine Kenntnisse betrifft, mit Klassen kann ich nichts anfangen, ansonsten verstehe ich Deine Codes und auch die von snb, ich bin auch in der Lage diese abzuwandeln.
Theoretisch habe ich heute auch kaum Zeit noch was zu machen.
Gruß
Edgar
Meine Antworten sind freiwillig und ohne Gewähr!
Über Rückmeldungen würde ich mich freuen.
Ja, mit dem aktuellen Hintergrundwissen von Edgars Problem: Man muss diese nicht immer neu erstellen.
Im Gegenteil, wenn diese einen eindeutigen Name besitzen, dann kann man diese gezielt ansprechen und dann deren Eigenschaften anpassen. Und fertig.
Wie immer in einem solchen Forum bekommt man aber als Helfender alle Details erst nach und nach zur Kenntnis.
Manche Lösungsvorschläge sind daher manchmal zuerst suboptimal.
Zumal hier die Frage nach dem Fehler beim Erstellen der Buttons lag. Das lockt einen, zumindest mich diesmal, auf die falsche Spur.
Zu Deinem Beispiel:
Ich bin bis gerade eben davon ausgegangen, dass eine hochgeladene Beispielmappe auch funktioniert. Sonst wäre diese kein Beispiel. ;)
Wenn diese aber gewollt nicht funktioniert und 'nur' zur Veranschaulichung des Weges dient, dann schau ich mir Deinen Code sehr gern mit diesem Blickwinkel genauer an. :)
@boskobiati:
Danke für den aktuellen Stand, dann machen wir bis heute Abend halt erst einmal eine Pause.