En esta entrada, solo apta para "macreros", trataremos un tema que desvela a todos al momento de generar formularios, y la forma en que estos deben comportarse como capa entre "los dedos de nuestros usuarios" y los datos que debemos almacenar.
VBA nos proporciona dos eventos muy poderosos y fáciles de usar, los cuales nos permitirán restringir la entrada de datos en, por ejemplo, un cuadro de texto: KeyPress y KeyDown.
Imaginemos un escenario en donde requerimos que ingresen la edad o el número de documento de identidad: esos valores sí o sí tienen que ser numéricos ¿puedo anular todas las letras del teclado para evitar que algún caracter alfabético sea incorporado? Si, y con muy poco código.
0123456789
[+/-] Ver el resto / OcultarPara los que ya están familiarizados con la programación, sabrán que cualquier caracter alfanumérico es, para nuestro ordenador, un número. El signo arroba es el número 64, la "b" el 98, la \ (barra invertida) el 92 y así con todas. Pueden revisar este link para obtener información adicional.
Sigamos. KeyPress y KeyDown son eventos que se disparan cuando presionamos una tecla, y son capaces (siempre hablando en términos generales) de capturar el número de tecla presionado. Y si yo puedo saber que tecla se pulsó, seré capaz de analizarla y proceder en consecuencia, es decir, la autorizo o no. Así de simple y sencillo.
Empecemos con KeyPress: con este evento capturo las teclas "normales": una letra, un número o cualquier signo (cardinal, ampersand, barra invertida, guión, etc, etc, etc). Para ir con el primer ejemplo, agregamos un formulario a nuestro proyecto en VBA y colocamos un cuadro de texto. Hacemos doble click sobre él para acceder a su ventana de código y, desde el combobox superior derecho, elegimos dicho evento:
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
End Sub
Dentro de este evento colocaremos el código que nos permitirá aceptar un determinado caracter, o no.
Existen muchas formas de hacerlo, pero les mostraré una fácil y que funciona a la perfección:
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If InStr(1, "0123456789", Chr(KeyAscii)) = 0 Then
'si el Chr(KeyAscii) no está dentro del segundo argumento, anulo a KeyAscii
'poniéndola en 0. Esta acción anula la tecla presionada
'si el Chr(KeyAscii) no está dentro del segundo argumento, anulo a KeyAscii
'poniéndola en 0. Esta acción anula la tecla presionada
KeyAscii = 0
End If
End Sub
¿Como funciona? El Sub KeyPress recibe una variable como argumento, llamada KeyAscii, la cual trae almacenado el número Ascii de la tecla presionada. Utilizo a Instr(posicion inicial, cadena, valor buscado) para determinar si el caracter (chr) de Ascii está dentro de "cadena". Un poco de lío, pero es fácil.
Veamos: el segundo argumento de InStr() es una cadena con números, del 0 al 9, es decir, solo aquellos caracteres que permito ingresar. El tercer argumento es KeyAscii, o sea que con el me llega que número de caracter se presionó. Imaginemos que nuestro usuario tocó la "A" (a mayúscula). Entonces, en KeyAscii me viene almacenado el número 65. Tomo ese 65 y lo convierto a caracter, con la función Chr().
Entonces: ya tengo que valores permito (del 0 al 9) y el caracter que presionó el usuario. Luego, con InStr() me fijo si "A" está dentro de "0123456789". Si esa función me devuelve 0.... listo, "A" no está permitida y pongo a KeyAscii en 0, para que anule el ingreso.
Supongamos que, ademas de esos números, solo permito el ingreso de otros caracteres. Entonces lo único que queda es incorporarlos en el segundo argumento de InStr():
Entonces: ya tengo que valores permito (del 0 al 9) y el caracter que presionó el usuario. Luego, con InStr() me fijo si "A" está dentro de "0123456789". Si esa función me devuelve 0.... listo, "A" no está permitida y pongo a KeyAscii en 0, para que anule el ingreso.
Supongamos que, ademas de esos números, solo permito el ingreso de otros caracteres. Entonces lo único que queda es incorporarlos en el segundo argumento de InStr():
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If InStr(1, "0123456789#$%&/", Chr(KeyAscii)) = 0 Then
KeyAscii = 0
End If
End Sub
En el Sub de arriba observarán que ahora, al margen de los números, también dejo ingresar los símbolos #$%&/.
Para hacer lo mismo (sólo con número) pero sin utilizar a InStr() sería esta forma:
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii < 48 Or KeyAscii > 57 Then
KeyAscii = 0
End If
End Sub
Es decir: si KeyAscii (o sea el nro del caracter presionado) es menor a 48 (cero) o mayor a 57 (el 9), entonces pongo a KeyAscii a 0 (cero) y listo, solo pasan los números. Es, definitivamente, mas sencillo que el primer ejemplo, pero mas limitado, ya que para incorporar otras excepciones deberíamos recurrir a muchos If... else... anidados.
Es cuestión de un poco de práctica. Incorporen un Form junto a un TextBox, copien y peguen el código de ejemplo y efectúen el "paso a paso", marcando un punto de interrupción y presionando F8.
Ahora vamos con el evento KeyDown. Es casi lo mismo a KeyPress, pero tiene una gran diferencia: con él podremos saber que "tecla especial" presionaron. Llamo "tecla especial" a: enter (return), borrar (delete), F1 al F12, control, etc, etc, etc. En pocas palabras: todas las teclas que no son letras ni números.
Imaginemos que ponemos un ComboBox para que el usuario selecciones cualquiera de los 12 meses del año.
El mes seleccionado, para evitar ambivalencias en nuestra base de datos, será directamente imputado a un campo, desde ese ComboBox. Ahora bien ¿que pasaría si nuestro usuario (sin querer, para no ser malpensados) borra un par de letras del mes? La respuesta es mas que obvia: mandaríamos cualquier cosa a la tabla, menos el mes correcto. ¿Como anulo la posibilidad de que mis usuarios puedan borrar los datos que están dentro del ComboBox? Exacto, con KeyDown:
Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
'podemos usar cualquier estructura de control, como Select Case:
Select Case KeyCode
Case Is = vbKeyDown
KeyCode = vbKeyDown
Case Is = vbKeyUp
KeyCode = vbKeyUp
Case Is = vbKeyReturn
KeyCode = vbKeyReturn
Case Is = vbKeyTab
KeyCode = vbKeyTab
Case Else
KeyCode = 0
End Select
End Sub
Analicemos: mediante KeyCode recibo el código de la tecla presionada. Si es KeyDown (flecha abajo) lo permito, al igual que la flecha arriba (KeyUp), enter (return) o el tabulador (tab). Cualquier otra tecla presionada la vuelvo a 0 (cero), anulándola en el acto. O sea: si presiona KeyDelete (borrar o delete) o la barra espaciadora, esta acción no tendrá ningún y mi usuario no podrá borrar o modificar ningún item del ComboBox. Aclaración: habrán notado que permití las flechas de desplazamiento, enter y tabulador... por el simple echo de que hablamos de un ComboBox y si las anulo.... no tendrán forma de desplazarse por los items o que el foco cambie a otro control del formulario.
Pero no solamente podemos "restringrir", si no también ampliar las funcionalidades de los controles. Si tenemos un ListBox, sería factible eliminar un item al presionar Suprimir (delete) sobre él:
Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
'si presiona Delete (suprimir), entonces borro un item del ListBox:
If KeyCode = vbKeyDelete Then
ListBox1.RemoveItem (ListBox1.ListIndex)
End If
End Sub
O bien podríamos llamar a algún formulario de ayuda, al presionar F1 sobre algún control, y así emular las funcionalidades del propio Windows:
Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = vbKeyF1 Then
frmAyuda.Show
End If
End Sub
Las posibilidades son infinitas y totalmente adaptables a cada proyecto. No lo mencioné antes para no confundir, pero ahora que el tema está mas claro, les comento que con KeyDown también es factible controlar las "teclas comunes", de la siguiente forma:
vbKeyA = A maýuscula
vbKey0 = número 0
vbKey1 = número 1
vbKeyG = G mayúscula
.... y así sucesivamente.
Les muestro un truco: escriban en la ventana de código esto: vbkey y luego (sin mover el cursor) presionen "control + j" (jota). Aparecerá una lista desplegable con todas las opciones disponibles:
Otro evento para que analicen: KeyUp, que se produce cuando el usuario "levanta" la tecla presionada. Funciona de la misma forma, pero su utilización dependerá de nuestras necesidades.
Bueno estimados, fin de la entrada. Ya tenemos otra forma de controlar el ingreso de datos en los proyectos de VBA que diseñemos.
Un abrazo y me veo obligado, nuevamente, a agradecer infinitamente todos los mensajes que recibo en mi correo electrónico, los cuales poseen gran valor para mí.
Imaginemos que ponemos un ComboBox para que el usuario selecciones cualquiera de los 12 meses del año.
Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
'podemos usar cualquier estructura de control, como Select Case:
Select Case KeyCode
Case Is = vbKeyDown
KeyCode = vbKeyDown
Case Is = vbKeyUp
KeyCode = vbKeyUp
Case Is = vbKeyReturn
KeyCode = vbKeyReturn
Case Is = vbKeyTab
KeyCode = vbKeyTab
Case Else
KeyCode = 0
End Select
End Sub
Analicemos: mediante KeyCode recibo el código de la tecla presionada. Si es KeyDown (flecha abajo) lo permito, al igual que la flecha arriba (KeyUp), enter (return) o el tabulador (tab). Cualquier otra tecla presionada la vuelvo a 0 (cero), anulándola en el acto. O sea: si presiona KeyDelete (borrar o delete) o la barra espaciadora, esta acción no tendrá ningún y mi usuario no podrá borrar o modificar ningún item del ComboBox. Aclaración: habrán notado que permití las flechas de desplazamiento, enter y tabulador... por el simple echo de que hablamos de un ComboBox y si las anulo.... no tendrán forma de desplazarse por los items o que el foco cambie a otro control del formulario.
Pero no solamente podemos "restringrir", si no también ampliar las funcionalidades de los controles. Si tenemos un ListBox, sería factible eliminar un item al presionar Suprimir (delete) sobre él:
Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
'si presiona Delete (suprimir), entonces borro un item del ListBox:
If KeyCode = vbKeyDelete Then
ListBox1.RemoveItem (ListBox1.ListIndex)
End If
End Sub
O bien podríamos llamar a algún formulario de ayuda, al presionar F1 sobre algún control, y así emular las funcionalidades del propio Windows:
Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = vbKeyF1 Then
frmAyuda.Show
End If
End Sub
Las posibilidades son infinitas y totalmente adaptables a cada proyecto. No lo mencioné antes para no confundir, pero ahora que el tema está mas claro, les comento que con KeyDown también es factible controlar las "teclas comunes", de la siguiente forma:
vbKeyA = A maýuscula
vbKey0 = número 0
vbKey1 = número 1
vbKeyG = G mayúscula
.... y así sucesivamente.
Les muestro un truco: escriban en la ventana de código esto: vbkey y luego (sin mover el cursor) presionen "control + j" (jota). Aparecerá una lista desplegable con todas las opciones disponibles:
aquí pueden visualizar la lista que les mencionaba, que aparecerá luego de presionar " ctrol + J "
Otro evento para que analicen: KeyUp, que se produce cuando el usuario "levanta" la tecla presionada. Funciona de la misma forma, pero su utilización dependerá de nuestras necesidades.
Bueno estimados, fin de la entrada. Ya tenemos otra forma de controlar el ingreso de datos en los proyectos de VBA que diseñemos.
Un abrazo y me veo obligado, nuevamente, a agradecer infinitamente todos los mensajes que recibo en mi correo electrónico, los cuales poseen gran valor para mí.
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Etiquetas
Macros
Etiquetas:
Macros
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Comentarios
Publicar un comentario