Excel VBA如何对单行范围进行排序

4

我有一个被定义为范围的变量

Set myRange=Range("$E$10,$G$10,$I$10")

这些单元格中的值是-1、-1.2、1。 当我遍历这个范围时,输出的值按照-1、-1.2、1的顺序打印。
我想对这个范围进行排序,以便遍历时看到:-1.2、-1、1
我不想在实际工作表中重新组织这些单元格。
基本上我试图模仿正常编程语言中的排序函数,但针对 Excel 范围,我希望 'cells' 在范围数据结构内重新排列。
我尝试了一种天真的方法。
myRange.Sort key1:=myRange.Item(1, 1), order1:=xlAscending, Header:=xlNo

但它并没有做任何事情。


你最好的做法是创建一个范围数组并对其进行排序。 - Tim Williams
@Tim,是的 - 看起来下面的建议答案基本上正在做这件事:从范围中提取值,将它们放入另一个数据结构中,然后对其进行排序。似乎在提取/排序过程中我将不得不丢失单元格地址 - 除非我构建一个自定义机制,在提取/排序步骤之后记住单元格地址。 - V P
不需要把值提取到一个数组中,只需要提取每个单元格。似乎可以很容易地调整下面的答案,根据其元素值对数组进行排序。 - Tim Williams
2个回答

3
Excel无法对非连续范围进行排序。但是使用ArrayList对值进行排序,很容易按顺序获取范围的值。将SortAnyRangeDesc参数设置为true,可以按降序对范围进行排序。enter image description here(仅限Windows)
Sub TestSortAnyRange()
    SortAnyRange Range("$E$10,$G$10,$I$10")
End Sub

Sub SortAnyRange(Target As Range, Optional Desc As Boolean)
    Dim r As Range
    Dim list As Object
    Set list = CreateObject("System.Collections.ArrayList")
    For Each r In Target
        list.Add r.Value
    Next

    list.Sort

    If Desc Then list.Reverse

    For Each r In Target
        r.Value = list(0)
        list.Remove list(0)
    Next

End Sub

MAC还是WINDOWS

这位用户请求一个子程序能在Mac或Windows平台上工作。因此,我重构了我的代码,用一个数组和一个冒泡排序程序代替了ArrayList(Mac上不可用)。

Sub SortAnyRange(Target As Range, Optional Desc As Boolean)
    Dim r As Range
    Dim list
    Dim i As Long, j As Long

    ReDim list(0 To Target.Cells.Count - 1)

    For Each r In Target
      list(i) = r.Value
      i = i + 1
    Next

    For i = LBound(list) To UBound(list)
        For j = i + 1 To UBound(list)
            If list(i) > list(j) Then
                SrtTemp = list(j)
                list(j) = list(i)
                list(i) = SrtTemp
            End If
        Next j
    Next i

    i = IIf(Desc, UBound(list), 0)

    For Each r In Target
        r.Value = list(i)
        i = i + IIf(Desc, -1, 1)
    Next

End Sub

谢谢。在 Mac Excel 2013+ 上会有 "System.Collections.ArrayList" 或 "System.Collections.SortedList" 吗?或者这个强大的.NET集成机制只能在 Windows 上使用?(我有一些用户仍在使用 Mac) - V P
感谢确认MacOS上的Excel无法访问.NET。同时,感谢提供手动实现冒泡排序的解决方法。不幸的是,在最后一个r.value = list(i)处出现了错误/异常。(我正在使用Desc=True)。 - V P
@VP Mac 必须是 Option Base 1。我已经更新了我的答案。 - user6432984

0

编辑:在 OP 澄清目标操作系统(Windows 和 MAC OS)并且他/她实际上想要“重新组织”单元格后,我进行了编辑。

我会使用 Excel 的 Sort() 方法和 Range 对象的所有内置功能来完成这个任务。

为此,我将使用一个“辅助”范围,将传递的范围值放入其中,对其进行排序,并从后向传递的范围中写入排序后的值,具体如下:

Sub OrderRange(rng As Range)
    Dim cell As Range
    Dim iCell As Long

    With rng.Parent.UsedRange
        With .Resize(1, 1).Offset(, .Columns.Count)
            For Each cell In rng '<-- fill "helper" range with passed range values
                .Offset(iCell).Value = cell.Value
                iCell = iCell + 1
            Next cell
            .Resize(iCell).Sort key1:=.Range("A1"), order1:=xlAscending, Header:=xlNo '<-- sort "helper" range values
            iCell = 0
            For Each cell In rng '<-- write sorted "helper" range values back to passed range
                cell.Value = .Offset(iCell).Value
                iCell = iCell + 1
            Next cell
            .Resize(iCell).ClearContents '<--| clear "helper" range
        End With
    End With
End Sub

用法如下:

OrderRange Range("$E$10,$G$10,$I$10")

@V P,你通过了吗? - user3598756

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接