Как заполнить ComboBox набором записей с помощью VBA

есть некоторая литература, доступная в обмен экспертов и теке республики об использовании combobox.recordset свойство для заполнения combobox в форме доступа.

эти элементы управления обычно заполняются строкой "SELECT *" в свойствах элемента управления "rowsource", ссылающейся на таблицу или запрос, доступные на стороне клиента приложения. Когда мне нужно отобразить данные на стороне сервера в combobox, я создаю временную локальную таблицу и импортировать запрошенные записи. Это отнимает много времени, особенно с большими таблицами.

возможность использовать набор записей для заполнения элемента управления combobox позволит пользователю напрямую отображать данные со стороны сервера.

вдохновленный 2 предыдущими примерами, я написал следующий код:

Dim rsPersonne as ADODB.recordset
Set rsPersonne = New ADODB.Recordset

Set rsPersonne.ActiveConnection = connexionActive
rsPersonne.CursorType = adOpenDynamic
rsPersonne.LockType = adLockPessimistic
rsPersonne.CursorLocation = adUseClient

rsPersonne.Open "SELECT id_Personne, nomPersonne FROM Tbl_Personne"

fc().Controls("id_Personne").Recordset = rsPersonne

где:

  • connexionActive: является ли мое постоянное соединение ADO с моим сервером баз данных
  • fc (): является ли мой текущий / активный форма
  • элементы управления ("id_Personne"): управление combobox для заполнения штатное расписание компании
  • версия доступа в 2003

к сожалению, это не работает!

в режиме отладки я могу проверить, что набор записей правильно создан, с запрошенными столбцами и данными и правильно связан с элементом управления combobox. К сожалению, когда я показываю форму, я продолжаю получать пустой combobox, без записей в нем! Любая помощь очень оцененный.

изменить:

это свойство набора записей действительно доступно для конкретного объекта combobox, а не для стандартного объекта управления, и я был очень удивлен, обнаружив его несколько дней назад. Я уже пытался использовать функцию обратного вызова combobox или заполнить список методом "addItem" combobox. Все это отнимает много времени.

6 ответов


Как было сказано, Вы должны получить RowSourceType в "Table/List" (или "Table / Requête", если на французском языке), чтобы показать результаты запроса в combobox.

проблемы с памятью возникают при открытии набора записей (rsPersonne) без его закрытия. Вы должны закрыть их при закрытии / выгрузке формы (но опять же у вас будут проблемы с областью, так как набор записей объявлен в функции, а не в форме).

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


чтобы задать элемент управления, который принимает rowsource в набор записей, выполните следующие действия:

Set recordset = currentDb.OpenRecordset("SELECT * FROM TABLE", dbOpenSnapshot)
Set control.recordset = recordset

работает с наборами записей DAO наверняка, я не пробовал наборы записей ADO, потому что у меня нет реальной причины их использовать.

когда это сделано таким образом, простой запрос не будет работать для обновления данных, вы должны повторить инструкцию set.


Я нашел трюк ... свойство " rowSourceType "элемента управления combobox должно быть установлено в"Таблица/список". Дисплей теперь в порядке, но теперь у меня есть еще одна проблема с памятью. Поскольку я использую эти наборы записей ADO в своих формах, использование памяти Access увеличивается каждый раз, когда я просматриваю форму. Память не освобождается ни при остановке просмотра, ни при закрытии формы, что делает MS Access нестабильным и регулярно замораживается. Я открою вопрос, если я не могу решить эту проблему


хороший метод с использованием свойства Recordset, спасибо за этот намек!

Патрик, метод, который вы показали на своей странице, имеет большой недостаток (я тоже пробовал это самостоятельно): список значений может быть только 32 КБ, если вы превысите этот предел, функция выдаст ошибку. Метод обратного вызова имеет большой недостаток, что он очень медленный и вызывается один раз для каждой записи, что делает его непригодным для более длинного списка. Использование метода recordset работает очень хорошо. Мне это было нужно, потому что моя строка SQL была длиннее 32 КБ (много значений индекса для where ID IN(x,x,x,x, x)...)).

вот простая функция, которая использует эту идею для установки набора записей в combobox:

' Fills a combobox with the result of a recordset.
'
' Works with any length of recordset results (up to 10000 in ADP)
' Useful if strSQL is longer than 32767 characters
'
' Author: Christian Coppes
' Date: 16.09.2009
'
Public Sub fnADOComboboxSetRS(cmb As ComboBox, strSQL As String)
    Dim rs As ADODB.Recordset
    Dim lngCount As Long

   On Error GoTo fnADOComboboxSetRS_Error

    Set rs = fnADOSelectCommon(strSQL, adLockReadOnly, adOpenForwardOnly)

    If Not rs Is Nothing Then
        If Not (rs.EOF And rs.BOF) Then
            Set cmb.Recordset = rs
            ' enforces the combobox to load completely
            lngCount = cmb.ListCount
        End If
    End If

fnADOComboboxSetRS_Exit:
    If Not rs Is Nothing Then
        If rs.State = adStateOpen Then rs.Close
        Set rs = Nothing
    End If
    Exit Sub

fnADOComboboxSetRS_Error:
    Select Case Err
        Case Else
            fnErr "modODBC->fnADOComboboxSetRS", True
            Resume fnADOComboboxSetRS_Exit
    End Select
End Sub

(функция fnADOSelectCommon открывает набор записей ADO и возвращает его. Функция fnErr показывает окно сообщения с ошибкой, если она была.)

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

в случае выгрузки формы вы можете дополнительно использовать " Set rs=Me.Comboboxname.Записей", а затем закройте его. Это не должно быть необходимо в отношении памяти, но может быть лучше освободить открытые соединения (если используется с серверным сервером базы данных).

спасибо,

христианин


элемент управления со списком не имеет свойства набора записей. У него есть свойство RowSource, но Access ожидает там строку SQL.

вы можете изменить тип RowSourceType на имя определяемой пользователем функции "обратного вызова". Доступ к справке даст вам больше информации, включая пример кода, расположив себя на RowSourceType и нажав F1. Я использую этот тип функции, когда хочу предоставить пользователям список доступных отчетов, букв дисков или других данных это недоступно через SQL-запрос.

Я не понимаю, что вы подразумеваете под третьим абзацем в отношении использования данных непосредственно со стороны сервера. Или, скорее, я не понимаю, в чем проблема с использованием стандартных запросов.


в MS Access это нормально, но в VB вы можете использовать что-то вроде этого, используя adodc (Jet 4.0):

Private sub Form1_Load()
   with Adodc1
     .commandtype = adcmdtext
     .recordsource = "Select * from courses"
     .refresh

     while not .recordset.eof
           combo1.additem = .recordset.coursecode
           .recordset.movenext
     wend
   end with
End Sub