VBA Zufallsziehung

Hallo Zusammen,

also ich bin kein VBA (Excel 2010) Profi daher meine Frage.

Ich bräuchte ein Makro, dass mir aus dem ersten Tabellenblatt zufällig einen Namen zieht und mir diesen im Tabellenblatt 2 in A1 schreibt. Beim nächsten klicken würde das Makro noch einen Namen ziehen und in A2 schreiben usw. Wichtig hierbei wäre das ein gezogener name nicht nochmal gezogen wird (kein name kommt doppelt) vor. Das i Tüpfelchen wäre wenn man z.B ein Sichtfenster hätte indem man die Namen durchlaufen und es bei dem gezogenen Namen stehen bleibt : )…
Ich hoffe die experten sind nicht überfordert : )bin wie gesagt VBA neuling

Tag,

also ermittele die Anzahl der Zeilen im Blatt2:

iAnzahl = activeworkbook.worksheets(„Blatt2“).Rows.count

Dann eine Zeile per Zufall bestimmen:

iZeile = 1 + (zufallszahl() * iAnzahl)

Der Name holen:

sName = activeworkbook.worksheets(„Blatt2“).range(„A“&iZeile)

Anzeigen im Blatt1:

activeworkbook.worksheets(„Blatt2“).range(„A1“) = sName

OK?

MfG
Pete

Hallo judoka,

Ich hab mal schnell was zusammengebastelt. Da du mir nicht gesagt hast, wo die namen auf dem sheet(1) stehen habe ich das einfach etwas anders gelöst.

Schritt 1:
Erstelle ein neues Klassenmodul mit dem Namen „clsPerson“ und folgendendem Code:


Option Explicit
Private m_strName As String

Public Property Get Name() As String

Name = m_strName

End Property

Public Property Let Name(ByVal strName As String)

m_strName = strName

End Property

2.Schritt: Erstelle ein Modul mit dem Namen „modZufall“ mit folgendem Code


Option Explicit

Sub Zufallsnamen()
Dim oPerson As clsPerson
Dim colPersonen As New Collection

Set oPerson = New clsPerson
oPerson.Name = „Peter“
colPersonen.Add oPerson

Set oPerson = New clsPerson
oPerson.Name = „Hans“
colPersonen.Add oPerson

Set oPerson = New clsPerson
oPerson.Name = „Klaus“
colPersonen.Add oPerson

Set oPerson = New clsPerson
oPerson.Name = „Gregor“
colPersonen.Add oPerson

Set oPerson = New clsPerson
oPerson.Name = „Kilian“
colPersonen.Add oPerson

'*****************************
'Nach dem Schema weitere Namen einfügen
'*****************************

'---------------------------
'Zufallsgenerator

Dim intAnzahl As Integer
Dim intZufallszahl As Integer
intAnzahl = colPersonen.Count

Do Until intAnzahl = 1
intAnzahl = colPersonen.Count 'Anzahl der Restpersonen
intZufallszahl = Int((intAnzahl - 1 + 1) * Rnd + 1) 'Zufallszahl ermitteln

Sheets(2).Cells(1, 1).Value = colPersonen.Item(intZufallszahl).Name 'Namen ausgeben

MsgBox "Zufallsname: " & colPersonen.Item(intZufallszahl).Name & Chr(13) & Chr(13) & „Nächster Name…“

colPersonen.Remove (intZufallszahl) 'Namen aus Liste entfernen
Loop
End sub


3.Schritt: Nach dem angegebenen Schema fügst du alle Namen ein, die du Zufällig auswählen willst

4.Schritt: Makro starten und die Zufallsperson wird in einer Msgbox ausgegeben, sowie in Sheet2!A1 geschrieben. Bei OK wird der nächste Name ausgegeben, bis alle durch sind.

Liebe Grüße und viel Spaß damit

Feedback erwünscht
OVM

Rückfragen sind nötig
Hi m.,
auch ein VBA-Neuling sollte Fragen so formulieren,
dass sie vielleicht beantwortet werden können.

Aus dem ersten Tabellenblatt soll ein Name gezogen werden.
Aha - auf dem ersten Tabellenblatt stehen also Namen.
Wo genau tun sie das dort? Vielleicht in Spalte A?
Ab Zeile 1 oder Zeile 2 (wenn in Zeile 1 eine Spaltenüberschrift steht)?

„Beim nächsten klicken …“
Aha - das soll bei einem Klicken passieren.
Was genau meinst du damit?
Auf welchem Blatt soll wohin geklickt werden,
um die nächste Ziehung auszulösen?

Und wie kommst du aus der Geschichte je wieder raus?
Bei jedem Klick wird ja neu ausgelost…
Du kannst z. B. die gezogenen Namen in Spalte nicht löschen.
Wenn du dahin klickst, wird nicht etwa eine Zelle zum Löschen ausgewählt,
stattdessen wird nur unten noch ein Eintrag angehängt. :frowning:

Könnte auch die Ausgabezelle als „Sichtfenster“ fungieren?
Mit VBA könnte man den Zellwert „laufen lassen“.

Was spräche eigentlich dagegen, die Auswahl ohne VBA in Excel zu erledigen?
Schau mal z. B. hier:
http://www.excelformeln.de/formeln.html?welcher=152
Mit INDEX könnte man anhand der gezogenen Zahlen die Namen anzeigen.

Rückmeldung wäre nett! - Grüße aus Kamp-Lintfort von Erich

Ich gehe davon aus, dass deine Namen in Tabelle1 in Spalte A untereinander stehen ohne Leerzeilen dazwischen!
Erzeuge noch eine neue Tabelle „Abgelegt“
Dann hier der Code:

Option Explicit
'##################################
Function Zufall(Obergrenze)
Zufall = Int(Obergrenze \* Rnd + 1)
End Function
'##################################
Function Last\_Row(Tabelle, Spalte)
Dim I As Long
Dim SpalteNr As Long
Dim CheckCell As String
Dim Dummy As String
Spalte = UCase(Spalte)
SpalteNr = Asc(Spalte) - 64

For I = 1 To 65535
 CheckCell = Application.Sheets(Tabelle).Cells(I, SpalteNr)
 If CheckCell = Empty Then
 Last\_Row = I - 1
 I = 65535
 End If
Next I
End Function
'##################################
Sub Button\_Zufall()
Dim ZufallsZahl As Long
Dim AnzahlNamen As Long
Dim AnzahlTreffer As Long
Dim AnzahlBestimmt As Long

Dim I As Long
Dim Gefunden As Boolean

AnzahlNamen = Last\_Row("Tabelle1", "A")
AnzahlTreffer = Last\_Row("Abgelegt", "A")
If AnzahlTreffer 
Den musst du in ein Modul schreiben.
Und Sub Button\_Zufall() mit einem Button verbinden. Willst Du die Sache mehrfach benutzen, musst du einen 2. Button mit NeuStart() verbinden
Ich habe die Ausgabe zur Vereinfachung mit MsgBoxes gemacht, man kann den Wert auch in eine Textbox schreiben.
Und das mit den durchlaufenden Namen ist Shit viel Code, das mach mal schön selber. Zumal die Namen ja auch von mal zu mal weniger werden, die Walze sich erst schnell und dann immer langsamer drehen muss, ....
Viel Glück

Hallo,
das ist ein relativ simples Problem, mit dem vielleicht ein Anfänger überfordert ist, aber kein mittelmäßiger Programmierer oder gar ein Experte! Dazu Folgendes;
a) Ich mache keine Codierungen, ich gebe nur Ratschläge
b) Ich stelle gerade auf Excel2010 um, meine alten Makros laufen fast alle noch, habe aber mit Excel2010 noch nichts programmiert.
3c) Die hierfür benötigte Funktion für Zufallszahlen habe ich unter VB verwendet, sie sollte aber bei VBA auch verfügbar sein.
Also:

  1. Man kann auf jede Zelle einer Excel-Tabelle lesend und schreibend zugreifen, z.B.: [Sheets().]Cells()
    Die Qualifikation mit Sheets(…) ist optional, lässt man sie weg bezieht man sich auf die aktuell offene Tabelle.
    ist entweder:
  • ein String, z.B. „Tabelle1“
  • eine Stringvariable mit dem Namen
  • eine Nummer (nicht empfehlenswert)
    Zur Erleichterung bei der Codierung empfiehlt sich die Qualifizierung mit:
    With Sheets(…)
    .Cells(…)
    End With
    ist enweder ein String, z.B. „C5“ oder ein Zahlenpaar, z.B. Cells(5,3). Hier sollte man natürlich Variablen verwenden, also Cells(row, col). Achtung: hier ist die Reihenfolge anders als bei der Stringnotierung, erst Zeile, dann Spalte). Im Beispiel entspricht „C5“ = 5,3. Und: rows sollte vom Typ long sein, da es größer als 32767 sein kann. Man kann auf alle Eigenschaften einer Zelle zugreifen (Farbe, Schriftart, Rahmen, etc.): Cells(…)[.], der Default ist der Inhalt.
  1. Um Zufallszahlen zu generieren gibt es die Funktion Rnd (Random), die vor dem ersten Aufruf mit Randomize initialisiert werden muss, sie liefert eine Zahl 0

Hallo judoka,

der folgende VBA-Code funktioniert in Verbindung mit einer UserForm:

Option Explicit

Dim bDoSearchProcess As Boolean
Dim bNotInsertItem As Boolean

Private Sub cmdCancel_Click()
bNotInsertItem = True
VBA.DoEvents
Unload Me
End Sub

Private Sub cmdOK_Click()
If Not bDoSearchProcess Then
DoSearchProcess
Else
bDoSearchProcess = False
End If
End Sub

Sub DoSearchProcess()
’ Liest einen zufälligen Eintrag aus der Namensliste heraus
’ der noch nicht in der Ausgabeliste enthalten ist

’ Die Augabeliste ist immer in der aktuellen Tabelle in der Spalte A

Dim rngNM As Range
Dim rngOut As Range
Dim rngFound As Range
Dim sName As String
Dim lRowOut As Long
Dim lCnt As Long
Dim sLabelCMDOK As String, sLabelCMDCancel As String, sProcCaption As String
Dim lTimer As Long

Set rngNM = ActiveWorkbook.Names(„Namensliste“).RefersToRange

sLabelCMDOK = Me.cmdOK.Caption
sLabelCMDCancel = Me.cmdCancel.Caption
Me.cmdCancel.Caption = „Abbrechen“
bDoSearchProcess = True

’ Verwendeten Bereich ermitteln

Set rngOut = ActiveSheet.UsedRange
Me.Repaint
Do
lTimer = Timer
Do
sName = rngNM.Cells((Rnd(1) * rngNM.Rows.Count - 1) + 1, 1).Text
Set rngFound = rngOut.Find(sName)
If Abs(lTimer - Timer) >= 1 Then
sProcCaption = "Suche " & String(Timer * 10 Mod 7, „.“)
If Not Me.cmdOK.Caption = sProcCaption Then
Me.cmdOK.Caption = sProcCaption
Me.Repaint
End If
End If
VBA.DoEvents
Loop While Not rngFound Is Nothing And Not bNotInsertItem
lCnt = lCnt + 1
Me.lblSearchProcess.Caption = IIf(rngFound Is Nothing, sName, „–“)
Me.cmdOK.Caption = "Übernehmen - " & Format(lCnt, „#,##0“)
Me.Repaint
Loop While bDoSearchProcess And Not bNotInsertItem

If rngFound Is Nothing And Not bNotInsertItem Then

lRowOut = rngOut.Rows.Count
While rngOut.Cells(lRowOut, 1).Text „“
lRowOut = lRowOut + 1
Wend

rngOut.Cells(lRowOut, 1).Formula = sName
End If

bDoSearchProcess = False

Me.cmdOK.Caption = sLabelCMDOK
Me.cmdCancel.Caption = sLabelCMDCancel
End Sub

Private Sub UserForm_Terminate()
bNotInsertItem = True
VBA.DoEvents
End Sub

Damit das VBA-Programm fehlerfrei funktioniert, müssen folgende Voraussetzungen erfüllt sein:

  • Benannter Bereich „Namensliste“ mit allen vorhandenen Namen
  • Eine UserForm mit einer label-Control „lblSearchProcess“ und zwei CommandButton-Objekte: „cmdOK“ und „cmdCancel“

Der CommandButton „cmdOK“ sollte mit dem Caption „Start“ beschriftet werden
Der CommandButton „cmdCancel“ bricht den Suchvorgang ab und schließt die UserForm.

Eine Beispiel-Excel-Datei kann gerne via eMail zugesandt werden.

Hinweis: Das VBA-Programm wurde unter Excel 2000 erstellt. Nach meinen Kenntnissen dürften keine Fehler in Excel 2010 auftreten.

Viele Grüße,
BigBen

Hallo m.,judoka
Zufallszahlen werden in VBA mit dem Befehl generiert. Diese Zahlen sind grösser oder gleich 0 und kleiner als 1. Arbeitsblatt wechseln kannst Du mit dem Befehl . Damit ein Name nicht doppelt gezogen wird, kannst Du entweder im Tabellenblatt eine Spalte einfügen, oder im VBA-Programm eine Variable generieren, welche bezeichnet, ob ein Objekt schon mal gezogen wurde.
Mit diesem Verfahren wird ein Name gezogen, wenn Du das mehrmals durchführen willst, machst Du am besten eine Schlaufe. Die kannst Du dann auch in ein Fenster ausgeben.
Viel Erfolg!
Rolf

Hallo Big Ben,

das sieht ja schon klasse aus! Leider habe ich das mit dem Commandbutton nicht ganz verstanden. Eine Beispielsexcel wäre Prima. Meine Mailadresse lautet: [email protected]

Vorab vielen Dank für deine Mühen!

Lieben Gruß
m.judoka

HY das ist auch ne coole Lösung! Wollte jedoch eine „elegantere“, da dies präsentiert werden soll. Hatte ich an ein Makro gedacht. Trotz dem ein hilfreicher Link da ich mir auch überlegt hatte ob die per Formel möglich wär.

Vielen Dank für deine Mühe!

Lieben Gruß
m.judoka

schade, kein Feedback bekommen =(

Hi,

sorry, ich kann Dir leider nicht helfen:

  1. meine VBA - Kenntnisse beziehen sich mehr auf Access
  2. ich verstehe dein Problem / vorhaben nicht

Gruß
Karsten

Hallo,

sehe ich das richtig? in Blatt A1 stehen in irgendeiner Spalte / Zelle Namen, die in ein zweites Blatt übernommen werden sollen? Das ist sicher machbar, erfordert ein wenig Aufwand es zu codieren und zu testen.

So kann man zB in Blatt 1 beginnend, alle Namen in ein Array einlesen, zu Blatt 2 wechseln und dort, nach der Anzeige in einem Listfeld die Namen zufällig wählen. Dann den gefundenen Namen eintragen, ihn aus dem Listfeld löschen und ev. nochmal wählen lassen.

Das Ergebnis wäre dann eine umsortierte Liste der Namen aus Blatt 1, wenn man bis zur bitteren Neige weiter arbeitet.

Gruß Peter

Danke dir trotz dem : )

Vielen dank hat jetzt alles klasse geklappt : )