Удалить строку, если она заполнена пробелами и нулями в пределах диапазона - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть отчет, в котором мне нужно удалить строки без данных в ячейках или ноль в столбце диапазона C - O.

Этот код у меня почти делает это отлично, но я нашелроковой недостаток в логике.Если строка имеет положительное и отрицательное значение, равное нулю, она будет удалена, в то время как мне все еще нужно будет сохранить эту строку.

Я очень ценю помощь этого сайта, так как мне удалось действительно автоматизировать многие из моих отчетов и помочь людям из других отделов!вы, ребята, рок!Спасибо!

Dim rw As Long, i As Long
rw = Cells(Rows.Count, 1).End(xlUp).Row
For i = rw To 6 Step -1
If Application.Sum(Cells(i, 3).Resize(1, 17)) = 0 Then
Rows(i).Delete
End If
Next

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Пустые ячейки рассматриваются как нули!?

При разработке кода для удаления строк и / или столбцов рекомендуется использовать свойство Hidden вместо метода Delete, поэтому неправильные вещи не будутудалитьПоэтому я бы пришел к выводу, что хорошей практикой будет также публиковать ее таким образом.
Вам придется изменить cBlnDEL на True, чтобы включить функцию УДАЛИТЬ , которую я бы рекомендовал вамделать только после того, как вы проверили код с активной функцией HIDDEN .

A 'Fast' Union Version

'*******************************************************************************
' Purpose:    Deletes or hides empty rows, and rows containing zero (0) in     *
'             a specified range, in the ActiveSheet (of the ActiveWorkbook).   *
'*******************************************************************************
Sub DeleteBlankAndZeroRows()

  Application.ScreenUpdating = False
  Application.Calculation = xlCalculationManual

  Const Col1 As Integer = 3         ' First Column of Source Range
  Const Col2 As Integer = 13        ' Last Column of Source Range
  Const Row1 As Integer = 6         ' First Row of Source Range
  Const cBlnDEL As Boolean = False  ' If True, Delete. If False, Hide.

  Dim rng As Range                  ' Check Range
  Dim rngU As Range                 ' Target Union Range

  Dim Row2 As Long                  ' Last Row of Source Range
  Dim i As Long                     ' Source Range Rows Counter
  Dim j As Long                     ' Source Range Columns Counter
  Dim k As Long                     ' Deleted Rows Counter
  Dim strMsg As String              ' Msgbox Text

  On Error GoTo ErrorHandler

  With ActiveWorkbook.ActiveSheet ' A reminder of where this is happening.
    ' Calculate last row of Source Range.
    Row2 = .Cells(.Rows.Count, 1).End(xlUp).Row
    ' Set bogus reference to "aquire range level" (Parent).
    Set rng = .Cells(1, 1)
  End With

  ' Loop through each row in Source Range.
  For i = Row1 To Row2

    ' Calculate the Check Range for current row in Source Range.
    Set rng = rng.Parent.Cells(i, Col1).Resize(1, Col2)

    ' If the cell at the intersection of column Col1 and the current row
    ' is 0, add it to the Target Union Range.
    ' Note: Unexpectedly, the value of an empty cell is treated as 0 here.

    ' Loop through each cell of the (one-row) Check Range.
    For j = 1 To rng.Columns.Count

      If rng.Cells(1, j).Value = 0 Then ' If 0 is found.
        k = k + 1                         ' Count to be deleted rows.
        If Not rngU Is Nothing Then       ' There already is a range in rngU.
          Set rngU = Union(rngU, rng.Cells(1, 1)) ' Add another.
         Else                             ' There is no range in rngU.
          Set rngU = rng.Cells(1, 1)              ' Add one.
        End If
        Exit For
'         Else                            ' If 0 is NOT found.
      End If

    Next ' (Cell in (one-row) Check Range)

  Next   ' (Row in Source Range)

  ' Note: If no 0 was found, the Target Union Range does NOT contain a range.

  If Not rngU Is Nothing Then ' Target Union Range contains range(s).
    If cBlnDEL Then ' DELETE is active. Delete Target Union Range.
      strMsg = "DeleteBlankAndZeroRows successfully deleted " & k _
          & " rows in " & rngU.Areas.Count & " areas."
      rngU.Rows.EntireRow.Delete
     Else           ' HIDDEN is active. Hide Target Union Range.
      strMsg = "DeleteBlankAndZeroRows has successfully hidden " & k _
          & " rows in " & rngU.Areas.Count & " areas."
      rngU.Rows.EntireRow.Hidden = True
    End If
   Else                       ' Target Union Range does NOT contain range(s).
    strMsg = "You may have used the DELETE feature of " _
        & "DeleteBlankAndZeroRows recently, because " _
        & " it could not find any zeros. Nothing deleted."
  End If

ProcedureExit:

  Set rngU = Nothing
  Set rng = Nothing

  Application.Calculation = xlCalculationAutomatic
  Application.ScreenUpdating = True

  MsgBox strMsg

Exit Sub

ErrorHandler:
  strMsg = "An unexpected error occurred. Error: " & Err.Number & vbCr _
      & Err.Description
  GoTo ProcedureExit

End Sub
'*******************************************************************************

Предыдущий код скрывает или удаляеткаждая строка с красной ячейкой в ​​желтой области, как показано на рисунке.

enter image description here

Специальные версии (не рекомендуется)

Sub DelBlankAndZeroRowsDontKnowHowIGotOutOfMyBedThisAfternoonVersion()
  Dim rw As Long, i As Long, j As Long
  Dim rng As Range, rngU As Range
    rw = Cells(Rows.Count, 1).End(xlUp).Row
    For i = rw To 6 Step -1
      Set rng = Cells(i, 3).Resize(1, 13)
      For j = 1 To rng.Columns.Count
        If rng.Cells(1, j).Value = 0 Then
          If Not rngU Is Nothing Then
            Set rngU = Union(rng.Cells(1, 1), rngU)
           Else
            Set rngU = rng.Cells(1, j)
          End If
        End If
      Next
    Next
    rngU.Rows.Hidden = True
  Set rngU = Nothing
  Set rng = Nothing
End Sub

Sub DelBlankAndZeroRowsThinkImGonnaStayInBedTodayVersion()
Dim rw As Long, i As Long, j As Long
Dim rng As Range, rngU As Range
rw = Cells(Rows.Count, 1).End(xlUp).Row
For i = rw To 6 Step -1
Set rng = Cells(i, 3).Resize(1, 13)
For j = 1 To rng.Columns.Count
If rng.Cells(1, j).Value = 0 Then
If Not rngU Is Nothing Then
Set rngU = Union(rng.Cells(1, 1), rngU)
Else
Set rngU = rng.Cells(1, j)
End If
End If
Next
Next
rngU.Rows.Hidden = True
Set rngU = Nothing
Set rng = Nothing
End Sub

Sub DelBlankAndZeroRowsNeverGonnaGetUpVersion()
Dim rw As Long, i As Long, j As Long, rng As Range, rngU As Range
rw = Cells(Rows.Count, 1).End(xlUp).Row: For i = rw To 6 Step -1
Set rng = Cells(i, 3).Resize(1, 13): For j = 1 To rng.Columns.Count
If rng.Cells(1, j).Value = 0 Then
If Not rngU Is Nothing Then
Set rngU = Union(rng.Cells(1, 1), rngU)
Else: Set rngU = rng.Cells(1, j): End If: End If: Next: Next
rngU.Rows.Hidden = True: Set rngU = Nothing: Set rng = Nothing: End Sub
0 голосов
/ 12 декабря 2018

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

Первый способ.

Изменение вашего кода:

Sub FFF()
    Dim rw As Long, i As Long, cntZeroes%, cntEmpty%
    rw = Cells(Rows.Count, 1).End(xlUp).Row
    For i = rw To 6 Step -1
        With Cells(i, 3).Resize(, 13)
            cntZeroes = Application.CountIf(.Cells, 0)
            cntEmpty = Application.CountIf(.Cells, vbNullString)
            If cntZeroes = 13 Or cntEmpty = 13 Then Rows(i).Delete
        End With
    Next
End Sub

Второй способ.

Использование вспомогательного столбца P (как и рядом с O) с помощью AutoFilter.Это довольно сложно, но это быстрее, чем построчное удаление:

Sub FFF2()
    Dim rw As Long, i As Long, cntZeroes%, cntEmpty%
    rw = Cells(Rows.Count, 1).End(xlUp).Row
    For i = rw To 6 Step -1
        With Cells(i, 3).Resize(, 13)
            cntZeroes = Application.CountIf(.Cells, 0)
            cntEmpty = Application.CountIf(.Cells, vbNullString)
            If cntZeroes = 13 Or cntEmpty = 13 Then
                Cells(i, "P") = 1
            End If
        End With
    Next
    With Rows(5)
        .AutoFilter Field:=16, Criteria1:=1
        On Error Resume Next
        With .Parent.AutoFilter.Range
            .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
        End With
        On Error GoTo 0
        .Parent.AutoFilterMode = False
    End With

End Sub
0 голосов
/ 11 декабря 2018

Вместо того, чтобы проверять СУММУ, циклически просматривайте каждую ячейку и проверяйте ее действительность.

Чтобы объяснить это лучше, я буду использовать для вас псевдокод:

  1. Создайте переменную-флаги установите его в false
  2. Создайте цикл, который будет проверять каждую ячейку в строке
  3. Если допустимое число, если найдено, установите флаг в true
  4. Прежде чем перейти кв следующей ячейке проверьте, установлен ли ваш флаг в ложь
  5. Если в вашем флаге указан ложь -> Перейти к следующей ячейке
  6. Цикл до конца всех ячеек в строке

Псевдокод, преобразованный в грубый код

Dim rw As Long, i As Long
Dim rng As Range
Dim validRow As Boolean
validRow = false

rw = Cells(Rows.Count, 1).End(xlUp).Row

For i = rw To 6 Step -1
    Set rng = (Cells(i, 3).Resize(1, 17))
    For Each cell In rng
         If Not IsEmpty(cell) Then
            If cell.value <> 0 Then
               validRow = true
            End If
         End If
         If validRow = true Then
        Exit For
         End If
    Next cell
    If validRow = false Then
        Rows(i).Delete
    End If
    validRow = false
Next

[@ LL edit: изменено> 0 на <> 0, также ищите что-либо отличное от нуля, чтобы учесть строки, заполненные только отрицательными значениями]

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