我正在尝试编写代码,其中某人可以输入数据应该排序的列名列表:
排序数据是位于同一张纸上的动态范围:
以下是我目前的代码:
updateTab = Sheets("RAW_DATA_SO").Range("B8")
lastRow = Sheets("RAW_DATA_SO").Range("A1048576").End(xlUp).Row
Dim sortBy() As String
ReDim sortBy(lastRow - 12)
For rowNumber = 12 To lastRow
sortBy(rowNumber - 12) = Sheets("RAW_DATA_SO").Range("A" & rowNumber)
Next
lastColumnAddress = Sheets("RAW_DATA_SO").Range("XFD1").End(xlToLeft).Address(False, False)
serchrange = "A1:" & lastColumnAddress
Set sortRange = Range(Cells(1, 10), Cells(lastRow, lastColumn))
For i = 0 To UBound(sortBy)
Set FindColumn = Sheets("RAW_DATA_SO").Range(serchrange).Find(What:=sortBy(i), LookIn:=xlValues, LookAt:=xlWhole)
sortByColumn = FindColumn.Address(ReferenceStyle)
sortRange.Sort key1:=Range(sortByColumn), order1:=xlAscending, Header:=xlYes
Next
问题是数据每次只排序一列。我如何重写数据按多列排序的排序过程?我发现代码可以添加更多列,但它们不灵活,总是假设我们现在按数据列排序多少列。我想让它可以添加排序依据列表...
答案 0 :(得分:1)
这里有一些代码我很快就被淘汰了所以按照名字排序....但你应该明白这个想法...
Public Sub SortColumns(ByVal DataTable As Range, ParamArray ColumnNames() As Variant)
Dim vColName As Variant
Dim rSortCol As Range
DataTable.Parent.Sort.SortFields.Clear
For Each vColName In ColumnNames
Set rSortCol = FindColumn(DataTable, vColName)
If Not rSortCol Is Nothing Then _
DataTable.Parent.Sort.SortFields.Add Key:=rSortCol, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
Next
With DataTable.Parent.Sort
.SetRange DataTable
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Public Function FindColumn(ByVal DataTable As Range, ByVal ColumnName) As Range
Dim rPtr As Range, rHeader As Range
Set rHeader = DataTable.Resize(1)
Set rPtr = rHeader.Find(ColumnName, rHeader(rHeader.Count), XlFindLookIn.xlValues, XlLookAt.xlWhole)
If Not rPtr Is Nothing Then Set FindColumn = rPtr.Resize(DataTable.Rows.Count)
End Function
答案 1 :(得分:1)
鉴于VBA可以同时执行最多三个键,看起来在列出的排序键字段中倒退是最好的。
Sub dynamic_sort()
Dim lc As Long, lr As Long, v As Long, k As Long, vKEYs As Variant
With Sheets("RAW_DATA_SO")
With .Range(.Cells(12, 1), .Cells(12, 1).End(xlDown))
vKEYs = .Value2
End With
Debug.Print LBound(vKEYs, 1) & ":" & UBound(vKEYs, 1)
Debug.Print LBound(vKEYs, 2) & ":" & UBound(vKEYs, 2)
For k = LBound(vKEYs, 1) To UBound(vKEYs, 1)
Debug.Print vKEYs(k, 1)
Next k
lr = .Cells(Rows.Count, 10).End(xlUp).Row
lc = .Cells(1, Columns.Count).End(xlToLeft).Column - 9
With .Cells(1, 10).Resize(lr, lc)
For v = UBound(vKEYs, 1) To 1 Step -3
Select Case v
Case Is > 2
.Cells.Sort Key1:=.Columns(Application.Match(vKEYs(v - 2, 1), .Rows(1), 0)), Order1:=xlAscending, _
Key2:=.Columns(Application.Match(vKEYs(v - 1, 1), .Rows(1), 0)), Order2:=xlAscending, _
Key3:=.Columns(Application.Match(vKEYs(v, 1), .Rows(1), 0)), Order3:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
Case 2
.Cells.Sort Key1:=.Columns(Application.Match(vKEYs(v - 1, 1), .Rows(1), 0)), Order1:=xlAscending, _
Key2:=.Columns(Application.Match(vKEYs(v, 1), .Rows(1), 0)), Order2:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
Case 1
.Cells.Sort Key1:=.Columns(Application.Match(vKEYs(v, 1), .Rows(1), 0)), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
End Select
Next v
End With
End With
End Sub
如果要排序的字段超过三个,则需要先对辅助字段进行排序,然后在逐步转向主键时继续排序。
Select Case statement提供三种排序选项,以便始终使用最大键数。
我可以从你的代码和示例图像中收集到的最好的是 SORT BY 列标签位于'RAW_DATA_SO'中!A11的排序键位于A12以下。排序范围的左上角是'RAW_DATA_SO'!J1,并且排序范围有一个标题行。