Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1576to1580
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Vorschläge für besseren Code

Vorschläge für besseren Code
04.09.2017 09:36:17
Peter
Hallo Leute,
ich habe eine UF mit einigen Comboboxen.
Es gibt auf einem Panel, immer 3 zusammen gehörende Comboboxen.
(Insgesamt 3x7, es werden also insgesamt 21 befüllt)
Die erste beinhaltet Spaltenüberschriften.
Die anderen beiden, erhalten Werte, entsprechend der Überschrift, also dem Inhalt der ersten Combobox.
Der Code den ich verwende, funktioniert.
Nur glaube ich, gibt es da was besseres und wollte euch fragen,
wie ihr das ganze machen würdet.
Der unten stehende Sub "AddHeaderToCombobox" wird in einem Klassenweiten Combobox_Changed Event aufgerufen und gilt für insgesamt 7 Comboboxen
Hier Code der die erste befüllt:

Option Explicit
Private probeSheet As Worksheet
Public Sub AddHeaderToCombobox(ByVal frm As MSForms.UserForm)
Dim dict As Dictionary
Dim varKey As Variant
Dim i As Integer
Set probeSheet = ThisWorkbook.Sheets("Probendaten")
Set dict = HeaderData
For i = 1 To 7
For Each varKey In dict.Keys
frm.Controls("cb_Probenform" & i).AddItem varKey
Next varKey
Next i
Set dict = Nothing
Set probeSheet = Nothing
End Sub
Private Function HeaderData() As Dictionary
Dim dict As New Dictionary
Dim tmp As String
Dim lCol As Long
Dim i As Integer
With probeSheet
lCol = LastCol()
For i = 1 To lCol
tmp = .Cells(1, i).value
If Not dict.Exists(tmp) And tmp  "" Then dict.Add tmp, 0
Next i
End With
Set HeaderData = dict
Set dict = Nothing
End Function
Private Function LastCol() As Long
With probeSheet
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
End Function

Hier der Code der die anderen beiden befüllt:

Private Function LastRow(ByVal column_ As Long) As Long
With probeSheet
LastRow = .Cells(.Rows.Count, column_).End(xlUp).Row
End With
End Function
Public Sub SpecificDataToForm(ByVal frm As MSForms.UserForm, comboIndex As Integer, varItem As  _
Variant)
Dim dict As Dictionary
Dim varListItem As Variant
Dim cb_1 As MSForms.ComboBox
Dim cb_2 As MSForms.ComboBox
Set probeSheet = ThisWorkbook.Sheets("Probendaten")
Set dict = DataDictionary(varItem)
Set cb_1 = frm.Controls("cb_Werkstatt" & comboIndex)
Set cb_2 = frm.Controls("cb_Prüfung" & comboIndex)
For Each varListItem In dict(dict.Keys(0))
cb_1.AddItem varListItem
Next varListItem
For Each varListItem In dict(dict.Keys(1))
cb_2.AddItem varListItem
Next varListItem
cb_1.Text = cb_1.list(0, 0)
cb_2.Text = cb_2.list(0, 0)
Set dict = Nothing
Set probeSheet = Nothing
End Sub
Private Function DataDictionary(ByVal varItem As Variant) As Dictionary
Dim dict As New Dictionary
Dim list_ As New ArrayList
Dim rng As Range, c
Dim lCol As Long
Dim lRow As Long
Dim i As Long
Dim firstAddress
lCol = LastCol
With probeSheet
Set rng = .Range(.Cells(1, 1), .Cells(1, lCol))
Set c = rng.Find(varItem, After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
If Not c Is Nothing Then
firstAddress = c.Address
Do
lRow = LastRow(c.Column)
For i = 2 To lRow
list.Add .Cells(i, c.Column).value
Next i
dict.Add (varItem & c.Column), list
Set list = Nothing
Set c = rng.FindNext(c)
Loop While Not c Is Nothing And c.Address  firstAddress
End If
End With
Set DataDictionary = dict
Set dict = Nothing
Set list = Nothing
End Function

4
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Vorschläge für besseren Code
04.09.2017 10:09:48
mmat
Hallo Peter,
was ist eigentlich ein "guter Code"?
Für mich: ich muss verstehen, was ich da verzappt hab (auch noch nach einem Jahr ...) und es muss funktionieren. Wenn ich nicht gerade mit extrem zeitkritischen Dingen zu Gange bin, dann ist die Frage, ob man das vielleicht eleganter schreiben könnte, ohne Belang.
Ich hab in deinem Code beim Überfliegen erstmal nix gesehen, was bei mir ein Stirnrunzeln hervorruft. Was möchtest du konkret mit einer Verbesserung erreichen ?
Aber vielleicht wissen die anderen ja noch was, deshalb lass ich das Ding offen.
vg, MM
AW: Vorschläge für besseren Code
04.09.2017 11:46:38
fcs
Hallo Peter,
dein Code als solches sieht erst einmal ziemlich sauber aus.
Wenn deine Tabelle mit den Aúsgangdaten sehr viele Datenzeilen enthält, dann wäre es sinnvoll diese mit der Anzeige des Userforms in ein Datenarray zu laden.
Dann kann man zur Erstellung der Auswahllisten für die Comboboxen auf dieses Array zurückgreifen.
Das geht wesentlich schneller als wenn man auf die Zellen im Tabellenblat zugreift.
Allerdings sind dann relativ viele Änderung am Code erforderlich - überall wo "= .Cells(Zeile,Spalte)" auftaucht muss dieser Ausdruck durch das ensprechende Array ersetzt werden. Auch die Funktion "Find" funktioniert dann in der Form nicht mehr und muss ersetzt werden.
Gruß
Franz
Anzeige
Danke für das Feedback
04.09.2017 13:41:53
Peter
Hallo,
erstmal danke für euer Feedback.
Ich finde den Code relativ lang für dass was er macht.
Ein Array beim Start zu erstellen bzw. ein Hashset(kann man nachahmen)
hatte ich mir überlegt. Leider passt dass nicht ganz.
Zur Laufzeit der Maske, werden diese Daten ggf. vom Nutzer erweitert oder verändert.
Deshalb habe ich mich für den Weg mit dem Range.Find entschlossen.
Allzu viele Daten sind es glücklicherweise auch nicht.
Das Makro hierfür muss nur ca. 40 spalten durchgehen mit maximal 20 Zeilen pro Spalte.
800 Daten Maximum also.
Kennt ihr hierfür was schnelleres?
04.09.2017 13:50:34
Peter
So, hier ein etwas anders "Problem".
Ich habe hier einen kleinen Code, der Daten per Quicksort sortiert.
Nun muss ich aber gut 20 mal den Quicksort bemühen, zum sortieren verschiedener Daten.
Dass passiert im Initialize Event der UF.
Ohne das Sortieren, ist die UF sofort da.
Mit sortieren dauert es einen Augenschlag, man sieht kurz den Lade-Pointer bei der Maus.
Leider bin ich ratlos wie ich das Sortieren schneller machen könnte, oder vermeiden könnte, zwei Quicksort zu schreiben, einmal Ascending und einmal Descending...
Vielleicht habt ihr ja eine Idee, wie es schneller gehen könnte...
Hier der Code:
Option Explicit
Public Sub SortDictionaryByKey(ByRef dict As Dictionary, _
Optional ByVal SortDescending As Boolean)
If IsMissing(SortDescending) Then SortDescending = False
'// If its not valid then go out now!
If dict Is Nothing Then Exit Sub
If (dict.Count = 0) Or (dict.Count = 1) Then Exit Sub
'// Declaring variables
Dim i As Long
Dim arr() As Variant
Dim default As Byte
Dim tmpDict As New Dictionary
'// Dictionary to Array
ReDim arr(0 To dict.Count - 1)
For i = 0 To dict.Count - 1
arr(i) = dict.Keys(i)
Next i
'// Sorting Keys
If SortDescending Then
QuickSortDescending arr, LBound(arr), UBound(arr)
Else
QuickSortAscending arr, LBound(arr), UBound(arr)
End If
'// Array To Dictionary
For i = LBound(arr) To UBound(arr)
tmpDict.Add arr(i), default
Next i
Erase arr
Set dict = tmpDict
Set tmpDict = Nothing
End Sub
'// QuickSort in Ascending Order
Public Sub QuickSortAscending(ByRef arrayToSort As Variant, _
Optional ByVal low As Variant, _
Optional ByVal high As Variant)
If IsMissing(low) Then low = LBound(arrayToSort)
If IsMissing(high) Then high = UBound(arrayToSort)
Dim i As Long: i = low
Dim j As Long: j = high
Dim tmp As Variant
Dim ref As Variant: ref = arrayToSort((low + high) / 2)
Do
While (arrayToSort(i)  ref): j = j - 1: Wend
If (i  j)
If (low  ref): i = i + 1: Wend
While (arrayToSort(j)  j)
If (low 

Anzeige

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige