VBA-删除某些行,其中某些列为空

时间:2019-12-27 15:24:40

标签: excel vba

我有一个excel表,如下所示:

Name  task date1  date2 date3  date4
John  t1    d1
Lucy  t2    
Mary  t3    d2    d3

我要删除第3列(即,来自date1之后的列为空的行(例如本例中的Lucy)

我找到了下面的示例,我认为它很接近,但是不确定如何通过选择第三列之后的空行而不是整个行来修改它。

Sub DeleteAllEmptyRows()
    Dim LastRowIndex As Integer
    Dim RowIndex As Integer
    Dim UsedRng As Range

    Set UsedRng = ActiveSheet.UsedRange
    LastRowIndex = UsedRng.Row - 1 + UsedRng.Rows.Count
    Application.ScreenUpdating = False

    For RowIndex = LastRowIndex To 1 Step -1
        If Application.CountA(Rows(RowIndex)) = 0 Then 'Some logic to add here to choose range
            Rows(RowIndex).Delete
        End If
    Next RowIndex

    Application.ScreenUpdating = True
End Sub

有什么建议吗?谢谢。

1 个答案:

答案 0 :(得分:1)

我想您所需要的就是首先计算使用范围内的最后一列,然后在循环内的CountA语句中使用它。

要计算最后一列,您可以在循环之前添加以下几行:

Dim LastColIndex As Integer: LastColIndex = UsedRng.Column - 1 + UsedRng.Columns.Count

If语句将需要看起来像这样:

If WorksheetFunction.CountA(Range(Cells(RowIndex, 3), Cells(RowIndex, LastColIndex))) = 0 Then

这将从当前行的第三列开始检查非空值。

合并后的代码如下:

Sub DeleteAllEmptyRows()
    Dim LastRowIndex As Integer
    Dim RowIndex As Integer
    Dim UsedRng As Range

    Set UsedRng = ActiveSheet.UsedRange
    LastRowIndex = UsedRng.Row - 1 + UsedRng.Rows.Count
    Application.ScreenUpdating = False

    Dim LastColIndex As Integer: LastColIndex = UsedRng.Column - 1 + UsedRng.Columns.Count

    For RowIndex = LastRowIndex To 1 Step -1
        If WorksheetFunction.CountA(Range(Cells(RowIndex, 3), Cells(RowIndex, LastColIndex))) = 0 Then
            Rows(RowIndex).Delete
        End If
    Next RowIndex

    Application.ScreenUpdating = True
End Sub

我还可以将For循环更改为从2倒数而不是1,以避免可能删除标题行,但是我想这取决于您的口味:)


如果是幻影值...

有时,像元具有一个或多个空格作为其值时,像元具有的值用肉眼不可见,但通过Excel的COUNTA函数进行计数。如果需要考虑这些情况,我们可以使用以下VBA功能单独检查每个单元:

Function IsBlankRange(ByRef rng As Range) As Boolean
    'For faster processing, read in the entire range into a memory variable
    '  instead of reading in each cell value from Excel
    Dim arr As Variant: arr = rng.Value

    'If the range contains a single value, check it and exit
    If Not IsArray(arr) Then 'With single-value ranges, arr will not be an array
        IsBlankRange = Trim(arr & "") = ""
        Exit Function
    End If

    'If we are here, the range contains an array of values,
    '  so we must loop through the array

    'Assume the range is not blank
    IsBlankRange = False

    Dim arrLb1 As Long: arrLb1 = LBound(arr, 1)
    Dim arrUb1 As Long: arrUb1 = UBound(arr, 1)
    Dim arrLb2 As Long: arrLb2 = LBound(arr, 2)
    Dim arrUb2 As Long: arrUb2 = UBound(arr, 2)
    Dim i As Long, j As Long
    For i = arrLb1 To arrUb1
        For j = arrLb2 To arrUb2
            'Return false (the value assumed above) on the first non-blank value
            If Trim(arr(i, j) & "") <> "" Then Exit Function
        Next
    Next

    'If we are here, no non-blank value was encountered, so the range is blank
    IsBlankRange = True
End Function

此功能可用于将If WorksheetFunction.CountA(...) = 0行更改为

        If IsBlankRange(Range(Cells(RowIndex, 3), Cells(RowIndex, LastColIndex))) Then

简而言之,新过程如下所示:

Sub DeleteAllEmptyRows()
    Dim LastRowIndex As Integer
    Dim RowIndex As Integer
    Dim UsedRng As Range

    Set UsedRng = ActiveSheet.UsedRange
    LastRowIndex = UsedRng.Row - 1 + UsedRng.Rows.Count
    Application.ScreenUpdating = False

    Dim LastColIndex As Integer: LastColIndex = UsedRng.Column - 1 + UsedRng.Columns.Count

    For RowIndex = LastRowIndex To 1 Step -1
        If IsBlankRange(Range(Cells(RowIndex, 3), Cells(RowIndex, LastColIndex))) Then
            Rows(RowIndex).Delete
        End If
    Next RowIndex

    Application.ScreenUpdating = True
End Sub

自然,还需要添加新的IsBlankRange函数(可能在DeleteAllEmptyRows代码下面)。如果该功能永远不会在其他任何地方使用,则可以将其设为模块私有。


但是,如果可以使用CONCAT ...

如果您拥有Excel 2019,可以简化IsBlankRange函数,并且可以使用新的CONCAT函数,该函数可以应用于范围:

Function IsBlankRange(ByRef rng As Range) As Boolean
    IsBlankRange = Trim(WorksheetFunction.Concat(rng) & "") = ""
End Function

{https://www.excelfunctions.net/excel-concat-function.html}解释了CONCAT函数

IsBlankRange除了可以使用CONCAT函数之外,还可以直接在If循环内的For语句中使用:

        If Trim(WorksheetFunction.Concat(Range(Cells(RowIndex, 3), Cells(RowIndex, LastColIndex))) & "") = "" Then

但是,我认为将范围评估留在单独的函数中可以更轻松地根据所使用的Excel版本进行自定义,并且使If语句更易于阅读。

相关问题