2009-06-08 41 views
7

Hay un poco de literatura disponible en expert's exchange y en teck republic sobre el uso de la propiedad combobox.recordset para llenar un cuadro combinado en un formulario de acceso.Cómo llenar un ComboBox con un conjunto de registros usando VBA

Estos controles generalmente se rellenan con una cadena "SELECT *" en las propiedades de 'rowsource' del control, haciendo referencia a una tabla o consulta disponible en el lado del cliente de la aplicación. Cuando necesito mostrar los datos del lado del servidor en un cuadro combinado, creo una tabla local temporal e importo los registros solicitados. Esto lleva mucho tiempo, especialmente con tablas grandes.

Ser capaz de utilizar un conjunto de registros para rellenar un control de cuadro combinado permitiría al usuario visualizar directamente los datos desde el lado del servidor.

Inspirado por los 2 ejemplos anteriores, he escrito algo de código como sigue:

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 

Dónde:

  • connexionActive: es mi conexión ADO permanente con el servidor de base de datos
  • FC() : es mi forma actual/activa
  • controles ("id_Personne"): es el combobox control para poblar con empresa 'S lista personal
  • versión de acceso en 2003

Por desgracia, no funciona!

En el modo de depuración, puedo verificar que el conjunto de registros se haya creado correctamente, con las columnas y datos solicitados, y que esté asociado correctamente al control del cuadro combinado. Desafortunadamente, cuando muestro el formulario, sigo obteniendo un combobox vacío, ¡sin registros en él! Cualquier ayuda es muy apreciada.

EDIT:

propiedad Este conjunto de registros es de hecho disponible para el objeto específico de cuadro combinado, no con el objeto de control estándar, y yo era muy sorprendidos al descubrir que hace unos días. Ya he intentado usar la función de devolución de llamada del combobox o llenar una lista con el método "addItem" del combobox. Todos estos requieren mucho tiempo.

Respuesta

3

Encontré el truco ... la propiedad "rowSourceType" del control de cuadro combinado debe establecerse en "Tabla/Lista". La pantalla ahora está bien, pero ahora tengo otro problema con la memoria. Como utilizo estos conjuntos de registros ADO en mis formularios, el uso de la memoria de Access aumenta cada vez que navego por un formulario. La memoria no se libera al detener la exploración o al cerrar el formulario, lo que hace que MS Access sea inestable y se congele con regularidad.Abriré una pregunta si no puedo resolver este problema

+0

No funciona para mí:/Tiene un error 91: Bloc No presente –

+0

Si desea un consejo, debe dar el código defectuoso e identificar la línea que arroja el error. –

+0

Descripción del error aquí: http://stackoverflow.com/questions/16231456/how-to-populate-a-listbox-with-a-adodb-recordset-error-91 –

0

Un control de cuadro combinado no tiene una propiedad de juego de registros. Tiene una propiedad RowSource pero Access espera una cadena SQL allí.

Puede cambiar RowSourceType por el nombre de una función de "devolución de llamada" definida por el usuario. La ayuda de acceso le proporcionará más información, incluido el código de muestra, colocándose en RowSourceType y presionando F1. Utilizo este tipo de función cuando quiero proporcionar a los usuarios una lista de informes disponibles, letras de unidad u otros datos que no están disponibles a través de una consulta SQL.

No entiendo lo que quiere decir con su tercer párrafo con respecto al uso de datos directamente desde el servidor. O mejor dicho, no entiendo cuál es el problema con el uso de consultas estándar.

+0

Gracias Tony. De hecho, esta propiedad de conjunto de registros está disponible para el objeto de cuadro combinado específico, no para el objeto de control estándar. También estoy usando esta función de devolución de llamada para situaciones similares a la tuya. Mi problema es encontrar una manera de rellenar cuadros combinados en el lado del cliente con datos del lado del servidor. Hasta ahora, estaba creando tablas temporales locales para hacerlo, pero me lleva mucho tiempo.Tenía la esperanza de que el uso de un conjunto de registros sea más eficiente. –

+0

¿Por qué crees que asignar un conjunto de registros al cuadro combinado será más eficiente que dejar que Access/Jet administre la recuperación de datos de una cadena SQL? ¿Quiere decir que está utilizando un juego de registros desconectado? No puedo imaginar por qué alguien necesitaría lo que estás pidiendo, no tiene ningún sentido para mí. –

+0

Sí, el conjunto de registros ADO está desconectado –

5

Como dije, debe obtener RowSourceType en "Tabla/Lista" (o "Tabla/Requinte" si está en francés) para mostrar los resultados de la consulta en caja combo.

Sus problemas de memoria surgen al abrir el conjunto de registros (rsPersonne) sin cerrarlo. Debe cerrarlos al cerrar/descargar el formulario (pero, una vez más, tendría problemas de alcance ya que el conjunto de registros se declara en la función y no en el formulario).

También podría tratar de crear y guardar una consulta con el creador de consultas integrado de Access y tapar esa misma consulta en el RowSource de su cuadro combinado. De esta forma, la consulta se valida y compila dentro de Access.

+0

Comprobaré su propuesta sobre el problema de la memoria y me pondré en contacto lo antes posible. –

2

buen método con el uso de la propiedad Recordset, gracias por esa pista!

Patrick, el método que muestra en su página tiene una gran desventaja (lo intenté por mi cuenta): la lista de valores solo puede ser de 32 KB; si excede este límite, la función arrojará un error. El método de devolución de llamada tiene la gran desventaja de que es muy lento y se llama una vez para cada entrada que lo hace inutilizable para una lista más larga. Usar el método recordset funciona muy bien. Lo necesitaba porque mi cadena de SQL tenía más de 32 KB (muchos valores de índice para WHERE ID IN (x, x, x, x, x ...)).

Aquí es una función simple que utiliza esta idea para establecer un conjunto de registros de la lista desplegable:.

' 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 

(El fnADOSelectCommon función abre un conjunto de registros ADO y lo devuelve La fnErr función muestra un cuadro de mensaje con el error , si hubiera uno.)

Como esta función cierra el conjunto de registros abierto no debería haber ningún problema con la memoria. Lo probé y no vi ningún aumento de la memoria que no se publicó después de cerrar el formulario con los cuadros combinados.

En el evento de descarga del formulario, puede utilizar adicionalmente un "Establecer rs = Me.Comboboxname.Recordset" y luego cerrarlo. Esto no debería ser necesario con respecto a la memoria, pero puede ser mejor liberar las conexiones abiertas (si se usa con un servidor de base de datos de fondo).

Saludos,

Cristiano

+0

Seguro que mi método es limitado. Lo construí porque tenía que completar una lista de una consulta muy lenta (herited) (1 minuto más o menos). Usar el truco de cadena permite reordenar la lista en cualquier columna muy rápidamente sin volver a ejecutar la consulta larga. –

0

En MS Access, que está bien, pero en VB, puede usar algo como esto utilizando 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 
3

Para establecer un control que acepta una fuente de filas a un conjunto de registros, haga lo siguiente:

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

Funciona con DAO Recordse Ciertamente, no he probado los conjuntos de registros ADO porque no tengo ningún motivo real para usarlos.

Cuando se hace de esta manera, una simple consulta no funcionará para actualizar los datos, debe repetir la instrucción set.

+0

Personalmente, olvidé usar la palabra Establecer para asignar un juego de registros a mi control. ¡Gracias! –

Cuestiones relacionadas