2

I am trying to write a code that if there is an IR clinic completed but all Biopsy entries are canceled for the same ID, then I want to delete the row where the IR is. Row 1 is headers. Column B is IDs, column L is either "Biopsy" or "IR clinic". Column C is either "Completed" or "Canceled"

For i = 2 To LastRow
    If Range("L" & i).Value = "IR Clinic" And Range("C" & i).Value = "Completed" Then
        For j = 2 To i
            If  Range("B" & j).Value = Range("B" & i).Value And _
                Range("L" & j).Value = "Biopsy" And _
                Range("C" & j).Value = "Canceled" Then

                    Selection.Rows(i).EntireRow.Delete
                    LastRow = Cells(Rows.Count, 2).End(xlUp).Row
                    i = i - 1
                    Exit For

            End If
        Next j
    End If
Next i

The problem with this code is if there is at least one Biopsy Canceled, it deletes the IR row. What I really need is if ALL biopsy for same ID are canceled it deletes it, but if at least one is completed, it does not delete the IR. Thank you for any help in advance.

3
  • 1
    stackoverflow.com/a/65751206/8422953 Commented Mar 13, 2022 at 2:30
  • 1
    @braX: I don't think that this is the case since i = i - 1 is covering it. Commented Mar 13, 2022 at 2:52
  • 1
    post sample dataset also Commented Mar 13, 2022 at 3:02

1 Answer 1

1

The Shortcomings of (Simplifications in) a For...Next Loop

The Code

Option Explicit

Sub Test()
    i = 2
    Do
    'For i = 2 To LastRow ' LastRow is stored; you cannot effectively modify it
        If Range("L" & i).Value = "IR Clinic" _
                And Range("C" & i).Value = "Completed" Then
            For j = 2 To i
                ' Note the change in this logic!
                If Range("B" & j).Value = Range("B" & i).Value _
                        And Range("L" & j).Value = "Biopsy" _
                        And Range("C" & j).Value <> "Canceled" Then ' or '= "Completed"'
                    Exit For
                End If
            Next j
            If j > i Then ' if the loop was uninterrupted; all canceled; none completed
                Rows(i).Delete
                LastRow = LastRow - 1
                i = i - 1
            'Else ' the loop was interrupted; not all canceled; at least one was completed
            End If
        End If
        i = i + 1
    Loop Until i > LastRow
End Sub

The Outer Loop

  • This illustrates why the line LastRow = Cells(Rows.Count, 2).End(xlUp).Row in your code is redundant (you might have used LastRow = LastRow - 1 to the same effect).
  • Whatever you do to fr or lr, it will only loop 5 times. Before entering the loop, VBA has stored the numbers fr and lr somewhere.
Sub ForNext1()
    Dim fr As Long: fr = 2 ' irrelevant
    Dim lr As Long: lr = 6
    Dim i As Long
    For i = fr To lr
        ' do your stuff
        fr = 2 * i ' irrelevant
        lr = 3 * i
        Debug.Print "i = " & i, "fr = " & fr, "lr = " & lr
    Next i
End Sub
  • Mimic the behavior of ForNext1 by using a Do...Loop.
Sub DoLoop()
    Dim fr As Long: fr = 2 ' irrelevant
    Dim lr As Long: lr = 6
    Dim i As Long: i = fr
    Do
        ' do your stuff
        fr = 2 * i ' irrelevant
        lr = 3 * i
        Debug.Print "i = " & i, "fr = " & fr, "lr = " & lr
        ' Next
        i = i + 1
        lr = 6 ' Gotcha! Here we can effectively change 'lr'!!!
    Loop Until i > lr
End Sub

The Inner Loop

  • This relates to the utilization of the line If j > i Then in the code.
  • When exiting uninterrupted, j is equal to i + 1 (6), not i (5).
Sub ForNextTEST2()
    Dim i As Long: i = 5
    Dim j As Long
    For j = 1 To i
    Next j
    Debug.Print "j = " & j, "i = " & i
End Sub
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.