如何使用Excel 2003中的VBA对混合日期和常规格式数据列进行排序

时间:2012-01-19 02:09:54

标签: excel optimization sorting vba excel-2003

首先,如果我在最佳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

1 个答案:

答案 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行)

注意,我做了几个小小的推文来让它运行