如何使用VBA使用Recordset填充ComboBox

时间:2009-06-08 22:44:43

标签: ms-access vba combobox adodb recordset

expert's exchangeteck republic提供了一些关于使用combobox.recordset属性填充Access表单中的组合框的文献。

这些控件通常在控件的“rowsource”属性中填充“SELECT *”字符串,引用应用程序客户端上可用的表或查询。当我需要在组合框中显示服务器端数据时,我创建一个临时本地表并导入请求的记录。这非常耗时,尤其适用于大型桌子。

能够使用记录集填充组合框控件将允许用户直接显示来自服务器端的数据。

受前面两个例子的启发,我写了一些代码如下:

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():是我当前/活跃的表格
  • controls(“id_Personne”):是 组合框控制填充 公司员工名单
  • 2003年访问版本

不幸的是,它不起作用!

在调试模式下,我能够检查记录集是否已正确创建,包括请求的列和数据,以及是否与组合框控件正确关联。不幸的是,当我显示表单时,我不断得到一个空的组合框,没有记录!任何帮助都非常感谢。

编辑:

这个记录集属性确实可用于特定的组合框对象,而不是标准控制对象,我几天前发现它时非常惊讶。 我已经尝试使用combobox的回调函数,或者使用组合框的“addItem”方法填充列表。所有这些都很耗时。

6 个答案:

答案 0 :(得分:5)

如前所述,您必须将RowSourceType设置为“Table / List”(或“Table /Requête”,如果是法语),以便在组合框中显示查询结果。

打开记录集(rsPersonne)而不关闭它会导致内存问题。关闭/卸载表单时应该关闭它们(但是由于记录集是在函数中而不是在表单中声明的​​,因此会有范围问题。)

您还可以尝试使用Access的内置查询创建器创建和保存查询,并在组合框的RowSource中插入相同的查询。这样,在Access中验证和编译查询。

答案 1 :(得分:4)

要设置接受行源到记录集的控件,请执行以下操作:

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

与DAO Recordsets一起使用肯定,我没有尝试过ADO记录集,因为我没有任何真正的理由使用它们。

当这样做时,一个简单的重新查询将无法刷新数据,你必须重复set语句。

答案 2 :(得分:3)

我发现了这个技巧......组合框控件的“rowSourceType”属性必须设置为“Table / List”。显示现在可以,但我现在有另一个内存问题。由于我在表单上使用这些ADO记录集,因此每次浏览表单时Access的内存使用量都会增加。通过停止浏览或关闭表单来释放内存,使MS Access不稳定并经常冻结。如果我不能解决这个问题,我会提出一个问题

答案 3 :(得分:2)

使用Recordset属性的好方法,谢谢你的提示!

帕特里克,你在页面上显示的方法有一个很大的缺点(我自己也尝试过):值列表只能是32 KB,如果超过这个限制,函数将抛出错误。 回调方法有一个很大的缺点,它非常慢,并且每个条目都会调用一次,这使得它对于较长的列表不可用。 使用记录集方法非常有效。我需要这个,因为我的SQL字符串超过32 KB(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显示一个带错误的消息框,如果有的话。)

由于此函数关闭打开的记录集,因此内存应该没有问题。我测试了它,并没有看到任何增加的内存,在使用组合框关闭表单后没有释放。

在表单的卸载事件中,您可以另外使用“Set rs = Me.Comboboxname.Recordset”然后将其关闭。这对于内存来说不是必需的,但最好是释放打开的连接(如果与后端数据库服务器一起使用)。

干杯,

基督教

答案 4 :(得分:0)

组合框控件没有记录集属性。它确实有一个RowSource属性,但Access期望在那里有一个SQL字符串。

您可以将RowSourceType更改为用户定义的“回调”功能的名称。访问帮助将通过将您自己定位在RowSourceType上并按F1来为您提供更多信息,包括示例代码。当我想给用户提供可用报告,驱动器号或其他通过SQL查询无法获得的数据时,我会使用这种类型的函数。

关于直接从服务器端使用数据,我不明白你的第三段是什么意思。或者说我不明白使用标准查询的问题是什么。

答案 5 :(得分:0)

在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