Search code examples
excelvbauserformexcel-2016

Reverse For Next Loop not fully looping


I have an excel userform that contains a listbox and command button. I want to be able to select multiple lines in the listbox and have them delete from a database range upon use of the command button.

The named range runs through a dictionary with the key as the range cell values and the item as the cell addresses. The listbox selection is popped through the dictionary to return the cell location to delete.

Currently when I make my selection the bottom most selection is the only entry deleted. The For Next loop should be starting at the listbox.count-1 and working down to 0. However, it does not seem to loop fully and there are no error messages. Thoughts?

Private Sub RemoveAnalyst()
' Select Tools->References from the Visual Basic menu.
' Check box beside "Microsoft Scripting Runtime" in the list.
Dim ws          As Worksheet
Dim i           As Long
Dim Location    As String
Dim MsgDelete   As String
Dim xCount   As Integer
Dim xFound      As Integer
Dim Cell        As Range
Dim dict        As Scripting.Dictionary

Set ws = ThisWorkbook.Sheets("Lists")

'Build Dictionary
Set dict = New Scripting.Dictionary
    dict.CompareMode = vbTextCompare  'Capitalization does not apply to dictionary

    For Each Cell In Range("Name").Cells 'Add named range to dictionary
        With Cell
            dict(Cell.Value) = Cell.Address(RowAbsolute:=False, ColumnAbsolute:=False) 'Key = Cell value (ie. Analyst name), Item = Cell address (ie. A2)
        End With
    Next Cell

    Set xCount = RemoveAnalystLB.ListCount - 1
    For i = xCount To 0 Step -1 'Reverse For Loop
        If RemoveAnalystLB.Selected(i) Then
            With ws
                Location = dict(RemoveAnalystLB.List(i)) 'Find Cell location via dictionary function
                xFound = xFound + 1
                MsgDelete = MsgDelete & vbCrLf & RemoveAnalystLB.List(i)
                .Range(Location).Delete Shift:=xlUp 'Delete cell at specified location
            End With
        End If
    Next i

    Set dict = Nothing
    Unload Remove_Analyst_Form 'Close out userform

    If xFound <> 0 Then MsgBox ("Analyst(s):" & MsgDelete & vbCrLf & "have been deleted from the database.") 'Msg names have been deleted


End Sub

Solution

  • Try this

    Private Sub RemoveAnalyst()
    'Tools ->References -> Microsoft Scripting Runtime
    '-------------------------------------------------
    Dim ws          As Worksheet
    Dim dict        As Scripting.Dictionary
    Dim cell        As Range
    Dim rng         As Range
    Dim location    As String
    Dim msgDelete   As String
    Dim xCount      As Integer
    Dim xFound      As Integer
    Dim i           As Long
    
    Set ws = ThisWorkbook.Sheets("Lists")
    Set dict = New Scripting.Dictionary
    dict.CompareMode = vbTextCompare
    
    For Each cell In Range("Name").Cells
        With cell
            dict(cell.Value) = cell.Address(RowAbsolute:=False, ColumnAbsolute:=False)
        End With
    Next cell
    
    xCount = RemoveAnalystLB.ListCount - 1
    
    For i = xCount To 0 Step -1
        If RemoveAnalystLB.Selected(i) Then
            With ws
                location = dict(RemoveAnalystLB.List(i))
                xFound = xFound + 1
                msgDelete = msgDelete & vbCrLf & RemoveAnalystLB.List(i)
                If rng Is Nothing Then Set rng = .Range(location) Else Set rng = Union(rng, .Range(location))
            End With
        End If
    Next i
    
    Set dict = Nothing
    Unload Remove_Analyst_Form
    
    If Not rng Is Nothing Then rng.Delete Shift:=xlUp
    If xFound <> 0 Then MsgBox ("Analyst(s):" & msgDelete & vbCrLf & "Have Been Deleted From The Database.")
    End Sub