Как отсортировать столбец со смешанными данными даты и общего формата с помощью VBA в Excel 2003 - PullRequest
0 голосов
/ 19 января 2012

Во-первых, извиняюсь, что я делаю много ошибок в лучшей практике VBA. В частности, я изучал язык для этого проекта, и, возможно, я делаю что-то не так, извините, если я заставлю кого-нибудь съежиться.

Далее проблема. Я пытаюсь отсортировать диапазон по дате (хранится в одном столбце) точно так, как работает функция сортировки в меню инструментов при сортировке «всего, что выглядит как число как число». Столбец представляет собой смесь дат в локали Великобритании и текстовых строк, содержащихся в «общих» отформатированных ячейках, которые по сути являются просто датами. Другими словами, что-то простое, как:

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

должен сделать трюк. Действительно, я думаю, что единственным исключением является то, что записанный код использует xlGuess для заголовка и включает значение для 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). Это делает работу сортировки. Также требуется 10 секунд, чтобы переформатировать столбец с 20 записями, потому что между листом и 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 Ответ

2 голосов
/ 19 января 2012

Вы правы, если говорите, что ссылка на лист в цикле медленная, но этого можно избежать, скопировав данные в массив вариантов и зациклив их, а затем скопируйте обратно на лист:

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 строк) </p>

Обратите внимание, я сделал несколько незначительных изменений, чтобы запустить его

...