Anda di halaman 1dari 18

CURSO DE VB

CAPTULO 61

ndice de contenido
SIGAMOS UN POCO MS CON DOCMD Y FORMULARIOS.....................................................2
LA PREPARACIN DEL EJEMPLO DE ESTE CAPTULO.......................................................2
SEGUNDA CONVERSACIN ODA AL PASAR........................................................................3
CONTROLES, CONTROLES........................................................................................................3
CUIDADO: AADIR REGISTROS O PASEARSE POR LOS REGISTROS...........................7
POR FIN APARECE NUESTRO SUBFORMULARIO.................................................................8
EL LTIMO DETALLE DE NUESTRO FORMULARIO...........................................................11
REUTILIZANDO NUESTRO FORMULARIO...........................................................................13
PARA FINALIZAR ESTE CAPTULO........................................................................................18

1 La BD donde estn los ejemplos de este captulo os la podis bajar aqu .

1
Vistame en http://siliconproject.com.ar/neckkito/
SIGAMOS UN POCO MS CON DOCMD Y FORMULARIOS

LA PREPARACIN DEL EJEMPLO DE ESTE


CAPTULO

Para no perder las buenas costumbres vamos a crear una


BD en blanco para ir probando las cosas que veremos. Dado
que no puedo dar por supuesto que se sepa a la
perfeccin cmo realizar lo que os voy a indicar en la BD
voy a ir explicando esta preparacin paso a paso.

La idea es la siguiente: vamos a dar de alta unos clientes, pero queremos dar de alta tambin
unos datos confidenciales del cliente. Esos datos confidenciales no los puede rellenar cualquier
usuario de la BD, sino que slo los podremos rellenar nosotros. Emplearemos la estructura de
subformulario para hacer eso, lo que nos permitir ver cmo podemos manipular controles
tanto de un formulario como de un subformulario.

La BD de ejemplo, en s, quiz no tenga mucho sentido. Ya sabis que lo que interesa es


pillar la mecnica de cmo se hacen las cosas, y no el ejemplo en s.

Manos a la obra:

1.- Creamos una tabla, que llamaremos TClientes, que contendr los siguientes campos:

[IdCli] Autonumrico y clave principal.


[NomCli] Texto (recoger el nombre del cliente)
[Casado] S/no (con NO como valor por defecto)
[NomConyu] Texto (nos recoger el nombre del cnyuge)

2.- Creamos otra tabla, que llamaremos TConfidencial, que contendr los siguientes campos:

[IdReg] Autonumrico y clave principal.


[IdCliConf] Numrico
[FechaCas] Fecha/Hora, con formato de fecha corta (nos recoger la fecha del enlace
matrimonial).
[Deporte] Texto

3.- Creamos un formulario basado en la tabla TClientes, al que pondremos por nombre
FClientes.

4.- Sacamos las propiedades del campo [NomConyu] y nos vamos a la pestaa Formato
Visible, y le situamos la propiedad en NO.

5.- Insertamos un subformulario basado en la tabla TConfidencial, y definimos la relacin entre


formulario principal y subformulario de la siguiente manera:
Campo del formulario: [IdCli]
Campo del subformulario: [IdCliConf]

6.- Guardamos el subformulario con el nombre de subFrmConfidencial

7.- Dentro del formulario principal, seleccionamos el subformulario recin creado, sacamos sus
propiedades y nos vamos a la pestaa Formato Visible: NO.

2
Vistame en http://siliconproject.com.ar/neckkito/
8.- Guardamos los cambios y cerramos FClientes.

9.- Abrimos subFrmConfidencial en vista diseo y sacamos


sus propiedades. Nos vamos a la pestaa Formato Vista
predeterminada: un nico formulario.

10.- Sacamos las propiedades del campo [FechaCas] y nos


vamos a la pestaa Formato Visible: NO

Y, por ahora, lo dejaremos aqu.

SEGUNDA CONVERSACIN ODA AL PASAR...

Cdigo VB: Hola, Forms!miFormulario! Con quin vienes?


Formulario: Hola. Te presento a mi hijo, subFrmMiSubform.
CVB: Caramba, qu ricura. Creo que le voy a reservar un nombre especial para l.
F: Y qu nombre le vas a poner?
CVB: Le llamar... Formulario subFrmMiSubform hijo de Forms!miFormulario
F: Qu cosa ms larga! No podras abreviarlo un poco?
CVB: Pues... el nombre definitivo ser: Forms!miFormulario.subFrmMiSubform.Form
F: Esto... qu entiendes t por abreviar...?

CONTROLES, CONTROLES...

Los controles, al igual que los formularios, tienen propiedades. Y, tambin como los
formularios, esas propiedades pueden ser modificadas a travs del cdigo. Pero antes debemos
identificar el control.

Y cmo se hace eso? Mi primera recomendacin: poned un nombre descriptivo al control


(Propiedades Pestaa Otras Nombre).

Cuando creamos un botn de comando, por ejemplo, Access por defecto le pone un nombre
enumerativo, del tipo Comando25. Para los cuadros combinados utiliza el mismo sistema:
Cuadro combinado13, y lo mismo podemos decir para el resto de controles. Como no
tengamos un nombre descriptivo para ellos vamos a tener que estar continuamente mirando
cmo se llamaba ese TextBox... Texto2 o Texto63? Eso es un latazo.

La segunda cosa que debemos saber es que para llamar a los controles debemos pasar por
identificar el formulario en el que estn. Es decir, si tenemos el cboSeleccionaProvincia no
podemos poner ese valor directamente en el cdigo, sino que debemos indicarle la ruta
completa, separada por puntos. As pues, si llamamos a ese combo deberamos escribir algo
as como: Forms!miFormulario.cboSeleccionaProvincia (o, como ya sabemos,
Me.cboSeleccionaProvincia).

A continuacin de la llamada al control debemos especificar o bien el mtodo que vamos a


utilizar o bien la propiedad que queremos manipular. Por ejemplo, si queremos actuar sobre el
color de la letra de un cuadro de texto txtLetra deberamos utilizar la propiedad forecolor, y
lo indicaramos as: Forms!miFormulario.txtLetra.Forecolor.

En resumen:

O bien: Forms!nombreFormulario.nombreControl.<mtodo>
O bien: Forms!nombreFormulario.nombreControl.<propiedad>

3
Vistame en http://siliconproject.com.ar/neckkito/
Vamos a ver una primera manipulacin muy sencilla. Si el
cliente est casado, el campo donde tengamos su nombre
se sombrear de amarillo y el color del texto ser rojo. Para
ello manipularemos la propiedad Despus de actualizar
del campo [Casado].

Ponemos pues nuestro formulario FClientes en vista diseo


y sacamos las propiedades del campo [Casado]. Nos vamos
a la pestaa Eventos Despus de actualizar, y le
generamos el siguiente cdigo:

Private Sub Casado_AfterUpdate()


Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
End If
End Sub

Sabemos que [Casado] siempre devuelve dos valores: Falso (valor que hemos establecido por
defecto) o Verdadero. Por este motivo definimos la variable vCas como booleana.

Vamos a coger el valor de [Casado] una vez hayamos hecho click (despus de actualizar). Para
ello tenemos que decir que queremos

El valor del campo / Casado / que est en el formulario FCliente

Como ya sabemos, para llamar un control debemos indicar primero en qu formulario est. Por
ello utilizamos Me (porque, como ya estudiamos en el captulo anterior, cdigo y formulario
son vecinos). A continuacin indicamos el nombre del control, y finalmente, separado por un
punto, la propiedad que queremos obtener. As, nos queda que vCas es igual a

vCas = Me.Casado.Value

Si el campo [Casado] est marcado (es Verdadero) debemos actuar de alguna manera. Por
ello utilizamos el bloque IF...END IF, de manera que:

If vCas = True Then

Y para llamar a las propiedades del campo que queremos manipular, que es [NomCli], ya
sabemos cmo llamarlas. Y tambin sabemos que como nos vamos a referir al mismo control
podemos utilizar el bloque WITH...END WITH, de manera que:

El color de la letra sea rojo Me.NomCli.Forecolor = vbRed


El color del fondo sea amarillo Me.NomCli.Backcolor = vbYellow

Si ahora situamos nuestro formulario en vista formulario, damos de alta un cliente y marcamos
la casilla de que est casado, veremos los cambios.

Pero ahora nos hemos dado cuenta de que hemos marcado que el cliente estaba casado por

4
Vistame en http://siliconproject.com.ar/neckkito/
error, pero que en realidad no est casado. Si desmarcamos el check... no pasa nada!

No pasa nada porque en el cdigo no hemos analizado que


pasa si el valor del campo [Casado] es False. Por ello,
podemos modificar nuestro cdigo de la siguiente manera:


Private Sub Casado_AfterUpdate()
Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
Else
With Me.NomCli
.ForeColor = vbBlack
.BackColor = vbWhite
End With
End If
End Sub

Bueno... Ahora parece que si probamos esto de marcar y desmarcar el check la cosa mejora.

Sigamos: vamos a manipular otra propiedad. En este caso queremos que si se marca el check
casado el campo [NomConyu] se haga visible. Para ello deberemos manipular la propiedad
<Visible> del campo [NomConyu], teniendo en cuenta de que el usuario se puede equivocar
y marcar el check (y desmarcarlo a continuacin).

Nuestro cdigo anterior debera ampliarse de la siguiente manera:

Private Sub Casado_AfterUpdate()


Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
Me.NomConyu.Visible = True
Else
With Me.NomCli
.ForeColor = vbBlack
.BackColor = vbWhite
End With
Me.NomConyu.Visible = False
End If
End Sub

Como vemos, lo nico que hemos hecho ha sido aadir que la propiedad <Visible> del campo
[NomConyu] de este formulario adquiera los valores True o False en funcin de si el check est
marcado o desmarcado; es decir:

5
Vistame en http://siliconproject.com.ar/neckkito/
Me.NomConyu.Visible = True

Me.NomConyu.Visible = False

Si probamos nuestro formulario veremos como [NomConyu]


aparece y desaparece a nuestro antojo.

Compliquemos la cosa: nuestro usuario marca nuestro


cliente como casado, escribe el nombre del cnyuge y, de
repente, se da cuenta, de que se ha equivocado.

Lgicamente, desmarca el check y asunto arreglado... o no?

Si probamos lo anterior y cerramos nuestro formulario, si a continuacin abrimos la tabla


TClientes veremos como el check est desmarcado, pero aparece un nombre de cnyuge. Y
eso no debera ser as.

Vamos a corregir ese error. Ya sabemos cmo coger el valor de un campo a travs de la
propiedad <value>. Pues para modificar un valor tambin recurrimos a su propiedad <value>.

En definitiva, lo que debemos decirle al cdigo es que si el check est desmarcado nos borre
el valor del campo [NomConyu] y despus lo convierta en invisible.

Para ello, nuestro cdigo quedara as:

Private Sub Casado_AfterUpdate()


Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
Me.NomConyu.Visible = True
Else
With Me.NomCli
.ForeColor = vbBlack
.BackColor = vbWhite
End With
With Me.NomConyu
.Value = Null
.Visible = False
End With
End If
End Sub

Como podis ver, lo que hemos hecho ha sido decirle que el valor de [NomConyu] sea NULO, a
travs de Me.NomConyu.Value = Null

Si repetimos la operacin anterior, cerramos el formulario y abrimos la tabla TClientes veremos


que ahora ya no nos aparece ningn cnyuge.

6
Vistame en http://siliconproject.com.ar/neckkito/
CUIDADO: AADIR REGISTROS O PASEARSE
POR LOS REGISTROS

Hay que tener en cuenta el comportamiento del formulario


segn la situacin en la que estemos. Hasta ahora hemos
estado aadiendo un solo registro. Pero, qu ocurre
cuando nos pasemos por los registros (teniendo en cuenta
que cuando digo pasear me refiero a todas las acciones
posibles de <Ir a registro... nuevo, anterior, siguiente, etc.>

Vamos a aadir un registro de un cliente que est casado. Una vez tengamos los campos
rellenos, vamos a aadir otro registro. Sorpresa?

Pues s: sorpresa. Nuestro campo [NomCli] nos aparece con fondo amarillo y el campo
[NomConyu] aparece visible. Y eso no debera ser as.

El problema lo encontramos porque cuando hemos modificado las propiedades de los controles
lo hacemos independientemente del registro en el que estemos, y la ltima modificacin es lo
ltimo que conserva el formulario y controles.

Para solucionar lo anterior debemos hacer que el formulario, cada vez que cambie un registro,
examine el valor del check [Casado] y acte en consecuencia. Y eso de cada vez que cambie
un registro es un evento de formulario que se denomina Al activar registro.

As pues, situamos nuestro formulario FClientes en vista diseo y sacamos sus propiedades.
Nos vamos a la pestaa Eventos Al activar registro, y le generamos el siguiente cdigo:

Private Sub Form_Current()


Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
Me.NomConyu.Visible = True
Else
With Me.NomCli
.ForeColor = vbBlack
.BackColor = vbWhite
End With
Me.NomConyu.Visible = False
End If
End Sub

Podemos ver que el cdigo es prcticamente igual al que hemos estado programando hasta
ahora. Lo que dice es, simplemente, que al cambiar registro me miras el valor del check
[Casado]: si su valor es Verdadero haces unas cosas; si es Falso haces otras.

Lgicamente, si ahora probamos nuestro formulario veremos que las cosas vuelven a funcionar
con normalidad.

7
Vistame en http://siliconproject.com.ar/neckkito/
Moraleja: cuando programemos un formulario debemos
tener siempre en cuenta lo que pasa cuando damos de
alta un registro y lo que pasa cuando recorremos los
registros. Ojo!

POR FIN APARECE NUESTRO SUBFORMULARIO

Volvamos a situar nuestro formulario FClientes en vista


diseo. En su cabecera aadimos un botn de comando,
que llamaremos cmdMuestraConfidencial.

Al hacer click sobre ese botn se nos mostrarn los datos confidenciales, siempre y cuando
sepamos una contrasea. El proceso para realizar lo anterior es:

1.- Definimos la contrasea


2.- Pedimos al usuario que introduzca una contrasea
3.- Comparamos si la contrasea introducida se corresponde con la contrasea correcta. Y si es
as...
4.- Muestra el subformulario subFrmConfidencial

Vamos pues:

.- La contrasea ser siempre la misma, por lo que el tipo de variable que utilizaremos ser
una constante.

.- Cmo solicitamos la entrada de datos al usuario? Pues a travs de un InputBox

.- Cmo realizamos la comparacin? Pues a travs de un bloque IF...END IF

.- Cmo mostramos el subformulario? Pues actuando sobre su propiedad <Visible>

El cdigo que asignaremos al evento Al hacer click del botn de comando ser, pues:

Private Sub cmdMuestraConfidencial_Click()


Const pass As String = "a123"
Dim userPass As Variant
'Solicitamos la introduccin de la constrasea
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos si el usuario pulsa el botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta hacemos visible el subformulario
Me.subFrmConfidencial.Form.Visible = True
Else
'Si no lo es avisamos. Se sale tras el End If del proceso sin hacer nada
MsgBox "La contrasea introducida no es correcta", vbCritical, "ERROR"
End If
End Sub

El cdigo est comentado, adems de que la mayora de acciones que realiza este cdigo ya
las hemos estudiado en captulos anteriores. Simplemente remarcar la llamada al
subformulario, que la realizamos de la siguiente manera:

8
Vistame en http://siliconproject.com.ar/neckkito/
Me.subFrmConfidencial.Form.Visible

Recordamos, en nuestra conversacin oda al pasar, lo de


<Forms!nombreForm.nombreSubForm.Form.<propiedad>
?

Evidentemente, en este caso hemos sustituido Forms!


NombreForm por ME.

Si probamos nuestro formulario veremos que con el pass correcto podemos ver el
subformulario.

Ricemos el rizo: en nuestro formulario tenemos el check [casado] marcado, pero en nuestro
subformulario el campo [FechaCas] no nos aparece. Eso no est bien. Y para llamar a un
control en un subformulario desde el formulario debemos utilizar:

Forms!nombreFormulario.nombreSubForm.Form.nombreControl.Propiedad

As pues, nuestro cdigo del botn de comando debera ser modificado as:

Private Sub cmdMuestraConfidencial_Click()


Const pass As String = "a123"
Dim userPass As Variant
Dim vCas As Boolean
'Miramos qu valor tiene el check [Casado]
vCas = Me.Casado.Value
'Solicitamos la introduccin de la constrasea
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos si el usuario pulsa el botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta hacemos visible el subformulario
Me.subFrmConfidencial.Form.Visible = True
'Si el check casado es verdadero mostramos el campo [FechaCas]
If vCas = True Then
Me.subFrmConfidencial.Form.FechaCas.Visible = True
End If
Else
'Si no lo es avisamos. Se sale tras el End If del proceso sin hacer nada
MsgBox "La contrasea introducida no es correcta", vbCritical, "ERROR"
End If
End Sub

Todo perfecto? Pues no todo es perfecto. Vamos a suponer que queremos que el
subformulario se mantenga visible hasta que no lo ocultemos. Aadimos un nuevo registro y...
nuestro campo [FechaCas] sigue visible.

Cmo podemos arreglar eso? Vamos a verlo, y para ello debemos recurrir de nuevo a la
propiedad de Al activar registro del formulario. Pero ahora tenemos no una condicin que
cumplir sino dos:
Que el subformulario est visible.
Que el check [Casado] est marcado

9
Vistame en http://siliconproject.com.ar/neckkito/
As que en nuestro cdigo de ese evento vamos a realizar
una pequea modificacin de la siguiente manera:


Private Sub Form_Current()
Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
Me.NomConyu.Visible = True
Else
With Me.NomCli
.ForeColor = vbBlack
.BackColor = vbWhite
End With
Me.NomConyu.Visible = False
End If
If Me.subFrmConfidencial.Form.Visible = True Then
If vCas = True Then
Me.subFrmConfidencial.Form.FechaCas.Visible = True
Else
Me.subFrmConfidencial.Form.FechaCas.Visible = False
End If
End If
End Sub

El primer bloque IF...END IF viene a decir:


.- Si el subformulario est visible
'Haz cosas
Y por omisin, si no est visible no hacemos nada

El segundo bloque IF...END IF dice que:


.- Si el check [Casado] est marcado
'Mustrame [FechaCas]
.- Si no lo est
'Ocltame [FechaCas]

Seguimos el razonamiento hasta ahora?

Y lo anterior nos plantea un problema, teniendo presente que estamos aadiendo un nuevo
registro. Si ahora damos de alta otro cliente y marcamos el check [Casado] nuestro campo de
subformulario [FechaCas] no nos aparece, porque no hemos realizado ningn tipo de
programacin para este supuesto.

Evidentemente, tendremos que modificar nuestro cdigo del evento Despus de actualizar,
pero esta vez teniendo en cuenta si el subformulario est visible o no.

As pues, la modificacin que debemos hacer es la siguiente:

Private Sub Casado_AfterUpdate()

10
Vistame en http://siliconproject.com.ar/neckkito/
Dim vCas As Boolean
vCas = Me.Casado.Value
If vCas = True Then
With Me.NomCli
.ForeColor = vbRed
.BackColor = vbYellow
End With
Me.NomConyu.Visible = True
Else
With Me.NomCli
.ForeColor = vbBlack
.BackColor = vbWhite
End With
With Me.NomConyu
.Value = Null
.Visible = False
End With
End If
If Me.subFrmConfidencial.Form.Visible = True Then
If vCas = True Then
Me.subFrmConfidencial.Form.FechaCas.Visible = True
Else
With Me.subFrmConfidencial.Form.FechaCas
.Visible = False
.Value = Null
End With
End If
End If
End Sub

Como vemos, el cdigo prcticamente es el mismo que el anterior. Lo nico que en este caso,
en el caso de que se desmarque el check, aprovechamos para decirle que nos borre cualquier
valor que haya podido introducirse.

He querido que se produjera una cierta reiteracin de los cdigos (con ligeras variaciones)
con la finalidad de que captis la mecnica de funcionamiento.

EL LTIMO DETALLE DE NUESTRO FORMULARIO

Vamos a situar nuestro FClientes en vista diseo y en su cabecera vamos a aadir un botn de
comando para cerrar la vista de los datos confidenciales. A este nuevo botn lo llamaremos
cdmOcultaConfidencial.

Vamos a sacar las propiedades de este nuevo botn y le vamos a poner como propiedad
predeterminada que est desactivado. Para ello nos vamos a la pestaa Datos->Activado: NO.

Lgicamente, queremos que cuando pulsemos sobre el botn cmdMuestraConfidencial se nos


active cmdOcultaConfidencial, pero al mismo tiempo, para evitar clicks accidentales, se
desactive cmdMuestraConfidencial.

De la misma manera, cuando pulsemos cmdOculta confidencial este mismo botn se desactive
para que cmdMuestraConfidencial quede activado.
Sacamos pues las propiedades de cmdMuestraConfidencial y modificamos el cdigo existente
de la siguiente manera:

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

Private Sub cmdMuestraConfidencial_Click()
Const pass As String = "a123"
Dim userPass As Variant
Dim vCas As Boolean
'Miramos qu valor tiene el check [Casado]
vCas = Me.Casado.Value
'Solicitamos la introduccin de la constrasea
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos si el usuario pulsa el botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta hacemos visible el subformulario
Me.subFrmConfidencial.Form.Visible = True
'Si el check casado es verdadero mostramos el campo [FechaCas]
If vCas = True Then
Me.subFrmConfidencial.Form.FechaCas.Visible = True
End If
Else
'Si no lo es avisamos y salimos del proceso sin hacer nada
MsgBox "La contrasea introducida no es correcta", vbCritical, "ERROR"
Exit Sub
End If
With Me
.cmdOcultaConfidencial.Enabled = True
.cmdOcultaConfidencial.SetFocus
.cmdMuestraConfidencial.Enabled = False
End With
End Sub

Vamos a ver qu hemos hecho:

1.- Con nuestro cdigo anterior, si la contrasea introducida era correcta, salamos el bloque
IF...END IF y la siguiente instruccin ya era END SUB. En este nuevo caso no podemos dejar
que el cdigo siga ejecutndose tras el END IF porque hemos aadido nuevo cdigo, por lo
que este s se ejecutara. Cmo lo solventamos? Pues forzando la salida del proceso a travs
de un EXIT SUB.

2.- Para volver activo el botn cmdOcultaConfidencial debemos llamar a su propiedad y


establecerle el valor True, que es lo que hacemos a travs de la propiedad ENABLED.

3.- Debemos saber (y si no no os preocupis que nuestro amigo Access se encargar de


avisarnos a travs de un mensaje) que no podemos desactivar un control si tiene el enfoque.
Es decir, que cuando yo hago click sobre el botn cmdMuestraConfidencial durante la ejecucin
de todo el cdigo el enfoque est situado sobre l. Si no obligamos a que el enfoque se mueva
a otro control no podremos manipular su propiedad.

Es por ello por lo que antes de manipular cmdMuestraConfidencial.Enabled = False debemos


mover el enfoque a otro control. Como cmdOcultaConfidencial ya est activo pues es el
candidato ms idneo, y de ah que aadamos la lnea Me.cmdOcultaConfidencial.SetFocus.

Probad una cosa: convertid esa lnea (Me.cmdOcultaConfidencial.SetFocus) en comentario


(os recuerdo que basta poner una comilla simple delante del ME) e intentad ejecutar el cdigo.

12
Vistame en http://siliconproject.com.ar/neckkito/
Veris qu hermoso mensaje nos lanza Access.

Evidentemente para solventar el problemilla basta quitar


la comilla simple que la convierte en comentario.

Vamos pues a por nuestro botn cmdOcultaConfidencial. Os


animo a pensar vosotros el cdigo que debera ir en ese
botn antes de mirar el que yo os proporciono.

Pues eso... El cdigo sera:

Private Sub cmdOcultaConfidencial_Click()


With Me
.cmdMuestraConfidencial.Enabled = True
.cmdMuestraConfidencial.SetFocus
.cmdOcultaConfidencial.Enabled = False
.subFrmConfidencial.Visible = False
End With
End Sub

Sencillo, no?

REUTILIZANDO NUESTRO FORMULARIO

Antes de entrar en materia vamos a hacer un par de operaciones:

1.- En FClientes aadimos una etiqueta en la cabecera y en ella escribimos: AADIR


CLIENTES. Le ponemos de nombre lblModoEntrada

2.- En las propiedades del formulario nos vamos a la pestaa Formato Titulo, y ah
escribimos ALTA CLIENTES

3.- Aadimos un botn de comando, que llamaremos cmdCierra, y le generaremos el siguiente


cdigo:

Private Sub cmdCierra_Click()


DoCmd.Close acForm, Me.Name
DoCmd.OpenForm "FMenu"
End Sub

En teora deberais saber perfectamente qu est haciendo este cdigo ;)

4.- Creamos un formulario en blanco y lo guardamos como FMenu.

5.- Aadimos un botn de comando y lo llamamos cmdAgregaClientes. Este botn nos servir
para dar de alta clientes.

6.- Aadimos otro botn de comando y lo llamamos cmdConsultaClientes. Este botn nos
servir para consultar clientes.

OK. Ahora tenemos dos botoncillos desde nuestro men que nos permitirn agregar o

13
Vistame en http://siliconproject.com.ar/neckkito/
consultar clientes. La pregunta del milln es: necesitamos un formulario para agregar y otro
formulario para consultar?

La respuesta es... No. Podemos reciclar nuestro


formulario para que sirva para ambas cosas. Vamos a ver la
primera opcin: agregar.

Como FClientes lo hemos diseado en principio para


agregar ninguna modificacin debemos hacer. Basta que
cojamos cmdAgregaClientes y le generemos el siguiente
cdigo (sabramos programarlo sin mirar la solucin?)

Private Sub cmdAgregaClientes_Click()


DoCmd.OpenForm "FClientes", , , , acFormAdd
DoCmd.Close acForm, Me.Name
End Sub

Y listo.

Vamos a por nuestro segundo botn.

La primera duda que se nos plantea es: quin va a consultar? Nosotros (que podemos ver
los datos confidenciales) u otro usuario? Vamos a pedrselo al propio usuario.

El cdigo pues, inicialmente, sera el siguiente:

Private Sub cmdConsultaClientes_Click()


Const pass As String = "a123"
Dim resp As Integer
Dim userPass As Variant
'Solicitamos el modo de consulta
resp = MsgBox("Consulta en modo administrador?", vbQuestion + vbYesNo, "TIPO
CONSULTA")
'Si la respuesta es s solicitamos el password
If resp = vbYes Then
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos la pulsacin del botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta abrimos el formulario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
DoCmd.Close acForm, Me.Name
Else
'Si no es correcta avisamos y salimos
MsgBox "Contrasea incorrecta", vbCritical, "ERROR"
Exit Sub
End If
Else
'Si la respuesta es no abrimos el formulario en modo usuario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
DoCmd.Close acForm, Me.Name
End If

14
Vistame en http://siliconproject.com.ar/neckkito/
End Sub

El cdigo, como es obvio, an no est completo. Vamos a


analizarlo:

La estructura del cdigo vemos que la conforma un


bloque IF dentro de otro bloque IF. El primer bloque lo que
hace es pedirnos si entramos como usuario o como
administrador.

El segundo bloque IF lo que hace es solicitarnos la contrasea para verificar que quien
intenta entrar posee los privilegios de administrador.

Como podis ver en este cdigo estamos combinando algo que vimos en captulos
anteriores (MsgBox para recabar informacin del usuario) y algo que hemos visto en este, que
es la solicitud de una contrasea para interactuar con el formulario.

Nos hemos cubierto las espaldas en el sentido de que cada cosa mal (por llamarlo de
alguna manera) fuerza a nuestro cdigo a salir sin abrir FClientes. Es decir:
Si se pulsa el botn cancelar Salimos del procedimiento
Si la contrasea es errnea Salimos del procedimiento

Vamos a por nuestra segunda duda: si entramos como usuario no podemos ver el
subformulario, lo cual es correcto, pero si entramos como administrador deberamos poder ver
el subformulario. Para ello debemos indicrselo en el cdigo, de la siguiente manera:

Private Sub cmdConsultaClientes_Click()


Const pass As String = "a123"
Dim resp As Integer
Dim userPass As Variant
'Solicitamos el modo de consulta
resp = MsgBox("Consulta en modo administrador?", vbQuestion + vbYesNo, "TIPO
CONSULTA")
'Si la respuesta es s solicitamos el password
If resp = vbYes Then
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos la pulsacin del botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta abrimos el formulario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
Forms!FClientes.subFrmConfidencial.Visible = True
DoCmd.Close acForm, Me.Name
Else
'Si no es correcta avisamos y salimos
MsgBox "Contrasea incorrecta", vbCritical, "ERROR"
Exit Sub
End If
Else
'Si la respuesta es no abrimos el formulario en modo usuario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
DoCmd.Close acForm, Me.Name

15
Vistame en http://siliconproject.com.ar/neckkito/
End If
End Sub

Recordad que estamos en el mdulo de FMenu, por lo


que no podemos utilizar ME, sino que debemos llamar al
formulario FClientes por su forma larga.

Ahora nos damos cuenta de que si el primer registro


muestra el check [Casado] marcado nuestro subformulario
no nos muestra la fecha de boda porque hemos establecido
su propiedad por defecto como no visible.

Qu podemos hacer? Pues simplemente decrselo al cdigo, as:

Private Sub cmdConsultaClientes_Click()


Const pass As String = "a123"
Dim resp As Integer
Dim userPass As Variant
'Solicitamos el modo de consulta
resp = MsgBox("Consulta en modo administrador?", vbQuestion + vbYesNo, "TIPO
CONSULTA")
'Si la respuesta es s solicitamos el password
If resp = vbYes Then
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos la pulsacin del botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta abrimos el formulario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
Forms!FClientes.subFrmConfidencial.Visible = True
DoCmd.Close acForm, Me.Name
With Forms!FClientes
If .Casado.Value = True Then
.subFrmConfidencial.Form.FechaCas.Visible = True
End If
End With
Else
'Si no es correcta avisamos y salimos
MsgBox "Contrasea incorrecta", vbCritical, "ERROR"
Exit Sub
End If
Else
'Si la respuesta es no abrimos el formulario en modo usuario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
DoCmd.Close acForm, Me.Name
End If
End Sub

Este nuevo cdigo nos sirve para ver que un bloque WITH...END WITH no slo nos permite
hacer referencia abreviada a los controles, propiedades o mtodos de un objeto, sino que
adems podemos introducir bloques decisionales (en este caso un IF...END IF) para operar
segn nuestras condiciones.

16
Vistame en http://siliconproject.com.ar/neckkito/
Bueno... Ahora ya tenemos que nuestro formulario se nos abre perfectamente adaptado a si el
usuario es un simple usuario o si es el administrador. Pero claro, tenemos
ahora un pequeo e insignificante problema: la vista del form nos est diciendo
que es para dar de alta, aunque no sea as.

Vamos a hacer inventario de las incongruencias:

El el ttulo del formulario es ALTA CLIENTES


La etiqueta lblModoEntrada nos muestra AADIR
CLIENTE
Los botones cmdMuestraConfidencial y cmdOcultaConfidencial no tienen mucho sentido
en este modo de consulta.
Aunque no sea una incongruencia estricta, nos gustara que nuestro botn de cerrar el
formulario estuviera a la izquierda del encabezado (suponiendo que lo tengamos a la derecha).

Lo que tenemos que hacer es cambiar todo lo anterior para que se adapte a nuestros gustos.

Para ocultar los dos botones ya sabemos que debemos actuar sobre su propiedad VISIBLE.
Eso ya lo tenemos claro.

Para actuar sobre ttulos de formularios y controles debemos manipular una propiedad que
se denomina CAPTION. La estructura del cdigo es, simplemente: Me.Caption = Nombre que
queramos poner

Para manipular la posicin horizontal de un control debemos actuar sobre la propiedad LEFT
del control, y asignarle un valor numrico, medido en twips. Aprovecho para comentaros que si
lo que queremos manipular es la posicin vertical podemos actuar sobre la propiedad TOP.

Tras lo anterior, nuestro cdigo quedara de la siguiente manera:

Private Sub cmdConsultaClientes_Click()


Const pass As String = "a123"
Dim resp As Integer
Dim userPass As Variant
'Solicitamos el modo de consulta
resp = MsgBox("Consulta en modo administrador?", vbQuestion + vbYesNo, "TIPO
CONSULTA")
'Si la respuesta es s solicitamos el password
If resp = vbYes Then
userPass = InputBox("Contrasea?", "PASSWORD")
'Detectamos la pulsacin del botn cancelar
If StrPtr(userPass) = 0 Then Exit Sub
'Comprobamos que la contrasea sea correcta
If userPass = pass Then
'Si es correcta abrimos el formulario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
Forms!FClientes.subFrmConfidencial.Visible = True
DoCmd.Close acForm, Me.Name
With Forms!FClientes
If .Casado.Value = True Then
.subFrmConfidencial.Form.FechaCas.Visible = True
End If
End With
Else

17
Vistame en http://siliconproject.com.ar/neckkito/
'Si no es correcta avisamos y salimos
MsgBox "Contrasea incorrecta", vbCritical, "ERROR"
Exit Sub
End If
Else
'Si la respuesta es no abrimos el formulario en modo
usuario
DoCmd.OpenForm "FClientes", , , , acFormReadOnly
DoCmd.Close acForm, Me.Name
End If
'Manipulamos las propiedades de FClientes y sus
controles
With Forms!FClientes
.Caption = "CONSULTA CLIENTES"
.lblModoEntrada.Caption = "CONSULTAR CLIENTES"
.cmdMuestraConfidencial.Visible = False
.cmdOcultaConfidencial.Visible = False
.cmdCierra.Left = 10
End With
End Sub

PARA FINALIZAR ESTE CAPTULO...

Hemos visto cmo llamar a subformularios en un formulario, y cmo llamar tambin a los
controles del subformulario. Hemos visto cmo manipulamos propiedades de formulario, de
subformulario y de controles. Evidentemente no hemos visto todas las propiedades, pero s ya
sabemos cmo es la estructura del cdigo para poder jugar con ellas, por lo que no creo que
tenga mucho sentido machacar ms este punto.

Cierto es que algunos controles tienen unas propiedades especiales que ya veremos en
captulos posteriores, pero digamos que ya tenemos una gran base para saber qu hacer en
funcin de nuestras preferencias.

Adems, os recuerdo que siempre est la maravillosa tecla F1 que nos muestra ayuda sobre lo
que estamos buscando y, con un poco de suerte, nos proporciona un ejemplo para entenderlo
mejor.

A partir de ah os recomiendo que elijis una propiedad (de control o de formulario, o ambos) y
que probis por vosotros mismos si sois capaces de manipularla a travs de cdigo (ojo,
pequeas metas son ms efectivas y asequibles que metas gigantescas!).

Suerte!

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