【问题标题】:Compare Cell with Cell above VBA Excel将单元格与 VBA Excel 上方的单元格进行比较
【发布时间】:2016-05-10 16:57:17
【问题描述】:

我是新来的。

我正在尝试构建一个快速 VBA 程序,以按层次结构(BOM 级别)和状态“扁平化”物料清单。

以下是一些示例数据:

示例数据显示了一个 BOM,其中 Car 作为顶级装配体,Wheel 和 Engine 作为二级装配体,以​​及在 BOM 的第三和第四级构成这些装配体的各种子零件。

我想删除所有具有“ZE”、“ZM”值的行,或者在C 列中为空白。

我还想删除任何具有值“ZA”并且也是另一个“ZA”项的直接子项的行。 (示例 - 从 BOM 中删除 Rim 行,因为 Wheel 是父项“ZA”项)

这是我目前所拥有的:

Sub deletechildren()

 Dim lr As Long, i As Long, k As Long

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

    For i = lr To 1 Step -1
        If i > 2 Then
            k = i - 1
        End If
        If Cells(i, 3).Value = "ZA" And Cells(i, 1).Value = Cells(k, 1).Value Then
            Cells(i, 3).EntireRow.Delete
        ElseIf Cells(i, 3).Value = "ZE" Then
            Cells(i, 3).EntireRow.Delete
        ElseIf Cells(i, 3).Value = "ZM" Then
            Cells(i, 3).EntireRow.Delete
        ElseIf Cells(i, 3).Value = "" Then
            Cells(i, 3).EntireRow.Delete
        End If
    Next i

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

End Sub

我在 If 语句的第一部分遇到了一些错误,我想从“ZA”父级解析出任何“ZA”状态子级。

有什么想法吗?

【问题讨论】:

  • 当循环第一次遇到 If 语句时,k 的值是多少?
  • 对不起,第一个 If 语句只是我在玩弄的东西。实际上,“k”应该始终是“i-1”。我试图使用“k”作为当前正在评估的行“i”正上方的行的标识符。
  • 我得到的是 k 在循环迭代之前可能没有被初始化。您确定 k 在第一次遇到 If 语句时有值吗?
  • 你遇到了什么错误?
  • 尝试在循环之前添加一个k = 0 值。我知道它应该得到一个值,因为 lr 应该大于 2,但是如果您单步执行宏(使用 F8),当它到达第一行 If Cells(i,3)... 时,将鼠标悬停在将鼠标悬停在k 上,看看它是否有弹出值。 (或在即时窗口中执行?k

标签: vba excel


【解决方案1】:
Sub DeleteChildren()

Dim lastRow As Long
Dim i As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

For i = 2 To lastRow

    If (Cells(i, 3).Value = "ZE" Or Cells(i, 3).Value = "ZM" Or Cells(i, 3).Value = "") And Cells(i, 1) <> "" Then
        Rows(i).EntireRow.Delete xlShiftUp
        i = i - 1
        GoTo NextIteration
    End If

    If Cells(i, 1).Value > 1 Then
        If (Cells(i, 3).Value = "ZA" And Cells(i - 1, 3).Value = "ZA") And Not Cells(i, 1).Value < Cells(i - 1, 1).Value Then ' This way is a there are multiple levels with "ZA" there can
            Cells(i, 5).Value = "Delete"
        End If
    End If

NextIteration:
Next i

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

For i = 1 To lastRow
    If Cells(i, 5).Value = "Delete" Then
        Rows(i).EntireRow.Delete xlShiftUp
        i = i - 1
    End If
Next i

End Sub

【讨论】:

    【解决方案2】:

    问题的一部分是变量k 未被用于正确识别父/子关系(如果我正确理解您的要求)。在您的情况下,您将每个值与其上方的行进行比较,但在物料清单中,父行可能是上方的多行,并由层次结构值 - 1 表示。

    请参阅下面我修改后的代码。在代码中,我们首先删除所有我们知道要删除的行(ZM、ZE 和 Blanks)。接下来,我们将层次结构值循​​环起来,直到在当前行上方找到一个层次结构值。这成为父行,然后从那里开始测试。

    如果您需要其他帮助,请告诉我。

    Sub deletechildren()
    
     Dim lr As Long, i As Long, k As Long
    
        lr = Cells(Rows.Count, 1).End(xlUp).Row
    
        For i = lr To 1 Step -1
            If i > 2 Then
                k = i - 1
                If Cells(i, 3) = "ZE" Or Cells(i, 3) = "ZM" Or Cells(i, 3) = "" Then
                    Rows(i).Delete
                Else
                    k = i - 1
                    Do Until i <= 2 Or (Cells(i, 1) - Cells(k, 1) = 1)
                        k = k - 1
                    Loop
    
                    'Now, k represents the parent row.
                    If Cells(i, 3) = "ZA" And Cells(k, 3) = "ZA" Then
                        Rows(i).Delete
                    End If
    
                End If
            End If
    
        Next i
    
        lr = Cells(Rows.Count, 1).End(xlUp).Row
    
    End Sub
    

    【讨论】:

      【解决方案3】:

      我会使用Range 对象的Autofilter()Sort() 方法,如下所示:

      Option Explicit
      
      Sub deletechildren()
      
          Dim i As Long
      
          With Worksheets("BOM")
      
              With .Range("A1:D" & .Cells(.Rows.Count, 1).End(xlUp).Row)
      
                  .AutoFilter Field:=3, Criteria1:=Array("ZE", "ZM", "="), Operator:=xlFilterValues                
                  With .Offset(1).Resize(.Rows.Count - 1)
                      If Application.WorksheetFunction.Subtotal(103, .Columns(1)) > 1 Then .SpecialCells(xlCellTypeVisible).EntireRow.Delete
                  End With
                  .AutoFilter
      
                  .Sort key1:=Range("C1"), order1:=xlAscending, key2:=Range("A1"), order2:=xlAscending, Header:=xlYes
      
                  i = .Rows(.Rows.Count).Row
                  Do Until .Cells(i, 1) = .Cells(2, 1)
                      i = i - 1
                  Loop
                  If i < .Rows.Count Then .Rows(i + 1).Resize(.Rows.Count - i).EntireRow.Delete
      
              End With
      
          End With
      
      End Sub
      

      【讨论】:

        猜你喜欢
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 2022-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多