Как заполнить ComboBox набором записей, используя VBA - PullRequest
8 голосов
/ 09 июня 2009

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

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

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

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

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 (): моя текущая / активная форма
  • control ("id_Personne"): это управление списком для заполнения штатное расписание компании
  • Версия доступа в 2003

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

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

EDIT:

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

Ответы [ 6 ]

5 голосов
/ 14 июля 2009

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

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

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

4 голосов
/ 01 февраля 2013

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

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

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

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

3 голосов
/ 09 июня 2009

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

2 голосов
/ 16 сентября 2009

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

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

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

' 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 показывает окно сообщения с ошибкой, если оно было.)

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

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

Приветствия

Christian

0 голосов
/ 12 декабря 2011

В 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
0 голосов
/ 09 июня 2009

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

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

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

...