首页 > 解决方案 > 在 Excel 中对数据块进行排序

问题描述

我在 Excel 中的数据格式如下例所示,信息块分布在 3 行中。有没有办法通过块中的一条数据对列进行排序?即按老师或房间对A列中的块进行排序?

A栏 B栏 C栏
A/Sc 类 A/Sc 类 B类/Sp
老师A 老师A 乙老师
1号房间 1号房间 2号房间
A类/嗨 A级/En B类/Sp
C老师 丁老师 乙老师
3号房间 4号房间 2号房间
A/Re 类 A类/Ge B类/Ru
C老师 乙老师 F老师
5号房间 2号房间 3号房间

我精通 VBA,但我无法找出任何适用于这种数据排列的排序方法。

非常感谢您的帮助。

编辑:结果将根据列出的字符之一对每一列进行独立排序,因此在上面的数据中,可以看出 A 列已按房间 (1,3,5) 排序,而 B 列不是 (1, 4,2)。

标签: excelvbasorting

解决方案


编辑:当我开始发帖时,没有看到已经接受的答案。我将把这个答案作为一种替代方法。


因为我们知道我们需要在将数据添加到数组时对其进行排序,所以我只使用可用的排序列表类之一。您必须包含有关记录高度的一些信息,以及有关如何将其存储回工作表的一些详细信息。

在下面的示例中,我使用了 SortedList 类。一个函数获取我们想要排序的记录“字段”。因此,如果要根据 Class 进行排序,请为第一个元素传入 1。对于老师,第二个元素传递 2 等等。(我肯定会包括一些边界检查以确保有人不会传递太大的数字。

由于数据最终排序,您只需将数据推回工作表即可。

如果您有任何后续问题,请告诉我。

Const HEIGHT_OF_RECORD As Integer = 3

Private Function SortColumnCuston(rng As Range, nSortElement As Integer) As Object
    Dim oList As Object
    Dim oTempDict As Object
    Dim startingCell As Range
    
    'Below just takes the first cell of the passed range and stores it to a variable
    'Doesn't matter if it's actually range("A1")
    Set startingCell = rng.Range("A1")
    
    Set oList = CreateObject("System.Collections.SortedList")
    
    For i = 0 To rng.Rows.Count - HEIGHT_OF_RECORD Step HEIGHT_OF_RECORD
        Set oTempDict = CreateObject("Scripting.Dictionary")
        oTempDict.Add "Class", startingCell.Offset(i).Value
        oTempDict.Add "Teacher", startingCell.Offset(i + 1).Value
        oTempDict.Add "Room", startingCell.Offset(i + 2).Value
        
        oList.Add rng.Range("A1").Offset(i + nSortElement - 1).Value, _
            oTempDict
    Next i
    
    Set SortColumnCuston = oList
End Function

Sub Test()
    Dim oDang As Object
    Dim sortDestinationStart As Range
    
    Set oDang = SortColumnCuston(Range("A1:A9"), 3)
    
    'This is where you want to paste the sorted data.
    'Note: it WILL overwrite what's there now, so be aware
    'of formulas, etc.
    Set sortDestinationStart = Range("F1")
    
    For i = 0 To oDang.Count - 1
        sortDestinationStart.Offset(i * HEIGHT_OF_RECORD).Value = _
            oDang.GetByIndex(i)("Class")
        sortDestinationStart.Offset(i * HEIGHT_OF_RECORD + 1).Value = _
            oDang.GetByIndex(i)("Teacher")
        sortDestinationStart.Offset(i * HEIGHT_OF_RECORD + 2).Value = _
            oDang.GetByIndex(i)("Room")
    Next i
End Sub

推荐阅读