Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Daten sortieren per VBA Skript

Forumthread: Daten sortieren per VBA Skript

Daten sortieren per VBA Skript
06.06.2024 15:36:09
tarzipan7
Hallo zusammen,
ich muss Einträge einer Tabelle sortieren:

die Basis dazu sieht in etwa so aus;
a1 0
a1 100
a1 200
b1 300
c1 400
c1 500
d1 600
d1 700
e1 800

das Ziel ist:
a1 0 100 200
b1 300
c1 400 500
d1 600 700
e1 800

Dies sollte per Button durch einen Skript erfolgen. Ich habe schon rumprobiert und bekomme es nicht hin, kann mir da jemand helfen?

Danke und Gruß
Anzeige

16
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Daten sortieren per VBA Skript
06.06.2024 15:57:43
daniel
Hi
könntest du dazu eine Beispieldatei hochladen, die Ausgangslage und Wunschergebnis enthält?
so ist noch nicht ganz klar, was wo steht und wie es am Ende aussehen soll.

Gruß Daniel
AW: Daten sortieren per VBA Skript
06.06.2024 16:08:11
Beverly
Hi,

wenn ich dich richtig verstanden habe und deine Werte in Spalte A und B ab Zeile 1 stehen dann z.B. so:

Sub Transponieren()

Dim lngZeile As Long
Dim intAnzahl As Integer
Dim blnLoeschen As Boolean
Dim lngLetzte As Long
Dim arrWerte
lngLetzte = IIf(IsEmpty(Cells(Rows.Count, 2)), Cells(Rows.Count, 2).End(xlUp).Row, Rows.Count)
For lngZeile = lngLetzte To 1 Step -1
intAnzahl = Application.CountIf(Columns(1), Cells(lngZeile, 1))
If intAnzahl > 1 Then
arrWerte = Application.Transpose(Range(Cells(lngZeile - intAnzahl + 1, 2), Cells(lngZeile, 2)))
Cells(lngZeile - intAnzahl + 1, 2).Resize(1, intAnzahl) = arrWerte
Range(Cells(lngZeile - intAnzahl + 2, 1), Cells(lngZeile, 1)).ClearContents
On Error Resume Next
Erase arrWerte
On Error GoTo 0
If blnLoeschen = False Then blnLoeschen = True
End If
lngZeile = lngZeile - intAnzahl + 1
Next lngZeile
If blnLoeschen Then Range(Cells(2, 1), Cells(lngLetzte, 1)).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub


Bedingung ist, dass identische Werte in Spalte A fortlaufend untereinander stehen.

Bis später
Karin

Link zur Homepage: https://excel-inn.de/
Anzeige
AW: Daten sortieren per VBA Skript
06.06.2024 16:57:29
daniel
Hi
brauchst du nur die Werte oder müssen auch die Formate übernommen werden?

im Prinzip brauchst du eigentlich nur zwei Formeln:

in D1: =Eindeutig(Filter(A:A;A:A>""))
in E1: =Mtrans(Filter(B:B;A:A=D1))

die Formel in D1 spillt die Werte automatisch nach unten, dh das passt sich an, wenn du neue Daten in A:B einfügst
die Formel in E1 müsstest du dann noch anpassen und aus E1 soweit nach unten kopieren wie Daten vorliegen.
Aufgrund der variablen Anzahl an Spalten hab ich noch keine Idee, wie man hier einen horizontalen und vertikalen Spill hinbekommt.

also das einfachste Makro wäre dann:

Sub TransponierenMitFormel()

With Range("D1")
.CurrentRegion.ClearContents
.Formula2R1C1 = "=UNIQUE(FILTER(C1,C1>""""))"
.SpillingToRange.Offset(0, 1).Formula2R1C1 = "=TRANSPOSE(FILTER(C2,C1=RC[-1]))"
.CurrentRegion.Formula = .CurrentRegion.Value
End With
End Sub

wenn man die Daten direkt "am Platz" umwandeln will oder wenn man nicht über Excel 365 verfügt, dann so:
Sub TransponierenKlassisch()

With Cells(1, 1).CurrentRegion
.Sort Key1:=.Cells(1, 1), order1:=xlAscending, Header:=xlGuess
With .Columns(.Columns.Count + 1)
.FormulaR1C1 = "=RC2&if(RC1=R[1]C1,""|""&R[1]C,"""")"
.Formula = .Value
End With
End With
Range("A:C").RemoveDuplicates 1, xlGuess
Columns(3).TextToColumns Destination:=Cells(1, 3), _
DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, _
Tab:=False, Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar:="|"
Columns(2).Delete
End Sub


Gruß Daniel
Anzeige
AW: Daten sortieren per VBA Skript
06.06.2024 16:27:49
Alwin Weisangler
Hallo,

da du nur die paar Strings hinterlassen hast, bin ich mal von Tabelle 1 ab Zelle A1 ausgegangen.
Sortiert ist es ja schon. Für den Rest so:


Option Explicit

Sub umbauen()
Dim i&, j&, tmp, arr, arrList(), tmpVar, objDic As Object
Set objDic = CreateObject("Scripting.Dictionary")
With Tabelle1
For i = 1 To .Cells(Rows.Count, 1).End(xlUp).Row
tmp = Split(.Cells(i, 1), " ")
objDic(tmp(0)) = 0
Next i
ReDim arrList(1 To objDic.Count)
For i = 1 To objDic.Count
arr = objDic.Keys
tmpVar = arr(i - 1) & " "
For j = 1 To .Cells(Rows.Count, 1).End(xlUp).Row
tmp = Split(.Cells(j, 1), " ")
If tmp(0) = arr(i - 1) Then
tmpVar = tmpVar & tmp(1) & " "
End If
Next j
arrList(i) = tmpVar
tmpVar = ""
Next i
.Columns(1).ClearContents
.Cells(1, 1).Resize(UBound(arrList) - LBound(arrList) + 1, 1) = WorksheetFunction.Transpose(arrList)
End With
End Sub


Gruß Uwe
Anzeige
Wenn es nicht unbedingt...
07.06.2024 09:56:43
Case
Moin, :-)

... VBA sein muss, bietet sich für diese Datenmanipulation Power Query an. Wenn das in Frage kommt und du ein Beispiel brauchst, melde dich. ;-)

Servus
Case
AW: Wenn es nicht unbedingt...
07.06.2024 10:14:01
tarzipan7
Hallo, ich schaue mir das bei Gelegenheit mal an (PowerQuery)

Werde natürlich auch die anderen von euch vorgeschlagenen Lösungen ausprobieren.




Sub Makro1()
'
' Makro1 Makro
Dim ws As Worksheet
Dim SrcCell As Range
Dim DstCell As Range
Dim suchBereich As Range
Dim zielBereich As Range
Dim suchWert As Variant
Dim DstRange As Long
Dim RowsCnt As Long
Dim i As Integer
Dim j As Integer
Dim gefunden As Range
Dim quelleBereich As Range
Dim firstAddress As String



' Arbeitsblatt festlegen
Set ws = ActiveSheet

' Quellbereich auswählen
On Error Resume Next
Set SrcCell = Application.InputBox("Bitte die Startzelle im Quellbereich eingeben:", "Startzelle eingeben", Type:=8)
On Error GoTo 0
SrcCell.Select

' Abbrechen, wenn keine Startzelle ausgewählt wurde
If SrcCell Is Nothing Then Exit Sub

Set DstCell = Application.InputBox("Bitte die Zielzelle im Zielbereich eingeben:", "Zielzelle eingeben", Type:=8)
On Error GoTo 0
DstCell.Select

' Abbrechen, wenn keine Zielzelle ausgewählt wurde
If DstCell Is Nothing Then Exit Sub

SrcCell.Cells.Select

Range(Selection, Selection.End(xlDown)).Select
Selection.Copy

DstCell.Cells.Select
ActiveSheet.Paste
Range(Selection, Selection.End(xlDown)).Select

Selection.RemoveDuplicates Columns:=1, Header:=xlNo

DstCell.Cells.Select
Range(Selection, Selection.End(xlDown)).Select
Set zielBereich = Selection
RowsCnt = Selection.Rows.Count 'used for later loop
Selection.End(xlDown).Select

ActiveCell.Offset(1, 0).Range("A1").Select
Application.CutCopyMode = False


'----------------------------------------------------------------------------------
' Suchbereich festlegen
Set suchBereich = ws.Range("A1:A100")
suchBereich.Select


For i = 1 To RowsCnt
suchWert = zielBereich.Rows(i)

' Suchwert finden
Set gefunden = suchBereich.Find(What:=suchWert, LookIn:=xlValues, LookAt:=xlWhole)
gefunden.Select

If Not gefunden Is Nothing Then
firstAddress = gefunden.Address

Do
' Bereich rechts neben dem gefundenen Suchwert festlegen
Set quelleBereich = gefunden.Offset(0, 1)
'Set quelleBereich = ws.Range(gefunden.Offset(0, 1), ws.Cells(gefunden.Row, ws.Columns.Count).End(xlToLeft))
quelleBereich.Select
' Zielbereich festlegen (rechte letzte Zelle im Zielbereich)
Set letzteZielZelle = ws.Cells(zielBereich.Row, ws.Columns.Count).End(xlToLeft)
If IsEmpty(letzteZielZelle.Value) Then
Set zielZelle = letzteZielZelle
Else
Set zielZelle = letzteZielZelle.Offset(0, 1)
zielZelle.Select
End If

' Kopieren der Werte
quelleBereich.Copy Destination:=zielZelle

' Nächstes Vorkommen des Suchwerts finden
Set gefunden = suchBereich.FindNext(gefunden)
gefunden.Select
Loop While Not gefunden Is Nothing And gefunden.Address > firstAddress
End If
Next i
End Sub




Ich habe mal ein wenig rumprobiert, aber in dieser Zeile funktioniert das nicht:
Set letzteZielZelle = ws.Cells(zielBereich.Row, ws.Columns.Count).End(xlToLeft)


Diese Selektion sollte ja bei einer neuen Anwahl von a1 zum nächsten zb b1 auch um eine Zeile runtergehen und die Werte rechts davon reinkopieren.
Ich weiss, dass einige "selects" nicht nötig sind, habe diese nur reingemacht, so das ich beim Debuggen sehen kann, ob die richtige Zelle gewählt wird :-)

Viele Grüsse

Anzeige
AW: Wenn es nicht unbedingt...
07.06.2024 13:04:18
Yal
Hallo zusammen,

Power Query würde so aussehen:

- wandle deine Liste in einer Tabelle: Menü "Einfügen", "Tabelle" (wenn keine Überschrift vorhanden, werden "Spalte1" und "Spalte2" vergeben),
- ein Zelle der Tabelle aktivieren und Menü "Daten", "Aus Tabelle/Bereich",
- Du bist in Power Query Editor.
- Spalte 2 aufsteigend sortieren,
- Überschrift der zweiten Spalte rechtsklicken, "Typ ändern", "Text" auswählen,
- erste Spalte markieren (Überschrift anklicken),
- Menü "Transformieren", "Gruppieren nach"
- in der Bearbeitungsformel, so ändern, dass es so aussieht:
= Table.Group(#"Geänderter Typ1", {"Spalte1"}, {{"Anzahl", each Text.Combine([Spalte2], ";")}})
- Menü "Datei", "Schliessen & laden"
Fertig.

Falls die Quelle sich ändert, auf die Ergebnistabelle rechtsklicken und "aktualisieren" (die Transformation ist im Hintergrund damit "festprogrammiert")

VG
Yal
Anzeige
AW: Wenn es nicht unbedingt...
07.06.2024 13:32:46
tarzipan7
Hallo Yal,

Das sieht ja schon fast perfekt aus, aber die einzelnen Werte sollten jeder in einer Zelle stehen.

VG
Martin
AW: Wenn es nicht unbedingt...
07.06.2024 15:32:55
Yal
Dann füge folgende Aktion:

nach dem letzten Schritt
- die Spalte "Anzahl" markieren,
- Menü "Transformieren", "Spalte teilen", "nach Trennzeichen", Semikolon als Trennzeichen verwenden.
- Es fügt sich anschliessend automatisch einen Schritt "Typ ändern". Dieser Schritt muss gelöscht werden, weil hier auf einem festen Anzahl an Spalten gerechnet wird, was auf reale Daten nicht der Fall sein wird.

Auch der vorige Schritt muss korrigiert werden. Aus:
= Table.SplitColumn(#"Gruppierte Zeilen", "Anzahl", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Anzahl.1", "Anzahl.2", "Anzahl.3"})
müsste so gekürzt werden:
= Table.SplitColumn(#"Gruppierte Zeilen", "Anzahl", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv))
somit wird vermieden, dass die Aktion auf genau 3 Spalten festgelegt wird.

Geht ohne zu sagen, aber vielleicht doch besser, wenn man es sagt: es könnte sein, dass bei der eigenen Realisierung leicht abweichende Code entsteht, u.a. weil immer auf dem vorigen Schritt aufgebaut wird (hier: #"Gruppierte Zeilen"). Daher diese Code nicht so übernehmen, sondern schauen, was weggeschnitten würde und im eigenen Code ähnlich agieren.

weitere Info über Power Query: https://excelhero.de/power-query/power-query-ganz-einfach-erklaert

VG
Yal


Anzeige
AW: Daten sortieren per VBA Skript
07.06.2024 08:12:33
Alwin Weisangler
Hallo,

habs mal in deiner Datei eingebaut.
Um die olle Sortiererei kurz zu halten nutze ich .SortedList
Da braucht es aber Microsoft NET Framwork 3.5.
Damit sind noch weitere Annehmlichkeiten anwendbar.


Option Explicit

Sub SortierenZuweisen()
Dim i&, j&, k&, liste As Object, arr(), tmp()
Set liste = CreateObject("System.Collections.SortedList") 'MS NET Framwork 3.5 ist erforderlich - ggf. nachinstallieren
With Tabelle1
arr = .Range(.Cells(3, 1), .Cells(Rows.Count, 1).End(xlUp)).Value
For i = 1 To UBound(arr)
If arr(i, 1) > "" Then liste(arr(i, 1)) = ""
Next
.Range(.Cells(3, 4), .Cells(.Cells(Rows.Count, 4).End(xlUp).Row, 20)).ClearContents
For i = 1 To liste.Count
.Cells(i + 2, 4) = liste.GetKey(i - 1)
Next
For i = 1 To liste.Count
For j = 1 To UBound(arr)
If arr(j, 1) = .Cells(i + 2, 4) Then
k = k + 1
ReDim Preserve tmp(1 To 1, 1 To k)
tmp(1, k) = .Cells(j + 2, 2)
End If
Next j
.Cells(i + 2, 5).Resize(1, UBound(tmp, 2)) = tmp
k = 0
ReDim Preserve tmp(1 To 1, 1 To 1)
Next i
End With
End Sub

https://www.herber.de/bbs/user/169897.xls

Gruß Uwe
Anzeige
AW: Daten sortieren per VBA Skript
07.06.2024 14:03:27
tarzipan7
Hallo Uwe,

Super, nur der erste Eintrag bei a1 wird nicht übernommen. Ist es möglich auch eine Zielzelle wo die Daten abgelegt werden sollen, auszuwählen?

Gruss
Martin
AW: Daten sortieren per VBA Skript
07.06.2024 15:28:31
Alwin Weisangler
das wäre dann so:


Option Explicit
Private Const Zielzeile& = 3
Private Const Zielspalte& = 4

Sub SortierenZuweisen()
Dim i&, j&, k&, liste As Object, arr(), tmp()
Set liste = CreateObject("System.Collections.SortedList") 'MS NET Framwork 3.5 ist erforderlich - ggf. nachinstallieren
With Tabelle1
arr = .Range(.Cells(3, 1), .Cells(Rows.Count, 1).End(xlUp)).Value
For i = 1 To UBound(arr)
If arr(i, 1) > "" Then liste(arr(i, 1)) = ""
Next
If .Cells(Rows.Count, Zielspalte).End(xlUp).Row >= Zielzeile Then
.Range(.Cells(Zielzeile, Zielspalte), .Cells(.Cells(Rows.Count, Zielspalte).End(xlUp).Row, 20)).ClearContents
End If
For i = 1 To liste.Count
.Cells(i + Zielzeile - 1, Zielspalte) = liste.GetKey(i - 1)
Next
For i = 1 To liste.Count
For j = 1 To UBound(arr)
If arr(j, 1) = .Cells(i + Zielzeile - 1, Zielspalte) Then
k = k + 1
ReDim Preserve tmp(1 To 1, 1 To k)
tmp(1, k) = .Cells(j + 2, 2)
End If
Next j
.Cells(i + Zielzeile - 1, Zielspalte + 1).Resize(1, UBound(tmp, 2)) = tmp
k = 0
ReDim Preserve tmp(1 To 1, 1 To 1)
Next i
End With
End Sub


Gruß Uwe
Anzeige
AW: Daten sortieren per VBA Skript
07.06.2024 16:43:52
tarzipan7
Ich habe die Wahl des Zielbereiches jetzt so gemacht:

Sub EingabeFuerZielwerte()

Dim ZielZelle As Range

On Error Resume Next
Set ZielZelle = Application.InputBox("Bitte wählen Sie die Zielzelle aus:", "Zielzelle Auswahl", Type:=8)
On Error GoTo 0

If ZielZelle Is Nothing Then
MsgBox "Keine gültige Zelle ausgewählt. Bitte wählen Sie eine Zelle aus."
Exit Sub
End If

SortierenZuweisen ZielZelle.Row, ZielZelle.Column
End Sub


Ist das so einigermassen sauber?

Anzeige
AW: Daten sortieren per VBA Skript
07.06.2024 17:16:13
tarzipan7
Hi Uwe,

die sortierung der ersten spalte a1, b1 usw. soll nicht erfolgen, einfach von oben runter abarbeiten..............................
AW: Daten sortieren per VBA Skript
07.06.2024 20:27:51
Alwin Weisangler
Hallo,

von oben nach unten entspricht aber nicht deinen ursprünglichen Vorgaben.
Von oben nach unten wäre nämlich so:
a1
c1
b1
d1
e1
Das wäre dann so umsetzbar:


Option Explicit
Private Const Zielzeile& = 3
Private Const Zielspalte& = 4

Sub SortierenZuweisen()
Dim i&, j&, k&, liste As Object, arr(), arrList, tmp()
Set liste = CreateObject("Scripting.Dictionary")
With Tabelle1
arr = .Range(.Cells(3, 1), .Cells(Rows.Count, 1).End(xlUp)).Value
For i = 1 To UBound(arr)
liste(arr(i, 1)) = 0
Next
arrList = liste.keys
If .Cells(Rows.Count, Zielspalte).End(xlUp).Row >= Zielzeile Then
.Range(.Cells(Zielzeile, Zielspalte), .Cells(.Cells(Rows.Count, Zielspalte).End(xlUp).Row, 20)).ClearContents
End If
.Cells(Zielzeile, Zielspalte).Resize(UBound(arrList) - LBound(arrList) + 1, 1) = WorksheetFunction.Transpose(arrList)
For i = 1 To liste.Count
For j = 1 To UBound(arr)
If arr(j, 1) = .Cells(i + Zielzeile - 1, Zielspalte) Then
k = k + 1
ReDim Preserve tmp(1 To 1, 1 To k)
tmp(1, k) = .Cells(j + 2, 2)
End If
Next j
.Cells(i + Zielzeile - 1, Zielspalte + 1).Resize(1, UBound(tmp, 2)) = tmp
k = 0
ReDim Preserve tmp(1 To 1, 1 To 1)
Next i
End With
End Sub


Gruß Uwe
Anzeige
;

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige