如何在Excel 2003中使用VBA对混合date和一般格式数据的列进行sorting

首先,如果我在最好的VBA练习中犯了很多错误,我很抱歉。 特别是我一直在学习这个项目的语言,可能有很多事情我做错了,如果我让任何人感到惭愧,那么很抱歉。

接下来是问题。 我想按照date排列一个范围(保存在一列中),就像在sorting“看起来像一个数字的数字的东西”时工具菜单上的sorting函数一样。 该列是英国本地语言date和文本string混合在“一般”格式的单元格中,基本上只是date。 换句话说,像这样简单的事情:

Range(rngFirstCell, rngLastCell).Sort Key1:= 2, Order1:=xlAscending, _ DataOption1:=xlSortTextAsNumbers, Header:=xlYes 

应该做的伎俩。 事实上,我认为唯一的例外是录制的代码使用xlGuess作为Header,并且包含OrderCustom的值为1,正是macros录制器产生的。 不用说,我试过logging的代码,结果相同。

问题是,而不是得到:

 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年的一个bug。我当前的解决scheme是首先将列中所有单元格的NumberFormat属性设置为“d / m / yyyy”,然后迭代在它们上面,用CDate(Cell.Value)的结果replace每个值。 它使sorting工作。 由于表单和VBA之间有太多的交互(从我读过的很慢),所以还需要10秒来重新格式化一个包含20个条目的列。 因为我需要按代码sorting的一些数据集完全有可能是数百个单元,我需要更快一些。

任何人都可以build议一个更好的方式做到这一点

为了清楚起见,我目前使用的代码看起来非常像:

 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 

在循环中引用表单是很慢的,但是可以通过将数据复制到variables数组并循环来避免,然后将其复制回表单:

 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秒(约13万行)的样本数据集上运行,

请注意,我做了一些小小的推文让它运行