Está en la página 1de 9

CUADROS COMBINADOS1

INTRODUCCIÓN
Nuestro amigo Sveinbjorn nos ha
preparado un excelente ejemplo de
múltiples maneras de tomar datos de un
cuadro combinado y manejarlos tanto a través de código
VBA como de funciones y expresiones. Es un ejemplo de
estudio que no tiene desperdicio.

Todo el texto que leeréis a partir del siguiente apartado es trabajo de Sveinbjorn, así como la
BD que acompaña este ejemplo. Oséase, que el mérito y las alabanzas deben ser para él. A mí
sólo me queda el agradecerle esta preparación 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 ¿cómo 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, países, provincias y poblaciones.

En segunda instancia, vamos a “complicar” un poco más 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 podéis bajar aquí

1
Visítame en http://neckkito.siliconproject.com.ar
1ª OPCIÓN: FUNCIÓN DBÚSQ (O DLOOKUP):
Vamos a crear un formulario en blanco, que llamaremos FEjemplo01, y en él vamos a insertar un
cuadro combinado para elegir una población, y dos cuadros de texto, que nos mostrarán la provincia y el
país de la población 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 botón 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 métodos para obtener el valor
“dependiente”, el primero “directamente” en la propiedad “origen del control” del cuadro de texto txtProv, y el
segundo usando código VBA.

-> Cuadro txtProv: en la propiedad “origen de Control”, escribimos esta fórmula:

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

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

-> Cuadro txtPais: en este caso vamos a obtener el valor por código, una vez que seleccionamos
una población en el cuadro combinado. Para ello, sacamos las propiedades de cboPobl, y nos vamos a la
pestaña Eventos->Después de actualizar. Hacemos clic en el espacio en blanco que hay a su derecha y nos
aparecerá un botón de puntos suspensivos. Hacemos clic sobre ese pequeño botón de puntos suspensivos
y, en la ventana que nos aparece, seleccionamos que queremos generar código. Se nos abrirá el editor de
VB (VBE), con dos líneas por defecto (Private Sub… y End Sub). En medio de esas líneas escribimos el

2
Visítame en http://neckkito.siliconproject.com.ar
siguiente código:
---
Private Sub cboPobl_AfterUpdate()

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

End Sub

---

2ª OPCIÓN: 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 población, y dos cuadros
de texto, que nos mostrarán la provincia y el país de la población 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 están.
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;
Además, tendremos que configurar otras propiedades del cuadro combinado:
 Pestaña 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 hubiéramos
seleccionado los campos en otro orden, por ejemplo Pobl, Prov, Pais, tendríamos que poner 1.

 Pestaña Formato -> Número de Columnas: aquí ponemos 3, en este caso, porque tenemos 3
campos seccionados.

 Pestaña 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í también vamos a ver dos métodos para obtener el valor “dependiente”, el primero
“directamente” en la propiedad “origen del control” del cuadro de texto txtProv, y el segundo usando
código VBA.

-> Cuadro txtProv: en la propiedad “origen de Control”, escribimos esta fórmula:

=[cboPobl].[column](1)

-> Cuadro txtPais: en este caso vamos a obtener el valor por código, una vez que seleccionamos
una población en el cuadro combinado. Para ello, escribimos el siguiente código:
---
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 país
será la 0, la de la provincia la 1 y la de la población la 2.

TRABAJANDO CON TABLAS RELACIONADAS

3
Visítame en http://neckkito.siliconproject.com.ar
Ahora vamos a ver cómo se haría al trabajar con dos tablas vinculadas.

1ª OPCIÓN: 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 código de
la provincia (CodProv):
 Origen de Fila: SELECT TProvincias.CodProv, TProvincias.Provincia, TProvincias.CCAA FROM
TProvincias;

 Columna Dependiente: 1
 Número 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 fórmula:
=DBúsq("Comunidad";"TCCAA";"CodCA=" & Nz([cboProv].[Column](2);0))
En este caso usamos una combinación de la función DBúsq 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. Además, uso la función Nz() para que no aparezca
#Error en [txtCCAA1] al estar en blanco [cboProv]
Al segundo cuadro de texto (txtCCAA2), le asignamos el valor por código, en el evento “Después de
actualizar” del cuadro combinado cboProv, con este código:
---
Private Sub cboProv_AfterUpdate()

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

End Sub

---

2ª OPCIÓN: QUE EL CUADRO COMBINADO DEPENDA DE UNA CONSULTA EN LA


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

4
Visítame 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 añadimos 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 función DBúsq, pues al trabajar sobre la consulta es más sencillo
usar la propiedad Columna, aunque lo vamos a ver igualmente.
· En txtCCAA1, en Origen de Control le ponemos: =DBúsq("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 código, poniendo en Después 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 podréis apreciar, la opción por código VBA es mucho más rápida que la que trabaja sobre el
origen del control del cuadro de texto, sobre todo si se usa la función DBúsq.

Además, trabajar por código tiene otra ventaja: nos permitiría guardar el valor dependiente en una
tabla, pues le podríamos asignar al cuadro de texto como origen de control el campo de una tabla, cosa que
con la otra opción no es posible, al llevar en dicha propiedad la fórmula para obtener el valor.

Habría otra opción de trabajo con el código VBA, que yo no recomendaría, que consiste en generar
el código 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
Visítame en http://neckkito.siliconproject.com.ar
Os habréis 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 aplicación “real de todo lo anterior, vamos a
crear un sistema de facturación muy sencillito. Para eso
necesitaremos las siguientes tablas:
· TClientes: con campos IDCliente (Autonumérico y Clave principal), Nombre y NIF (ambos Texto)

· TProductos: con campos IDProd (Autonumérico y Clave), Producto (Texto) y Precio (Moneda)

· TFacturas: con campos IDFact (Autonumérico y Clave), Fecha (Fecha/Hora), Cliente (numérico, que nos
enlazará con IDCliente de TClientes) y TotalFra (Moneda)
· TDetalleFact: con campos ID, Factura (numérico, que enlazará con IDFact), Producto (numérico, que
enlazará con TProductos), Precio (moneda) y Cantidad (numérico)

Rellenamos las tablas TClientes, y TProductos con algunos datos, y nos vamos a centrar en la parte
de facturación. 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, fijándonos en escoger una distribución tabular. Al finalizar el
asistente, le decimos de abrir en Vista Diseño para hacerle unos pequeños 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 código del
producto, y además, mostrará su descripción al desplegarlo. Su Origen de fila será: SELECT
[TProductos].[IDProd], [TProductos].[Titulo] FROM TProductos; 2 su número de columnas, y en mi
caso 2,544cm;4,544cm su ancho de columnas.

3. Vamos a añadir un cuadro de texto, llamado txtDescripcion, que nos mostrará la descripción del
producto seleccionado, pero sólo a título 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 automáticamente en función del valor seleccionado en el


combo [Producto]. Para ello, en el evento “Después de Actualizar” de [Producto], le generamos el
siguiente código:
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. Añadimos 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
Visítame en http://neckkito.siliconproject.com.ar
6. En el pie del formulario, añadimos 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 fórmula:
=Suma([Precio]*[Cantidad])

7. Y por último, en el evento “Después de


actualizar” de [Cantidad], le vamos a generar
un código 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 distribución en columnas, colocamos los 4 campos a nuestro gusto, y le
hacemos los siguientes “retoques”, para dejarlo así de bonito:

7
Visítame 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 Número de columnas y Ancho de columnas

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

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

4. En este caso, vamos a mostrar la información del cliente por código, por lo que en el evento
“Después de actualizar” del cuadro Cliente, le generamos este código:
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
Visítame 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 código.

· Para mostrar la descripción del producto, la propiedad Column en


el origen del registro
· Para mostrar el precio, la función DBúsq por en el código, y en este
caso, además guardamos el valor en la tabla correspondiente-

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

9
Visítame en http://neckkito.siliconproject.com.ar

También podría gustarte