Espero todos esten bien! Mi consulta de hoy es: Hay alguna manera de
personalizar la forma en que los usuarios ingresen datos en un TextBox?
Lo que busco exactamente es lo siguiente: en un Userform yo tengo un TextBox
en el cuál hay que ingresar un dato manualmente que es una fecha. De la
manera como está ahora los usuarios, si por ejemplo deben ingresar 22/06/07,
deben ingresar cada uno de los caracteres (incluyendo las barras "/"). La
cuestión es que esto puede dar lugar a errores, como que los usuarios tipeen
2206/07 (salteando una barra, por ejemplo) o 22/06 (olvidando ingresar el
año), o 22/06/077 (ingresando un 7 de más), etc, etc. Lo que yo necesitaria
es algo así como una "máscara de entrada" (del tipo que hay en access) de
modo que los usuarios tengan en el TextBox predefinido el formato _ _ / _ _
/ _ _ del cual no puedan apartarse. De esta manera obligaría a los usuarios
a ingresar los datos de una manera standarizada, en la cual no hayan ni
olvidos ni agregados en el dato, y evito todos los trastornos que puedan
generar en las operaciones los errores de ingreso.
Espero haberme explicado correctamente.
Saludos y desde ya muchas gracias!!
Mariano
--
CONTADURIA
> ... alguna manera de personalizar la forma en que los usuarios ingresen datos en un TextBox?
> ... en un Userform... un TextBox... ingresar un dato... fecha...
> ... algo asi como una "mascara de entrada" (del tipo que hay en access) [...]
toma en cuenta que un control textbox [por su misma caracteristica] 'acepta' datos de todo tipo...
suponiendo que diferentes usuarios pudieran tener diferentes *costumbres* en el orden de fechas...
y considerando que NO es 'el fuerte' de excel... andar 'enmascarando' las entradas del usuario...
op1: inserta a tu formulario un control DTPicker o un control Calendar
op2: utilza TRES controles textbox para usarlos segun el orden de fechas que vayas a controlas [dd/mm/aa <-> mm/dd/aa]
si cualquier duda... comentas ?
saludos,
hector.
p.d. el control DTPicker requiere que esta instalado y registrado...
-> el componente [+/- C:\Windows\System[32]\mscomct2.ocx]...
el control calendar requiere que este instalado y registrado...
-> el componente [C:\Archivos de programa\Microsoft Office x.0\Officexx\MSCal.ocx]
disculpad que me meta, pero estaba liadillo preparando esta respuesta y hasta que no la he tenido acabada (+/-) no he
visto la de hector, que posiblemente lo dice (casi)todo sobre el `marron' que puede llegar a suponer la conjuncion
fechas/controles vba (al menos en lo que a mi experiencia se refiere)
pero, bueno ya que esta hecho, y aprovechando que hector podria comentarnos posibles inconvenientes en el uso ( que
seguro existen, sobre todo con determinadas teclas) de estos codigos, y ademas puede darle alguna idea a Mariano, aqui
la mando
Nota: aunque normalmente, por lo que he visto, la validacion numerica suele hacerse en keypress o quizas en keydown,
aqui he hecho una especie de conglomerado que al menos y sin demasiadas pruebas parece funcionar relativamente bien
' modulo del formulario:
'
Dim Borrar As Boolean
'
'en el mismo modulo del form (la funcion, si prefieres tenerla disponible para otros formularios de la aplicacion puedes
ponerla en uno normal como public)
Function Mascara_Fecha(ByRef TextB As MSForms.TextBox, _
ByRef b_Borrar As Boolean)
Dim n As Byte, nl As Byte, lt As String
With TextB
If .Text = "" Then b_Borrar = False: Exit Function
nl = Len(.Text): lt = Mid(.Text, nl, 1)
Select Case nl
Case Is = 1
If Not IsNumeric(lt) Or Val(lt) > 3 Then .Text = ""
Case Is = 2
If Not IsNumeric(lt) Or Val(.Text) > 31 Or _
Val(.Text) < 1 Then
.Text = Left(.Text, nl - 1)
Else
.Text = .Text & "/"
End If
Case Is = 3
If b_Borrar Then .Text = Left(.Text, 1)
Case Is = 4
If Not IsNumeric(lt) Or _
Val(lt) > 1 Then .Text = Left(.Text, nl - 1)
Case Is = 5
If Not IsNumeric(lt) Or _
Val(Mid(.Text, nl - 1, 1) & lt) > 12 Or _
Val(Mid(.Text, nl - 1, 1) & lt) < 1 Then
.Text = Left(.Text, nl - 1)
Else
.Text = .Text & "/"
End If
Case Is = 6
If b_Borrar Then .Text = Left(.Text, 4)
Case Is > 8
.Text = Left(.Text, 8)
Case Else
End Select
End With
b_Borrar = False
End Function
' ejemplo de uso (es importante el codigo de KeyDown)
Private Sub TextBox1_Change()
Mascara_Fecha TextBox1, Borrar
End Sub
' para permitir el borrado con la tecla retroceso sin interferencias (seguramente convendria controlar alguna tecla
mas)
'
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
If KeyCode = vbKeyBack Then Borrar = True
End Sub
bueno, como dice Hector creo que hay otras soluciones mucho mejores, pero para practicar no esta mal
un saludo
Ivan
siguiendo con el 'entretenimiento' y ya de paso aprovechando para consultarle una 'curiosidad' a Hector Miguel, esta
otra incluiria una validacion para los bisiestos (por cierto se me olvido comentar que esta hecha para el formato y
configuracion regional 'dd/mm/aa'). La consulta la pongo al final
Function Mascara_Fecha(ByRef TextB As MSForms.TextBox, _
ByRef b_Borrar As Boolean)
Dim n As Byte, nl As Byte, lt As String, max As Byte
With TextB
If .Text = "" Then b_Borrar = False: Exit Function
nl = Len(.Text): lt = Mid(.Text, nl, 1)
Select Case nl
Case Is = 1
If Not IsNumeric(lt) Or Val(lt) > 3 Then .Text = ""
Case Is = 2, Is = 5
If nl = 2 Then max = 31 Else max = 12
If Not IsNumeric(lt) Or _
Val(Mid(.Text, nl - 1, 1) & lt) > max Or _
Val(Mid(.Text, nl - 1, 1) & lt) < 1 Then
.Text = Left(.Text, nl - 1)
Else
If nl = 5 And Not IsDate(.Text & "/00") Then _
.Text = Left(.Text, nl - 1) Else _
.Text = .Text & "/"
End If
Case Is = 3, Is = 6
If b_Borrar Then .Text = Left(.Text, nl - 2)
Case Is = 4
If Not IsNumeric(lt) Or _
Val(lt) > 1 Then .Text = Left(.Text, nl - 1)
Case Is = 8
If Left(.Text, 2) = "29" And Mid(.Text, 4, 2) = "02" And _
Val(Right(.Text, 2)) Mod 4 > 0 Then .Text = Left(.Text, nl - 1)
Case Is > 8
.Text = Left(.Text, 8)
Case Else
End Select
End With
b_Borrar = False
End Function
bueno, aunque se que el tema de las fechas da para rato, y ya (me) has dado unas cuantas explicaciones por el foro, aqui
va la consulta:
en la validacion del Case Is = 8 creia que esto me valdria para validar los bisiestos
If Not IsDate(.Text) Then .Text = Left(.Text, nl - 1)
y sin embargo, solo parece funcionar hasta el 99, a partir del '00' admite cualquier numero . Probando en la ventana
inmediato he visto que por ej. devuelve esto
?cdate("29/02/01")
01/02/2029
quiere esto decir que si existe una posibilidad de 'escape' para evitar el error cdate busca tira de otra configuracion
aunque no sea la regional ni la del propi vba, y no genera error?? eso es lo que me da la impresion, pero me parece
curioso
bueno, sobre todo es eso, una curiosidad mas, pero ya sabes ...
un saludo y hasta pronto
Ivan
habria que cambiar elfinal del select case, pues para el 7 y el 8 no habia restringido la entrada a numeros. Habria que
cambiar desde el Case is=8 (incluido hasta el final del select por esto=
Case Is = 8
If Not IsNumeric(lt) Or (Left(.Text, 2) = "29" And Mid(.Text, 4, 2) = "02" And _
Val(Right(.Text, 2)) Mod 4 > 0) Then _
.Text = Left(.Text, 7)
Case Is > 8
.Text = Left(.Text, 8)
Case Else
If Not IsNumeric(lt) Then .Text = Left(.Text, nl - 1)
End Select
creo que asi ya quedaan cubiertas casi todas las posibilidades, a falta de problemas con teclado y a saber ....
un saludo
Ivan
1) comentarte que la *enmascarada* que le has dado a los textboxes me parece *genial*
[y como ya lo comentas] el unico inconveniente es que queda circunscrita para un orden de fechas dd/mm/aa
2) con relacion al comportamiento que describes de la funcion CDate(...) [y hasta donde se]...
a) sirve para convertir/verificar/validar datos-fecha *basada* en la configuracion regional del sistema
b) me atrae la atencion el ejemplo que expones de la ventana de inmediato: ?cdate("29/02/01") -> 01/02/2029
-> da la impresion de que en TU configuracion regional, el formato de fecha *corta* incluye 4 digitos para el a#o -?-
c) cuando CDate encuentra *conflictos*... que puede resolver... los resuelve *como Dios le de a entender* :))
lo que incluye invertir el orden de fecha *corta* mm/dd/aa <-> dd/mm/aa <-> aa/mm/dd
si NO los puede resolver... [simplemente] devuelve un error 13 "el tipo no coincide" [con alguna fecha *valida* para CDate] :-(
d) por ejemplo, en 'mi' caso, con una configuracion de fecha *corta* con el orden d/m/aa esto es lo que obtengo [inmediato]
? cdate("29/02/01") -> 2/1/29 <= OJO: cambio de: dd/mm/aa a: -> m/d/aa
? format(cdate("29/02/01"),"mm/dd/yyyy") -> 01/02/2029
? cdate("02/29/01") -> error 13 [no existe la fecha feb/29/2001]
2) fechas en excel y vba ???... [como ya lo expones, *da para rato*]...
como que hay que pensar en lo que *conlleve* las menores complicaciones posibles :))
es conveniente visitar la siguiente exposicion de manejos de fechas [de Stephen Bullen]:
-> http://www.bmsltd.ie/ExcelProgRef/Ch22/default.htm
[nota: aunque ya le debes conocer... es probable que le sirva tambien a OP] :))
saludos,
hector.
__ la consulta original __
> bueno, aunque se que el tema de las fechas da para rato, y ya (me) has dado unas cuantas explicaciones por el foro
> aqui va la consulta:
>
> en la validacion del Case Is = 8 creia que esto me valdria para validar los bisiestos
>
> If Not IsDate(.Text) Then .Text = Left(.Text, nl - 1)
>
> y sin embargo, solo parece funcionar hasta el 99, a partir del '00' admite cualquier numero.
> Probando en la ventana inmediato he visto que por ej. devuelve esto
>
> ?cdate("29/02/01")
> 01/02/2029
>
> quiere esto decir que si existe una posibilidad de 'escape' para evitar el error
> cdate busca tira de otra configuracion aunque no sea la regional ni la del propi vba, y no genera error?
muchas gracias de nuevo, tanto por tu ayuda como por este comentario
=>
>> que la *enmascarada* que le has dado a los textboxes me parece *genial*
aunque ten por seguro que si (realmente) tiene algo de genial la mayor
parte de la culpa es tuya (y no es falsa modestia). Aun asi no deja de
'ayudar' viniendo de tu parte.
>> b) me atrae la atencion el ejemplo que expones de la ventana de inmediato: ?cdate("29/02/01") -> 01/02/2029
tienes razon. Estoy harto de verlo y ni siquiera se me habia ocurrido
fijarme
>> c) cuando CDate encuentra *conflictos*... que puede resolver... los resuelve *como Dios le de a entender* :))
eso me parecia, con lo que, si no se quieren correr riesgos lo mas
seguro debe ser la opcion del DTPicker que mencionas
>> 2) fechas en excel y vba ???... [como ya lo expones, *da para rato*]...
tan es asi que supongo que, aun revisando el enlace, por estos lares,
'volveremos' a molestarte mas de una vez con el tema
>> [nota: aunque ya le debes conocer... es probable que le sirva tambien a OP] :))
estoy convencido de que 'OP' tambien le sacara partido, tanto al
enlace como al hilo. Ya nos comentara
bueno, lo dicho, muchas gracias de nuevo y hasta pronto
Ivan
Saludos,
Feliciano.
--------------------------------------------------------------------------------
"Ivan" <lom...@teleline.es> escribió en el mensaje
news:1182959642.0...@c77g2000hse.googlegroups.com...
hola Feliciano,
como parece que no lo recuerdas, te pego un trozo de la conversacion
en la que yo me entere de lo que era OP (para que eches un ojo)
---------------------------------------------------------------------
----------------------------------------------------------------------
Hola Hector
: > [ahora que lo mencionas]... debo asumir que OP [probablemente]
esta
> utilizando macros o algun otro 'mecanismo' -?-
> [definitivamente] OP necesita ofrecer detalles mas...
'significativos' > :D
Disculpa mi ignorancia. ¿Que es OP?. ¿Operacion de Pegado?.
Saludos,
Feliciano.
--------------------------------------------------------------------------------
hola, Feliciano !
> ... Que es OP?. Operacion de Pegado?.
es un termino adoptado en las comunidades entre usuarios desde UseNet
significa: Original Post(er) [la consulta original o quien hizo la
consulta original/inicial] :))
saludos,
hector.
------------------------------------------------------------------------------------
Hola Hector :
Muchas gracias por la información.
Saludos,
Feliciano.
----------------------------------------------------------------------------------
------------------------------------------------------------------------------------
en cualquier caso estoy de acuerdo en que posiblemente lo mejor sea
usar controles especificos para las fechas
un saludo
Ivan
Saludos,
Feliciano.
--------------------------------------------------------------------------------
"Ivan" <lom...@teleline.es> escribió en el mensaje
news:1182975690.9...@n60g2000hse.googlegroups.com...
Muchas gracias por todas las respuestas! La verdad que me sorprendió ver
todo el "hilo"que se generó por mi pregunta! Pero justamente esto es lo
positivo del foro.
En fin, les cuento como me fue con sus propuestas.
De las 2 opciones que me menciona Hector Miguel, la primera (DTPicker o un
control Calendar) no tengo idea como es ni como incorporarlo. Tampoco parece
que tenga el archivo ese que menciona instalado en todas las maquinas, lo
cual puede ser un problema para los usuarios.
La segunda opción (usar 3 Textbox) la experimenté con éxito, ya que esta más
al alcanze de mis conocimientos.
Después probé varias veces el enmascarador de Ivan, pero lamentablemente
presione la tecla que presione siempre me tira el mismo error "El tipo de
argumento de ByRef no coincide". Intente ver si podía ver cual podía ser el
error en el código y descubri que había olvidado poner la línea "Dim Borrar
As Boolean". Ahora anda perfectamente (hasta donde lo he probado). Es
genial!!
También hoy aprendí el siginificado del termino OP!
Bueno, les estoy infinitamente agradecido por todo.
Muchas gracias y saludos!!
Mariano
"Héctor Miguel" <NOhemio...@PLShotmail.com> escribió en el mensaje
news:#qOJnhEu...@TK2MSFTNGP04.phx.gbl...