首先,如果我在最佳VBA练习中犯了很多错误,我会道歉。我一直在学习这个项目的语言,并且可能有很多我做错的事情,如果我让任何人畏缩,那就很抱歉。
接下来,问题。我正在尝试按日期(在一列中保存)对范围进行排序,完全按照工具菜单上的排序功能在排序“任何看起来像数字的数字”时的工作方式。该列是英国语言环境日期和文本字符串的混合,保存在“一般”格式化单元格中,基本上只是日期。换句话说,简单的事情如下:
Range(rngFirstCell, rngLastCell).Sort Key1:= 2, Order1:=xlAscending, _
DataOption1:=xlSortTextAsNumbers, Header:=xlYes
应该做的伎俩。实际上,我认为唯一的例外是记录的代码使用xlGuess作为Header,并包含OrderCustom为1的值,这正是宏记录器产生的。毋庸置疑,我已尝试使用相同结果录制代码。
问题是,而不是得到:
Type Date
gen 01/3/2008
date 02/4/2008
date 17/4/2008
gen 25/7/2009
我明白了:
Type Date
date 02/4/2008
date 17/4/2008
gen 01/3/2008
gen 25/7/2009
由于这适用于更高版本的Excel,我在2003年得出结论是一个错误。我当前的解决方案是首先将列中所有单元格的NumberFormat属性设置为“d / m / yyyy”,并且然后迭代它们并用CDate(Cell.Value)的结果替换每个值。它使排序工作。重新格式化一个包含20个条目的列需要10秒钟,因为工作表和VBA之间存在很多交互(从我读过的内容很慢)。因为我需要按代码排序的一些数据集完全有可能是数百个单元格,所以我需要更快的东西。
有人能建议更好的方法吗?
为清楚起见,我现在使用的代码看起来很像:
Range(rngFirstCell, rngLastCell).Columns(2).NumberFormat = "d/m/yyyy"
Dim intIndex As Long, varCellRef As Variant
For intIndex = 0 to Range(rngFirstCell, rngLastCell).Columns(2).End(xlDown).Row
Set varCellRef = Range(rngFirstCell, rngLastCell).Columns(2)(intIndex)
varCellRef.Value = CDate(varCellRef.Value)
Next
Range(rngFirstCell, rngLastCell).Sort Key1:= 2, Order1:=xlAscending, _
DataOption1:=xlSortTextAsNumbers, Header:=xlYes
答案 0 :(得分:2)
你是正确的说,在循环中引用工作表很慢,但可以通过将数据复制到变量数组并循环遍历它,然后复制回工作表来避免它:
Dim rngFirstCell As Range
Dim rngLastCell As Range
' Setting a sample range for my testing...
Set rngFirstCell = [B12]
Set rngLastCell = [C131084]
Dim dat As Variant
Dim rng As Range
Dim i As Long
Set rng = Range(rngFirstCell, rngLastCell) ' this includes the header row
dat = rng.Columns(2)
rng.Columns(2).NumberFormat = "d/m/yyyy"
Dim intIndex As Long, varCellRef As Variant
For i = 2 To UBound(dat, 1)
dat(i, 1) = CDate(dat(i, 1))
Next
rng.Columns(2) = dat
rng.Sort Key1:=rng.Cells(1, 2), Order1:=xlAscending, _
DataOption1:=xlSortTextAsNumbers, Header:=xlYes
这是在<<< 1秒(约130,000行)
注意,我做了几个小小的推文来让它运行