PDA

Vollständige Version anzeigen : Selektion durch mehrere Comboboxen


pidi6376
03.07.2014, 13:37
Hallo zusammen

Mein Problem ist folgendes, ich habe eine UF in welcher ich Daten eingebe und diese dann in die Mastertabelle übergebe, das Funktioniert auch einwandfrei.
In einer zweiten UF (Aufträge Editieren) möchte ich nun die Datensätze aus der Mastertabelle in die UF holen um sie weiter zu verarbeiten.
Nun mein Problem:
Ich wähle über 6 Comboboxen aus welche Datensätze ich sehen möchte. Die Kriterien stehen ebenfalls in der Mastertabelle in den Spalten 31 bis 36. Ich habe es fertig gebracht mit einem Kriterium (fast) aber wie stelle ich es an das alle sechs Kriterien berücksichtigt werden? Ich vermute es wäre besser den Code dann in ein separates Modul zu stellen, aber ich habe gerade wirklich keine Ahnung wie der Code aussehen sollte.
Bei einem Kriterium habe ich einfach das Problem das er mir anhand der ausgewählten Bestell Nr. den falschen Datensatz einliest sobald WAHR oder FALSCH zum zuge kommt. dort stehe ich gerade auf dem Schlauch weshalb er mir dann die Zeilen falsch zählt.

Wenn mir jemand noch sagen könnte wie ich bei diversen sehr langen Codes eine Schleife einbauen könnte damit es auch etwas angenehmer aussieht wäre ich auch sehr froh, denn mit schleifen habe ich so meine Mühe, das habe ich noch nicht so ganz geschnallt.
Da die Datei zu gross ist kann ich sie nicht hochladen und hänge deshalb den Link an.

https://drive.google.com/file/d/0Bybjwo_IquA5SVlnNG5PVmhoVG8/edit?usp=sharing

Ich hoffe ich habe meine Probleme klar beschrieben und Ihr könnt mir weiter Helfen

Gruss Peter

R J
03.07.2014, 20:52
Hi Peter,

hab Dir das mal ansatzweise angepasst.
Der Suchbutton vergleicht als erstes, ob die Checkboauswahl identisch mit den entsprechenden Spaltenwerten ist (allen) und falls ja, schreibt er die Bestellnr in die dafür vorgesehene Box (setzt aber vorraus, dass jede bestellnr tatsächlich immer nur 1 x vorhanden ist!)
Private Sub cmdSuchenMLP1_Click()
Dim zeile As Double

cboBestellNr.Clear

For zeile = 2 To Worksheets("Mastertabelle").UsedRange.Rows.Count
If chkErfasst.Value = Range("AF" & zeile) _
And chkGeplant.Value = Range("AE" & zeile) _
And chkFreigegeben.Value = Range("AG" & zeile) _
And chkMontiert.Value = Range("AH" & zeile) _
And chkGeprüft.Value = Range("AI" & zeile) _
And chkVersandfertig.Value = Range("AJ" & zeile) _
Then
cboBestellNr.AddItem (Range("E" & zeile))

End If
Next zeile

End Sub

Wenn Du jetzt die Auswahl in der Combobox änderst, sucht er nach der Bestellnr in Spalte E und ermittelt die entsprechende Zeile. Hab mal die ersten 3 TextBoxen befüllt, der Rest ist für Dich...:)
Private Sub cboBestellNr_Change()
Dim zeile&

With Worksheets("Mastertabelle").Range("E1:E" & Worksheets("Mastertabelle").Cells.SpecialCells(xlLastCell).Row)
zeile = .Find(what:=CInt(cboBestellNr.Value), lookat:=xlWhole).Row
txtKundenNr = .Cells(zeile, 1)
txtKunde = .Cells(zeile, 2)
txtLand = .Cells(zeile, 4)
'' txtBestellNr = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 5)
' txtKundenAuftragsNr = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 6)
' txtFertigungsAuftragsNr = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 7)
' txtDatumBestellung = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 8)
' txtWunschtermin = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 9)
'' txtAbholtermin = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 10)
' txtMontiertAm = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 11)
' txtGeprüftAm = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 12)
' txtVersandfertigAm = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 13)
' txtDispoAbholer = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 14)
' txtMaschinenNr = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 15)
' txtMaschinentyp = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 17)
' txtSonstiges = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 18)
' txtAnzahl = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 19)
' lblAufwandMontage_T = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 20)
' lblAufwandPrüfen_T = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 21)
' txtZusAufwandMontage = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 22)
' txtZusAufwandPrüfen = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 23)
' lblTotalMontage_T = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 24)
' lblTotalPrüfen_T = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 25)
'' txtKapazitätMontage = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 26)
'' txtKapazitätPrüfen = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 27)
' chkMehrereLose = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 28)
' txtLos = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 29)
' txtVon = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 30)
' chkGeplant = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 31)
' chkErfasst = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 32)
' chkFreigegeben = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 33)
' chkMontiert = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 34)
' chkGeprüft = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 35)
' chkVersandfertig = Worksheets("Mastertabelle").Cells(cboBestellNr.ListIndex + 2, 36)

End With
End Sub

pidi6376
04.07.2014, 07:19
Hallo

SUPER!!!
Danke dir vielmals

Nur zwei kleine Probleme damit es läuft. Werden x1LastCell und x1Whole als Range definiert?

Private Sub cboBestellNr_Change()
Dim zeile&

With Worksheets("Mastertabelle").Range("E1:E" & Worksheets("Mastertabelle").Cells.SpecialCells(x1LastCell).Row)
zeile = .Find(what:=CInt(cboBestellNr.Value), lookat:=x1Whole).Row
txtKundenNr = .Cells(zeile, 1)

aber sonst....
....Genial!!!

Ich muss noch viel lernen :-/

Gruss Peter

R J
04.07.2014, 07:33
...wie kommst Du auf x1 (sprich: ix eins)? Das heißt xl (sprich: ix ell).
Das sind keine Ranges sondern Excelkonstanten. Excel weiß dann schon, was es dann zu tun hat...

pidi6376
04.07.2014, 09:35
Toll, sorry :-(
Man sollte erst mal überlegen am morgen früh und besser lesen :-/

Jetzt habe ich aber noch folgendes Problem das mir diese Zeile Laufzeitfehler 13 bringt.


Private Sub cboBestellNr_Change()
Dim zeile&

With Worksheets("Mastertabelle").Range("E1:E" & Worksheets("Mastertabelle").Cells.SpecialCells(xlLastCell).Row)
zeile = .Find(what:=CInt(cboBestellNr.Value), lookat:=xlWhole).Row

Sorry das ich so viele Probleme habe, aber bin noch ziemlicher Anfänger in VBA :-/

R J
04.07.2014, 11:13
...den Fehler kann ich bei mir nicht reproduzieren. Makro läuft ohne Beanstandung durch.

Welchen Wert hat denn cboBestellNr.Value ? Du hast doch hoffentlich nicht die Spalten verändert?

Probeweise kannst Du aus dem CInt mal ein CLng machen, oder die Konvertierung ganz weglassen:
zeile = .Find(what:=cboBestellNr.Value, lookat:=xlWhole).Row

pidi6376
04.07.2014, 11:26
Hallo
Nein, es wurden keine Spalten verändert. Habe alle drei Versionen ausprobiert, geht alles nicht. Ganz ohne Konvertierung bringt er laufzeitfehler 91.
Der Wert der cboBestellNr.Value ist ""

Die Daten werden beim Initializieren der UF richtig eingelesen, erst wenn ich mit der Combobox Auswahl die Auswahlkriterien anpasse läufts in den Fehler

Gruss Peter

pidi6376
04.07.2014, 11:30
Hier nochmals die angepasste Datei:

https://drive.google.com/file/d/0Bybjwo_IquA5ZXAxXzVpLVJBNFU/edit?usp=sharing

R J
04.07.2014, 12:19
...smile... ist ja logisch... schau Dir mal das Click Ereignis vom Suchenbutton an. Da hast Du die komplette Logik vergessen... Das Kann ja nicht gehen.
Hier noch mal der Code, den Du einfügen musst:

Private Sub cmdSuchenMLP1_Click()
Dim zeile As Double

cboBestellNr.Clear

For zeile = 2 To Worksheets("Mastertabelle").UsedRange.Rows.Count
If chkErfasst.Value = Range("AF" & zeile) _
And chkGeplant.Value = Range("AE" & zeile) _
And chkFreigegeben.Value = Range("AG" & zeile) _
And chkMontiert.Value = Range("AH" & zeile) _
And chkGeprüft.Value = Range("AI" & zeile) _
And chkVersandfertig.Value = Range("AJ" & zeile) _
Then
cboBestellNr.AddItem (Range("E" & zeile))

End If
Next zeile

End Sub

Und bei den Routinen cmdSpeichernMLP2_Click() und cmdSpeichernMLP1_Click() arbeitest Du auch noch mit dem Listindex der Kombobox. Das geht dann auch in die Hose! Der Listindex nutzt Dir garnichts! Du benötigst die Werte (wie beim Change Ereignis der Bestellnrbox...
Also, da wartet noch Arbeit auf Dich...;)

pidi6376
04.07.2014, 12:37
Ne, die Logik ging nicht vergessen, hab auf dem Frame mit den cbo einen Button "Anzeigen" erstellt und den Code dort hinterlegt.
Allerdings kommt der Fehler auch bereits wenn ich bei einer cbo die Auswahl verändere ohne überhaupt schon den Button betätigt zu haben.

Mit den beiden Routinen des Speicherns hast Du natürlich recht, aber so weit bin ich ja leider noch gar nicht gekommen.

Ich bin dir wirklich sehr Dankbar für deine Hilfe!!!

Gruss Peter

pidi6376
04.07.2014, 12:43
Nein, Stimmt nicht, Laufzeitfehler 13 kommt nach betätigen des "Anzeigen" Buttons.
Sorry

R J
04.07.2014, 12:54
...also.... einen Anzeigen Button kann ich nicht entdecken...

R J
04.07.2014, 12:55
...sorry... ganz unten... seh es mir mal an...

R J
04.07.2014, 13:12
...laut lach...

da hast Du Dir aber viel Arbeit für nichts gemacht (und ich hab die falschen Objekte ausgewertet...:D )

Also, hab das erst jetzt gesehen... Du willst, dass die Listboxen (unten, vor dem neuen Anzeigebutton) ausgewertet werden und die Checkboxen, rechts entsprechende Werte annehmen.

Ich habe aber die Checkboxen ausgewertet und die Listboxen vollkommen ignoriert. Im Grunde ist eins von beiden überflüssig...

Was passiert denn bei Dir? Du fügst der Bestellnr Combobox Werte hinzu, wenn Du auf die Listboxen klickst... Ich überprüfe die jetzt aber nicht. Schmeiß die ganzen Listboxroutinen raus. Die sind überflüssig und produzieren zudem jede Menge Fehler. Werte die WERTE stattdessen (EINMALIG!) im Click Ereignis des Anzeigebuttons aus (nur, dass Du jetzt die Werte der Listboxen und nicht die der Checkboxen überprüfen musst.

Wenn Du jetzt mal die Listboxen weglässt und Deine Auswahl per Checkboxen triffst, dann läuft das Makro auch ordentlich...

pidi6376
04.07.2014, 14:13
Nein nein ;-)

Also, die Checkboxen bekommen ihren Wert ob WAHR oder FALSCH von wo anders und verändern sich im laufe der Abarbeitung des Auftrages. Zum Teil werden diese Manuel gesetzt, zum Teil werden Sie automatisch gesetzt nachdem etwas bestimmtes passiert ist.
In Dem Frame "Die Aufträge die ich sehen möchte sind..." sind ja die 6 cbo. Mit diesen möchte ich auswählen welche Datensätze aus der Mastertabelle ich in der UF angezeigt bekommen möchte, und dies zwar in Abhängigkeit voneinander. Mit dem Button "Anzeigen" kann ich den Befehl dann auslösen.

Aber ich glaube ich brauche mal ne pause von diesem Projekt, ich habe auch nicht geschnallt das mit deinem Code die chk und nicht die cbo ausgwertet werden.

Im Moment schnall ich gar nichts mehr...
Ich habe die Auswertung auf die cbo geändert, aber es kommt trotzdem immer noch Laufzeitfehler 13

GrussPeter

R J
05.07.2014, 20:34
Hi Peter,

nun lass mal die Flügel nicht hängen!

Klar, die Sache wird jetzt etwas komplizierter, da ja 3 Zustände (ja, nein, egal) ausgewertet werden müssen, das bedeutet aber nicht, dass es nicht möglich ist.

Zunächst musst Du alle Ereignisroutinen Deiner "Egal/Ja/Nein"-Komboxen löschen oder wenigstens auskommentieren. Denn die Auswertung soll ja immer nur dann erfolgen, wenn alle Komboboxwerte gesetzt wurden und der Anwender auf den Anzeigebutton klickt.

Die Auswertung erfolgt also NUR(!) im Anzeigebutton!
Der Code dafür sieht so aus:

Private Sub cmdAnzeigen_Click()
Dim zeile As Double
Dim spalte As Byte
Dim bCBOZustand As Boolean
Dim bEgal As Boolean

cboBestellNr.Clear

With Worksheets("Mastertabelle")
For zeile = 2 To .UsedRange.Rows.Count
For spalte = 31 To 36 'AE = 31 bis AJ = 36
'Zustand auswerten
Select Case (spalte)
'Nur bei cbo-wert 'nein' gilt generell False.
' Bei 'egal' oder 'ja', soll die Zeile vorerst in Auswertung übernommen werden
Case 31: bCBOZustand = IIf(cboGeplant.Value = "nein", False, True):
bEgal = IIf(cboGeplant.Value = "egal", True, False)

Case 32: bCBOZustand = IIf(cboErfasst.Value = "nein", False, True):
bEgal = IIf(cboErfasst.Value = "egal", True, False)

Case 33: bCBOZustand = IIf(cboFreigegeben.Value = "nein", False, True):
bEgal = IIf(cboFreigegeben.Value = "egal", True, False)

Case 34: bCBOZustand = IIf(cboMontiert.Value = "nein", False, True):
bEgal = IIf(cboMontiert.Value = "egal", True, False)

Case 35: bCBOZustand = IIf(cboGeprüft.Value = "nein", False, True):
bEgal = IIf(cboGeprüft.Value = "egal", True, False)

Case 36: bCBOZustand = IIf(cboVersandfertig.Value = "nein", False, True):
bEgal = IIf(cboVersandfertig.Value = "egal", True, False)
End Select
bCBOZustand = IIf(bEgal, .Cells(zeile, spalte).Value, bCBOZustand)
'Wenn nicht 'egal' aber bCBOZustand vom Zielzellwert abweicht, dann prüfe nächste Zeile
If bEgal = False And bCBOZustand <> .Cells(zeile, spalte).Value Then
bCBOZustand = False 'von der Aufnahme ausschließen
Exit For 'Nächste Zeile, sobald Bedingung falsch ist
Else
'sonst bCBOZustand' auf True setzen, damit Bestellnr aufgenommen werden kann
bCBOZustand = True
End If
Next spalte
'nur wenn bCBOZustand wahr, dann Bestllnr in Listbox aufnehmen
If bCBOZustand Then cboBestellNr.AddItem (Range("E" & zeile))

Next zeile
End With

End Sub

Ich hab den jetzt nicht zu 100% gecheckt, er sollte aber passen...

pidi6376
07.07.2014, 15:23
Hallo Ralf

Du bist Genial!!!
An Select Case habe ich auch gedacht, aber wusste im besten Fall nicht wie der Code aussehen sollte damit es funktioniert. Die Versuche die ich gestartet habe, hatten zumindest nicht den geringsten Erfolg.

Ich habe jedoch nach wie vor einen Laufzeitfehler 91 in der Zeile welche ich schon in Beitrag #5 beschrieben habe.
Wenn ich die UF öffne kann ich das erste mal auch die Auswahl mit den Comboboxen selektionieren und über den Anzeigen Button holen und es wird alles korrekt angezeigt.
Sobald ich dann aber die Auswahl nochmals ändere bringt er mir den Laufzeitfehler.
Woran könnte das liegen?

Gruss Peter

R J
07.07.2014, 16:30
...setz den gesamten With Block in eine If-Anweisung....

If cboBestellNr.Value <> "" Then
With Worksheets("Mastertabelle").Range("E1:E" & Worksheets("Mastertabelle").Cells.SpecialCells(xlLastCell).Row)
zeile = .Find(what:=cboBestellNr.Value, lookat:=xlWhole).Row
...
...
chkVersandfertig = .Cells(zeile, 36)
End With
End If

pidi6376
08.07.2014, 09:30
Hallo Ralf

Jetzt Funkts (freu freu freu )

Vielen vielen Dank für deine super Hilfe!!!!
Ohne Dich wäre ich am A.... gewesen.

Ich hoffe jetzt bekomme ich wieder einiges alleine hin ;-)

Gruss Peter

pidi6376
10.07.2014, 11:25
Hallo Ralf

Das mit dem "einiges alleine hin bekommen" war ein Trugschluss :-(
Ich stehe schon an der nächsten Knacknuss an.
Den "Suchen" Button hast Du ja bereits schon mal gesehen, nun sollte der natürlich auch eingesetzt werden können :-]
Ich möchte das in der Mastertabelle nach dem Wert gesucht wird welcher in der Aktiven TextBox stehen würde. Soll heissen wenn z.B. die TextBox Kunden Nr. Aktiv ist soll er in der Mastertabelle nach der Kunden Nr. suchen welche ich in der Suchen Box eingebe.
Dies habe ich mit der Standard Suchfunktion auch hinbekommen.
Nun kommt aber mein Problem.
Anhand des gefundenen Wertes soll er mir wieder die dazugehörigen Bestell Nr. in der entsprechenden Combobox auflisten. Dies kann dann eine oder mehrere sein.
Ich habe gehofft das ich dies mit einem Schnipsel aus deinem Code der "Anzeigen Funktion" machen kann, aber weit gefehlt....

Private Sub cmdSuchenMLP1_Click()
Dim strSuche As String
Dim zeile As Double

cboBestellNr.Clear
With Worksheets("Mastertabelle")
strSuche = Application.Dialogs(xlDialogFormulaFind).Show
If strSuche <> "" Then
cboBestellNr.Additem (Range("E" & zeile))
Else
Call MsgBox("Keine Übereinstimmung gefunden", vbOKOnly, "Suche")
End If
End With

End Sub


Wie kann ich dies anstellen das es funktioniert???

Und schon wieder...

Besten Dank jetzt schon für jede Hilfe und Unterstützung!!!!

Gruss Peter

R J
10.07.2014, 14:08
...ich ahne, worauf du hinauswillst. Muss Dich aber warnen, wie leicht haust du dir da die datensätze kaputt. wenn du das so pauschal machen willst, dann schmeiß am besten den Speicher-Button raus...;)
...oder lagere die suche in ein anderes Formular aus... das wäre vielleicht sogar das beste. schmeiß eine list- oder kombobox drauf, die alle textboxnamen zur Auswahl stellt, eine TextBox zur aufnahme des suchbegriffs und einen Fertig-Button... wird wohl die einfachste Variante sein...

R J
10.07.2014, 20:22
...bevor Du wieder nachfragst...
hab ja jetzt nicht die aktuelle Version, deshalb nur den code, den ich ergänzt habe:

im Editformular für den Suchbutton:
Private Sub cmdSuchenMLP1_Click()
Dim lz&, c, zeile&
frmSuchen.Show vbModal
If SucheNach.Suchspalte > 0 Then
cboBestellNr.Clear
lz = Worksheets("Mastertabelle").Cells.SpecialCells(xlLastCell).Row

With Worksheets("Mastertabelle").Range(Cells(2, SucheNach.Suchspalte), Cells(lz, SucheNach.Suchspalte))

Set c = .Find(what:=SucheNach.Suchbegriff, LookIn:=xlValues, lookat:=xlWhole)
If Not c Is Nothing Then
zeile = c.Row
Do
cboBestellNr.AddItem (Worksheets("Mastertabelle").Range("A" & zeile))
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Row <> zeile
End If
End With
cboBestellNr.Text = cboBestellNr.List(0)
End If

End Sub

in einem allg. Modul:
Option Explicit

Type Ergebnis
Suchspalte As Byte
Suchbegriff As String
End Type

Public SucheNach As Ergebnis

Und in einem neuen Formular (frmSuche) 2 Comboboxen (bitte auf die Namensgebung achten) und einen Button hinzufügen (s. Bild).

Option Explicit

Private Sub cbSpalte_Change()
Dim lZeile&, zeile&
cmdOK.Enabled = False
With Worksheets("Mastertabelle")
lZeile = .UsedRange.Rows.Count
cbWerte.Clear
For zeile = 2 To lZeile
If CStr(.Cells(zeile, cbSpalte.ListIndex + 1)) <> "" Then
If Not istVorhanden(CStr(.Cells(zeile, cbSpalte.ListIndex + 1))) Then cbWerte.AddItem (.Cells(zeile, cbSpalte.ListIndex + 1))
End If
Next
End With
If cbWerte.ListCount > 0 Then
cmdOK.Enabled = True
cbWerte.Text = cbWerte.List(0)
SucheNach.Suchspalte = cbSpalte.ListIndex + 1
End If

End Sub

Private Sub cmdOK_Click()
SucheNach.Suchbegriff = cbWerte.Text
Unload Me
End Sub

Private Sub UserForm_Activate()
Dim sp As Byte
cmdOK.Enabled = false
SucheNach.Suchspalte = 0
cbSpalte.Clear
With Worksheets("Mastertabelle")
For sp = 1 To 13 'Bis zu: versandfertig am (Spalte M)
cbSpalte.AddItem (.Cells(1, sp))
Next sp
End With
End Sub

Function istVorhanden(was As String) As Boolean
'Keine doppelten Einträge zulassen
Dim x%
If cbWerte.ListCount = 0 Then
istVorhanden = False
Exit Function
End If

For x = 0 To cbWerte.ListCount - 1
If VBA.UCase$(cbWerte.List(x)) = VBA.UCase$(was) Then
istVorhanden = True
Exit Function
End If
Next
istVorhanden = False
End Function

...hoffe, ich hab nix vergessen...

pidi6376
12.07.2014, 07:43
Hallo Ralf

Genial und Gute Idee mit der Extra UF!!!
Funktioniert tadellos!!!

Du bist ein Grandios!!

Gruss Peter