【问题标题】:VBA code deleting incorrect rowsVBA 代码删除不正确的行
【发布时间】:2016-12-14 20:43:12
【问题描述】:

如果 D 到 L 列中有空单元格,我有此代码删除一行。
出于某种原因,它还删除了我位于 C8 的标题单元格。
有谁知道为什么?以及如何解决?

Sub RemoveEmptyRows()

Dim ws As Worksheet
For Each ws In Sheets
ws.Activate

  Dim n As Long
    Dim nlast As Long
    Dim rw As Range
    Set rw = ActiveWorkbook.ActiveSheet.UsedRange.Rows
    nlast = rw.count
    For n = nlast To 1 Step -1
        If (rw.Cells(n, 4).Value = "" And rw.Cells(n, 5).Value = "" And rw.Cells(n, 6).Value = "" And rw.Cells(n, 7).Value = "" And rw.Cells(n, 8).Value = "" And rw.Cells(n, 9).Value = "" And rw.Cells(n, 10).Value = "" And rw.Cells(n, 11).Value = "") Then
            rw.Rows(n).Delete
        End If
    Next n
    Next ws
End Sub

【问题讨论】:

  • 如果顶部有空白行,UsedRange 的行索引不一定与工作表的行索引匹配。
  • 好吧,代码有点乱。例如。在循环中定义变量让我感到恶心。但实际上它正在删除从第 4 (D) 列到第 11 (K) 列没有任何内容的每一行。因此,如果 D8:K8 中的单元格为空,则第 8 行将被删除。尝试使用 F8 单步执行您的代码。
  • 我认为@Comintern 的评论可能是原因,但无论如何你总是使用行作为从UsedRange 开始的偏移量 - 它实际上是 columns 你没有从UsedRange 的开头偏移。我敢打赌,您在 A、B 或 C 列中都有一个完全空的列,因此 rw.Cells(n, 4) 不是指 D 列(等)
  • 您是否只需将 For 循环更新为 For n= nlast to 2 step -1,因为标头已计入 UsedRange
  • 你的UsedRange的例子是什么?

标签: vba excel


【解决方案1】:

问题是您使用UsedRange 的行和列索引,并假设它们与Worksheet 的索引匹配。情况不一定如此。正如您在 cmets 中向 @YowE3K 指出的那样,您有一些完全空的列。

解决方案非常简单 - 只需使用 ws.Cells 而不是 rw.Cells。我还将循环内的所有内容都放入With 块中,以使其更快、更易读。您还可以通过将长 If 语句转换为 Select Case 梯形图来缩短它:

Sub RemoveEmptyRows()
    Dim ws As Worksheet
    For Each ws In ThisWorkbook.Sheets
        With ws
            Dim n As Long
            Dim nlast As Long
            nlast = .UsedRange.Rows(.UsedRange.Rows.Count).Row
            For n = nlast To 9 Step -1
                Select Case False
                    Case .Cells(n, 4).Value = vbNullString
                    Case .Cells(n, 5).Value = vbNullString
                    Case .Cells(n, 6).Value = vbNullString
                    Case .Cells(n, 7).Value = vbNullString
                    Case .Cells(n, 8).Value = vbNullString
                    Case .Cells(n, 9).Value = vbNullString
                    Case .Cells(n, 10).Value = vbNullString
                    Case .Cells(n, 11).Value = vbNullString
                    Case Else
                        .Rows(n).Delete
                End Select
            Next n
        End With
    Next ws
End Sub

请注意,还有更可靠的方法可以找到工作表的最后一行。

【讨论】:

  • @MTBthePRO - 是的。固定。
  • For n = nlast To 9 Step -1
【解决方案2】:

您的标题在 C8 中,然后在第 1 行之前不要删除:

替换

For n = nlast To 1 Step -1

通过

For n = nlast To 9 Step -1

【讨论】:

    【解决方案3】:

    这是您的代码稍作修改。

    Sub RemoveEmptyRows()
    
        Dim ws As Worksheet
        Dim n As Long
        Dim nlast As Long
        Dim rw As Range
    
        For Each ws In Worksheets 'changed. In case there are Chart Sheets.
        'deleted ws.activate. AVOID THAT AS PLAGUE
            Set rw = ws.UsedRange.Rows
            With rw
                nlast = .Count
                For n = nlast To 2 Step -1 'Note the 2, to skip title row. As was pointed in comments.
                    If (.Cells(n, 4).Value2 = "" And .Cells(n, 5).Value2 = "" And .Cells(n, 6).Value2 = "" And .Cells(n, 7).Value2 = "" And .Cells(n, 8).Value2 = "" And .Cells(n, 9).Value2 = "" And .Cells(n, 10).Value2 = "" And .Cells(n, 11).Value2 = "") Then
                        .Rows(n).Delete
                    End If
                Next n
            End With 'rw
        Next ws
    End Sub
    

    【讨论】:

      【解决方案4】:

      你可以试试这个(未经测试的)代码:

      Sub RemoveEmptyRows()
          Dim ws As Worksheet
          Dim nCols As Long
      
          For Each ws In Sheets
              With Intersect(.Range("D:K"), .UsedRange)
                  nCols = .Columns.Count
                  With .SpecialCells(xlCellTypeBlanks)
                      For iArea = .Areas.Count To 1 Step -1
                          If .Areas(iArea).Count = nCols Then .Areas(iArea).EntireRow.Delete
                      Next
                  End With
              End With
          Next ws  
      End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-26
        • 1970-01-01
        • 2019-02-17
        相关资源
        最近更新 更多