Хорошей практикой является явная квалификация объекта, с которым вы работаете. Это причудливый способ сказать "определить объект"
Возможно, вы уже читали что-то подобное раньше, и я уверен, что вы будете читать что-то подобное снова и снова. Проблема с вашим кодом оказывается отличным примером того, почему это хорошая практика.
Рассмотрим фразу: «это хорошая практика».
Что такое Я говорю или, что более важно, на что я намекаю?
Я не говорю прямо, что вы обязаны квалифицировать объект; на самом деле, я неявно говорю, что у вас есть выбор, что это не требование.
Это именно то, что вы сделали с этой строкой: Rows.Delete
Rows
является свойством объекта рабочего листа, и свойства не существуют в вакууме, они всегда сопровождают объект, которому они принадлежат. Вы не указали явно объект рабочего листа, скорее, вы неявно разрешили VBA использовать объект рабочего листа по умолчанию.
Итак, вы неявно написали следующее: ActiveSheet.Rows.Delete
И это именно то, что ваш макрос делает, он удаляет строки активного листа.
Я рекомендую запустить код после замены его на эту строку: cell.EntireRow.Delete
Если вы сделаете это, вы должны заметить что-то смешное , Если раньше вы последовательно удаляли каждую строку на рабочем листе, то теперь вы непоследовательно удаляете всего 50% строк, которые хотите удалить.
Почему? Мы исправили это, что случилось?
Удаление элементов из индексированного списка - распространенная проблема для новых программистов. Использовать настольную игру в качестве аналогии. Вы запланировали всю игру. Вы делаете один ход, затем другой и так далее. Но вы полностью пренебрегли своим противником. Они тоже по очереди!
Позвольте мне спросить вас, если вы удалите первую строку на рабочем листе, с какого номера строки начнется рабочий лист?
Итак, что происходит, вы удаляете строку, и Excel сразу же сдвигает строки вверх со строки 2, становясь строкой 1. Поэтому, когда вы переходите к строке 2, вы фактически пропускаете строку 2 и приземляетесь в 3.
Хорошая новость заключается в том, что эту проблему легко решить. Просто go назад. В случае таблицы это означает запуск с последней строки и переход к первой строке.
Это можно сделать с помощью For
l oop, используя необязательный параметр Step
со значением из -1.
Например (половина каламбура предназначена):
For I = objTable.Listrows.Count to 1 Step -1
К сожалению, вы должны использовать итератор индексации. For Each
не работает Step
.
Теперь ваш код должен работать, как и ожидалось.
Но прежде чем класс закрывается, давайте поговорим о Select
.
В слово: «Не»
Как и в «Вы не макро-рекордер, поэтому не пишите такой код». Это сделает ваш код медленным. Это по-прежнему делает ваш код более подверженным ошибкам и ошибкам.
Так что у вас есть. Ваша домашняя работа состоит в том, чтобы научиться явно квалифицировать объекты, чтобы избежать неявного использования ActiveSheet
. Как использовать Step
в For
l oop. И как избежать использования Select