excelvbaglobal-variablesinputbox

ListBox list identical after second run of Sub with different InputBox variable value


So I have a spreadsheet with a bunch of sheets that list names in the first column. On one sheet, the Input sheet, I have a command button that opens a Sub that prompts the user to perform a search of the names columns on each sheet by requesting a string via searchStr = InputBox(“Please enter text to search for:”,”Search for name”), where searchStr is declared as a global variable with Public searchStr As String.

Upon submission of this input, all names in all sheets are sifted through for string matches and returned to a ListBox in a UserForm. The user then makes a selection from the names that populate the ListBox and is redirected to the sheet which contains their selection.

This all works great – until the user runs the sub the second time. The InuptBox, once again, prompts the user for input and the user obliges and submits only to be met with the exact same ListBox list of names even though their input was vastly different and the potential matches also wildly dissimilar… and so the user hits the Cancel button.

And then on the third run, it corrects itself and the ListBox populates as it should, which is to say correctly.

What’s going on, and how can I fix it?

Here's the code that passes the search string to the UserForm:

Sub searchRostSheets()
    
    searchStr = InputBox("Please enter the text you wish to search for:", "Search")
    
'   Check for existence of roster data

    Dim rosterSh As Worksheet
    Dim numStudents As Integer, totalStudents As Integer
    totalStudents = 0
    
    For Each rosterSh In ThisWorkbook.Worksheets
        Set rosterSh = ThisWorkbook.Sheets(rosterSh.Name)
        
        If rosterSh.Name Like "*Roster*" Then
            numStudents = rosterSh.Range("A" & rosterSh.Range("A:A").Rows.Count).End(xlUp).row
        
            If numStudents = 1 Then
                ' MsgBox "You have not entered any roster data for " & rosterSh.Name & ".", vbExclamation, "Alert"
                GoTo nextSheet
            Else
                ' Proceed
            End If
            
            numStudents = numStudents - 1
        End If
        
        totalStudents = totalStudents + numStudents
        
nextSheet:
    Next rosterSh
    
    If totalStudents = 0 Then
        MsgBox "You have not entered any roster data." & vbNewLine & vbNewLine & _
        "You must enter roster data to perform this task.", vbExclamation, "Alert"
        Exit Sub
    Else
        ' Proceed
    End If

    UserForm9.Show
    
Exit Sub

End Sub

And here is the code that pertains to the UserForm with the ListBox:

Private Sub UserForm_Initialize()

    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
    End With
    
    Dim sheet As Worksheet, rosterSh As Worksheet
    Dim numStudents As Integer, searchCell As Range, i As Integer, listboxValCheck As Boolean
    Dim firstSearchAddr As String, lastSearchAddr As String
    Dim searchDict As Object
    Set searchDict = CreateObject("Scripting.Dictionary")
        
    For Each sheet In ThisWorkbook.Sheets
    
        If sheet.Name Like "*Roster*" Then
            Set rosterSh = ThisWorkbook.Sheets(sheet.Name)
             
            firstSearchAddr = "A2" 'in cell A2
            lastSearchAddr = "C" & rosterSh.Columns("C").Find("*", , xlValues, , xlByRows, xlPrevious).row
            
            
                
                For Each searchCell In rosterSh.Range(firstSearchAddr & ":" & lastSearchAddr)
                    Dim listboxStr As String
                    If InStr(searchCell.Value, searchStr) > 0 Or InStr(UCase(searchCell.Value), UCase(searchStr)) > 0 Or InStr(LCase(searchCell.Value), LCase(searchStr)) > 0 Then
                        Select Case searchCell.Column
                            Case 1
                                listboxStr = searchCell.Value & "   [" & Replace(rosterSh.Name, " Roster", "") & "]" & "                                   " & searchCell.Address
                            Case 2
                                listboxStr = searchCell.Offset(0, -1).Value & "   [" & Replace(rosterSh.Name, " Roster", "") & "]" & "                                   " & searchCell.Offset(0,-1).Address
                            Case 3
                                listboxStr = searchCell.Offset(0, -2).Value & "   [" & Replace(rosterSh.Name, " Roster", "") & "]" & "                                   " & searchCell.Offset(0,-2).Address
                        End Select
                        
                        If searchDict.Exists(listboxStr) Then
                            ' listboxStr is already in dictionary
                        Else
                            searchDict.Add listboxStr, searchDict.Count
                            selectionListBox.AddItem listboxStr
                        End If
EndfOfLoop:
                    End If
                    
                Next searchCell
                       
        End If
        
    Next sheet
        
    searchDict.RemoveAll
        
    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With

End Sub

Private Sub OK_Click()

    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
    End With

'   Set sheet to current sheet
    Dim rosterSh As Worksheet, rosterShName As String
    Dim selectedStu As String, stuAddr As String
    
    If selectionListBox.ListIndex < 0 Then
        MsgBox "You did not make a selection. Please make a selection or press " & Chr(34) & "Cancel" & Chr(34) & " to continue.", vbExclamation, "Alert"
        Exit Sub
    Else
        selectedStu = selectionListBox.List(selectionListBox.ListIndex)
        rosterShName = Trim(Split(Replace(Split(selectedStu, "[")(1), "]", ""), "$")(0)) & " Roster"
        stuAddr = Split(Trim(Split(selectedStu, "]")(1)), "$")(2)
    End If
    
    Set rosterSh = ThisWorkbook.Sheets(rosterShName)
    rosterSh.Activate
    rosterSh.Rows(stuAddr & ":" & stuAddr).Select

    Call unloadUserForm9
    UserForm9.Hide
    
    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With
    
Exit Sub

End Sub

Private Sub Cancel_Click()
    If Not UserForm9 Is Nothing Then
        Call unloadUserForm9
        UserForm9.Hide
    End If
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    UserForm9.Hide
    Call unloadUserForm9
    If CloseMode = 0 Then
        ' DO NOTHING
    End If
End Sub

I also have a Public searchStr As String declaration in Module 1.

EDIT 2: I’ve tried adding a selectionListBox.Clear in the unloading function, but that didn’t work.


Solution

  • Use

    Unload UserForm9
    

    to correctly destroy the instance of the user form object on your click events. Only if you use Unload (not .Hide) to close the userform the initialize event will trigger when showing the userform again which will fill the listbox correctly.

    After you used Unload (in a macro or not) you have to remove all UserForm related code in your macros such as UserForm9.Hide after that unloading call. This would otherwise always trigger the initialize event again with the old value of your global variable. If you unload your userform, make sure, you do it at the end of all doings in the userform unless you want to initialize it again.

    And please do not make use of jump points in your code. Especially your loops are terribly designed with this jump marks.