Excel VBA如何对单行范围进行sorting

我有一个范围定义为

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

这些单元格中的值是-1,-1.2,1当我遍历范围时,我得到打印的值的顺序为-1,-1.2,1

我想sorting这个范围,所以当我遍历范围,我会看到: -1.2,-1,1

我不想在实际的工作表中重新组织这些单元格。

我基本上是试图模仿一个正常的编程语言的sortingfunction,但对于Excel的范围,我期望的'细胞'重新安排在范围数据结构

我试过一个天真的

 myRange.Sort key1:=myRange.Item(1, 1), order1:=xlAscending, Header:=xlNo 

但它什么都不做

Excel不会sorting非连续的范围。

但是使用ArrayList对值进行sorting很容易获得范围值。 使用SortAnyRange并将其Desc参数设置为true将按降序对范围进行sorting。

在这里输入图像描述

只有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

OP要求可以在Mac或Windows平台上工作的子程序。 出于这个原因,我重构了我的代码,用数组和BubbleSort例程代替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 

在OP澄清目标操作系统(包括Windows和MAC OS)之后进行编辑 ,他/她实际上希望细胞被“重组”

我会使用Range对象的excel Sort()方法,并利用它的所有内置function

为此,我将使用一个“助手”范围,把传入的范围值,sorting,并将sorting的值从后面写入传递的范围,如下所示:

 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")