【问题标题】:Delete all rows in Excel workbook with column C empty using VBA使用VBA删除Excel工作簿中C列为空的所有行
【发布时间】:2021-08-21 20:28:58
【问题描述】:

我正在开展一个项目,为特定的导入规范清理几百张 excel 表。如果任何行的特定值为空白,则导入过程会出错,因此如果该行中的 C 列为空,我正在寻找删除整个工作簿中所有行的最佳方法。我发现这个在活动工作表上工作的简单 VBA 代码,但我需要它来遍历工作簿中的所有工作表。有什么关于更好的流程的建议,这样我就不必运行它 > 100 次了吗?

Sub DelBlankRows()
    Columns("C:C").Select
    Selection.SpecialCells(xlCellTypeBlanks).Select
    Selection.EntireRow.Delete
End Sub

【问题讨论】:

  • 不使用 select 可能会加快速度,但不确定是否有办法一举编辑所有工作表。
  • 您的问题对我来说有点模棱两可:您是要求遍历每个工作表,并删除那些工作表上在 C 列中有值的行,还是要求从 all 表如果 any 表在该行的 C 列中有值? (即如果 Sheet1 的单元格 C3 中有值,则从 所有 表中删除第 3 行,即使单元格 C3 中没有值?)

标签: excel vba


【解决方案1】:

删除列的空白行

Option Explicit

Sub DelRowsOfColumnBlanksTEST()
    
    Const wsCol As Variant = "C" ' or 3
    'Const wsCol As String = "C"
    'Const wsCol As Long = 3
    
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    
    Application.ScreenUpdating = False
    
    Dim ws As Worksheet
    For Each ws In wb.Worksheets
        DelRowsOfColumnBlanks ws, wsCol
    Next ws

    Application.ScreenUpdating = True

End Sub

Sub DelRowsOfColumnBlanks( _
        ByVal ws As Worksheet, _
        ByVal WorksheetColumnID As Variant)
    
    If ws Is Nothing Then Exit Sub ' no worksheet
        
    If ws.AutoFilterMode Then
        ws.AutoFilterMode = False
    End If
    
    Dim urg As Range: Set urg = ws.UsedRange
    If urg.Rows.Count = 1 Then Exit Sub ' only one row
    
    On Error Resume Next
    Dim crg As Range: Set crg = ws.Columns(WorksheetColumnID)
    On Error GoTo 0
    If crg Is Nothing Then Exit Sub ' invalid Worksheet Column ID
    
    Dim tcrg As Range: Set tcrg = Intersect(urg, crg)
    ' ... is only the same as 'Set tcrg = urg.Columns(WorkhseetColumnID)',...
    ' ... if the first column of the used range is column 'A'.
    If tcrg Is Nothing Then Exit Sub ' no intersection
    
    Dim drg As Range: Set drg = tcrg.Resize(tcrg.Rows.Count - 1).Offset(1)
                                                                                                                                                                        
    tcrg.AutoFilter 1, "=" ' ... covers blanks: 'Empty', "=""""", "'"... etc.
    
    ' Note that although it contains the word 'Blanks',...
    ' ... 'SpecialCells(xlCellTypeBlanks)' only covers 'Empty'.
    
    On Error Resume Next
    Dim spcrg As Range: Set spcrg = drg.SpecialCells(xlCellTypeVisible)
    On Error GoTo 0
    If Not spcrg Is Nothing Then
        spcrg.EntireRow.Delete
    'Else
        ' no 'visible' cells (to delete)
    End If
    
    ws.AutoFilterMode = False
    
End Sub

【讨论】:

    【解决方案2】:
    Option Explicit
    
    Sub CleanWorkbook()
        Application.ScreenUpdating = False
        Application.Calculation = xlCalculationManual
        Dim sh As Worksheet
        For Each sh In ActiveWorkbook.Worksheets
            DeleteRowsOfEmptyColumn sh, "C"
        Next
        Application.ScreenUpdating = True
        Application.Calculation = xlCalculationAutomatic
    End Sub
    
    Sub DeleteRowsOfEmptyColumn(sh As Worksheet, col as string)
        Dim rowsToDelete As New Collection
        Dim cell
        For Each cell In Intersect(sh.UsedRange, sh.Columns(col))
            If cell.Value = "" Then
                rowsToDelete.Add cell.Row
            End If
        Next
        
        Dim i As Integer
        For i = rowsToDelete.Count To 1 Step -1
            sh.Rows(rowsToDelete(i)).Delete
        Next
    End Sub
    

    【讨论】:

    • 我真的很喜欢这个。我还在学习,以前没有使用过集合。我惊讶地发现,在针对我提供的代码测试您的代码时,尽管我使用了激活和选择,但我的代码更快。知道为什么会这样吗?
    • @El-Tabei Mohamed:你可以用sh.Columns(col)代替sh.Range(col & ":" & col)
    • @Mackanachi 可能是因为第二个循环,这将使工作簿在每次删除一行时重新计算,而您的代码同时删除工作表上的所有行。如果这段代码开头包含Application.Calculation = xlCalculationManual: Application.ScreenUpdating = False,结尾包含Application.Calculation = xlCalculationAutomatic: Application.ScreenUpdating = True,我怀疑你会发现差异消失了。
    • 在我的 Excel 2016 上,集合限制为 256 个元素,这使得该解决方案不适用于我的用例
    • @lalebarde 我尝试将“很多”超过 256 个项目添加到集合中,并且成功了。
    【解决方案3】:

    我已经为任何在 C 中没有值的工作表设置了一个非常基本的错误陷阱。您可能需要自己改进它。

    编辑:更新错误陷阱

        Sub DelBlankRows()
        
        Dim sh As Worksheet
    
        Application.ScreenUpdating = False
        
        On Error GoTo Handle
        For Each sh In ThisWorkbook.Worksheets
            sh.Activate
            Columns("C:C").Select
            Selection.SpecialCells(xlCellTypeBlanks).Select
            Selection.EntireRow.Delete
    Cont:
        Next sh
        
        Application.ScreenUpdating = True
       
        Exit Sub
    
    Handle:
        If Err.Number = 1004 Then Resume Cont
        
    End Sub
    

    【讨论】:

    • 您可以尝试使用 Range 对象,而不是使用 Select,例如Set CellsWithValues = sh.Columns(3).SpecialCells(xlCellTypeBlanks),然后测试If Not (CellsWithValues Is Nothing) Then CellsWithValues.EntireRow.Delete,而不是等待它抛出错误。
    猜你喜欢
    • 2017-12-03
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    相关资源
    最近更新 更多