You are on page 1of 7

BUSCAR EN VARIAS BD'S1

Bueno... Puede ser que, por temas de operativa, por temas


de tamao o simplemente porque a nosotros, como
administradores, nos va bien as, tengamos la informacin
relativa a un ao en una BD. Finaliza ese ao y empezamos
una BD nueva para el nuevo ao.
En definitiva, que guardamos la informacin diferentes BD's
en funcin del ao.
De todas maneras tened en cuenta que lo anterior es lo que se me ocurre en un supuesto al
que le veo cierta lgica, pero el ejemplo funcionara igual si tenemos varias BD's,
independientemente de si la informacin se ajusta al supuesto que yo he planteado lneas ms
arriba.
Lo que s debemos tener claro son los siguientes puntos:

La ruta (y nombre) de cada una de las BD's en las que vamos a realizar la bsqueda.
El nombre de la tabla que contiene la informacin donde queremos buscar.
El nombre del campo que contiene los datos donde queremos buscar.

Cul ser la mecnica que vamos a seguir?


A nivel de usuario se va a solicitar un valor a travs de un InputBox al pulsar un botn, y se
van a mostrar los resultados en una tabla.
A nivel de funcionamiento interno vamos a valernos de una tabla de informacin operada slo
por el administrador, donde vamos a informar de la ruta y nombre de las BD's antiguas, y de
una tabla auxiliar cuya informacin se ir reconstruyendo cada vez que el usuario pulse el
botn.
Dnde debemos llevar cuidado?
Para que la BD de ejemplo funcione en vuestros ordenadores, si os la bajis, yo he cambiado
ligeramente la mecnica de funcionamiento a la hora de desarrollar este ejemplo. Es decir, que
yo he utilizado una carpeta llamada <<BDsAntiguas>>, que se halla situado en el mismo
directorio donde tenemos la BD principal. Y eso me obliga a no poder definir, en la tabla que os
comentaba de las rutas, rutas absolutas, sino que he tenido que definir rutas relativas.
De todas maneras os dar, a la hora de desarrollar el cdigo y a lo largo del ejemplo, las
indicaciones oportunas para poder adaptar esto a vuestra situacin. De esta manera podris
ver cmo hacerlo si utilizamos rutas absolutas y rutas relativas.
Y dicho esto, que quiz ahora pueda sonaros un poco lioso, no os preocupis porque lo
iremos entendiendo (espero) a medida que vayamos desarrollando este ejemplo.

PREPARANDO LA ESTRUCTURA INICIAL


Como necesito una materia prima antes de poder realizar el ejemplo os indico lo que he
hecho para preparar el terreno.

La BD de ejemplo os la podis bajar aqu

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

Tened en cuenta que, a efectos de simplificar el ejemplo, la


informacin que va a aparecer en las BD's de ejemplo
puede ser que no tenga demasiado sentido en un supuesto
real. Sin embargo, no perdis de vista que lo que interesa
es la mecnica de cmo se hace la bsqueda, y no tanto la
informacin que pueda haber en el ejemplo.
Creamos
una
BD
(que
yo
he
llamado
<BuscarVariasBDs.mdb>) y, en ella, creamos una tabla, a
la que llamaremos TDatos, que va a servirnos como una
simple tabla donde tenemos los datos en los cuales
queremos buscar la informacin. He construido TDatos con
la siguiente estructura:

En el mismo directorio donde tenemos la BD creamos una nueva carpeta, a la que llamaremos
BDsAntiguas (esto no sera necesario si vamos a utilizar rutas absolutas).
Copiamos nuestra BD y la pegamos dos veces dentro de <BDsAntiguas>. A la primera copia la
llamamos Ejercicio2011.mdb y a la segunda Ejercicio2012.mdb2
A continuacin he rellenado la tabla TDatos de cada una de las BD's con algunos registros
inventados. Para que os hagis una idea os muestro algunos de estos registros:

Y ahora s... vamos al meollo del asunto...

CREANDO NUESTRA TABLA DE RUTAS


Vamos a crearnos una tabla en la BD principal, a la que llamaremos TRutas. Dicha tabla tendr
la siguiente estructura:

Como estoy desarrollando el ejemplo sobre Access 2003 yo utilizo la extensin mdb. Lgicamente, si vosotros trabajis con Access
2007 2010, la extensin que deberis utilizar es accdb.

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

Cmo vamos a rellenar la tabla? Pues eso va a depender de si estamos utilizando rutas
absolutas o rutas relativas.
Si utilizamos rutas absolutas debemos indicar la ruta
completa donde tenemos las BD's. Supongamos que las
tenemos en una carpeta llamada <MisBDs>, que est en la
carpeta <Trabajos>, que a su vez est en la unidad C.
Luego deberamos rellenar la tabla con los siguientes datos:

Si utilizamos rutas relativas (os recuerdo que, en este sentido, estoy queriendo decir que las
BD's se hallan dentro de una carpeta que est en el mismo directorio donde tenemos la BD
principal), y aplicado a este ejemplo, deberamos rellenarla simplemente con el nombre de la
carpeta. Es decir:

Tambin os recuerdo que yo estoy utilizando Access 2003, y de ah que utilice la extensin
mdb. Si usamos una versin posterior de Access deberamos indicar la extensin correcta, esto
es, accdb

CREANDO NUESTRA TABLA DE RESULTADOS


A continuacin vamos a crear una nueva tabla, que llamaremos TResultados, que tendr la
siguiente estructura:

CREANDO NUESTRO BOTN DE BSQUEDA


En el formulario que queramos (un formulario tipo Men, un formulario de consultas...)
aadimos un botn de comando. Vamos a ponerle de nombre cmdBuscaTablas 3. En el evento
Al hacer click generamos el siguiente cdigo4:

3
4

Para asignar un nombre a un control lo que debemos hacer es sacar las propiedades de ese control e irnos a la Pestaa Otras
Nombre. Ah escribimos el nombre que queramos.
Para generar cdigo debemos sacar las propiedades del control Pestaa Eventos, y nos situamos en la parte blanca a la
derecha del evento que queremos programar. Veremos un pequeo botn de puntos suspensivos. Si hacemos click sobre l nos
aparecer una ventana que nos pedir qu operacin deseamos realizar. Le indicamos que queremos generar cdigo.

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

Private Sub cmdBuscaTablas_Click()


'Declaramos las variables
Dim vBuscado As Variant
'Solicitamos la informacin al usuario
vBuscado = InputBox("Introduzca el valor a buscar", "BSQUEDA")
'Detectamos la pulsacin del botn CANCELAR
If StrPtr(vBuscado) = 0 Then Exit Sub
'Llamamos al procedimiento realizoBusqueda
Call realizoBusqueda(vBuscado)
End Sub

Como podemos ver el botn lo nico que hace es reclamar la informacin al usuario para, a
continuacin, realizar una llamada a un procedimiento que explicaremos a continuacin.

CREANDO NUESTRO MDULO Y CDIGO


La creacin del mdulo es un proceso simple. El cdigo que explicar aqu se refiere a
referencias relativas. Es decir, que si utilizamos referencias absolutas deberemos utilizar el
mismo cdigo pero en el epgrafe siguiente os explicar qu lneas debemos modificar para
adaptarlo a dicho tipo de referencias.
Para crear ese nuevo mdulo nos vamos al editor de VB (si no lo tenemos visible pulsamos la
combinacin de teclas ALT+F11 y se nos abrir el VBE) y nos vamos a Men Insertar
Mdulo.
Una vez creado ese mdulo lo guardamos con el nombre mdlBuscaTablas
Para los sufridos usuarios de Access 2003 vamos a necesitar registrar una referencia (si no la
tenemos registrada ya), que es la referencia Microsoft DAO 3.6 Object Library5
En ese mdulo vamos a escribir nuestro procedimiento realizoBusqueda(). Si sabemos algo de
VB veremos que hay elementos que se pueden simplificar. Sin embargo, a efectos
pedaggicos, he preferido realizar una versin extensa para que entendemos mejor el
funcionamiento.
Su cdigo es el siguiente (est comentado para que sepis que hace prcticamente cada una
de las lneas):

Public Sub realizoBusqueda(vBusc)


'Neckkito --- 19/01/13
'Requiere registro de la referencia "Microsoft DAO 3.6 Object Library" o
'mdulo equivalente
'Inserto un control de errores por si no se encontrara la ruta o la BD
On Error GoTo sol_err
'Declaro las variables
Dim dbsRuta As DAO.Database
Dim dbs As DAO.Database
Dim rstTDatos As DAO.Recordset
Dim rstTRuta As DAO.Recordset
Dim rstTResultados As DAO.Recordset
Dim rst As DAO.Recordset
Dim rutaCompleta As String
Dim vCampo As String
'Eliminamos los registros que pudiera contener TResultados
DoCmd.SetWarnings False 'Desactivamos los warnings
5

Para registrar una referencia debemos irnos, en el editor de VB, a Men Herramientas Referencias... Se nos abrir una
ventana mostrndonos todas las referencias disponibles. Buscamos la que nos interese, marcamos su check y aceptamos.

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

DoCmd.RunSQL ("DELETE FROM TResultados")


DoCmd.SetWarnings True 'Reactivamos los warnings
'Definimos dbs
Set dbs = CurrentDb
'Abrimos el recorset sobre nuestra tabla TRutas
Set rstTRuta = dbs.OpenRecordset("TRutas", dbOpenSnapshot)
'Abrimos el recordset sobre nuestra tabla TResultados
Set rstTResultados = dbs.OpenRecordset("TResultados", dbOpenTable)
'Nos movemos al primer registro de TRutas
rstTRuta.MoveFirst
'Empezamos el anlisis de la rutas de TRutas
Do Until rstTRuta.EOF
'Construimos la ruta entera de la BD donde debemos buscar
rutaCompleta = Application.CurrentProject.Path & "\" _
& rstTRuta.Fields("Ruta").Value & "\" & rstTRuta.Fields("Archivo").Value
Set dbsRuta = DBEngine.OpenDatabase(rutaCompleta)
'Abrimos un recorset sobre la tabla TDatos de la BD analizada
Set rstTDatos = dbsRuta.OpenRecordset("TDatos", dbOpenSnapshot)
'Nos situamos en el primer registro
rstTDatos.MoveFirst
'Iniciamos el recorrido de registros
Do Until rstTDatos.EOF
'Analizamos la coincidencia con el valor buscado
vCampo = rstTDatos.Fields("Estados").Value
If InStr(1, vCampo, vBusc) <> 0 Then 'Si hay coincidencia...
'Escribimos la coincidencia en TResultados
rstTResultados.AddNew
rstTResultados.Fields("Nombre").Value = rstTDatos.Fields("Nombre").Value
rstTResultados.Fields("Estado").Value = rstTDatos.Fields("Estados").Value
rstTResultados.Fields("EnBD").Value = rstTRuta.Fields("Archivo").Value
rstTResultados.Update
End If
'Nos movemos al siguiente registro
rstTDatos.MoveNext
Loop
'Nos movemos a la siguiente BD a analizar
rstTRuta.MoveNext
Loop
'Buscamos en la BD actual
Set rst = dbs.OpenRecordset("TDatos", dbOpenSnapshot)
'Nos movemos al primer registro
rst.MoveFirst
'Iniciamos el recorrido de registros
Do Until rst.EOF
'Analizamos la coincidencia con el valor buscado
vCampo = rst.Fields("Estados").Value
If InStr(1, vCampo, vBusc) <> 0 Then
'Escribimos la coincidencia en TResultados
rstTResultados.AddNew
rstTResultados.Fields("Nombre").Value = rst.Fields("Nombre").Value
rstTResultados.Fields("Estado").Value = rst.Fields("Estados").Value
rstTResultados.Fields("EnBD").Value = "Actual"
rstTResultados.Update
End If
'Nos movemos al siguiente registro
rst.MoveNext
Loop
'Abrimos la tabla de resultados en modo slo lectura
DoCmd.OpenTable "TResultados", , acReadOnly
'Cerramos conexiones y liberamos memoria
rst.Close
rstTDatos.Close
rstTRuta.Close
rstTResultados.Close
dbs.Close
dbsRuta.Close
Set rst = Nothing
Set rstTDatos = Nothing
Set rstTRuta = Nothing
Set rstTResultados = Nothing
Set dbs = Nothing

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

Set dbsRuta = Nothing


Salida:
Exit Sub

sol_err:
If Err.Number = 3044 Then 'No encontramos la ruta
MsgBox "No se encuentra la ruta a la base de datos", vbCritical, "ERROR"
Resume Salida
End If
If Err.Number = 3024 Then 'No encontramos la BD
MsgBox "No se encuentra la base de datos", vbCritical, "ERROR"
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description,
vbCritical, "ERROR"
End If

End Sub

SI LAS REFERENCIAS SON ABSOLUTAS...


Si nuestras referencias son absolutas debemos realizar lo siguiente:
1.- Nos situamos en la lnea de cdigo que definen la variable rutaCompleta, que son:

'Construimos la ruta entera de la BD donde debemos buscar


rutaCompleta = Application.CurrentProject.Path & "\" _
& rstTRuta.Fields("Ruta").Value & "\" & rstTRuta.Fields("Archivo").Value

2.- Las cambiamos por las siguientes:

'Construimos la ruta entera de la BD donde debemos buscar


rutaCompleta = rstTRuta.Fields("Ruta").Value & "\" & rstTRuta.Fields("Archivo").Value

UNOS COMENTARIOS SOBRE EL CDIGO

La estructura del cdigo en cuanto a bsqueda y escritura de resultados, en abstracto,


es la siguiente:

Localizo la ruta y la BD a examinar (a travs del recordset rstTRuta)

Abro la tabla TDatos de esta primera BD que examino y recorro los registros (a travs de
rstTDatos)

Si encuentro alguna coincidencia la escribo en TResultados (a travs de rstTResultados)

Cuando he acabado con esa BD me muevo a la siguiente BD a analizar (a travs de


rstTRuta.movenext / Loop)

Repito el proceso con TDatos, pero de la nueva BD a analizar

Cuando acabo con los registros de TRutas me centro en la BD actual, realizando el mismo
proceso de lectura (de TDatos) y de escritura (de TResultados).

La bsqueda del valor la he hecho utilizando la funcin InStr(), que, para entendernos,
6

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

funciona en este caso similar a un LIKE. Sabemos (y si no lo sabamos lo sabremos ahora) que
si InStr() devuelve el valor 0 (cero). Por eso yo utilizo el IF diciendo que si devuelve un valor
distinto de cero (<>0) es porque se ha producido alguna coincidencia, y por tanto s debo
escribir ese valor
como resultado.

Si bien el cdigo lleva un control de errores para


gestionar los dos principales errores que, desde mi punto
de vista, podran producirse, que son que no exista la ruta a
las BD's o que directamente no existan las BD's, lo que no
lleva es un control de errores para registros. Qu significa
esto? Pues simplemente que si un registro no tuviera valor
en el campo [Estados] obtendramos un error de cdigo.
Cmo solucionamos eso? Pues quiz la manera ms sencilla es obligar a que haya un valor,
aunque no lo haya. Y eso se consigue con la funcin NZ().
Es decir, que si me salta un error en la lnea:
rst.Fields(Estados).Value
porque en ese registro no hay ningn valor, podra sustituir esa expresin por
Nz(rst.Fields(Estados).Value, )
De manera que si no hay valor devolvera una cadena vaca (representada por las dos comillas
dobles del segundo argumento de Nz().

PARA FINALIZAR EL EJEMPLO...


Dado que este ejemplo no es precisamente de los ms sencillos es por ello por lo que lo he
ubicado en la seccin Ejemplos Especiales de la Web.
Creo que si lo analizamos con calma y sin prisas veremos como le podemos coger el
tranquillo y entenderlo para aplicarlo a nuestra propia aplicacin (eso espero!).
Como curiosidad os dir que, si queremos, en vez de abrir la tabla podramos crearnos un
formulario basado en TResultados, mejor en vista de formularios continuos, para ver la
informacin en un formulario. En este caso deberamos cambiar la lnea de cdigo
'Abrimos la tabla de resultados en modo slo lectura
DoCmd.OpenTable "TResultados", , acReadOnly

Por
'Abrimos el formulario de resultados en modo slo lectura
DoCmd.OpenForm "NombreFormulario", , , , acFormReadOnly

De una manera u otra deseo que os sea de utilidad.


Un saludo, y...
suerte!

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

You might also like