planteamiento inicial

Anuncio
SISTEMA DE AYUDA1
El control TreeView es uno de estos controles ActiveX que
está ahí y que, hace años, me preguntaba: ¿para qué
servirá en Access?
Por otro lado, también hace años, las ayudas de los
controles (entre otros) venían en un formato de archivo de
extensión *.chm.
¿Cuál es el problema? Que no se proporciona ninguna aplicación que lea archivos *.chm, por lo
que toda la información incluida en dichos archivos resulta inaccesible (hay programas
disponibles en la Red, pero, hasta donde yo sé, todos son de pago).
Entonces es cuando “se enciende la bombilla” y se me ocurre encontrarle una utilidad práctica
al TreeView para poder crearnos un sistema de ayuda “chulo” para nuestra aplicación en
Access.
Seamos realistas: el sistema no es algo que “deslumbre” (creo yo) si lo comparamos con, por
ejemplo, crearnos un pdf con marcas, pero creo que sí queda bastante “resultón” de cara al
usuario. Puede ser que no obtengamos una ayuda visualmente impactante, pero, al fin y al
cabo, sí obtendremos una ayuda muy práctica (de nuevo, creo yo).
Este ejemplo no explica el funcionamiento detallado del control TreeView (si nos interesa
profundizar en el mismo podemos echar un vistazo a este ejemplo), sino sólo se explica cómo
utilizarlo de cara a crearnos nuestro sistema de ayuda.
Y dicho todo esto vamos a ver cómo hacer funcionar nuestro sistema de ayuda.
PLANTEAMIENTO INICIAL
Vamos a reflexionar un momento sobre lo que queremos obtener. Plantearemos la ayuda a tres
niveles:
1er nivel: los grandes epígrafes
2º nivel: los subepígrafes
3er nivel: los títulos, que llevarán aparejada su ayuda correspondiente.
Para que nos entendamos, un ejemplo de lo anterior podría ser:
1er nivel: LIBROS DE ACCESS
2º nivel:
ACCESS BÁSICO
ACCESS INTERMEDIO
3er nivel (dentro de ACCES BÁSICO, por ejemplo):
Mi primer Access (y en la ayuda saldría la información del libro)
Nadando con Access
Access para torpes
Aunque podríamos complicarlo bastante, lo dejaremos en la estructura anterior, de manera que
sólo cuando el usuario haga clic sobre el título de uno de los libros le salga la ayuda.
El ejemplo anterior es eso, sólo un ejemplo. Yo voy a utilizar una descripción de los contenidos
1
La BD de ejemplo os la podéis bajar aquí
1
Visítame en http://neckkito.siliconproject.com.ar
de la BD para “ayudar” al usuario.
PLANIFICANDO NUESTRAS TABLAS
Si no perdemos de vista la estructura que acabamos de
explicar veremos que la misma nos determina la estructura
de las tablas que vamos a necesitar.
Así pues vamos a crearnos una tabla, que guardaremos con
el nombre de TAyudaEpigrafes, que tendrá la siguiente
estructura.
Ahí construimos lo que hemos llamado nuestro primer nivel. Para que os hagáis una idea esto
son los datos que he introducido:
Vamos a construirnos una segunda tabla, que guardaremos
TAyudaSubEpigrafes, que tendrá la siguiente estructura:
con
el
nombre
de
Esta tabla constituirá nuestro segundo nivel. Los datos que yo he introducido han sido:
Por ahora no tenemos ninguna relación entre la primera tabla y la segunda. Esta relación la
definiremos en nuestra tercera tabla, que contendrá los descriptores del tercer nivel y el texto
de ayuda.
Así pues, esta tercera tabla, que guardaremos como TAyudaTextos, tendrá la siguiente
estructura:
2
Visítame en http://neckkito.siliconproject.com.ar
Como vemos en su estructura, tenemos el primer nivel
([IdTE]), el segundo nivel ([IdTSubE]) y el tercer nivel
([DescripT]), con su texto de ayuda.
Aquí es donde deberemos, como comentaba antes, crearnos la estructura de dependencias que
le queramos dar a nuestro árbol de ayuda.
Para que os situéis un poco parte de los datos que he introducido son:
Si nos fijamos, y si convertimos los identificadores es su texto descriptivo, tenemos para el
primer registro, por ejemplo:
Introducción
→ Sistema de ayuda
→ Prólogo: En esta base de datos... (bla, bla...)
MUY IMPORTANTE
El control TreeView funciona a través de claves o “keys”. Estas claves deben ser únicas, dado
que precisamente son “identificadores inequívocos”. Si pudiera haber dos iguales no sabríamos
a cuál de ellos nos referiríamos.
Como vamos a utilizar los descriptores de los epígrafes, subepígrafes y descriptor de texto, ello
nos obliga a utilizar nombres diferentes para cada uno de ellos.
Si convertimos la estructura anterior en “keys” (que serán las que utilizaremos) obtendríamos:
introducción
→ sistema de ayuda
→ prólogo
Los tres valores son diferentes: ningún problema. Si tuviéramos lo siguiente, por ejemplo:
introducción
→ prólogo
→ prólogo
El código nos dará error cuando intente asignar la clave “prólogo” en el nivel tres del TreeView
porque “prólogo” ya existe como “key” en el nodo del nivel dos.
Hay que tener esto en cuenta cuando vayamos a rellenar los valores en las tablas para
3
Visítame en http://neckkito.siliconproject.com.ar
evitarnos errores de código en la creación del TreeView. ¡Ojo!
CREANDO NUESTRA CONSULTA CAYUDA
Para facilitarnos la búsqueda de valores en el código vamos
a crearnos una consulta, que llamaremos CAyuda. Dicha
consulta tendrá la siguiente estructura:
Si os fijáis, de alguna manera lo que nos hace la consulta es mostrarnos la tabla TAyudaTextos
con las descripciones en lugar de los identificadores (más o menos, quiero decir).
CREANDO NUESTRO FORMULARIO DE AYUDA
Vamos a crearnos un formulario en blanco, que guardaremos como FAyuda. En dicho
formulario vamos a insertar el control ActiveX “Microsoft TreeView Control, version 6.0”. Vamos
a sacar sus propiedades y le pondremos de nombre miTreeVw2.
Introducimos también un cuadro de texto, al que pondremos de nombre txtAyuda.
Con algo de maña nos trabajamos el diseño y a mí me ha quedado una cosa así:
Vamos a sacar las propiedades del propio TreeView (las propiedades del objeto Tree Ctrl) 3 y
vamos a configurar lo siguiente:
•
2
3
Nos aseguramos que la propiedad <LineStyle> esté en <1 – tvwRootLines>
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.
Seleccionamos el control TreeView → Clic con el botón de la derecha → En el menú emergente seleccionamos la opción “Objeto de
Tree Ctrl” → Propiedades
4
Visítame en http://neckkito.siliconproject.com.ar
•
•
Nos aseguramos que la propiedad <LabelEdit> esté en <1 – tvwManual>
En la pestaña “Fuente” podemos configurar la fuente y algunas de sus características
para que se adapten mejor a nuestra aplicación.
PROGRAMANDO EL RELLENO DE
NUESTRO TREEVIEW
Como queremos que nuestro TreeView sea lo más flexible
posible debemos construirlo cada vez que abramos el
formulario para que “lea” los datos de las tablas de ayuda
que nos hemos creado. Así, podremos ir incluyendo datos
en esas tablas tranquilos de que cuando se abra FAyuda
esos datos aparecerán en el TreeView.
Para ello vamos a sacar las propiedades del formulario y en su evento “Al cargar” generamos el
siguiente código:
…
Private Sub Form_Load()
'Requiere registro de referencia "Microsoft DAO 3.6 Object Library" o
'módulo equivalente
'Declaramos las variables
Dim miMarca As String, miKey As String
Dim miEpi As String, miSubEpi As String
Dim miSql As String
Dim misNodos As Node
Dim rst As DAO.Recordset
'-----FASE 1: CREAMOS LOS EPÍGRAFES
'Creamos el recordset sobre la tabla TAyudaEpigrafes
Set rst = CurrentDb.OpenRecordset("TAyudaEpigrafes", dbOpenForwardOnly)
'Manipulamos el recordset
With rst
'Iniciamos el recorrido de registros
Do Until .EOF
'Cogemos la descripción del epígrafe
miMarca = .Fields(1).Value
'Convertimos la marca en mi key
miKey = LCase(Trim(miMarca))
'Añadimos el nodo a nuestro TreeView
Set misNodos = Me.miTreeVw.Nodes.Add(, , miKey, miMarca)
'Lo marcamos en azul
Me.miTreeVw.Nodes.Item(miKey).ForeColor = vbBlue
'Nos movemos al siguiente registro
.MoveNext
Loop
End With
'-----FASE 2: CREAMOS LOS SUBEPÍGRAFES
'Creamos una SQL sobre la consulta CAyuda
miSql = "SELECT DISTINCT CAyuda.SubEpigrafe, CAyuda.Epigrafe FROM CAyuda"
'Creamos el recordset sobre nuestra SQL
Set rst = CurrentDb.OpenRecordset(miSql)
'Manipulamos el recordset
With rst
'Nos movemos al primer registro
.MoveFirst
'Iniciamos el recorrido de registros
Do Until .EOF
'
'Cogemos la descripción del epígrafe
miEpi = .Fields(1).Value
'Lo transformamos en la key
miEpi = LCase(Trim(miEpi))
5
Visítame en http://neckkito.siliconproject.com.ar
'Cogemos la descripción del subepígrafe
miSubEpi = .Fields(0).Value
'Creamos la key
miKey = LCase(Trim(miSubEpi))
'Lo añadimos al treeview
Set misNodos = Me.miTreeVw.Nodes.Add(miEpi, tvwChild, miKey,
miSubEpi)
'Lo marcamos en magenta
Me.miTreeVw.Nodes.Item(miKey).ForeColor = vbMagenta
'Nos movemos al siguiente registro
.MoveNext
Loop
End With
'-----FASE 3: CREAMOS LOS ELEMENTOS DE AYUDA
'Manipulamos de nuevo el recordset
Set rst = CurrentDb.OpenRecordset("CAyuda")
With rst
'Nos situamos en el primer registro
.MoveFirst
'Recorremos los registros
Do Until .EOF
'Cogemos la descripción del subepígrafe
miSubEpi = .Fields(1).Value
'Lo convertimos en la key
miSubEpi = LCase(Trim(miSubEpi))
'Cogemos la descripción de la ayuda
miMarca = .Fields(2).Value
'Creamos la key
miKey = LCase(Trim(miMarca))
'Lo añadimos al treeview
Set misNodos = Me.miTreeVw.Nodes.Add(miSubEpi, tvwChild, miKey, miMarca)
'Nos movemos al siguiente registro
.MoveNext
Loop
End With
'Cerramos conexiones y liberamos memoria
rst.Close
Set rst = Nothing
End Sub
…
Cotilleemos un poco sobre el código (que está ya ampliamente comentado):
•
Lo primero que vemos es que como tenemos tres niveles lo hemos dividido en tres
fases, que van desde el nivel superior al nivel inferior.
•
Para el primer nivel creamos un recordset sobre TAyudaEpigrafes (y lo abrimos como
dbOpenForwardOnly para que la lectura de los registros sea lo más rápida posible).
Vamos recorriendo los registros, cogemos el valor de la descripción, lo convertimos en
minúsculas y eliminamos posibles espacios en blanco (LCase(Trim(...)), lo que nos
permite darles valor a dos variables: miMarca y miKey.
•
Con el Set misNodos = … añadimos esa “key” y su descripción en el nodo
correspondiente.
•
En la fase 2 echamos mano de la consulta CAyuda que nos hemos creado
anteriormente. Sin embargo, no recurrimos a ella directamente, sino que lo hacemos a
través de una SQL. Esa SQL lo único que hace es cogernos los valores únicos de la
descripción de los subepígrafes, eliminando los duplicados. La diferencia es que, a partir
de aquí, también debemos “pillar” las claves que constituyen el nodo superior y de las
cuales dependen los nuevos valores que vamos rellenando en el TreeView.
•
Creamos el recordset y la recorremos, de nuevo rellenando las variables que nos van a
proporcionar la clave y la descripción. Os remito al código para ver los detalles.
6
Visítame en http://neckkito.siliconproject.com.ar
•
He aprovechado la ocasión para marcar los nodos de primer
y segundo nivel de otro color. Eso ofrece una ayuda visual
adicional. Si no nos gusta simplemente eliminamos esas
líneas de asignación de color del código.
•
Finalmente, para la fase 3, sí que creamos un recordset
directamente sobre CAyuda y repetimos el proceso de crear
“key” y valor de la key, junto con la clave del nodo
inmediatamente superior del cual dependen.
Aunque a primera vista el código puede parecer muy complejo si lo dividimos en elementos
más simples veremos su lógica, ya que la mecánica es simplemente ir repitiendo el bucle a
través del recorrido de registros y asignar los valores correspondientes (¡qué fácil es decirlo,
¿verdad? Je, je...).
PROGRAMANDO LA ACCIÓN DEL TREEVIEW
Si sacamos las propiedades “normales” del TreeView veremos que tenemos muy pocos eventos
disponibles. Y, además, de los que tenemos ahí ninguno nos sirve.
Para hacer operativo el funcionamiento del TreeView debemos utilizar un evento que no existe
en esas propiedades, que es “Al hacer clic”.
Para ello, en el módulo asociado al formulario FAyuda, vamos a escribir el siguiente código,
describiendo nosotros “a mano” el tipo de evento:
…
Private Sub miTreeVw_Click()
'Declaramos las variables
Dim laAyuda As String
Dim laKey As Variant
'Cogemos el valor seleccionado por el usuario
laKey = Me.miTreeVw.SelectedItem.Text
'Buscamos su equivalencia en la descripción
laAyuda = Nz(DLookup("TextoAyuda", "TAyudaTextos", "DescripT='" & laKey & "'"), "")
'Si laAyuda devuelve un valor nulo salimos
If laAyuda = "" Then Exit Sub
'Pasamos el texto de la ayuda al textbox
Me.txtAyuda.Value = laAyuda
End Sub
…
Con esto cada vez que hagamos clic sobre el TreeView se ejecutará el código. Pero hemos
dicho que los nodos de los niveles uno y dos no tienen ayuda asociada. ¿Cómo lo solventamos?
Pues en el código veréis que existe un DLookup que nos busca el texto de ayuda. Si no hay
devuelve un valor NULL, que convertimos a una cadena vacía (“”) gracias a la función NZ(). Y,
a continuación, le decimos simplemente que si el valor devuelto es una cadena vacía pues... a
salir del proceso.
Finalmente, cuando por fin encuentra algún texto de ayuda, lo traspasa al textbox del
formulario... y así se “obra el milagro”... ji, ji...
PARA FINALIZAR EL EJEMPLO
Bueno. Como indicaba en la introducción al ejemplo, creo que ha salido un ejemplo bastante
7
Visítame en http://neckkito.siliconproject.com.ar
“resultón” y práctico. Si necesitáis utilizar este sistema en vuestras aplicaciones sólo tendréis
que construíroslo o bien, más fácil, importar de la BD de ejemplo tablas, consulta y formulario,
y, evidentemente, sustituir los valores que yo he introducido por los que se adapten a vuestra
BD.
Espero que el ejemplo os sea útil.
Un saludo, y...
¡suerte!
8
Visítame en http://neckkito.siliconproject.com.ar
Descargar