Удалить строки с повторяющимися данными VBA

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

Вот пример набора данных:

9:30:01 584.7
9:30:01 590
9:30:01 595
9:30:02 584.51
9:30:03 584.62
9:30:04 584.44
9:30:05 584.05

Мне нужна только одна строка в секунду, поэтому из первых 3 строк должна остаться только одна. Мне все равно, первый это или последний, но код, который я использовал, сохраняет последний, 595 в данном случае.

Я делаю это с помощью цикла for, который очищает содержимое строки, которая имеет то же время, что и строка под ней. Затем я сортирую весь диапазон.

Я предполагаю, что есть более простой способ просто удалить лишнюю строку с самого начала. Однако, когда я использую удаление в диапазоне вместо очистки, он не удалит все повторяющиеся строки.

Вот как я хочу, чтобы данные выглядели так:

9:30:01 595
9:30:02 584.51
9:30:03 584.62
9:30:04 584.44
9:30:05 584.05

Мне нужно, чтобы это произошло для всего листа. Время — столбец B, а значения — столбец C.

Вот код, который я использую,

LastRow = ActiveSheet.UsedRange.row - 1 + _
    ActiveSheet.UsedRange.Rows.Count

For RowNum = 2 To LastRow
    If (Range("B" & RowNum) = Range("B" & RowNum + 1)) Then
    Range("B" & RowNum).EntireRow.Clear
    End If
Next RowNum

Range("A2:C" & LastRow).Sort key1:=Range("B2:B" & LastRow), _
order1:=xlAscending, Header:=xlNo

person mks212    schedule 23.05.2014    source источник
comment
Если вы зацикливаете снизу вверх, вы можете мгновенно удалить строку. Поделитесь своим кодом, и я помогу вам с этим.   -  person Automate This    schedule 23.05.2014
comment
@PortlandRunner представляет отличное решение — вы также можете потенциально использовать для этого метод Range.RemoveDuplicates (тем более, что ваша структура столбцов так хорошо определена)... Вот ссылка на MSDN: msdn.microsoft.com/en-us/library/office/   -  person Dan Wagner    schedule 23.05.2014
comment
@Portland Runner Я добавил код. Ваша идея звучит очень умно.   -  person mks212    schedule 23.05.2014


Ответы (2)


Не зацикливайтесь. Используйте RemoveDuplicates. Намного быстрее, чем любой цикл. Одна строка кода.

Sub test()
    ActiveSheet.Range("B:C").RemoveDuplicates Columns:=1, Header:=xlNo
End Sub

Изменить: скриншоты

ДО

введите здесь описание изображения

ПОСЛЕ

введите здесь описание изображения

Изменить: не работает в Excel 2011 для Mac (поймите).

person teylyn    schedule 23.05.2014
comment
Это работает только тогда, когда значения в обоих столбцах дублируются. Он не удаляет строки, основываясь только на том факте, что 9:30:01 повторяется. - person mks212; 23.05.2014
comment
@user2926358 user2926358 Я добавил несколько скриншотов и изменил код в столбцах B и C вместо A и B. - person teylyn; 23.05.2014
comment
@teylyn Возможно ли, что это не работает на Mac? Я использую Excel 2011 и не играю в кости. Я запускал его на своем старом ПК, и он работал. Спасибо. - person mks212; 23.05.2014
comment
Вы никогда не упоминали Mac. Я не делаю Мак. Есть ли на ленте данных значок «Удалить дубликаты»? - person teylyn; 23.05.2014
comment
+1 и за это решение. Но комментарий выше +1 за циклы, они всегда работают (даже на Mac ;-)) - person Jzz; 23.05.2014
comment
Оно делает. И код будет работать до тех пор, пока данные в столбцах B и C повторяются. Какой-то позор, так как это обрабатывается только одной строкой, а не циклом. - person mks212; 23.05.2014
comment
Кажется, есть доказательство того, что метод RemoveDuplicates не работает на Mac. - person teylyn; 23.05.2014
comment
Это не первый случай, когда метод не работает в Excel 2011. Спасибо, что нашли эту ссылку. - person mks212; 23.05.2014

Это должно помочь:

Sub jzz()
Dim i As Long
For i = 1 To Cells.SpecialCells(xlLastCell).Row 'loop from row 1 to last row
    If Cells(i, 1) <> vbNullString Then 'check if something is in the cell
        If Cells(i, 1) = Cells(i + 1, 1) Then 'check if cell is the same as next cell
            Cells(i + 1, 1).EntireRow.Delete 'if so; delete
            i = i - 1 'go back one row
        End If
    End If
Next i
End Sub

Другой вариант — идти снизу вверх, например:

Sub jzz()
Dim i As Long
For i = Cells.SpecialCells(xlLastCell).Row to 1 step -1'loop from last row to row 1
    If Cells(i, 1) <> vbNullString Then 'check if something is in the cell
        If Cells(i, 1) = Cells(i + 1, 1) Then 'check if cell is the same as next cell
            Cells(i + 1, 1).EntireRow.Delete 'if so; delete
        End If
    End If
Next i
End Sub

что вы предпочитаете использовать, если личное. Пожалуйста, рассмотрите также ответ тейлина, в этой ситуации он очень удобен.

person Jzz    schedule 23.05.2014
comment
Спасибо Джзз. У меня было что-то подобное, и он удаляет только второй элемент и оставляет третий. - person mks212; 23.05.2014
comment
Извините, это моя ошибка! Просто забыл одну (важную) строку кода. Я отредактировал свой ответ. Хитрость заключается в том, чтобы вернуться на одну строку назад после удаления строки под ней, чтобы значение снова оценивалось. - person Jzz; 23.05.2014
comment
Jzz, это делает это! Я мог бы поспорить на большую сумму денег, что попробовал именно это, но это не сработало. Я прогоню это на полном наборе данных завтра, надеюсь, это сработает. Спасибо еще раз. - person mks212; 23.05.2014
comment
Ааа, я имел в виду: For i = Cells.SpecialCells(xlLastCell).Row to 1 Step -1 но тогда вам нужно изменить кое-что еще. - person Automate This; 23.05.2014
comment
Каков правильный шаг, чтобы цикл for начинался снизу? Кажется, я не могу заставить его работать. (новичок в VBA, я знаю) - person mks212; 23.05.2014