2012-04-09 4 views
4

Я пытаюсь написать макрос, чтобы удалить все строки, которые имеют «True» в столбце A.VBA: Удаление строк с определенным значением

Вот то, что я до сих пор:

Sub deleteBlankRows3() 
Dim lastrow as Long 
Dim x as Long 

lastrow = 4650 
For x=8 to x=lastrow 
    If (Range("A1").Offset(x,0) = True) Then 
    Range("A1").Offset(x,0).EntireRow.Delete 
    x = x + 1 
End if 
Next x 

End Sub 

Я не могу сказать, что случилось!

ответ

4

Здесь могут быть три вещи.

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

If (Range("A1").Offset(x,0).Value = True) Then 

Без saying.Value, я думаю, что ячейка по умолчанию возвращает это свойство Text для тесты эквивалентности с недиапазонным свойством.

Во-вторых, ваши клетки, вероятно, содержат строку «True», а не значение True так попробуйте использовать

If (Range("A1").Offset(x,0).Value = "True") Then 

Наконец, если вы на самом деле найти строку и удалить его, то ваш будет фактически конец (строка 5 становится строкой 4 и т. д.), но вы также просто увеличили x, поэтому вы будете пропускать строку сразу после каждой удаленной строки , Чтобы это исправить, либо цикл в порядке убывания:

For x=lastrow to 8 step -1 

или не увеличивают х, если вы только что удалил строку:

If (Range("A1").Offset(x,0).Value = "True") Then 
    Range("A1").Offset(x,0).EntireRow.Delete 
Else 
    x = x + 1 
EndIf 
+0

Спасибо большое!Прямо на всех трех моментах, ха-ха. –

2

Без тестирования вы лучше так:

For x=lastrow to 8 step -1 
     If (Range("A1").Offset(x,0) = True) Then 
      Range("A1").Offset(x,0).EntireRow.Delete 
     End if 
    Next 

Подсчет вопроса о том, что если вы удалите одну строку со всеми строками после ее перемещения вверх, а также заставьте ваш цикл не смотреть на все строки. И поскольку вы добавляете 1 к x в тех случаях, вы делали это еще хуже. -1 было бы лучше, за исключением того, что тогда вы по-прежнему проверяете 4650 + number_of_deleted_rows, что может привести к другим проблемам. Начав в конце и двигаясь к началу, вы предотвращаете обе эти проблемы.

1

Проблема в том, что алгоритм неверен. Классический случай для переменной коррумпированного цикла. Проблема в том, что переменная, зависящая от цикла, изменяется, поэтому она неверна.

Правильный способ сделать это именно так.

Dim x as integer 
x = 8 
do 
    if (Range("a1").Offset(x, 0) = True) Then 
     Range("a1").Offset(x, 0).EntireRow.Delete 
    Else 
     x = x + 1 'We only increase the row number in the loop when we encounter a row that is false for containing true in cell a1 and their offsets 
    End If 
Loop Until (x > 4650) 
+0

Извините, я не видел, что вопрос был решен во время редактирования моего ответа. – ervinbosenbacher

6

Я знаю, что у вас уже есть то, что вы искали. Тем не менее, здесь еще один метод, использующий Autofilter. Это намного быстрее, чем цикл по каждой строке и проверка значения.

Sub Sample() 
    Dim lastRow As Long 

    With Sheets("Sheet1") 

     lastRow = .Range("A" & Rows.Count).End(xlUp).Row 

     '~~> Remove any filters 
     .AutoFilterMode = False 

     '~~> Filter, offset(to exclude headers) and delete visible rows 
     With .Range("A1:A" & lastRow) 
      .AutoFilter Field:=1, Criteria1:="TRUE" 
      .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete 
     End With 

     '~~> Remove any filters 
     .AutoFilterMode = False 
    End With 
End Sub 

НТН

+1

+1 намного лучше, чем цикл – brettdj

+0

+1 Согласен с brettdj –

0

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

Sub DelError() 
    Dim i As Integer 
    Dim rngErrRange As Range 
    With ActiveSheet 
     Do 
      Set rngErrRange = .Columns("A:A").Find(What:="#REF!", _ 
       After:=.Cells(1), LookIn:=xlFormulas, _ 
       LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
       MatchCase:=False, SearchFormat:=False) 
       If Not rngErrRange Is Nothing Then 
        rngErrRange.EntireRow.Delete 
       Else 
        End 
       End If 
     Loop 
    End With 
End Sub 
Смежные вопросы