Combobox sortieren, Sorted-Funktion will nicht?

  • Excel

Es gibt 31 Antworten in diesem Thema. Der letzte Beitrag () ist von Katey.

    Combobox sortieren, Sorted-Funktion will nicht?

    Hallo zusammen.
    Eine ComboBox hat die Eigenschaft Sorted, womit man nur noch

    Visual Basic-Quellcode

    1. ComboBox1.Sorted = True

    eingeben muss und es funzt... Soweit zur Theorie.
    Ich habe das jetzt bei meinem Code unter

    Visual Basic-Quellcode

    1. Private Sub UserForm_Initialize()

    neben dem anderen Kram, der da so steht, reingeschrieben, jedoch kennt er "Sorted" nicht und gibt mir als Fehlermeldung "Fehler beim Kompilieren: Methode oder Datenobjekt nicht gefunden."
    Daraus schließe ich mal ganz stark, dass ich was falsch gemacht habe.
    Kann mir einer von euch sagen, wo der Fehler liegt?
    Ich hab Excel2007, falls das was hilft.
    Hallo Katey,
    die Sorted-Eigenschaft kann nur zur Entwurfszeit gesetzt
    werden. Also im Eigenschaftenfenster Sorted auf True
    stellen.


    Sorry, das stimmte so nicht. Ich bin von einem anderen Control
    ausgegangen.
    Gruss,

    Neptun

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Neptun“ ()

    Wer hat dir gesagt, dass es diese Funktion gibt?
    Unten ein Auschnitt der Methoden der Combobox aus der VBA.
    Da gibts kein Sorted .... Diese Funktion ist unter Visual Basic 2005 bis 2012 verfügbar aber nicht in VBA (VisaulBasicforAplications)
    Die einzige Möglichkeit ist hier entweder ein Array zu bestücken und dieses dann sortiert in die Combo zu schupsen oder gleich die Tabellenspalten vorher sortieren und dann einlesen.
    Bilder
    • 5.jpg

      21,93 kB, 165×128, 9.192 mal angesehen
    Okay, danke tulla, dann hab ich da wohl beim Recherchieren was durcheinander geworfen.
    Vorher sortieren ist leider keine Option, die müssen erst in der Box sortiert werden.
    Mit Arrays kenn ich mich leider nicht aus.
    Schade, hatte gehofft, da gibt es eine einfache Lösung.
    Mal zu dem Code in dem Link (weil ich inzwischen nichts gefunden habe, was klappt):
    Ich schreibe "SortierenCombobox" an das Ende meines UserForm_Initialize()
    und kopiere dann den kompletten Sub "SortierenCombobox".
    Ich passe den Namen von UserForm und ComboBox an und erhalte... eine Fehlermeldung: "Laufzeitfehler '70': Eigenschaft List konnte nicht gesetzt werden. Zugriff verweigert"
    Kann damit einer von euch was anfangen?
    Hallo Katey,

    das hängt schlicht damit zusammen, dass du die Combobox über "Rowsource" befüllst. Mit dieser Methode hast du keine Möglichkeit, weitere Daten hinzuzufügen, außer du veränderst die Rowsource (den Bereich in der Tabelle). Rowsource ist eigentlich selbsterklärend.
    Wenn du die Daten weiterhin über Rowsource befüllen willst, dann musst du die Zellen im Tabellenblatt sortieren, dann sind diese auch in der Combobox sortiert!

    Andernfalls müsstest du die Werte in einer Schleife einlesen (ACHTUNG, Falls Eigenschaft Rowsource gesetzt ist, musst du diese löschen!!) und anschließend den Sortieralgo umsetzen.

    Visual Basic-Quellcode

    1. for i = erstezeile to letztezeile
    2. deinecombobox.additem thisworkbook.sheets("deintabellenblatt").range("A" & i).value
    3. next


    Welchen Weg du wählen willst, hängt von dir ab! ;)

    lg Markus
    :!: Danke an alle, die ihr Wissen freiwillig teilen und stets so kompetent & höflich sind :!:
    Er sagte ja bereits, dass er die Daten in dem Tabellenblatt nicht sortieren kann.
    Was spricht eigendlich gegen ein temporäres Array? Was bei Additem mit Sort ausgegeben wird?

    Welche Art von Daten hast da überhaupt, Zahlen oder Text?

    EDIT:
    Muss gerade geststellen, dass das sortieren von Arrays auch nicht mehr so unterstützt wird wie gedacht.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „tulla“ ()

    Zahlen, Kundennummern, um genau zu sein.
    Der aktuelle Code sieht so aus:

    Visual Basic-Quellcode

    1. Private Sub UserForm_Initialize()
    2. Dim vTabelle As Worksheet
    3. Dim vStartZeilenIndex As Integer
    4. Dim vSpaltenindex As Byte
    5. Dim vEndZeilenIndex As Integer
    6. Dim vControlIndex As Byte
    7. Set vTabelle = ThisWorkbook.Sheets("Kundendaten")
    8. vStartZeilenIndex = 3
    9. vSpaltenindex = 23
    10. vEndZeilenIndex = vTabelle.Range("A" & Rows.Count).End(xlUp).Row
    11. For vControlIndex = 1 To 1
    12. Me.Controls("Combobox" & vControlIndex).RowSource = vTabelle.Name & "!" & _
    13. (Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    14. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address).Address)
    15. Next
    16. Set vTabelle = Nothing
    17. End Sub

    Ich weiß, dass der RowSource-Code da eigentlich zu umständlich ist, die Box soll wirklich nur aus Spalte 24 die Werte ab Zeile 3 bis letzte belegte Zeile enthalten und das alphabetisch sortiert. Wär es also besser, die Werte anders auslesen zu lassen?

    EDIT: Hab den Code jetzt mal angepasst:

    Visual Basic-Quellcode

    1. Private Sub UserForm_Initialize()
    2. Dim vTabelle As Worksheet
    3. Dim vEndZeilenIndex As Integer
    4. Set vTabelle = ThisWorkbook.Sheets("Kundendaten")
    5. Set vEndZeilenIndex = vTabelle.Range("X" & Rows.Count).End(xlUp).Row
    6. For i = 3 To vEndZeilenIndex
    7. ComboBox1.AddItem ThisWorkbook.Sheets("Kundendaten").Range("X" & i).Value
    8. Next
    9. Set vTabelle = Nothing
    10. End Sub

    Allerdings geht das mit dem EndZeilenIndex nicht, da erzählt er mir was von "Objekt erforderlich".
    Was ist da nun schon wieder falsch?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Katey“ ()

    tulla schrieb:

    Er Sie sagte ja bereits, dass er die Daten in dem Tabellenblatt nicht sortieren kann.


    :)

    Katey, das Problem, was du jetzt wahrscheinlich noch nicht siehst ist, dass du mit dem Listindex in direkter Verbindung mit der Tabelle arbeitest.
    Wenn jetzt Zeile 20 im Tabellenblatt auf einmal (durch Sortierung) an zweiter Stelle in der Combobox steht, wirft das dein Konzept über den Haufen...

    Du kannst jetzt selber den Sortieralgo nutzen und dir die Kundennummern alphanumerisch einlesen lassen. Dann musst du aber bei jeder Änderung der Combobox nicht mehr den Listindex ansprechen, sondern eine Suche im Tabellenblatt nach der richtigen Kundennummer machen.

    lg Markus
    :!: Danke an alle, die ihr Wissen freiwillig teilen und stets so kompetent & höflich sind :!:
    @xpecidy
    Hast recht, hab ich nicht drauf geachtet.

    @Katey
    SORRY ! :rolleyes:
    Wenn die Liste (RowSource) nicht geändert wird, sonder nur angehangen läuft alles ^^


    Die andere Möglich ist nach Auswahl in der Box nochmal in der Source nach dem Eintrag und dessen Zeile zu schauen.

    Löst zwar immer noch nicht das Hauptproblem des sortierens.
    Also ich würde es mit nem Bubblesort lösen...
    Namen ggf. anpassen.

    Visual Basic-Quellcode

    1. vArr = vtabelle.Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    2. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address)
    3. While vAenderung = False
    4. vAenderung = False
    5. i = 1
    6. While i < UBound(vArr)
    7. If (vArr(i + 1, 1) < vArr(i, 1)) Then
    8. vDummy = vArr(i, 1)
    9. vArr(i, 1) = vArr(i + 1, 1)
    10. vArr(i + 1, 1) = vDummy
    11. i = 1
    12. vAenderung = True
    13. End If
    14. i = i + 1
    15. Wend
    16. Wend
    17. For t = 1 To UBound(vArr)
    18. Me.ComboBox2.AddItem vArr(t, 1)
    19. Next


    Jetzt kannst du natürlich nicht mehr mit dem Listindex direkt arbeiten, sondern musst die Artikelnummer suchen.. das könntest du so machen:

    Visual Basic-Quellcode

    1. Set vSuche = vtabelle.Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    2. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address).Find(Me.ComboBox2.List(Me.ComboBox2.ListIndex))
    3. If Not vSuche Is Nothing Then
    4. MsgBox vsuche.Row
    5. 'Liefert dir die Zeile in der die Kundennummer steht
    6. End If
    7. Set vSuche = Nothing


    Versuchs mal selber bei dir reinzubasteln ;)
    :!: Danke an alle, die ihr Wissen freiwillig teilen und stets so kompetent & höflich sind :!:
    Hab das jetzt in meinen Code ergänzt, der jetzt so aussieht:

    Visual Basic-Quellcode

    1. Private Sub UserForm_Initialize()
    2. Dim vTabelle As Worksheet
    3. Dim vStartZeilenIndex As Integer
    4. Dim vSpaltenindex As Byte
    5. Dim vEndZeilenIndex As Integer
    6. Dim vControlIndex As Byte
    7. Set vTabelle = ThisWorkbook.Sheets("Kundendaten")
    8. vStartZeilenIndex = 3
    9. vSpaltenindex = 23
    10. vEndZeilenIndex = vTabelle.Range("A" & Rows.Count).End(xlUp).Row
    11. For vControlIndex = 1 To 1
    12. Me.Controls("Combobox" & vControlIndex).RowSource = vTabelle.Name & "!" & _
    13. (Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    14. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address).Address)
    15. Next
    16. vArr = vTabelle.Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    17. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address)
    18. While vAenderung = False
    19. vAenderung = False
    20. i = 1
    21. While i < UBound(vArr)
    22. If (vArr(i + 1, 1) < vArr(i, 1)) Then
    23. vDummy = vArr(i, 1)
    24. vArr(i, 1) = vArr(i + 1, 1)
    25. vArr(i + 1, 1) = vDummy
    26. i = 1
    27. vAenderung = True
    28. End If
    29. i = i + 1
    30. Wend
    31. Wend
    32. For t = 1 To UBound(vArr)
    33. Me.ComboBox1.AddItem vArr(t, 1)
    34. Next
    35. Set vSuche = vTabelle.Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    36. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address).Find(Me.ComboBox1.List(Me.ComboBox1.ListIndex))
    37. If Not vSuche Is Nothing Then
    38. MsgBox vSuche.Row
    39. End If
    40. Set vSuche = Nothing
    41. End Sub


    Allerdings lädt sich mein Excel da fast zutode und hängt sich auf...
    Ich vermute, mit so vielen Werten (570) kann es nicht umgehen oder es ist mal wieder was falsch im Code...
    Joah bei 600 Einträgen rattert der DualCore auf arbeit 5 Sekunden.. Pervers lange. :) :)

    Alternativ sollte man die Daten einfach temporär kompieren und Hausinternen Excelsortierrhytmus benutzen.

    • Neues Workbook anlegen
    • TempWorkbook.Range(Bereich).value = Workbook.range(Bereich)
    • Tempworkbook.Sort
    • In schleife Werte aus tempworkbook einlesen
    • Tempworkbook.saved = True
    • Tempworkbook.close 'oder hier erst savechange=false

    • Am besten mit Screenupdating arbeiten, damit nichts "flackert"
    :!: Danke an alle, die ihr Wissen freiwillig teilen und stets so kompetent & höflich sind :!:
    Je größer das Array, desto ineffizienter wird BubbleSort.
    Ggf. würde da QuickSort die Performance um einiges erhöhen.
    Beispiele: msdn.microsoft.com/de-de/library/bb979305.aspx

    xpecidy schrieb:

    bei 600 Einträgen rattert der DualCore auf arbeit 5 Sekunden.
    Das würden bei mir die wenigsten Benutzer akzeptieren.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Wären es nur 5 Sekunden, wäre es ja noch okay, aber mein Excel ist ganz abgestürzt.
    Zu dem Quicksort-Dings: Hübscher Code, aber irgendwie seh ich nicht, wie ich den auf meine ComboBox anpasse. Wenn ich ihn einfach so reinkopiere, sortiert er (wenig überraschend) natürlich nichts, es bleibt alles beim alten. (Was man ihm zugute halten kann, ist, dass er auch keine Fehlermeldung ausspuckt.)
    Ich habe eine Zeile "QuickSort" in meinem Pirvate Sub UserForm_Initialize() hinzugefügt und dann darunter den Code kopiert, aber wie gesagt, woher soll er wissen, was er damit anstellen soll? Könnte mir da nochmal jemand auf die Sprünge helfen? Code sieht aktuell so aus:

    Visual Basic-Quellcode

    1. Private Sub CommandButton2_Click()
    2. Unload Me
    3. End Sub
    4. Private Sub CommandButton1_Click()
    5. Dim z As Integer
    6. z = ComboBox1.ListIndex + 3
    7. For sp = 2 To 13
    8. If IsNumeric(Controls("TextBox" & sp).Text) Then
    9. Cells(z, sp).Value = Cells(z, sp).Value + Controls("TextBox" & sp).Text
    10. End If
    11. Next sp
    12. Cells(z, 1).Select
    13. Unload Me
    14. End Sub
    15. Private Sub UserForm_Initialize()
    16. Dim vTabelle As Worksheet
    17. Dim vStartZeilenIndex As Integer
    18. Dim vSpaltenindex As Byte
    19. Dim vEndZeilenIndex As Integer
    20. Dim vControlIndex As Byte
    21. Set vTabelle = ThisWorkbook.Sheets("Kundendaten")
    22. vStartZeilenIndex = 3
    23. vSpaltenindex = 23
    24. vEndZeilenIndex = vTabelle.Range("A" & Rows.Count).End(xlUp).Row
    25. For vControlIndex = 1 To 1
    26. Me.Controls("Combobox" & vControlIndex).RowSource = vTabelle.Name & "!" & _
    27. (Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    28. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address).Address)
    29. Next
    30. Set vSuche = vTabelle.Range(Cells(vStartZeilenIndex, vControlIndex + vSpaltenindex).Address & ":" & _
    31. Cells(vEndZeilenIndex, vControlIndex + vSpaltenindex).Address).Find(Me.ComboBox1.List(Me.ComboBox1.ListIndex))
    32. If Not vSuche Is Nothing Then
    33. MsgBox vSuche.Row
    34. End If
    35. Set vSuche = Nothing
    36. QuickSort
    37. End Sub
    38. Private Sub QuickSort( _
    39. ByRef ArrayToSort As Variant, _
    40. ByVal Low As Long, _
    41. ByVal High As Long)
    42. Dim vPartition As Variant, vTemp As Variant
    43. Dim i As Long, j As Long
    44. If Low > High Then Exit Sub ' Rekursions-Abbruchbedingung
    45. ' Ermittlung des Mittenelements zur Aufteilung in zwei Teilfelder:
    46. vPartition = ArrayToSort((Low + High) \ 2)
    47. ' Indizes i und j initial auf die äußeren Grenzen des Feldes setzen:
    48. i = Low: j = High
    49. Do
    50. ' Von links nach rechts das linke Teilfeld durchsuchen:
    51. Do While ArrayToSort(i) < vPartition
    52. i = i + 1
    53. Loop
    54. ' Von rechts nach links das rechte Teilfeld durchsuchen:
    55. Do While ArrayToSort(j) > vPartition
    56. j = j - 1
    57. Loop
    58. If i <= j Then
    59. ' Die beiden gefundenen, falsch einsortierten Elemente
    60. austauschen:
    61. vTemp = ArrayToSort(j)
    62. ArrayToSort(j) = ArrayToSort(i)
    63. ArrayToSort(i) = vTemp
    64. i = i + 1
    65. j = j - 1
    66. End If
    67. Loop Until i > j ' Überschneidung der Indizes
    68. ' Rekursive Sortierung der ausgewählten Teilfelder. Um die
    69. ' Rekursionstiefe zu optimieren, wird (sofern die Teilfelder
    70. ' nicht identisch groß sind) zuerst das kleinere
    71. ' Teilfeld rekursiv sortiert.
    72. If (j - Low) < (High - i) Then
    73. QuickSort ArrayToSort, Low, j
    74. QuickSort ArrayToSort, i, High
    75. Elsea
    76. QuickSort ArrayToSort, i, High
    77. QuickSort ArrayToSort, Low, j
    78. End If
    79. End Sub
    80. Private Sub ComboBox1_Change()
    81. Label25.Caption = ThisWorkbook.Sheets("Kundendaten").Range("A" & ComboBox1.ListIndex + 3).Value
    82. End Sub