2010-09-08 4 views
3

У меня есть форма в Excel с элементом управления со списком. Я хочу, чтобы значения были заполнены из таблицы базы данных, когда поле со списком открывается с использованием того, что уже было введено в качестве критериев LIKE. Это код, который я до сих пор делал для события DropButtonClick для достижения этого.Проблема со списком Excel

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 

Проблема заключается в том, что пожары событие DropButtonClick и когда поле со списком открывается, и когда она закрыта. Если этот вспомогательный элемент выполняется, когда поле со списком закрывается, код, который очищает поле со списком, вызывает удаление пользователя.

Я пытаюсь сказать, когда ящик закрыт, используя переменную is_open, которая чередуется между истиной и ложью каждый раз, когда выполняется событие sub. Это кажется хрупким решением проблемы. Есть ли способ лучше?

ответ

1

Я нашел простой способ решить эту проблему. Кажется, что это не сработает, но если я просто переназначаю значение поля со списком после перестройки списка, он не отбрасывает выбранное значение.

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

Единственная проблема, с которой вы могли столкнуться, заключается в том, что значение, выбранное пользователем, не возвращается из запроса, но этого никогда не должно произойти, правильно? –

+0

На самом деле это должно произойти, если они ищут что-то, чего там нет, но законно назначать значение в поле со списком, которое не существует в выпадающем списке. – Tmdean

0

Вместо этого используйте GotFocus().

Private Sub ComboBox1_GotFocus() 
    MsgBox "caca" 
End Sub 

Триггеры, только когда комбо получают фокус.

НТН

+0

GotFocus - событие .NET, я думаю ... Excel использует много (и много) старых элементов управления. Эквивалентным событием управления VBA является Enter, но проблема в том, что критерии поиска будут введены после того, как элемент управления получит фокус, поэтому мне действительно нужно, чтобы событие обрабатывалось прямо перед открытием поля со списком. – Tmdean

1

Вы на правильном пути, используя is_open логического значения для отслеживания состояния поля со списком, но то, что вы действительно хотите, чтобы отслеживать это состояние «я должен повторно заполнить поле со списком с данные базы данных? "

Когда вы хотите, чтобы в списке было заполнено поле? В настоящее время вы хотите, чтобы поле списка заполнялось каждый раз, когда пользователь щелкает раскрывающийся список (не принимая во внимание вашу переменную состояния is_open). Это действительно то, что вы хотите?

Я бы предположил, что вы действительно хотите, чтобы поле со списком только обновляло после чего-то другого.. Возможно, вы хотите, чтобы раскрывающийся список обновлялся при первой форме. Возможно, вы хотите, чтобы данные изменялись при изменении текста в окне поиска. Если это так, вам нужно основывать свою логику на состоянии, когда вы действительно хотите выполнить обновление.

Например, предположим, что вы хотите обновить поле со списком только в том случае, если текст в поле поиска изменился. На данный момент я не смотрю на Excel, но давайте притворимся, что у вас есть текстовое поле с именем txtSearch с свойством Text. Я хотел бы начать, добавив переменную модуля или на уровне класса для поддержания состояния предыдущего ввода текста:

Private mPreviousSearchText As String 

Тогда я обновить свой код события, как так:

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 

Вся точка заключается в том, чтобы установить , когда вы действительно хотите выполнить обновление и узнать способ привязать свое логическое решение к состоянию, связанному с тем, когда вы хотите выполнить действие, которое только по совпадению связано с нажатием на раскрывающийся список пользователя коробка.

+0

Очень хороший момент, но на самом деле я уже использую эту логику в своем коде. search_text - статическая переменная, и мои вспомогательные файлы сразу же появляются, если search_text не изменился между вызовами. – Tmdean

+0

Поле поиска и поле со списком - это одно и то же - критерии поиска вводятся в поле со списком, а затем, когда оно открыто, оно заполняется из таблицы. Проблема заключается в том, что если вы выберете элемент из выпадающего списка, значение combo box изменится, поэтому, когда процедура события снова запустится, она не спасется, и элемент списка, который был выбран, будет отброшен. – Tmdean

+1

@Tmdean Хорошо, теперь я вижу проблему, с которой вы сталкиваетесь. Вы используете одно и то же поле со списком, чтобы предоставить данные для запроса и служить в качестве цели для обновленного списка? Я понимаю, почему у вас проблемы. Поскольку процесс потребует нескольких кликов в любом случае, вы можете подумать о переносе функциональности на два разных элемента управления: один для предоставления ввода для поиска, а другой - для предоставления списка элементов. Таким образом, вы можете лучше управлять состоянием, когда вам нужно выполнить обновление. Поскольку пользователь уже должен щелкнуть, это не похоже на компромисс. –

1

Это работает для меня, вместо того, присваивая значение, я присвоить ListIndex свойство.

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 
Смежные вопросы