Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1916to1920
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

Makro zum Array-Sortieren gesucht

Makro zum Array-Sortieren gesucht
26.01.2023 13:02:01
Konrad
Bin auf der Suche nach einem Makro, das Arrays sortieren kann, und zwar so, dass die Reihenfolge der Zeilen bei gleichen Einträgen in der Sortierspalte nicht geändert wird. Denn nur so kann man in mehreren Ebenen sortieren, indem man rückwärts sortiert.
Die Sortierfunktion in Excel macht das. Das Makros, die ich gefunden habe, zerstören eine bestehende Reihenfolge.
Zum Beispiel soll caa zu aac sortiert werden, ohne die beiden a zu vertauschen, was in den anderen Spalten der a-Zeilen erkennbar ist.
Wenn ich in Excel nach Spalte A, dann nach Spalte B, und darin nach Spalte C sortieren will, dann sortiere ich erst nach C, dann nach B und dann nach A.
Das Makros, das ich suche, soll das können. Habe einige ausprobiert, aber keines lieber nach der zweiten Suche ein richtiges Ergebnis.
Wenn jemand von euch ein solches Makro kennt und auch anwendet, das dies tut, würde ich mich über Tipps freuen.
LG, Konrad

5
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Makro zum Array-Sortieren gesucht
26.01.2023 13:09:32
snb
Ich konnte deine Beispieldatei nicht herunterladen.
AW: Makro zum Array-Sortieren gesucht
26.01.2023 13:13:28
Daniel
Hi
wird schwierig.
die Codes, die man findet, sind in der Regel der Quicksort und der ist nicht eben nicht stabil (dh die reihenfolge gleicher Werte kann sich ändern).
Du brauchst aber eine stabile Sortiermethode.
das einfachste dürfte tatsächlich sein, die Werte in eine Exceltabelle zu kopieren, dort mit der Excelsortierung zu sortieren und dann die Werte wieder ins Array zu schreiben.
Das kann man auch mit Basiskenntnissen selber programmieren und verstehen.
um den Quicksort verwenden zu können, wäre es wahrscheinlich am einfachsten, dem Array eine zusätzliche Spalte hinzuzufügen, und dort den Sortierbegriff einzufügen. Im Sortierbegriff verkettet man alle Spalten, nach denen sortiert werden soll zu einem Begriff und fügt am Schluss noch zusätzlich die Indexnummer der Zeile hinzu, so dass man einen eindeutigen Sortierbegriff hat. Man sollte darauf achten, dass in der Verkettung alle Werte für eine Spalte die gleiche länge haben (bei Texten mit Leerzeichen am Ende und bei zahlen mit führenden Nullen auffüllen).
Dann könnte man den Quicksort, dessen Code man ja finden kann, ohne große Änderung verwenden.
Gruß Daniel
Anzeige
AW: Makro zum Array-Sortieren gesucht
26.01.2023 14:32:46
Nepumuk
Hallo Konrad,
teste mal damit:
Option Explicit
Public Sub Test()
    Dim intColumn As Integer
    Dim lngRow As Long
    Dim avntArray(1 To 10000, 1 To 30) As Variant
    Dim avntSortArray As Variant
    'die zu sortierenden Spalten
    'negative Zahl = Spalte absteigend sortieren
    'positive Zahl = Spalte aufsteigend sortieren
    avntSortArray = Array(1, -2, 8, 3, -4, -5)
    'TestArray füllen
'    Randomize Timer
'    For lngRow = 1 To 10000
'        For intColumn = 1 To 30
'            vntArray(lngRow, intColumn) = Fix((5 * Rnd) + 1)
'        Next
'    Next
    'Sortierroutine starten
    Call Sort(avntSortArray, avntArray())
    'Ausgabe Testarray
'    Application.ScreenUpdating = False
'    Range("A1:AD10000").Value = vntArray
'    Application.ScreenUpdating = True
End Sub
Private Sub Sort(ByVal pvavntSortArray As Variant, ByRef pravntArray() As Variant)
    Dim intIndex As Integer
    Dim lngIndex1 As Long, lngIndex2 As Long, lngRowsArray() As Long
    Dim lngRowsCount As Long, lngRangeCount As Long
    Dim vntTemp As Variant
    ReDim lngRowsArray(0 To 1, 0 To UBound(pravntArray) * 2)
    'Array für den 1. Sortierlauf
    lngRowsArray(0, 0) = LBound(pravntArray)
    lngRowsArray(0, 1) = UBound(pravntArray)
    lngRowsCount = 1
    For intIndex = LBound(pvavntSortArray) To UBound(pvavntSortArray)
        'Wenn eine Spalte angegeben
        If pvavntSortArray(intIndex) > 0 Then
            lngRangeCount = -1
            'Schleife zum sortieren der einzelnen Bereiche
            For lngIndex1 = 0 To lngRowsCount Step 2
                'Sortieren des Bereichs, wenn Zeilenzahl größer 1
                If lngRowsArray(0, lngIndex1) > lngRowsArray(0, lngIndex1 + 1) Then
                    Call QuickSort(CLng(lngRowsArray(0, lngIndex1)), _
                        CLng(lngRowsArray(0, lngIndex1 + 1)), CInt(Abs(pvavntSortArray(intIndex))), _
                        CBool(pvavntSortArray(intIndex) > 0), pravntArray())
                    'sortierten Bereich merken
                    lngRangeCount = lngRangeCount + 2
                    lngRowsArray(1, lngRangeCount - 1) = lngRowsArray(0, lngIndex1)
                    lngRowsArray(1, lngRangeCount) = lngRowsArray(0, lngIndex1 + 1)
                End If
            Next
            lngRowsCount = -1
            'Durchsuchen der soeben sortierten Spalte nach Wertewechsel
            For lngIndex1 = 0 To lngRangeCount Step 2
                '1. Zeile des zu sortierenden Bereichs
                vntTemp = pravntArray(lngRowsArray(1, lngIndex1), Abs(pvavntSortArray(intIndex)))
                lngRowsCount = lngRowsCount + 1
                lngRowsArray(0, lngRowsCount) = lngRowsArray(1, lngIndex1)
                'Suche nach Wechsel innerhalb des Bereichs
                For lngIndex2 = lngRowsArray(1, lngIndex1) To lngRowsArray(1, lngIndex1 + 1)
                    If vntTemp > pravntArray(lngIndex2, Abs(pvavntSortArray(intIndex))) Then
                        lngRowsCount = lngRowsCount + 2
                        lngRowsArray(0, lngRowsCount - 1) = lngIndex2 - 1
                        lngRowsArray(0, lngRowsCount) = lngIndex2
                        vntTemp = pravntArray(lngIndex2, Abs(pvavntSortArray(intIndex)))
                    End If
                Next
                'letzte Zeile des zu sortierenden Bereichs
                lngRowsCount = lngRowsCount + 1
                lngRowsArray(0, lngRowsCount) = lngRowsArray(1, lngIndex1 + 1)
            Next
        End If
    Next
End Sub
Private Sub QuickSort(lngLbound As Long, lngUbound As Long, _
    intSortColumn As Integer, bntSortKey As Boolean, pravntArray() As Variant)
    Dim intIndex As Integer
    Dim lngIndex1 As Long, lngIndex2 As Long
    Dim vntTemp As Variant, vntBuffer As Variant
    lngIndex1 = lngLbound
    lngIndex2 = lngUbound
    vntBuffer = pravntArray((lngLbound + lngUbound) \ 2, intSortColumn)
    Do
        If bntSortKey Then
            Do While pravntArray(lngIndex1, intSortColumn)  vntBuffer
                lngIndex1 = lngIndex1 + 1
            Loop
            Do While vntBuffer  pravntArray(lngIndex2, intSortColumn)
                lngIndex2 = lngIndex2 - 1
            Loop
        Else
            Do While pravntArray(lngIndex1, intSortColumn) > vntBuffer
                lngIndex1 = lngIndex1 + 1
            Loop
            Do While vntBuffer > pravntArray(lngIndex2, intSortColumn)
                lngIndex2 = lngIndex2 - 1
            Loop
        End If
        If lngIndex1  lngIndex2 Then
            If pravntArray(lngIndex1, intSortColumn) > _
                pravntArray(lngIndex2, intSortColumn) Then
                For intIndex = LBound(pravntArray, 2) To UBound(pravntArray, 2)
                    vntTemp = pravntArray(lngIndex1, intIndex)
                    pravntArray(lngIndex1, intIndex) = _
                        pravntArray(lngIndex2, intIndex)
                    pravntArray(lngIndex2, intIndex) = vntTemp
                Next
            End If
            lngIndex1 = lngIndex1 + 1
            lngIndex2 = lngIndex2 - 1
        ElseIf lngIndex1 = lngIndex2 Then
            lngIndex1 = lngIndex1 + 1
            lngIndex2 = lngIndex2 - 1
        End If
    Loop Until lngIndex1 > lngIndex2
    If lngLbound  lngIndex2 Then Call QuickSort(lngLbound, _
        lngIndex2, intSortColumn, bntSortKey, pravntArray())
    If lngIndex1  lngUbound Then Call QuickSort(lngIndex1, _
        lngUbound, intSortColumn, bntSortKey, pravntArray())
End Sub
Gruß
Nepumuk
Anzeige
AW: Makro zum Array-Sortieren gesucht
26.01.2023 16:18:09
snb
So geht das:
In M_snb_2D_array_sortieren wird nur eien 2D-array ersellt zum illustrieren.
Du kansst jedes Array dort einfügen.
Die Function F_snb macht die Sortierung.
Das argument y in Function F_sort(sn, y) ist die Spaltenummer (0- basiert)
Sub M_snb_2D_array_sortieren()
   Randomize
   ReDim sn(9, 9)
   
   For j = 0 To 9
      For jj = 0 To 9
        sn(j, jj) = IIf(jj = 5, Date - 365 * Rnd, IIf(jj = 2, Rnd, Chr(66 + jj) & Int(100 * Rnd)))
     Next
   Next
   
   sn = F_sort(sn, 3)
   Cells(30, 1).CurrentRegion.Resize(UBound(sn), UBound(sn, 2)) = sn
End Sub
Function F_sort(sn, y)
   Set lb = CreateObject("New:{8BD21D20-EC42-11CE-9E0D-00AA006002F3}") '  - Microsoft Forms 2.0 ListBox
   With CreateObject("ADODB.recordset")
        For j = 0 To UBound(sn, 2)
            If TypeName(sn(1, j)) = "String" Then
               .Fields.Append "item" & j, 129, 30
            Else
                .Fields.Append "item" & j, Array(0, 0, 3, 131, 4, 0, 5, 7, 0, 0, 0, 11)(VarType(sn(1, j)))
            End If
        Next
        .Open
        For j = 0 To UBound(sn)
            .AddNew
            For jj = 0 To UBound(sn, 2)
                .Fields("item" & jj) = sn(j, jj)
            Next
            .Update
        Next
        .Sort = "item" & y
        
        lb.Column = .GetRows
        F_sort = lb.List
    End With
End Function

Anzeige

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige