Vous êtes sur la page 1sur 9

CUADROS COMBINADOS1

INTRODUCCIN
Nuestro amigo Sveinbjorn nos ha
preparado un excelente ejemplo de
mltiples maneras de tomar datos de un
cuadro combinado y manejarlos tanto a travs de cdigo
VBA como de funciones y expresiones. Es un ejemplo de
estudio que no tiene desperdicio.

Todo el texto que leeris a partir del siguiente apartado es trabajo de Sveinbjorn, as como la
BD que acompaa este ejemplo. Osase, que el mrito y las alabanzas deben ser para l. A m
slo me queda el agradecerle esta preparacin que me haya permitido compartir este ejemplo
con vosotros.

Espero que os guste.

CUADROS COMBINADOS
Una duda muy habitual en los foros trata sobre los cuadros combinados, concretamente cmo puedo
mostrar un valor en un cuadro de texto que dependa del valor elegido en un cuadro combinado?
Como hay distintas formas de conseguir este efecto, las voy a agrupar todas en un mismo ejemplo,
explicando sus pros y contras. Este ejemplo es aplicable a cuadros de listas, y en menor medida a cuadros
de texto.

PREPARATIVOS
En primera instancia, vamos a partir de la tabla del ejemplo Combos en Cascada, para explicar las
distintas formas de responder a la pregunta. Es una tabla muy sencilla, con tres campos: Pais, Prov y Pobl,
para introducir, respectivamente, pases, provincias y poblaciones.

En segunda instancia, vamos a complicar un poco ms el asunto, trabajando con dos tablas
relacionadas: TCCAA, con campos CodCA y Comunidad, y TProvincias, con campos CodProv, Provincia y
CCAA (ste relacionado con CodCA de TCCAA)

1 La BD de ejemplo os la podis bajar aqu

1
Vistame en http://neckkito.siliconproject.com.ar
1 OPCIN: FUNCIN DBSQ (O DLOOKUP):
Vamos a crear un formulario en blanco, que llamaremos FEjemplo01, y en l vamos a insertar un
cuadro combinado para elegir una poblacin, y dos cuadros de texto, que nos mostrarn la provincia y el
pas de la poblacin elegida. A estos cuadros los llamaremos respectivamente cboPobl, txtProv y txtPais.

El cuadro combinado, lo podemos crear usando el asistente, en cuyo caso le decimos que
queremos usar una tabla (TDatos), y seleccionamos el campo [Pobl] y configuramos a nuestro gusto hasta
el final; o lo podemos crear a las bravas, trabajando directamente sobre la propiedad Origen de la Fila.
En este caso, si dominamos el lenguaje SQL podemos construir directamente la SQL que nos devolver los
valores que mostrar el cuadro combinado, o en caso contrario, usar el Generador de Consultas pulsando
en el botn con los 3 puntos de la derecha de esa fila.

En cualquier caso, al final obtendremos esta SQL: SELECT TDatos.Pobl FROM TDatos ORDER BY
TDatos.Pobl;

Aprovechando que tenemos dos cuadros de texto, vamos a ver dos mtodos para obtener el valor
dependiente, el primero directamente en la propiedad origen del control del cuadro de texto txtProv, y el
segundo usando cdigo VBA.

-> Cuadro txtProv: en la propiedad origen de Control, escribimos esta frmula:

=DBsq("Prov";"TDatos";"[Pobl]='" & [Formularios]![FEjemplo01]![cboPobl] & "'")

Fijaros que al ser un dato de texto, hay que poner las comillas simples antes y despus del valor de
cboPobl.

-> Cuadro txtPais: en este caso vamos a obtener el valor por cdigo, una vez que seleccionamos
una poblacin en el cuadro combinado. Para ello, sacamos las propiedades de cboPobl, y nos vamos a la
pestaa Eventos->Despus de actualizar. Hacemos clic en el espacio en blanco que hay a su derecha y nos
aparecer un botn de puntos suspensivos. Hacemos clic sobre ese pequeo botn de puntos suspensivos
y, en la ventana que nos aparece, seleccionamos que queremos generar cdigo. Se nos abrir el editor de
VB (VBE), con dos lneas por defecto (Private Sub y End Sub). En medio de esas lneas escribimos el

2
Vistame en http://neckkito.siliconproject.com.ar
siguiente cdigo:
---
Private Sub cboPobl_AfterUpdate()

Me.txtPais=DLookup(Pais,TDatos,Pobl= &
Me.cboPobl & )

End Sub

---

2 OPCIN: USAR LA PROPIEDAD COLUMNA


(COLUMN) DEL COMBO
Vamos a crear un formulario en blanco, que llamaremos FEjemplo02, y en l vamos a insertar de
nuevo, y con los mismos nombres de antes, un cuadro combinado para elegir una poblacin, y dos cuadros
de texto, que nos mostrarn la provincia y el pas de la poblacin elegida.
El cuadro combinado, en este ejemplo, lo crearemos cogiendo las tres columnas de TDatos,
ajustando el ancho de las columnas correspondientes a [Pais] y [Prov] a 0 para que parezca que no estn.
Si el cuadro lo hacemos usando el asistente, ajustaremos el ancho de las mismas cuando nos lo pregunte, y
cuando nos pregunte qu valor queremos guardar, elegimos [Pobl]
Si optamos por hacerlo manualmente, en origen de la fila tendremos esta SQL: SELECT
TDatos.Pais, TDatos.Prov, TDatos.Pobl FROM TDatos ORDER BY TDatos.Pobl;
Adems, tendremos que configurar otras propiedades del cuadro combinado:
Pestaa Datos-> Columna Dependiente: aqu ponemos 3, porque es el valor que queremos
almacenar, el correspondiente a [Pobl], que est en tercer lugar en la SQL. Si hubiramos
seleccionado los campos en otro orden, por ejemplo Pobl, Prov, Pais, tendramos que poner 1.

Pestaa Formato -> Nmero de Columnas: aqu ponemos 3, en este caso, porque tenemos 3
campos seccionados.

Pestaa Formato -> Ancho de Columnas: aqu ponemos 0cm;0cm;3cm, porque queremos ocultar
las dos primeras columnas (correspondientes a Pais y Prov) y 3cm que ser el ancho de la tercera.

Aqu tambin vamos a ver dos mtodos para obtener el valor dependiente, el primero
directamente en la propiedad origen del control del cuadro de texto txtProv, y el segundo usando
cdigo VBA.

-> Cuadro txtProv: en la propiedad origen de Control, escribimos esta frmula:

=[cboPobl].[column](1)

-> Cuadro txtPais: en este caso vamos a obtener el valor por cdigo, una vez que seleccionamos
una poblacin en el cuadro combinado. Para ello, escribimos el siguiente cdigo:
---
Private Sub cboPobl_AfterUpdate()

Me.txtPais= Me.cboPobl.Column(0)

End Sub

---

Fijaros que Access por defecto, empieza a numerar en 0 en vez de en 1. As, la columna del pas
ser la 0, la de la provincia la 1 y la de la poblacin la 2.

TRABAJANDO CON TABLAS RELACIONADAS

3
Vistame en http://neckkito.siliconproject.com.ar
Ahora vamos a ver cmo se hara al trabajar con dos tablas vinculadas.

1 OPCIN: QUE EL CUADRO


COMBINADO DEPENDA DE LA
TABLA HIJA (TProvincias)
Creamos un formulario en blanco
(FEjemplo03), con un cuadro combinado (cboProv) y dos cuadros
de texto (txtCCAA1 y txtCCAA2). El cuadro combinado lo
configuramos para que coja los tres campos de TProvincias,
muestre la segunda columna (la provincia) y almacene el cdigo de
la provincia (CodProv):
Origen de Fila: SELECT TProvincias.CodProv, TProvincias.Provincia, TProvincias.CCAA FROM
TProvincias;

Columna Dependiente: 1
Nmero de columnas: 3
Ancho de columnas: 0 cm; 3 cm; 0 cm
Al primer cuadro de texto (txtCCAA1), en origen de control, le asignamos la siguiente frmula:
=DBsq("Comunidad";"TCCAA";"CodCA=" & Nz([cboProv].[Column](2);0))
En este caso usamos una combinacin de la funcin DBsq y la propiedad Columna, para buscar
en la tabla TCCAA el nombre de la comunidad que corresponda al CodCA de la provincia seleccionada, que
nos lo da la tercera columna del cuadro combinado. Adems, uso la funcin Nz() para que no aparezca
#Error en [txtCCAA1] al estar en blanco [cboProv]
Al segundo cuadro de texto (txtCCAA2), le asignamos el valor por cdigo, en el evento Despus de
actualizar del cuadro combinado cboProv, con este cdigo:
---
Private Sub cboProv_AfterUpdate()

Me.txtCCAA2 = DLookup("Comunidad", "TCCAA", "CodCA=" & Me.cboProv.Column(2))

End Sub

---

2 OPCIN: QUE EL CUADRO COMBINADO DEPENDA DE UNA CONSULTA EN LA


QUE SE RELACIONEN AMBAS TABLAS
En esta opcin, en primer lugar vamos a crear una consulta con esta estructura, que llamaremos
CProvCCAA:

4
Vistame en http://neckkito.siliconproject.com.ar
Ahora, de nuevo, construimos un formulario con los mismos controles que el del ejemplo anterior (o
hacemos un copia-pega de FEjemplo03) y le aadimos otros dos cuadros de texto (txtxCCAA3 y txtCCAA4).
Al cuadro combinado le cambiaremos el Origen de la Fila a este: SELECT CProvCCAA.CodProv,
CProvCCAA.Provincia, CProvCCAA.Comunidad FROM CProvCCAA;
Aqu tiene menos sentido usar la funcin DBsq, pues al trabajar sobre la consulta es ms sencillo
usar la propiedad Columna, aunque lo vamos a ver igualmente.
En txtCCAA1, en Origen de Control le ponemos: =DBsq("Comunidad";"CProvCCAA";"CodProv="
& Nz([cboProv];0))

En txtCCAA2, en Origen de Control le ponemos: =[cboProv].[Column](2)

A txtCCAA3 y txtCCAA4 se lo asignamos por cdigo, poniendo en Despus del actualizar de [cboProv]
lo siguiente:

Private Sub cboProv_AfterUpdate()

Me.txtCCAA3 = DLookup("Comunidad", "CProvCCAA", "CodProv=" & Me.cboProv)

Me.txtCCAA4 = Me.cboProv.Column(2)

End Sub

UN PAR DE COMENTARIOS
Como podris apreciar, la opcin por cdigo VBA es mucho ms rpida que la que trabaja sobre el
origen del control del cuadro de texto, sobre todo si se usa la funcin DBsq.

Adems, trabajar por cdigo tiene otra ventaja: nos permitira guardar el valor dependiente en una
tabla, pues le podramos asignar al cuadro de texto como origen de control el campo de una tabla, cosa que
con la otra opcin no es posible, al llevar en dicha propiedad la frmula para obtener el valor.

Habra otra opcin de trabajo con el cdigo VBA, que yo no recomendara, que consiste en generar
el cdigo no en el cuadro combinado, sino en el propio cuadro de texto, por ejemplo en el evento Al recibir
el enfoque o en Al entrar.

5
Vistame en http://neckkito.siliconproject.com.ar
Os habris fijado que uso dos notaciones
distintas para referirme al cuadro combinado
en el Origen de Control: unas veces la larga
([Formularios]![FEjemplo01]![cboPobl]) y otras
la corta ([cboPobl].[column](1)). Ambas son
indistintas.

UN GRAN EJEMPLO
Para ver una aplicacin real de todo lo anterior, vamos a
crear un sistema de facturacin muy sencillito. Para eso
necesitaremos las siguientes tablas:
TClientes: con campos IDCliente (Autonumrico y Clave principal), Nombre y NIF (ambos Texto)

TProductos: con campos IDProd (Autonumrico y Clave), Producto (Texto) y Precio (Moneda)

TFacturas: con campos IDFact (Autonumrico y Clave), Fecha (Fecha/Hora), Cliente (numrico, que nos
enlazar con IDCliente de TClientes) y TotalFra (Moneda)
TDetalleFact: con campos ID, Factura (numrico, que enlazar con IDFact), Producto (numrico, que
enlazar con TProductos), Precio (moneda) y Cantidad (numrico)

Rellenamos las tablas TClientes, y TProductos con algunos datos, y nos vamos a centrar en la parte
de facturacin. Necesitaremos un Formulario sobre TFacturas y un Subformulario sobre TDetalleFact.
Vamos a ello!
Por comodidad, vamos a empezar por el subformulario, al que llamaremos subFDetalleFact. Lo
creamos directamente con el asistente, fijndonos en escoger una distribucin tabular. Al finalizar el
asistente, le decimos de abrir en Vista Diseo para hacerle unos pequeos ajustes:

1. El campo [Factura] lo vamos a ocultar (la propiedad Visible la cambiamos a No)


2. El campo [Producto] ser un cuadro combinado, que nos mostrar y almacenar el cdigo del
producto, y adems, mostrar su descripcin al desplegarlo. Su Origen de fila ser: SELECT
[TProductos].[IDProd], [TProductos].[Titulo] FROM TProductos; 2 su nmero de columnas, y en mi
caso 2,544cm;4,544cm su ancho de columnas.

3. Vamos a aadir un cuadro de texto, llamado txtDescripcion, que nos mostrar la descripcin del
producto seleccionado, pero slo a ttulo informativo, pues no interesa guardar ese dato en
TDetalleFact. En su origen de control le ponemos: =[Producto].[Column](1)

4. El campo [Precio] lo vamos a rellenar automticamente en funcin del valor seleccionado en el


combo [Producto]. Para ello, en el evento Despus de Actualizar de [Producto], le generamos el
siguiente cdigo:
Private Sub Producto_AfterUpdate()

If Nz(Me.Producto, 0) = 0 Then Exit Sub

Me.Precio = DLookup("Precio", "TProductos", "IdProd=" & Me.Producto)

Me.Cantidad.SetFocus

End Sub

5. Aadimos otro cuadro de texto, txtSubTot, para ir calculando subtotales, que en este caso ser el
[Precio] por la [Cantidad], y as se lo indicamos en su Origen de control: =[Precio]*[Cantidad]

6
Vistame en http://neckkito.siliconproject.com.ar
6. En el pie del formulario, aadimos otro cuadro de texto,
txtSubTotal, que estar oculto, y nos servir para pasar el Total a la
Factura. En su origen de Control, le ponemos esta frmula:
=Suma([Precio]*[Cantidad])

7. Y por ltimo, en el evento Despus de


actualizar de [Cantidad], le vamos a generar
un cdigo que nos coger el valor del cuadro
txtSuvTotal (que est oculto en el pie del subformulario) y lo pasar
a [TotalFra], que ser:

Private Sub Cantidad_AfterUpdate()

Dim vTotal As Currency

'Guardamos el registro

DoCmd.RunCommand acCmdSaveRecord

Me.Recalc

DoCmd.RunCommand acCmdRecordsGoToNew

'Cogemos el valor del cuadro de texto que creamos en el pie del subformulario

vTotal = Me.txtSubTotal.Value

'Lo asignamos al total factura

Me.Parent.TotalFra = vTotal

End Sub

A m me ha quedado una cosa as:

Ahora le toca el turno al formulario, que llamaremos FFacturas. Lo creamos con el asistente,
eligiendo en este caso una distribucin en columnas, colocamos los 4 campos a nuestro gusto, y le
hacemos los siguientes retoques, para dejarlo as de bonito:

7
Vistame en http://neckkito.siliconproject.com.ar
1. El campo Cliente lo convertimos en un cuadro combinado, que mostrar las 3 columnas de
TClientes y almacenar el IDCliente, cosa que logramos con este origen de fila: SELECT
[TClientes].[IdCliente], [TClientes].[NIF], [TClientes].[Nombre] FROM TClientes ORDER BY [NIF]; y
jugando con las propiedades Nmero de columnas y Ancho de columnas

2. Aadimos dos cuadros de texto independientes (txtNIF y txtNombre) para mostrar los datos del
cliente al seleccionarlo en el cuadro combinado.

3. Aadimos el subformulario creado antes, y relacionamos los campos IDFact del formulario principal
con Factura del subformulario.

4. En este caso, vamos a mostrar la informacin del cliente por cdigo, por lo que en el evento
Despus de actualizar del cuadro Cliente, le generamos este cdigo:
Private Sub Cliente_AfterUpdate()

If Nz(Me.Cliente, 0) = 0 Then

Me.txtNIF = Null

Me.txtNombre = Null

Else

Me.txtNIF = Me.Cliente.Column(1)

Me.txtNombre = Me.Cliente.Column(2)

End If

End Sub

5. Para acabar, y para que al cambiar de registro se muestren correctamente los datos del cliente, al
evento Al activar registro del Formulario, le hacemos una llamada al evento anterior:
Private Sub Form_Current()

8
Vistame en http://neckkito.siliconproject.com.ar
Call Cliente_AfterUpdate

End Sub

Como veis, en este ejemplo final, he


usado las distintas formas explicadas
anteriormente:
Para mostrar los datos del cliente, la propiedad Column por cdigo.

Para mostrar la descripcin del producto, la propiedad Column en


el origen del registro
Para mostrar el precio, la funcin DBsq por en el cdigo, y en este
caso, adems guardamos el valor en la tabla correspondiente-

Y esto es todo, que no es poco. Espero que os sirva para vuestras aplicaciones.

9
Vistame en http://neckkito.siliconproject.com.ar

Vous aimerez peut-être aussi