Está en la página 1de 20

AGENDA SEMANAL1

Llegada una petición a mis manos sobre cómo podría


hacerse una agenda semanal os traigo aquí este ejemplo
que, lo que hace es… ¡tachán! ¡Una agenda semanal!

Como ya sabéis, los ejemplos que están dentro de la


categoría “Ejemplos Especiales” de la web, como este
mismo, son quizás un poco complejos (aunque intento
simplificar al máximo las bases para que no salga un
ejemplo indigesto). Y este que tenéis ahora en vuestras
manos no es una excepción.

Una problemática, a efectos pedagógicos, que tiene el presente ejemplo es que me va a


resultar un poco difícil seguir una explicación “lineal”, dado que hay elementos que se diseñan
de una determinada manera porque dependen de otros. Así que os pido que hagáis un “acto
de fe” y que confiéis en lo que os explique en determinados momentos, aunque no le veáis
sentido, porque más adelante descubriréis los motivos cuando veamos el “otro” elemento en
cuestión que obligaba a hacer las cosas de un modo u otro.

Siguiendo con mi idiosincrasia a la hora de redactar mis ejemplos, y relacionado con lo que os
escribía en el párrafo anterior, en algunos puntos me detendré a explicar “qué pasaría si...”,
dado que eso me lleva automáticamente a que veáis el “por qué lo hago así”. Creo que es una
manera muy práctica de que podáis ver “los problemas con los que me he topado” y cómo los
he ido resolviendo.

Finalmente, y adelantándome a futuras peticiones, realizaré dos añadidos al ejemplo: uno,


para poder moverse entre semanas en el propio informe y, dos, poder editar un día y hora
seleccionado en el informe. Eso significa que dividiré el ejemplo en tres partes, de manera que
al final de la primera podríamos decir que “el ejemplo está acabado y operativo”. Para quien
quiera avanzar más que siga con la segunda parte, que con su final también se encontrará con
el ejemplo “acabado y operativo”. Y quien quiera ser un poco masoquista pues que se atreva
con la tercera… todo esto bajo vuestra responsabilidad… je, je…

Dicho lo anterior empecemos la faena…

PRIMERA PARTE

NUESTRAS TABLAS Y SUS DATOS


A efectos de simplificar al máximo vamos a ver qué tablas van a ser las básicas. La primera,
llamada TCitas, tendrá la siguiente estructura inicial:

1 La BD de ejemplo os la podéis bajar aquí

1
Visítame en http://bit.ly/NckAccess
Y, a mayor abundamiento, los datos que recogerá serán del estilo:

A esta tabla le haremos un “añadido”, pero lo veremos un


poco más adelante.

Vamos a necesitar una tabla auxiliar que nos va a recoger el intervalo de horas que vamos a
querer que se muestre en nuestra agenda semanal, y que llamaremos THoras. Por ejemplo, y
para este ejemplo, yo he creado un intervalo de horas desde las 8:00 a las 20:00, con una
periodicidad de cada media hora.

Así, la estructura de la tabla sería:

Y alguno de sus datos, a modo de ejemplo, y así hasta un total de 25 registros:

Ni que decir tiene que la información de esta tabla puede ser la que queráis. Por ejemplo, yo
podría haber empezado por otra hora y que los bloques fueran de dos horas de duración, así:

Hasta aquí nuestras tablas básicas. Sin embargo, nos falta una tabla temporal que recogerá los
datos filtrados por la semana que el usuario haya seleccionado. Así que crearemos otra tabla
que llamaremos TTempAgenda, con la siguiente estructura inicial:

2
Visítame en http://bit.ly/NckAccess
Vamos a tener que realizar un pequeño ajuste a nuestra tabla temporal, pero lo veremos más
adelante.

NUESTRA CONSULTA CTEMPAGENDA


Voy a explicaros paso a paso la construcción de esta
consulta y, con ello, la justificación de los cambios que
debemos hacer en las tablas anteriores, para que se
entienda un poco mejor por qué hago el proceso así.

Y, como os comentaba en la introducción, aquí tendréis que


hacer un acto de fe y creerme que, en una primera
instancia del proceso, la tabla TTempAgenda se va a
rellenar con tantas horas haya en THoras por cada uno de
los días de la semana seleccionada por el usuario.

Dicho de otra manera, voy a necesitar que si se selecciona la semana del 21 al 27 de agosto se
creen tantas horas necesarias para el 21 como horas hemos determinado en THoras. Lo mismo
para el día 22, 23… hasta el 27.

Eso no lo haremos con la consulta CTempAgenda, sino que lo haremos después, al trabajar
con el código. Lo que sí os mostraré serán los resultados parciales de esa acción:

--→ Estos serán los primeros registros que mostrará TTempAgenda,


una vez ejecutado el código pertinente.

Y estos serán los últimos registros que se --→


mostrarán. Fijaos que la tabla contiene un total
de 175 registros (7 días x 25 franjas horarias
que contiene mi tabla THoras).

Es a partir de ahí cuando nuestra consulta CTempAgenda va a ser la


que nos relacione los datos de TTempAgenda con los datos de TCitas.

Una primera aproximación para esa consulta sería relacionar ambas tablas por el primer
elemento del binomio fecha/hora: la fecha. Si empezamos la consulta con esa idea
obtendríamos:

Sin embargo, lo que obtenemos es un resultado extraño, que no nos da los resultados
correctos. Si tuviéramos una cita el 21/08 a las 08:30, por ejemplo, obtendríamos:

3
Visítame en http://bit.ly/NckAccess
Es decir, solo nos mostraría el día de la cita y la cita en todas las horas. Si quisiéramos
arreglar lo anterior, y dado que los 175 registros que nos interesan inicialmente (insisto en lo
de inicialmente aunque podrían ser más, pero eso os lo explicaré más adelante: como os decía
en la introducción, resulta muy difícil explicaros “linealmente” el ejemplo), podríamos cambiar
el tipo de combinación de la relación y establecer que se nos muestren todos los registros de
TTempAgenda y solo los coincidentes en TCitas:

Ahora nuestra consulta sí nos mostrará los 175 registros, pero, ¡oh desgracia!, en todos los
registros muestra la misma cita:

¿Qué se nos ocurre? Pues relacionar también por el campo de la hora de la cita. ¿Sencillo, no?
Sencillo, quizás, pero efectivo…

4
Visítame en http://bit.ly/NckAccess
Y cuando queremos ejecutar la consulta nuestro amigo Access nos
echa un cubo de agua fría sobre la cabeza

“¿Para qué me cuenta todo este rollo?”, podríais pensar. En


primer lugar, porque en alguna ocasión podríais tener un
problema parecido y, en segundo, me sirve para justificar la
operación que vamos a hacer en nuestras tablas. Así que…
ahí va el razonamiento.

Vemos que necesitamos dos campos para poder relacionar en la consulta. Sin embargo,
resulta imposible, así como hemos hecho la aproximación, que nuestra consulte se ponga a
andar. ¿Cómo podemos resolver esta situación?

La respuesta está en: si con dos campos no funciona, convirtamos esos dos campos en un solo
campo. Y, a efectos de este campo, voy a dejar que Access haga todo el trabajo. Así pues, lo
que haremos será situar la tabla TCitas en vista diseño y añadir un campo calculado, llamado
[FHCita], de la siguiente manera:

Fijaos que la expresión del campo calculado concatena ambos campos, el de la fecha y el de la
hora.

Nos vamos a TTempAgenda y realizamos la misma operación, añadiendo el campo calculado


[FHCitaTemp]:

Hecho lo anterior sí podemos volver a nuestra consulta CTempAgenda y relacionar ambas


tablas por este nuevo campo, de manera que el tipo de combinación sea la 2 (o la 3, según el
caso), es decir, mostrar todos los campos de la tabla TTempAgenda y solo los coincidentes en
TCitas.

5
Visítame en http://bit.ly/NckAccess
Fijaos que, para que me queden los datos bien ordenados, he fijado el criterio de ordenación
en “Ascendente” tanto en la fecha como en la hora.

Ahora el resultado de la consulta, siguiendo con la idea de nuestra cita del 21/08 a las 8:30, se
mostrará de la siguiente manera:

Que, evidentemente, es como queremos que se muestre: día-hora y, a) no hay cita: se


muestra en blanco; b) hay cita: se muestra el motivo de la misma.

Y, dado que nos hemos construido esta consulta, vamos a aprovecharla para añadir una serie
de campos calculados que nos proporcionarán unos datos que vamos a necesitar más
adelante. De nuevo haced un acto de fe y ya os explicaré después por qué vamos a necesitar
esos datos.

Así que en CTempAgenda vamos a añadir tres campos calculados, que serán los siguientes:

El primero, para conseguir del nombre del día de la semana (teniendo en cuenta que el último
cero significa que estamos indicando que la semana empieza en lunes):

NomDiaSem: NombreDíaDeLaSemana(DíaSemana([FechaCitaTemp];0))

El segundo nos va a concatenar la fecha con su nombre de día de la semana. Este campo me
dará el trabajo hecho cuando tenga que configurar los encabezados del informe (que veremos
más adelante), y por eso lo he llamado [Cabecera]:

Cabecera: [FechaCitaTemp] & " " & [NomDiaSem]

El tercero, que nos va a decir qué dia de la semana es en número; esto es, nos dará un 1 si es
lunes, un 2 si es martes, y así hasta 7, domingo.

DiaSem: DíaSemana([FechaCitaTemp];0)

La estructura de la consulta se me ha convertido en algo así (los campos calculados quedan


cortados porque si no no me cabe todo… je, je…)

6
Visítame en http://bit.ly/NckAccess
Y los resultados, según veníamos trabajando con el ejemplo del 21/08, serían:

UN INCISO: PARA LO SIGUIENTE NECESITAMOS DATOS EN NUESTRA TABLA


TEMPORAL
Dado que aún no hemos hablado del código que nos “preparará” nuestra tabla TTempAgenda
con datos oportunos si siguiéramos haciendo los pasos de los epígrafes siguientes no nos
quedarían las “estructuras base” correctas y no os saldría el ejemplo si lo estáis intentando
recrear desde estas instrucciones.

Así que, para conseguir los datos mínimos, a mano vamos a introducir directamente en
TTempAgenda los siguientes datos: elegimos una semana cualquiera y, muy importante,
introducimos siete registros, uno por cada día de la semana, con la hora que queramos,
empezando por el lunes. Por ejemplo, si yo elijo la semana del 7 de agosto de 2017 mis datos
serían:

Insisto: es muy importante introducir una semana entera porque si no la construcción de un


futuro informe que necesitaremos va a ser defectuosa y, con eso, nada va a funcionarnos.

NUESTRA CONSULTA DE REFERENCIAS CRUZADAS


La consulta CTempAgenda tiene los elementos que necesitamos para mostrar los datos en una
agenda, pero no tiene el formato que necesitamos.

¿Qué formato necesitamos, pues? La respuesta es obvia: un formato de agenda. Es decir, algo
del estilo…

7
Visítame en http://bit.ly/NckAccess
XX/XX/XX XX/XX/XX
lunes ... domingo
8:00
8:30 Cita Z
9:00 Cita W
...

¿Quién nos proporciona ese tipo de formato? Pues nada


más y nada menos que una consulta de referencias
cruzadas. Así que vamos a crearnos la consulta
CBaseRAgenda utilizando el asistente de Access para
referencias cruzadas. Los pasos a seguir para su
configuración son los siguientes:

1.- Seleccionamos la opción de “Consultas” y elegimos nuestra consulta CTempAgenda

2.- Como título de fila, si seguimos nuestro formato de ejemplo, vemos que debemos elegir las
horas; esto es, [HoraCitaTemp]

3.- Como encabezado de columna vamos a elegir… uhmmm… ¿qué elegimos? Lo lógico sería
pensar que, en atención a nuestra tabla de formato, el campo que deberíamos elegir sería
[Cabecera]. Sin embargo, hacerlo así sería un error, y al hablar del futuro informe que
necesitamos crear os explicaré por qué. Por ahora, y de nuevo, haced un acto de fe y confiad
en mí: elegid el campo [DiaSem]

8
Visítame en http://bit.ly/NckAccess
4.- Como estamos hablando que los datos que se van a mostrar en las intersecciones de fila y
de columna van a ser los motivos de la cita, esto es, datos de texto, no necesitamos realizar
operaciones matemáticas con ellos. Así que el campo a elegir será [MotivoCita] y la función
que utilizaremos para mostrar esos datos será la de “Primero”. E, importante (que si no queda
un churro), desmarcad el check para incluir sumas de filas (sumar texto es algo un poco…
¿estrambótico?)

5.- Le damos, como nombre, CBaseRAgenda.

Y, si seguimos de nuevo con el ejemplo de nuestra cita del 21, obtendríamos…

NUESTRO INFORME RAGENDA


Vamos a crearnos, sobre CBaseRAgenda, un informe que llamaremos RAgenda. Veremos que
lo que conseguimos es algo prácticamente igual a la tabla de estilo que mencionábamos en el
epígrafe anterior. Es decir, y siguiendo con el ejemplo del 21 de agosto:

9
Visítame en http://bit.ly/NckAccess
Como esos encabezados no nos van a servir cuando
saquemos nuestra agenda definitiva vamos a situar el
informe en vista diseño. Lo que haremos será coger el
encabezado automático (en la ilustración,
“CBaseRAgenda”), vamos a sacar sus propiedades, pestaña
Otras, y en la propiedad Nombre vamos a sustituir el
nombre que hay por lblTitulo

A continuación haremos lo mismo con las etiquetas de los


números de días, es decir, el 1, 2,…, 7, y como nombre
vamos a ponerles, correlativamente, lbl1, lbl2, lbl3, lbl4,
lbl5, lbl6 y lbl7.

A modo de ejemplo...

Hechos estos pasos necesarios después ya podemos meter el informe en la lavadora y que
cada uno le dé el formato que más le guste.

Por ejemplo, yo he configurado su orientación en horizontal y, tras algo de maquillaje y corte


de pelo, me ha quedado una cosa así:

En mi caso he reducido el tamaño de fuente y alto de los campos de la sección de talle porque
al tener tantas franjas horarias el informe parecía más un ejercicio de práctica de scroll vertical
que otra cosa. Así que cada uno deberá ajustarlo en función de cómo considere que se adapta
mejor a sus circunstancias… o al menos eso os recomendaría yo.

Y, a continuación, desvelemos el misterio del truco…

¿Por qué, en la consulta de referencias cruzadas, hemos seleccionado el campo


[DiaSem] y no [Cabecera]?

Si utilizáramos solo la tabla de referencias cruzadas para ver la información que nos interesa,
sin necesidad de utilizar informe alguno, sí hubiéramos podido elegir el campo que hubiéramos
querido. Eso es así porque los datos, en la tabla de referencias cruzadas, se adaptan en todo
momento a la información origen que queremos extraer.

Ahora bien, con la necesidad de tener que utilizar un informe la cosa cambia. Los informes,
una vez construidos, permanecen estáticos en sus elementos (olvidemos que existe VBA, a
estos efectos). Ojo, digo en sus elementos, no en la información que muestran, que se adapta
perfectamente a la que se obtiene de la consulta o tabla de origen.

10
Visítame en http://bit.ly/NckAccess
Imaginemos que hemos pedido la semana del 21 de agosto de 2017. La consulta de
referencias cruzadas hubiera devuelto un valor de cabecera, para ese día, así: 21/08/17 lunes,
así:

Imaginemos que, con esa información, creamos el informe.


En consecuencia, esa etiqueta de cabecera que hemos visto
con el valor 1 ahora mostraría 21/08/17 lunes, pero
también lo haría el campo correspondiente en la sección
detalle, así:

¿Qué pasa cuando cambiamos de semana? Supongamos que ahora elegimos la semana
siguiente, la del 28. Se nos remozan los datos en nuestra tabla TTempAgenda y, con esos
nuevos datos, abrimos la consulta de referencias cruzadas:

Lo que vemos es que la consulta de referencias cruzadas se adapta perfectamente a los


nuevos datos solicitados, aunque nos aparece el problema de la ordenación de las fechas.

Si, a continuación, intentamos abrir el informe, obtenemos lo siguiente:

Es decir, que nuestro informe no adapta dinámicamente los nombres de los campos del
informe y, en consecuencia, si cambia el nombre del campo nuestro informe “casca”.

De lo anterior se deriva que necesitamos utilizar un campo que, aunque cambien las fechas, su
valor no cambie. Y precisamente ese campo es [DiaSem], que es el que hemos utilizado.
Obviamente, el valor que devuelve [DiaSem] para el 21/08/17 es 1 (porque es lunes), y el
valor que devuelve para el 28/08/17 también es 1, porque sigue siendo lunes. Ergo, que no
cambie nos permite utilizarlo en un informe sin que este nos “casque” por cambios en los
nombres de los campos.

11
Visítame en http://bit.ly/NckAccess
Espero que hayáis podido entenderme… y, si no, os animo a probarlo ;-)

EL INICIO DEL PROCESO: UN FORMULARIO


Para este ejemplo voy a iniciar el proceso desde un objeto
que sea, en principio, el más evidente: un formulario con
un cuadro de texto donde el usuario introducirá la fecha
que desee y un botón que lanzará todo lo que deba lanzar.

Pero, para no circunscribirlo a un solo formulario, lo que es


el grueso del código lo llevaremos a un módulo. Pero eso
vendrá después, y en la segunda parte entenderéis porque
es mejor utilizar un módulo estándar.

En la base de datos que acompaña a este ejemplo he creado el textbox y el botón de comando
directamente en FMenu, pero podemos ponerlo en el formulario que queramos.

Así, imaginando que estamos en el formulario deseado, añadiremos un cuadro de texto al que
pondremos de nombre2 txtFechUser. Para evitar problemas de introducción de datos, en sus
propiedades → Pestaña Formato, elegiremos el formato de “Fecha corta”.

Creamos a continuación un botón de comando que llamaremos cmdAbreAgenda, y en su


evento “Al hacer clic” generaremos el siguiente código3:


Private Sub cmdAbreAgenda_Click()
Dim diaElegido As Byte

'Si no hay fecha seleccionada salimos


If IsNull(Me.txtFechUser) Then Exit Sub

'Miramos qué día a elegido el usuario y determinamos el lunes de la semana elegida


diaElegido = Weekday(Me.txtFechUser, vbMonday)

'Pasamos el valor del lunes a la variable pública


pSemana = DateAdd("d", -diaElegido + 1, Me.txtFechUser)

'Llamamos al procedimiento que realiza el proceso


Call subPreparoAgenda
End Sub

Fijaos que este código lo único que hace es tratar el día elegido por el usuario y transformarlo
a la fecha correspondiente al lunes. Dicho de otra manera, supongamos que elijo el 26/08/17,
sábado.

Con la función Weekday() informamos que la variable diaElegido es el 6.

Con ese valor podemos calcular qué día correspondería a lunes, y lo asignamos a una variable
pública llamada pSemana. La función DateAdd() nos dice:

Añade “n” días a la fecha elegida por el usuario. ¿Qué valor toma n? Pues es -6+1, es decir,
añádele -5 (o, de otra forma, resta cinco días) a la fecha seleccionada por el usuario.

En consecuencia, el día 26, menos 5 días, se queda en el 21, que es el lunes 21/08/17.

2 Para asignar un nombre a un control lo que debemos hacer es sacar las propiedades de ese control e irnos a la Pestaña > Otras >
Nombre. Ahí escribimos el nombre que queramos.
3 Para generar código debemos sacar las propiedades del control > Pestaña Eventos, y nos situamos en la parte “blanca” a la
derecha del evento que queremos programar. Veremos un pequeño botón de puntos suspensivos. Si hacemos clic sobre él nos
aparecerá una ventana que nos pedirá qué operación deseamos realizar. Le indicamos que queremos “generar código”.

12
Visítame en http://bit.ly/NckAccess
Tras eso llama al procedimiento subPreparoAgenda.

Moraleja: la variable pSemana siempre debe recogernos un lunes.

NUESTRO CÓDIGO VBA


Creémonos un módulo estándar4, que llamaremos
mdlAgendaSemanal.

Lo primero que vamos a hacer será declarar la variable


pública. Para ello, bajo la/s línea/s Option la declaramos
así:


Option Compare Database
Option Explicit

Public pSemana As Date


A continuación vamos a escribir nuestro procedimiento. Pero antes de mostrároslo os indico


qué procesos realiza, con unos comentarios al respecto.

1.- Borra los datos de la tabla TTempAgenda

2.- Inserta en TTempAgenda todos los rangos horarios que hayamos dado de alta en THoras
en función de los días de la semana seleccionada. Recordemos que el primer día de la semana
nos lo da la variable pSemana (¡siempre debería recoger un lunes, insisto!), y a esa fecha de
pSemana le vamos añadiendo 1 día más hasta llegar al domingo.

Recordad que, cuando empezamos a hablar de la consulta CTempAgenda, os decía que, en una
primera fase, los datos se rellenaban por código. Esta parte 2 es la SQL que rellena dichos
datos.

3.- Una vez hecho lo anterior ya sabemos que TTempAgenda nos recoge cada uno de los días
con las franjas horarias. Es decir, lunes a las 8:00, lunes a las 8:30, lunes a las 9:00, etc.
Hasta aquí, todo claro.

¿Qué pasa si hemos dado de alta una cita a las 7:00 de la mañana? ¿O a las 8:45? Porque, en
el primer caso, esa hora no está en nuestros rangos horarios y, en el segundo, aunque cae
dentro de nuestros rangos horarios no está contemplada esa hora en TTempAgenda.

En consecuencia, este tercer paso lo que hace es mirar coincidencias entre los datos de
TTempAgenda y TCitas para el día en concreto que se esté analizando. Si no existe la hora de
la cita lo que hace es añadirla a TTempAgenda.

Dicho de otra manera:

a) Cita a las 8:00 → Ya existe la franja horaria de las 8:00 en TTempAgenda → No hago nada
b) Cita a las 8:45 → No existe esa franja horaria en TTempAgenda → Se la agrego

4.- Comprobamos si existen citas en la semana seleccionada. Si no hubiera citas en esa


semana avisamos para que, cuando se abra el informe y no se vean datos, el usuario no se
“asuste” y piense que se trata de un error.

5.- Abrimos el informe RAgenda en vista Informes

4 Para insertar un módulo estándar podemos abrir el editor de VB (ALT+F11) y nos vamos a Menú > Insertar > Módulo

13
Visítame en http://bit.ly/NckAccess
6.- Cambiamos los textos de las etiquetas 1, 2, 3,…, 7 y la etiqueta del encabezado del
informe.

De ahí la importancia de haber cambiado los nombres de


esas etiquetas por lbl1, lbl2, etc., dado que el código hace
un recorrido por los controles de tipo etiqueta y, en función
del nombre, le asigna el texto correspondiente.

¿Qué texto? El que nos muestra el campo calculado


[Cabecera] de nuestra consulta CTempAgenda. De ahí que
os dijera que utilizamos esta consulta para aprovecharnos
del cálculo automático que realizaban los campos calculados
que creamos en su momento.

Por fin, ahí tenéis el código que hace lo anterior:


Public Sub subPreparoAgenda()

Dim i As Integer, j As Integer


Dim miSql As String
Dim ctl As Object
Dim rst As DAO.Recordset
Dim dbs As DAO.Database

'Instanciamos la base de datos


Set dbs = CurrentDb

'1.- Borramos los datos que pudiera haber en la agenda


dbs.Execute ("DELETE FROM TTempAgenda")

'2.- Insertamos los días de la semana solicitada y todos los rangos horarios que
'hayamos establecido en THoras
For i = 0 To 6
For j = 1 To DCount("*", "THoras")
CurrentDb.Execute ("INSERT INTO TTempAgenda(FechaCitaTemp,HoraCitaTemp)" _
& " VALUES ('" & pSemana + i & "','" _
& DLookup("Hora", "THoras", "IdHora=" & j) & "')")
Next j
Next i

'3.-Insertamos en TTempAgenda las franjas horarias que no estén predeterminadas


'pero que existan en la tabla de citas
miSql = "SELECT FechaCita, HoraCita FROM TCitas WHERE FechaCita BETWEEN #" _
& Format(pSemana, "mm/dd/yy") & "# AND #" & Format(DateAdd("d", 7, pSemana), "mm/dd/yy") & "#"

Set rst = dbs.OpenRecordset(miSql)


If rst.RecordCount = 0 Then GoTo Compruebo_Existen_Datos
With rst
.MoveFirst
Do Until .EOF
If DCount("*", "TTempAgenda", "FechaCitaTemp=#" & Format(.Fields(0), "mm/dd/yy") _
& "# AND HoraCitaTemp=#" & .Fields(1) & "#") = 0 Then 'No existe la franja horaria
dbs.Execute ("INSERT INTO TTempAgenda(FechaCitaTemp,HoraCitaTemp)" _
& " VALUES ('" & .Fields(0) & "','" & .Fields(1) & "')")
End If
.MoveNext
Loop
End With

Compruebo_Existen_Datos:

'4.- Comprobamos si existen citas para la semana seleccionada. Si no, avisamos, aunque dejamos seguir el
proceso
If DCount("*", "CTempAgenda", "MotivoCita<>NULL") = 0 Then
MsgBox "No hay citas para la semana seleccionada", vbInformation, "SIN CITAS"
End If

14
Visítame en http://bit.ly/NckAccess
'5.- Abrimos el informe
DoCmd.OpenReport "RAgenda", acViewReport

'6.- Le cambiamos el nombre de las etiquetas del encabezado, sabiendo que su nombre es lblX, con 1<=X<=7
For i = 1 To 7
For Each ctl In Reports!RAgenda
If ctl.ControlType = acLabel Then
If ctl.Name = "lbl" & i Then
ctl.Caption = DLookup("Cabecera", "CTempAgenda", "DiaSem=" & i)
End If
End If
Next ctl
Next i

'También le cambiamos el texto del título


Reports!RAgenda.lblTitulo.Caption = "Agenda del " & pSemana & " al " & DateAdd("d", 6, pSemana)

'Cerramos conexiones y liberamos memoria


rst.Close
dbs.Close
Set rst = Nothing
Set dbs = Nothing
End Sub

FIN DE LA PRIMERA PARTE


Con lo explicado hasta aquí ya tenéis el ejemplo totalmente operativo para funcionar. Podemos
seleccionar un día y ver la agenda para la semana de ese día. Si saco la agenda para la
semana del 31/07/17 en la base de datos de ejemplo podemos ver lo siguiente:

SEGUNDA PARTE
Podría darse el caso de que alguien dijera: “Sería fantástico tener un botón para poder ir a la
semana anterior o a la semana siguiente desde el propio informe, ¿no?”

15
Visítame en http://bit.ly/NckAccess
Y esto es lo que vamos a programar en esta segunda parte del ejemplo.

También supongo que alguien podría pensar: “Si lo ha


dejado para una segunda parte seguro que es complicado,
¿verdad?” Y lo cierto es que no es en absoluto
complicado :-)

Lo he querido poner así para que os dierais cuenta de que si


planificamos bien nuestra aplicación las cosas que
queremos añadir se convierten en algo sencillo. Y como
nosotros hemos planificado bien el ejemplo (ji, ji…) pues
fácil será. ¿Por qué?

Porque, básicamente, tenemos una variable pública pSemana que podemos manipular
fácilmente y tenemos un procedimiento público en un módulo estándar, lo que significa que
puede llamarse desde cualquier parte de la aplicación.

Veamos…

MODIFICANDO RAGENDA
Vamos a situar RAgenda en vista diseño y vamos a añadirle dos botones de comando, que
llamaremos cmdSemAnterior y cmdSemSiguiente. Creo que no hará falta deciros cuál es cuál
en la imagen:

El código que vamos a asignar a cmdSemAnterior será:


Private Sub cmdSemAnterior_Click()
Call subCambioSemana(1)
End Sub

Y el código que vamos a asignar a cmdSemSiguiente será:


Private Sub cmdSemSiguiente_Click()
Call subCambioSemana(2)
End Sub

Ahora, en el módulo asociado al informe, bajo la/s línea/s Option, escribimos el siguiente
procedimiento:

16
Visítame en http://bit.ly/NckAccess

Option Compare Database
Option Explicit

Private Sub subCambioSemana(elMov As Byte)


'elMov: 1 para semana anterior / 2 para semana siguiente

'Desactivamos el refresco de pantalla


Echo False

'Cerramos el informe
DoCmd.Close acReport, Me.Name

'Restamos o sumamos una semana en función del valor del argumento elMov
If elMov = 1 Then 'Si elegimos la semana anterior...
pSemana = DateAdd("d", -7, pSemana) 'le restamos 7 días al valor de pSemana
Else 'Si elegimos la semana siguiente...
pSemana = DateAdd("d", 7, pSemana) 'le sumamos 7 días al valor de pSemana
End If

'Llamamos a nuestro procedimiento en el módulo para que recalcule todos los datos
'y nos abra de nuevo el informe
Call subPreparoAgenda

'Reactivamos el refresco de pantalla


Echo True
End Sub

Como veis, el “quid” de la cuestión estaba simplemente en saber si tenemos que sumar o
restar 7 días a pSemana. El resto se hace prácticamente solo.

FIN DE LA SEGUNDA PARTE


Con esto tan sencillito hemos añadido esa utilidad a nuestra aplicación para desplazarnos entre
semanas directamente desde la agenda. Y, si lo dejamos aquí, evidentemente la aplicación nos
funcionará sin problemas (o, al menos, eso es lo que se pretende).

TERCERA PARTE
Esta parte quizá sea un poco más complicadilla, pero no demasiado. ¿Qué veremos en esta
tercera parte? Pues veremos la posibilidad de, en nuestro informe RAgenda, poder hacer doble
clic sobre una intersección de fila y columna y abrir el formulario para, si no hay cita, poder
dar una de alta y, si la hay, poder modificarla.

Sí, sí… estoy seguro de que si no incluyo esta tercera parte alguien me hubiera enviado un
mensaje diciendo: “en tu ejemplo de la agenda semanal, ¿sería posible ir a la fecha y hora
haciendo doble clic en el campo correspondiente del informe?” Je, je… ¡Que nos conocemos
todos! xDD

NUESTRO FORMULARIO FCITAS


Vamos a crearnos un formulario llamado FCitas sobre nuestra tabla TCitas. Algo así:

17
Visítame en http://bit.ly/NckAccess
MODIFICANDO NUESTRO INFORME RAGENDA
Pensemos, pensemos… con el dinero, ¿qué hacemos?

Para poder acceder a una cita desde RAgenda necesitamos dos datos: la fecha de la “celda”
que seleccionamos (columna) y la hora de la “celda” que seleccionamos (fila).

Para conseguir la hora no tenemos mayor problema, pues eso nos lo da el valor del campo
[HoraCitaTemp] del registro en el que estemos (el que hemos seleccionado).

Sin embargo, la fecha ya parece algo más complicado (no demasiado, realmente). ¿De dónde
me saco el dato, pues?

Recordemos cómo se ve RAgenda en vista diseño:

Y lo que vemos es que, independientemente de donde hagamos doble clic (porque ese será el
evento que utilizaremos para desencadenar el proceso) en el informe en vista Informes, el
valor que no cambia es el nombre del campo (de la sección detalle, por supuesto): 1, 2, 3, 4,
5, 6 o 7.

Y si tenemos el nombre del campo, y tenemos el valor del lunes almacenado en nuestra
maravillosa variable pSemana, ¿no tenemos ya los elementos necesarios para saber qué día
representa nuestra selección?

Dicho de otra manera, si pSemana almacena el valor 07/08/17 y hacemos doble clic sobre el
campo 1, la fecha que estamos seleccionando es: 07/08/17 + 1 – 1 = 07/08/17.

Si hacemos doble clic sobre el 2 la fecha que estamos seleccionando es 07/08/17 + 2 – 1=


07/08/17 + 1 = 08/08/17

18
Visítame en http://bit.ly/NckAccess
Y, lógicamente, así sucesivamente.

En consecuencia ya tenemos el problema de “qué diantres


he seleccionado” resuelto.

Solo necesitamos saber si existe algún registro con esa


fecha y hora o no. Y, en principio, una función de dominio
como dcount(), aplicando un filtro por fecha y hora, nos lo
diría: si devuelve 0 (cero) es que no hay registros y, por
tanto, hay que abrir FCitas en un registro nuevo; si
devuelve 1 es que ha encontrado una coincidencia y, por
tanto, hay que abrir FCitas filtrado por ese registro.

Sin embargo, como manejar fechas y horas es un poco “pesado”, y como, repito, somos muy
listos, vamos a simplificar el filtro utilizando un solo valor. ¿Cuál? El que nos devuelve nuestro
campo calculado [FHCita] (por eso somos muy listos: porque lo teníamos todo previsto). Eso,
además de manejar solo un valor nos permitirá manejar un valor de texto, sin tener que
preocuparnos de formatos de fechas, almohadillas y demás.

Así que, en RAgenda, vamos a seleccionar el campo [1] de la sección detalle y en su evento
“Al hacer doble clic” generaremos el siguiente código (no os preocupéis si veis que Access
renombra, en el código, el “1” como “Ctl1”):


Private Sub Ctl1_DblClick(Cancel As Integer)
Call subAbroCita(Me.HoraCitaTemp, 1)
End Sub

En el evento “Al hacer doble clic” del campo [2] (siempre de la sección detalle) generaremos el
siguiente código:


Private Sub Ctl2_DblClick(Cancel As Integer)
Call subAbroCita(Me.HoraCitaTemp, 2)
End Sub

Y como estoy seguro de que le habéis cogido “el tranquillo” el resto de códigos serán
exactamente iguales, solo que haciendo coincidir el segundo argumento del procedimiento
subAbroCita() por el número del nombre del campo. Si tenéis dudas tenéis la base de datos
que acompaña a este ejemplo para examinar los códigos a vuestro gusto ;-)

Evidentemente ahora solo nos queda programar el procedimiento subAbroCita(). Ese


procedimiento lo escribiremos en el módulo asociado al informe, debajo, por ejemplo, de
subCambioSemana()

El código será el siguiente:


Private Sub subAbroCita(laHora As Date, numFecha As Byte)
Dim laFH As String
Dim laFecha As Date

'Calculamos la fecha solicitada


laFecha = pSemana + numFecha - 1

'Creamos el campo calculado


laFH = laFecha & laHora

19
Visítame en http://bit.ly/NckAccess
'Miramos si hay cita en la selección del usuario
If DCount("*", "TCitas", "FHCita='" & laFH & "'") = 0 Then 'No hay cita. Abrimos
el formulario para añadir
DoCmd.OpenForm "FCitas", , , , acFormAdd
'Y lo dejamos todo preparado para añadir el motivo de la cita
With Forms!FCitas
.FechaCita = laFecha
.HoraCita = laHora
.MotivoCita.SetFocus
End With
Else 'Hay cita. Abrimos el formulario filtrado para modificar
DoCmd.OpenForm "FCitas", , , "FHCita='" & laFH & "'"
End If

'Cerramos el informe
DoCmd.Close acReport, Me.Name
End Sub

Fijaos que calculamos la fecha solicitada (variable laFecha) según el planteamiento algebraico
que os mostraba al principio de este epígrafe. A continuación creamos nuestra variable laFH
que nos concatena la fecha y la hora (el mismo sistema utilizado para el campo calculado de la
tabla). Finalmente, analizamos si existe o no la cita y abrimos FCitas en el modo adecuado.

Remarcar que hemos aprovechado la situación para que, si abrimos el formulario en una nueva
cita, automáticamente ya se nos rellenen los valores de los campos de la fecha y de la hora
(eso para que el usuario no tenga que trabajar tanto, pobrecito…).

PARA FINALIZAR EL EJEMPLO


Bueno… nos ha salido un ejemplo un tanto denso, pero he querido aprovechar el mismo no
solo para daros la solución “directamente hecha”, sino que, como habréis visto si habéis
llegado hasta aquí, para mostraros los problemas que han salido y de qué manera los he ido
resolviendo. Espero que si algún día os encontráis con problemas similares podáis acordaros
de este ejemplo y aplicar alguna sistemática parecida a la utilizada por mí para “salir del
atolladero” en vuestra aplicación.

Y, de verdad, ¿a qué ha quedado una agenda bastante “resultona”? ;-)

Un saludo, y…

¡suerte!

20
Visítame en http://bit.ly/NckAccess

También podría gustarte