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

у удалить все строки, которые не содержат значение «Всего» в диапазоне («B11: B25»).

Ниже мой код.

Dim cell As Range

For Each cell In Range("B11:B25")
    If cell.Value <> "Total" Then
    cell.EntireRow.Delete
End If

Next

End Sub

Приведенный выше код удалит только некоторые строки с ячейками, которые не имеют значения «Итого». Если мне придется удалить все строки, которые не содержат «Всего», мне придется выполнить это несколько раз, что нецелесообразно.

 Patrick Honorez18 дек. 2017 г., 17:26
Когда вы удаляете строки, вы всегда должны зацикливаться снизу вверх.
 Patrick Honorez18 дек. 2017 г., 17:29
и я бы не назвал переменнуюcell что, вероятно, зарезервированное слово
 Mathieu Guindon18 дек. 2017 г., 19:18
@PatrickHonorez, это чрезвычайно наивная и неэффективная идея. Изменение коллекции, которую вы повторяете, - ужасный совет на любом языке, VBA ничем не отличается. Также еслиcell было незаконно, код не будет компилироваться. VBA не только размещен в Excel; не все приложения хоста VBA имеют ячейки.cell быть "сдержанным" не имеет смысла.
 Taelsin18 дек. 2017 г., 17:39
@PatrickHonorezcell не является зарезервированным словом в VBA. Я не могу найти источник для этого от Microsoft, ноВот это то, что я нашел с помощью быстрого поиска в Google

Ответы на вопрос(2)

которую вы повторяете, всегда плохая идея. Конечно, вы могли бы начать с конца и назвать это днем, но тогда ваш следующий вопрос будет звучать так: «мой код мучительно медленный, как мне сделать его быстрее?»

ЕстьCombineRanges функция, ответственная заUnionдиапазоны:

Private Function CombineRanges(ByVal source As Range, ByVal toCombine As Range) As Range
    If source Is Nothing Then
        Set CombineRanges = toCombine
    Else
        Set CombineRanges = Union(source, toCombine)
    End If
End Function

Теперь измените ваш цикл так, чтобы вместо удаления строк он определял, какие строки нужно удалить:

Dim toDelete As Range
Dim cell As Range
For Each cell In ActiveSheet.Range("B11:B25")
    If cell.Value <> "Total" Then Set toDelete = CombineRanges(toDelete, cell)
Next

If Not toDelete Is Nothing Then toDelete.EntireRow.Delete

И теперь у вас есть эффективный цикл (всегда повторяйте коллекции объектов сFor Each цикл), который не изменяет коллекцию объектов, которую он повторяет, делает только одно, и у вас есть одинDelete продолжается операция, которая вызовет только один листChanged событие, один единственный пересчет, и будет хорошо работать независимо от того, удаляете ли вы 20 или 2000 строк.

он будет цикл от строки 25 до 11 в обратном направлении и найти что-нибудь не "Всего"

Dim i As Integer
For i = 25 To 11 Step -1 ' change to whatever row you want
    If Range("B" & i) <> "Total" Then
        Range("B" & i).EntireRow.Delete
    End If
Next
 NCHBanna18 дек. 2017 г., 17:51
Спасибо за эту работу. Однако, как мне выполнить обратный цикл, если я не знаю, где заканчиваются мои данные в этом столбце. Данные всегда начинаются с B11. Я попытался использовать функцию .end VBA, но не смог заставить ее работать.
 SilentRevolution18 дек. 2017 г., 18:41
Если ваши данные всегда начинаются с B11 и непрерывны до конца (без пустых строк), используйтеFor i = 11 to Cells(11,2).End(xlDown).Row Step -1 В качестве примечания, этот и остальная часть кода предполагаютActiveSheet что может быть плохой идеей, если у вас есть несколько листов или рабочих книг, которые могут быть активными.

Ваш ответ на вопрос