Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
CAPTULO 111
ndice de contenido
OBJETOS DE ACCESO A DATOS (II)...............................................................................................2
RECORDSET..................................................................................................................................2
LA MANERA MS FCIL DE ACCEDER A UN RECORDSET: CLONARLO........................3
UN POCO DE TEORA..................................................................................................................5
ABRIR UN RECORDSET PARA CONSULTAR UN DATO........................................................6
RECORRER UN CONJUNTO DE REGISTROS..........................................................................7
MODIFICANDO UN REGISTRO..................................................................................................9
MODIFICANDO TODOS LOS REGISTROS.............................................................................10
Modificando todos los registros pero con ms de un campo....................................................11
Consultando una consulta.........................................................................................................12
Consultando una consulta que an no existe.............................................................................14
Error porque el valor no existe?.........................................................................................15
BSQUEDA RPIDA: Seek........................................................................................................17
AADIENDO UN REGISTRO....................................................................................................18
UNOS PREPARATIVOS NECESARIOS.....................................................................................19
EL EJEMPLO FINAL: UN MIX DE TODO LO APRENDIDO...............................................21
Cmo sera nuestra SQL...........................................................................................................21
ESTRUCTURACIN DEL CDIGO......................................................................................22
DESARROLLANDO EL CDIGO.........................................................................................22
UNAS PALABRAS FINALES......................................................................................................25
1
Vistame en http://siliconproject.com.ar/neckkito/
OBJETOS DE ACCESO A DATOS (II)
En el captulo anterior hemos visto el mtodo de acceso a
datos DAO. Sin embargo, nos faltaba algo.
Manos a la obra.
RECORDSET
Recordset, recordset... potito palabro. Access nos aclara qu es un recordset de la siguiente
manera:
<<Un objeto Recordset representa los registros de una tabla base o los registros resultantes
de la ejecucin de una consulta>>
Bueno... Ahora todos podemos presumir de que ya sabemos qu es un recordset, verdad? Je,
je...
Por ahora, lo que tenemos claro es que es un objeto, y, como tal, tiene sus propiedades y
mtodos, y es manipulable (os suena la frase?)
Si abrimos una tabla o de una consulta podemos ver los datos que hay en ellas, organizados
en registros. El conjunto de esos registros constituira un recordset. Pero la idea de recordset
lleva implcita algo ms, algo que podramos llamar inmaterial.
Lo que voy a comentaros a continuacin es algo que est totalmente alejado de tecnicismos y
teora y, en el fondo, es una reflexin ma de carcter personal. Sin embargo, considero que
tras su lectura todo el mundo debera tener una idea ms que clara de lo que es un recordset.
Vamos a hacer un smil, ponindonos un poco filosficos: abrimos una tabla (con datos, claro),
miramos intensamente la pantalla y cerramos los ojos. Si queremos podemos ver, en nuestra
mente, reproducida esa tabla con su informacin. Es ms, podemos centrarnos en un registro
e imaginar que ese registro desaparece. O nos centramos en un registro, siempre en nuestra
mente, y ms en concreto en un campo y un dato. Y ah donde pone electricista (por
ejemplo) nos imaginamos que pone fontanero. Y , por nuestra voluntad, automticamente
slo vemos los registros en los que en ese campo hay el valor fontanero, y los otros
desaparecen.
Pues Access sera como nosotros mismos, y los recordset seran esa imagen que tenemos en
el cerebro. As como nosotros podemos imaginar que desaparecen registros Access puede
hacer desaparecer registros, aadir de nuevos, sustituir los existentes, aadir ms campos,
etc.
Dnde est fsicamente ese recordset que maneja Access? Pues para nosotros no est, en el
sentido que no podemos verlo en la aplicacin. Slo podemos tener acceso visible al mismo
cuando Access escribe los resultados en una tabla o consulta, o, a veces, ni siquiera eso,
2
Vistame en http://siliconproject.com.ar/neckkito/
puesto que nos informa a travs de un MsgBox.
Y despus de este ambiente chillout en que nos hemos sumergido vamos a ver un par de cosas
sobre los recordset.
El cdigo que vamos a programar nos solicitar un DNI. Acto seguido clonar el recordset de la
tabla. Qu significa eso? Que por una parte tendremos el recordset de la tabla y por otro
tendremos una copia de dicho recordset. En definitiva, que estaremos operando con dos
recordsets: original y copia.
Por qu hacemos eso? Pues porque nos es ms cmodo, para la operacin que vamos a
realizar, trabajar sobre un recordset inmaterial que no directamente sobre la tabla. Y ello es
as porque el recordset copia tiene una serie de propiedades y mtodos que podemos
manipular a nuestro antojo.
Nos acordamos cuando, en el primer apartado, yo hablaba de nuestra mente? Pues el clon
del recordset que hemos creado se aloja en memoria del ordenador, lo que implica que est
consumiendo un espacio. Por ello, una vez obtenido el resultado, y dado que ya no
necesitamos ms ese clon, podemos cerrarlo, primero, y eliminarlo, despus, de la memoria,
tal y como aprendimos en el captulo anterior (nos acordamos de Close y de =Nothing?).
As, tal y como lo hemos creado, lo hacemos desaparecer.
Vimos este sistema en el captulo dedicado a filtros, por lo que ya os debera sonar todo lo
que vamos a ver. Pero esta vez el enfoque de la explicacin ser desde el punto de vista de
DAO.
.
Private Sub cmdRecordsetClon_Click()
'Declaramos las variables
3
Vistame en http://siliconproject.com.ar/neckkito/
Dim nDNI As Long
Dim filtro As String
Dim rst As Recordset
'Solicitamos al usuario que introduzca un DNI
nDNI = InputBox("Introduzca un DNI a buscar", "DNI")
'Creamos el filtro
filtro = "[DNI]=" & nDNI
'Clonamos el recordset
Set rst = Me.Recordset.Clone
'Manipulamos el recordset del clon para buscar un DNI a
travs
'del mtodo Recordset.FindFirst()
rst.FindFirst filtro
'Cuando lo encuentra aadimos un marcador a nuestro clon para
'"fijar" el registro que cumple con el filtro a travs de la propiedad
'Recordset.Bookmark
'Traspasamos ese marcador al recordset original. De esta manera
'en pantalla nos situaremos en el registro que cumple con el filtro
Me.Bookmark = rst.Bookmark
'Cerramos el recordset clon
rst.Close
'Lo eliminamos de memoria
Set rst = Nothing
End Sub
Forms!NombreForm.Recordset.Clone
A partir de ah, para referirnos a nuestro clon, siempre utilizaremos rst. (rst punto). Y
ya tenemos posibilidad, con esta nomenclatura, de actuar sobre sus propiedades y mtodos.
De hecho, primero actuamos sobre el mtodo FindFirst y despus actuamos sobre la propiedad
Bookmark.
En el ejemplo, el traspaso del resultado se produce a travs de la igualacin de la
misma propiedad (Me.Bookmark rst.Bookmark)
Para cerrar el recordset siempre utilizamos rst.Close
Para liberar memoria le tenemos que decir a Access que el recordset es nada. Ello lo
conseguimos a travs de la instruccin Set rst = Nothing
Siguiendo con este ejemplo, vamos a complicar el cdigo ligeramente. Qu pasa si el DNI
introducido y buscado no existe? Pues manipulamos otra propiedad del recordset. En este caso
la propiedad afectada es NoMatch. Como ya sabemos cmo actuar sobre ella (rst. +
propiedad) pues... la cosa est hecha.
4
Vistame en http://siliconproject.com.ar/neckkito/
El cdigo nos quedara as:
Creo que no hace falta realizar ningn comentario. Deberamos ser capaces de entender el
cdigo perfectamente con todo lo que ya sabemos... je, je...
UN POCO DE TEORA
Vamos a relajar un poco los dedos, despus de tanto ejemplo, y vamos a darle al coco con
un poco de teora. Os aseguro que nos ser til para ms adelante.
Podemos abrir un recordset de cuatro maneras diferentes, cada una con sus caractersticas.
Vamos a verlas:
a) dbOpenTable
Este sistema nos permite abrir una tabla. La principal ventaja es que nos permite utilizar los
ndices de la tabla. Con este sistema de apertura podemos aadir o modificar los datos de la
tabla (a no ser que le indiquemos que la abra en modo slo lectura).
Tambin debemos tener en cuenta que este sistema no es aplicable si lo que tenemos son
tablas vinculadas. Ello nos implicara abrir el recordset con otro sistema.
b) dbOpenDynaset
Por Dynaset podramos entender la idea de hoja de respuestas dinmica. Este mtodo de
apertura representa el resultado de una consulta cuyos registros pueden actualizarse.
5
Vistame en http://siliconproject.com.ar/neckkito/
Dado que podemos realizar consultas sobre varias tablas una ventaja de este sistema es,
precisamente, el poder trabajar sobre los datos de varias tablas.
c) dbOpenSnapshot
d) dbOpenForwardOnly
Si volvemos a utilizar el traductor veremos que eso significa slo hacia adelante. Es decir, es
como si abriramos un snapshot (=slo lectura), pero slo podemos desplazarnos por los
registros hacia adelante. Si la caracterstica de dbSnapshot era la velocidad, pues la
caracterstica de dbOpenForwardOnly es la velocidad multiplicada.
Es interesante saber lo anterior dado que, segn la accin que necesitemos realizar sobre el
recordset (operar sobre l o slo consultarlo), podemos optimizar el funcionamiento del cdigo.
Tambin debemos tener en cuenta que hay propiedades y mtodos que funcionan con todos
los sistemas, pero hay otros que slo funcionan en unos pero no en otros. No os preocupis
pro eso porque los errores de cdigo nos advertirn inmediatamente de que utilizamos un
cuchillo para comer sopa.
Y como estoy seguro de que estamos ya saturados de tanta teora (je, je...) volvamos a
nuestra BD para poner en prctica esto que acabamos de entender.
6
Vistame en http://siliconproject.com.ar/neckkito/
Set rst = Nothing
Set dbs = Nothing
End Sub
Recordando la teora aprendida hace unos instantes, el modo de apertura que hemos elegido
ha sido dbOpenSnapshot, porque slo nos interesaba mirar qu valor tena ese primer campo
del primer registro.
nomTrab = rst.Fields(Nombre).Value
BOF
Vendra a significar Begin Of Files. Lo que est indicando es que el puntero del recordset est
antes de la primera fila del recordset.
EOF
Vendra a significar End Of Files. Nos indica que el puntero del recordset se halla despus de la
ltima fila del recordset.
7
Vistame en http://siliconproject.com.ar/neckkito/
Si combinamos la idea del bloque DO UNTIL...LOOP con estas dos propiedades podemos ver
cmo le damos las instrucciones al cdigo para el recorrido del recordset.
rst.MoveFirst
Do Until rst.EOF
'Acciones a desarrollar
rst.MoveNext
Loop
rst.MoveLast
Do Until rst.BOF
'Acciones a desarrollar
rst.MovePrevious
Loop
Vamos a conseguir que el cdigo nos diga los nombres de los trabajadores de nuestra tabla.
As pues escribimos lo siguiente:
8
Vistame en http://siliconproject.com.ar/neckkito/
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
MODIFICANDO UN REGISTRO
Vamos a abrir directamente la tabla y vamos a modificar el nombre del ltimo trabajador.
Vamos a cambiar Laura por Laurita.
Primero, indicar al cdigo que nos disponemos a realizar una edicin del registro
Segundo, indicar el campo que queremos y qu nuevo valor va a contener
Tercero, actualizar la informacin modificada en la tabla.
With rst
.Edit
.Fields(x).Value = <NuevoValor>
.Update
End With
9
Vistame en http://siliconproject.com.ar/neckkito/
MsgBox "Cambios realizados correctamente", vbInformation, "OK"
'Cerramos conexiones y liberamos memoria
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
Supongamos que queremos que todos los nombres de los trabajadores estn en mayscula.
Esta operacin ya la sabemos hacer de lo aprendido en captulos anteriores. As pues os
animo a que, antes de mirar el cdigo que os pongo a continuacin, intentis programarlo
vosotros mismos, para ver dnde fallamos (si es que fallamos).
10
Vistame en http://siliconproject.com.ar/neckkito/
Como vemos si analizamos el cdigo, con lo aprendido hasta ahora resulta muy fcil (s?)
adaptar el cdigo a nuestras necesidades. Ya comentaba en el captulo anterior que esto es
como un mecano: con las piezas correctas podemos construir una estructura segn
nuestras necesidades.
.Fields(1).Value = UCase(.Fields(1).Value)
Vamos a modificar el valor del segundo registro, y nuestra Eva se va a convertir en Rambo.
Evidentemente, debemos cambiar tambin el sexo de nuestro Rambo, porque dejarlo como
Mujer sera... inconveniente?
11
Vistame en http://siliconproject.com.ar/neckkito/
Set rst = Nothing
Set dbs = Nothing
End Sub
Fijaos en:
y fijaos en
With rst
.Edit
.Fields(1).Value = "RAMBO"
.Fields(2).Value = "Hombre"
.Update
End With
Simplemente remarcar que el .Edit edita todo lo que est a continuacin, hasta que damos la
orden de actualizar los datos (.Update). As, todos los campos que queramos modificar iran
ah dentro.
S que alguien puede pensar: eso es un poco tontera, pero insisto en que lo que os intento
transmitir no es esto se hace as, sino que con todo lo que sabemos hasta ahora podemos
realizar muchas operaciones simplemente combinando cdigos o sistemas.
El cdigo que podramos programar para conseguir lo que queremos sera, por ejemplo:
12
Vistame en http://siliconproject.com.ar/neckkito/
rst.MoveFirst
'Iniciamos el proceso de recuento
Do Until rst.EOF
'Miramos el valor del campo sexo y sumamos una unidad
If rst.Fields("Sexo").Value = "Hombre" Then
nH = nH + 1
Else
nM = nM + 1
End If
'Nos movemos al siguiente registro
rst.MoveNext
Loop
'Mostramos los resultados
MsgBox "Hay " & nM & " mujeres y " & nH & " hombres", vbInformation, "RECUENTO"
'Cerramos conexiones y liberamos memoria
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
Como abrimos una consulta pues debemos abrir el recordset con el mtodo
dbOpenDynaset (hubiramos podido utilizar un dbOpenSnapshot sin problemas). Lo que no
podramos utilizar es el mtodo dbOpenTable.
Si hubiramos utilizado este ltimo mtodo nos saldra un pedazo mensaje dicindonos:
Recordaros que podemos hacer referencia al campo que queremos capturar o bien por
su ndice o bien por su nombre. En este caso yo he utilizado el nombre
(rst.Fields("Sexo").Value)
El bloque IF...END IF nos examina el valor del campo y suma una unidad al contador
que corresponda. Sin problemas, supongo.
Por ltimo, ved que he declarado las variables nH y nM como Integer. Si nuestra BD
tuviera ms de 32.767 registros que cumplieran la condicin el cdigo nos dara error. En ese
caso recordad que deberamos declarar esas variables como Long (que tiene una capacidad
mayor).
13
Vistame en http://siliconproject.com.ar/neckkito/
Consultando una consulta que an no existe
Es en estos momentos tan duros de nuestro captulo
cuando empezamos a apreciar la importancia de las
consultas SQL.
Para hacernos una idea es como si dijramos: necesito esto Y esto aparece por arte de
magia en nuestra mano Ya no lo necesito Y esto desaparece tambin como por arte de
magia.
Vamos a ver una consulta SQL muy simple, que nos filtrar un trabajador por DNI solicitado.
Como resultado obtendremos un MsgBox con la informacin de ese trabajador/trabajadora.
El cdigo sera:
La mecnica es muy similar a la que hemos visto hasta ahora. Simplemente nuestro recorset
ha tomado los datos de una SQL.
SELECT
nombreTabla.nombreCampo
14
Vistame en http://siliconproject.com.ar/neckkito/
FROM
nombreTabla
WHERE
condicin
En cuanto al WHERE tened en cuenta que funcionan las mismas peculiaridades, segn el tipo
de campo, que comentbamos en los filtros. Es decir, en nuestro caso, al ser un dato tipo
numrico, el filtro ha sido directo ( WHERE TTrabajadores.DNI = & nDNI)
Si hubiramos filtrado por un valor de tipo texto deberamos haber encerrado la variable entre
comillas simples. Por ejemplo, as: WHERE TTrabajadores.Nombre=' & nom & '
Es importante que os fijis que entre las comillas y el WHERE hay un espacio. Como podis ver
la SQL es un String. Si no ponemos ese espacio la SQL nos quedara escrita as (por ejemplo):
SELECT TTrabjadores.* FROM TTrabajadoresWHERE TTrabajadores.DNI = 123
Y al entender la SQL que la tabla de origen se llama TTrabajadoresWHERE nos saltara error de
cdigo porque, evidentemente, esa tabla no existe.
As, si reescribimos nuestro cdigo aadiendo unas lneas de cdigo que nos controlen lo
anterior podremos evitar dicho error.
15
Vistame en http://siliconproject.com.ar/neckkito/
Private Sub cmdSQLSinDatos_Click()
'Declaramos las variables
Dim nDNI As Integer
Dim miSql As String
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
'Definimos la BD de trabajo
Set dbs = CurrentDb
'Solicitamos el DNI al usuario
nDNI = InputBox("Introduzca un DNI inexistente", "DNI")
'Creamos la SQL
miSql = "SELECT TTrabajadores.* FROM TTrabajadores"
miSql = miSql & " WHERE TTrabajadores.DNI=" & nDNI
'Abrimos el recordset sobre la SQL
Set rst = dbs.OpenRecordset(miSql, dbOpenSnapshot)
'Comprobamos que la consulta devuelve registros. Si no hay registros
'lanza un mensaje de advertencia y sale del proceso
If rst.RecordCount = 0 Then
MsgBox "No hay trabajadores con el DNI solicitado", vbCritical, "SIN DATOS"
Exit Sub
End If
'Si hay datos mostramos la informacin
MsgBox "DNI: " & nDNI & vbCrLf & "Nombre: " & rst.Fields("Nombre").Value _
& vbCrLf & "Sexo: " & rst.Fields("Sexo").Value, vbInformation, "DATOS"
'Cerramos conexiones y liberamos memoria
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
Otro sistema sera comprobar si el inicio del recordset y el final del recordset son coincidentes.
Si lo son es que no hay ningn registro entre ellos, ergo no hay informacin que mostrar. El
cdigo sera el siguiente:
16
Vistame en http://siliconproject.com.ar/neckkito/
If rst.BOF And rst.EOF Then
MsgBox "No hay trabajadores con el DNI solicitado", vbCritical, "SIN DATOS"
Exit Sub
End If
'Si hay datos mostramos la informacin
MsgBox "DNI: " & nDNI & vbCrLf & "Nombre: " &
rst.Fields("Nombre").Value _
& vbCrLf & "Sexo: " & rst.Fields("Sexo").Value,
vbInformation, "DATOS"
'Cerramos conexiones y liberamos memoria
rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
Si queremos realizar una bsqueda por DNI con este mtodo el cdigo sera:
17
Vistame en http://siliconproject.com.ar/neckkito/
Fijaos que:
- Indicamos que la bsqueda es indexada, a travs de
(rst.Index = "PrimaryKey")
La bsqueda utilizando Seek sigue la estructura
<rst.Seek comparador matemtico, valor a buscar (si hay
ms ndices definidos se colocan a continuacin, separados
por comas)>.
Hemos realizado una simplificacin a la hora de
mostrar la informacin. En lugar de utilizar nuestro
conocido rst.Fields(1).Value lo hemos simplificado a rst(1)
Con tan pocos datos no notamos diferencia, pero con muchos registros os aseguro que se nota
la velocidad del Seek.
AADIENDO UN REGISTRO
Hemos visto cmo modificar un registro. Ahora vamos a ver cmo aadimos un registro a una
tabla.
With rst
.AddNew
.Fields(x).Value = <NuevoValor>
.Update
End With
Vamos a crear una tabla, que llamaremos TAdiciones, que contendr dos campos:
[NomTrab] De tipo texto
[Sex] De tipo texto, tamao 1
Lo que haremos ser recorrer los registros de la tabla TTrabajadores y copiaremos el nombre
del trabajador en TAdiciones, junto con la inicial de su sexo.
El cdigo sera:
18
Vistame en http://siliconproject.com.ar/neckkito/
.Fields("Sex").Value = Left(rst.Fields("Sexo").Value, 1)
.Update
End With
'Nos movemos al registro siguiente
rst.MoveNext
Loop
'Abrimos la tabla para ver los resultados
DoCmd.OpenTable "TAdiciones", , acReadOnly
'Cerramos conexiones y liberamos memoria
rst.Close
rstAdd.Close
dbs.Close
Set rst = Nothing
Set rstAdd = Nothing
Set dbs = Nothing
End Sub
Como vemos, hemos utilizado un recordset dentro de otro recordset para ir aadiendo los
datos en funcin de los valores de origen, registro por registro.
Fijaos que rst lo hemos abierto en modo dbOpenSnapshot, porque slo nos interesaba mirar
los datos; en cambio, rstAdd lo hemos tenido que abrir en modo dbOpenTable, porque
necesitbamos modificar/aadir datos en la tabla.
As pues vamos a hacer un alto en el camino y vamos a aumentar nuestra informacin dentro
de las BD's con las que vamos a operar.
1.- Vamos a aadir un campo a nuestra tabla TTrabajadores, de tipo texto, que llamaremos
[Dpto]. Aadimos unos cuantos trabajadores ms y les asignamos un departamento. Nos
moveremos con tres valores: Comercial / Administracin / Ventas.
2.- Vamos a aadir una tabla en nuestra BD de pruebas que nos va a recoger unos cuantos
trabajos realizados por nuestros trabajadores. A esa tabla la vamos a llamar TTrabajos. Tendr
la siguiente estructura:
19
Vistame en http://siliconproject.com.ar/neckkito/
Tened en cuenta que el campo [IdTrab]
est creado a travs del asistente,
buscando en la tabla TTrabajadores y
seleccionando los campos [DNI] y
[Nombre]. Evidentemente el valor que
nos guardar ser la clave principal,
esto es, el DNI del trabajador.
4.- Vamos a crearnos otra base de datos (otro archivo de Access), al que vamos a llamar
Retribuciones.mdb (o .accdb. Recordad que debis mantener la extensin que le hayis puesto
cuando escribamos el cdigo). Nuestra BD de pruebas y esta otra BD estarn en el mismo
directorio.
4.- En esa nueva BD vamos a crear una tabla, que llamaremos TPrecioHora, que tendr la
siguiente estructura:
20
Vistame en http://siliconproject.com.ar/neckkito/
Bueno, bueno... ya tenemos la carne en el asador.
Sigamos.
Una consulta que nos sume las horas realizadas por cada trabajador.
Una consulta que nos indique el nombre del trabajador que estamos examinando en ese
momento y el departamento al que pertenece.
Estas dos consultas podran resumirse en un solo paso, pero yo lo har en dos para practicar el
tema de los recordset sobre SQL.
Qu pasa? Pues, por ahora, nuestros conocimientos de SQL son un poco limitados. Vamos a
hacer un poco de trampa y le diremos a Access que nos de una pista de cmo construir
nuestra SQL
1.- Creamos una consulta en vista diseo sobre la tabla TTrabajos. Aadimos slo los campos
[IdTrab] y [Horas] y la convertimos en una consulta de totales. Agrupamos el campo [Horas]
por suma. Nos debera quedar una cosa as:
21
Vistame en http://siliconproject.com.ar/neckkito/
Ahora situamos esta consulta en vista SQL. Nos encontraremos con lo siguiente:
Es decir:
La SQL sqlSumaHoras nos proporciona dos datos: el identificador del trabajador y el nmero
de horas.
Conclusin, puedo utilizar el DNI para otra SQL, sqlDatos, que me devuelva esos dos datos que
voy a necesitar.
Para qu me sirve el nmero de horas? Pues para multiplicar las horas por el precio hora.
Pero no hay un solo precio hora, sino que depende del departamento. Y de dnde saco el
departamento? Pues me lo va a dar sqlDatos, como comentbamos hace un momento, y si s
el departamento s el precio hora.
Bueno: ahora ya tengo el identificador del trabajador, su nombre, sus horas y su precio hora
segn el departamento. Qu hago con todos esos datos? Pues necesito escribirlos en la tabla
TRetribuciones.
Creo que, en principio, ya tenemos todos los pasos ms o menos claros para meterme con el
cdigo.
Vamos all
DESARROLLANDO EL CDIGO
Os voy a poner el cdigo extensamente comentado. Pensad que todo lo que vamos a hacer, de
una manera u otra, ya lo hemos visto en apartados anteriores. Slo nos falta la soltura para
combinarlo todo... y para eso estamos, para que cojis soltura.
22
Vistame en http://siliconproject.com.ar/neckkito/
En vez de asignaciones directas voy a pasar todos los valores por variables. Creo que de esta
manera lo veris ms claro.
El cdigo sera:
Private Sub cmdCalculoPagoHoras_Click()
'Declaramos las variables
Dim bdExt As String 'Nos definir la ruta, nombre y
extensin de Retribuciones.mdb
Dim sqlSumaHoras As String 'SQL que nos dar el total
de horas por trabajador
Dim sqlDatos As String 'SQL que nos dar los datos del nombre y departamento
Dim vDNI As Integer 'Variable que recoge el DNI del trabajador
Dim vNom As String 'Variable que recoge el nombre del trabajador
Dim vDep As String 'Variable que recoge el departamento del trabajador
Dim vPH As Currency 'Variable que recoge el Precio Hora
Dim vNH As Integer 'Variable que recoge el nmero de horas
Dim dbs As DAO.Database 'Ser nuestra base actual
Dim dbsRetrib As DAO.Database 'Ser nuestra base Retribuciones.mdb
Dim rstRetrib As DAO.Recordset 'Ser el recordset sobre la tabla TPrecioHora
Dim rstSumaHoras As DAO.Recordset 'Ser el recordset de sqlSumaHoras
Dim rstDatos As DAO.Recordset 'Ser el recordset de sqlDatos
Dim rst As DAO.Recordset 'Ser el recordset sobre la tabla TRetribuciones
'Definimos las dbs's
Set dbs = CurrentDb
bdExt = Application.CurrentProject.Path & "\Retribuciones.mdb"
Set dbsRetrib = DBEngine.OpenDatabase(bdExt)
'Creamos el recordset que nos debe rellenar la tabla TRetribuciones
Set rst = dbs.OpenRecordset("TRetribuciones", dbOpenTable)
'Creamos la SQL sqlSumaHoras (recordad que hemos copiado el cdigo de la consulta
'que hemos creado y que hemos puesto en vista SQL. NO PONEMOS EL PUNTO Y COMA
FINAL!
sqlSumaHoras = "SELECT TTrabajos.IdTrab, SUM(TTrabajos.Horas) AS SumaDeHoras"
sqlSumaHoras = sqlSumaHoras & " FROM TTrabajos GROUP BY TTrabajos.IdTrab"
'Creamos el recorset sobre la sql
Set rstSumaHoras = dbs.OpenRecordset(sqlSumaHoras, dbOpenSnapshot)
'Comprobamos que haya registros. Si no hay registros salimos
If rstSumaHoras.RecordCount = 0 Then Exit Sub
'Nos movemos al primer registro
rstSumaHoras.MoveFirst
'Iniciamos el recorrido de los registros
Do Until rstSumaHoras.EOF
'Cogemos el identificador del trabajador y el total de horas realizadas
vDNI = rstSumaHoras.Fields(0).Value
vNH = rstSumaHoras.Fields(1).Value
'Ya tenemos el DNI. Vamos a crear la consulta sqlDatos que nos d los datos
'que necesitamos, que son el nombre y el departamento. Crearemos la sql
'ya filtrada por DNI
sqlDatos = "SELECT TTrabajadores.Nombre, TTrabajadores.Dpto FROM TTrabajadores"
sqlDatos = sqlDatos & " WHERE TTrabajadores.DNI=" & vDNI
'Creamos el recordset sobre esta consulta
Set rstDatos = dbs.OpenRecordset(sqlDatos, dbOpenSnapshot)
'Cogemos los valores que necesitamos
vNom = rstDatos.Fields(0).Value
vDep = rstDatos.Fields(1).Value
23
Vistame en http://siliconproject.com.ar/neckkito/
'Ya sabemos el departamento. Vamos a buscar el precio hora de ese departamento,
'pero la bsqueda la realizaremos en la BD Retribuciones.mdb, en la tabla
'TPrecioHora. Para ello, recorreremos los registros de TPrecioHora hasta encontrar
'la coincidencia de departamentos
'Creamos el recordset
Set rstRetrib = dbsRetrib.OpenRecordset("TPrecioHora",
dbOpenSnapshot)
'Aqu podra haber un control de registros,
pero ya sabemos cmo hacerlo
'Nos situamos en el primer registro
rstRetrib.MoveFirst
'Iniciamos el recorrido de registros
Do Until rstRetrib.EOF
'Aplicamos el criterio a travs de un bloque IF...END IF
If rstRetrib.Fields("Departamento").Value = vDep Then
vPH = rstRetrib("Precio").Value
Exit Do 'Ya hemos encontrado lo que buscbamos. Podemos salir
End If
'Nos movemos al siguiente registro
rstRetrib.MoveNext
Loop
'Y ya tenemos todos los elementos que necesitbamos. Vamos a crear el registro
'de resultados en nuestra tabla TRetribuciones
With rst
.AddNew
.Fields("DNI").Value = vDNI
.Fields("Nombre").Value = vNom
.Fields("ACobrar").Value = vNH * vPH
.Update
End With
'Listo para un registro de sqlSumaHoras. Vamos a analizar el siguiente
rstSumaHoras.MoveNext
Loop
'Mostramos los resultados
DoCmd.OpenTable "TRetribuciones", , acReadOnly
'Cerramos conexiones y liberamos memoria
rstRetrib.Close
rstSumaHoras.Close
rstDatos.Close
rst.Close
dbs.Close
dbsRetrib.Close
Set rstRetrib = Nothing
Set rstSumaHoras = Nothing
Set rstDatos = Nothing
Set rst = Nothing
Set dbs = Nothing
Set dbsRetrib = Nothing
End Sub
Ahora tendra que decir lo de Fcil, verdad?, pero creo que, para este ejemplo, no os lo
dir... je, je... Lo cambiar por
nimo!
24
Vistame en http://siliconproject.com.ar/neckkito/
UNAS PALABRAS FINALES
Hasta aqu el sistema DAO. Nos queda pendiente la
coleccin ERROR, pero lo veremos como algo independiente
en un captulo prximo. Creo que este captulo ha sido
bastante intenso y dejaremos descansar nuestros pobres
cerebros.
25
Vistame en http://siliconproject.com.ar/neckkito/