Home » excel » vba – Excel combo box problem

vba – Excel combo box problem

Posted by: admin April 23, 2020 Leave a comment

Questions:

I have a form in Excel with a combo box control. I want the values to be filled from a database table when the combo box is opened using what has already been typed in as a LIKE criteria. This is the code I have so far for the DropButtonClick event to achieve this.

Private Sub cboVariety_DropButtonClick()
    Static search_text As String
    Static is_open As Boolean
    Dim rs As New Recordset

    If is_open Then
        is_open = False
        Exit Sub
    End If
    is_open = True

    If search_text = cboVariety Then Exit Sub
    search_text = cboVariety

    cboVariety.Clear
    cboVariety.AddItem search_text
    If Len(search_text) > 2 Then
        rs.Open _
            "SELECT Name FROM tbl_Varieties " & _
            "WHERE Name LIKE '%" & search_text & "%' " & _
            "ORDER BY Name", connect_string, adOpenStatic
        Do Until rs.EOF
            If rs!Name <> search_text Then cboVariety.AddItem rs!Name
            rs.MoveNext
        Loop
        rs.Close
    End If
End Sub

The problem is that the DropButtonClick event fires both when the combo box is opened and when it is closed. If this sub executes when the combo box is closing, the code that clears the combo box causes the user’s selection to be erased.

I’m trying to tell when the box is closed using the is_open variable, which alternates between true and false each time the event sub is executed. This seems like a brittle solution to the problem. Is there a better way?

How to&Answers:

You are on the right track by using the is_open boolean to track the state of the combo box, but what you really want to track is the state of “should I re-populate the combo box with database data?”

When do you want the list box populated? Currently, you want the list box to be populated every time the user clicks the drop-down box (not taking into account your is_open state variable). Is this really what you want?

I would imagine that what you really want is to have the combo box only update after something else changes. Perhaps you only want the drop down list to update when the form first opens. Maybe you only want the data to change when the text in a search box changes. If this is the case, you need to base your logic on the state of when you actually want to perform the update.

For example, let’s say you want to update the combo box only if the text in a search box changes. I’m not looking at Excel at the moment, but let’s pretend you have a text box called txtSearch with a Text property. I’d start by adding a module or class level variable to maintain the state of the previous text entry:

Private mPreviousSearchText As String

Then I’d update my event code like so:

Private Sub cboVariety_DropButtonClick()                                      
    Dim rs As New Recordset                    
    Dim search_text As String

              search_text = txtSearch.Text

    If mPreviousSearchText = search_text Then                      
       'The current search matches the previous search,'
       'so we do not need to perform the update.'
        Exit Sub                    
    End If                                                    

    cboVariety.Clear                    
    cboVariety.AddItem search_text                    
    If Len(search_text) > 2 Then                    
        rs.Open _                    
            "SELECT Name FROM tbl_Varieties " & _
            "WHERE Name LIKE '%" & search_text & "%' " & _
            "ORDER BY Name", connect_string, adOpenStatic
        Do Until rs.EOF                    
            If rs!Name <> search_text Then cboVariety.AddItem rs!Name
            rs.MoveNext                    
        Loop                    
        rs.Close                                
    End If             
    'Set the previousSearchText var to be the search_text so that it does'
    'not run unless the value of my text box changes.'
    mPreviousSearchText = search_text 
End Sub

The entire point is to establish when you actually want to perform the update and find out a way to tie your logic decision to the state associated with when you want to perform the action, which is only coincidentally related to the user clicking on the drop-down box.

Answer:

I found a simple way to solve this. It doesn’t seem like it should work, but if I just reassign the value of the combo box after rebuilding the list, it doesn’t discard the value that is selected.

Private Sub cboVariety_DropButtonClick()
    Static search_text As String
    Dim rs As New Recordset

    If search_text = cboVariety Then Exit Sub
    search_text = cboVariety

    cboVariety.Clear
    If Len(search_text) > 2 Then
        rs.Open _
            "SELECT Name FROM tbl_Varieties " & _
            "WHERE Name LIKE '%" & search_text & "%' " & _
            "ORDER BY Name", connect_string, adOpenStatic
        Do Until rs.EOF
            cboVariety.AddItem rs!Name
            rs.MoveNext
        Loop
        rs.Close
    End If

    '' Reassign cboVariety in case this event was triggered by combo close
    cboVariety = search_text
End Sub

Answer:

This worked for me, instead of assigning the value, i assign the ListIndex property.

index = cb.ListIndex

cb.Clear

while condition
    cb.AddItem item
Wend

If index < cbLinia.ListCount Then
    cb.ListIndex = index
Else
    cb.ListIndex = -1
End If

Answer:

Use GotFocus() instead.

 Private Sub ComboBox1_GotFocus()
    MsgBox "caca"
 End Sub

Triggers only when the combo get focus.

HTH