2016-05-10 3 views
0

Я новичок здесь.Сравнить Ячейка с ячейкой выше VBA Excel

Я пытаюсь построить быструю программу VBA, чтобы «сгладить» Билль материалов по иерархии (BOM Level) и Status.

Вот некоторые примерные данные: Sample BOM Data

Данные примера показывает BOM с автомобилем в качестве верхнего уровня сборки, колеса и двигателя, как сборки второго уровня, а также различных детских части, которые составляют эти узлы на третьего и четвертого уровня спецификации.

Я хочу удалить любые строки, которые имеют значение «ZE», «ZM», или пробел в столбце C.

Я также хочу удалить любые строки, которые имеют значение «ZA», а также прямые дочерние элементы другого «ZA». (Пример - Удалить строку Rim из спецификации, потому что колеса является Родитель «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».

Любые идеи?

+0

Что такое значение 'k', когда цикл первых хитов, что если заявление? –

+0

Извините, первый оператор If был чем-то, с чем я играл. Реально, «k» всегда должно быть «i-1». Я пытался использовать «k» в качестве идентификатора строки непосредственно над текущей оценкой «i». –

+0

Что я получаю, так это то, что 'k', возможно, не было инициализировано до этой итерации цикла. Вы уверены, что значение k имеет значение в первый раз, когда оно попадает в оператор 'If'? –

ответ

0

Часть проблемы заключается в том, что переменная k не используется для правильной идентификации отношений между родителями и детьми (если я правильно понимаю ваши требования). В вашем случае вы сравниваете каждое значение с строкой над ним, но в ведомости материалов родительская строка может быть несколько строк выше и обозначается значением иерархии - 1.

См. Мой пересмотренный код ниже. В коде мы сначала удалим любые строки, которые мы знаем для удаления (ZM, ZE и Бланки). Затем мы зацикливаем значения иерархии, пока не найдем одно значение иерархии выше текущей строки. Это становится родительской строкой, а оттуда мы тестируем.

Дайте мне знать, если вам нужна дополнительная помощь.

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 
0

Я хотел бы использовать Autofilter() и Sort() методы Range объекта, как следует:

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 
0
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