Hola a todos,
Una vez mas recurro al foro para encontrar respuestas...
He preparado una "mini calculadora" construida en un Formulario de Excel, a base de un TextBox y 16 Botones. El TextBox sirve para visualizar los numeros y los resultados que se introducesn desde cada uno de los botones, debidamente programados cada uno, para que se visualice el numero que representa cada boton o el resultado de las operaciones indicadas... Hasta aqui, todo esta bien. Sencillo y operativo. La he preparado para incluirla en una Hoja Excel tipo contabilidad y poder "llamar" a la calculadora en determinados momentos. Y me adelanto a explicar que la he preparado asi, porque la Calculadora de Windows que se puede invocar facilmente desde Excel, resulta de tamaño pequeño y no parece que se pueda ampliar su tamaño.
La prepgunta que planteo en el foro, es si hay alguna manera relativamente sencilla para que ademas de introducir el numero 1 por ejemplo, desde el boton correspondiente, se pueda introducir desde el teclado numerico. Y asi los demas numeros, como los signos de las operaciones matematicas de suma, resta, multiplicacion y división desde el teclado numerico, ademas, repito, de poder hacerlo desde cada uno de los botones puestos para ello.
La macro que asocio a cada uno de los botones es algo tan simple como esto:
En el boton llamado "1":
Private Sub CommandButton1_Click()
Me.TextBox1 = Me.TextBox1 & "1"
End Sub
En el boton "2":
Private Sub CommandButton2_Click()
Me.TextBox1 = Me.TextBox1 & "2"
End Sub
En el boton "+":
Private Sub CommandButton11_Click()
Me.TextBox1 = Me.TextBox11 & "+"
End Sub
Etc.
En la calculadora de Windows, esta entrada de datos puede hacerse indiferentemente desde los botones de la calculadora, o desde el teclado... La pregunta es : ¿Puede hacerse esto en este caso de una calculadora "artesanal" tan sencilla?
Saludos cordiales.
Jose Luis
Yo capturaría el evento keypress, keyup o keydown (dependiendo del tipo de funcionamiento que quieras.
Dentro de este evento, pon un SELECT CASE y permite únicamente ejecutarse las teclas equivalentes a los botones. En caso de que KeyCode sea 1, entonces lanza el evento que ya tienes programado para cuando pulsas el botón del 1, y así con todo.
Hay una salvedad: Esto solo funcionará cuando tengas activo el control sobre el que capturas el keypress. Lo que yo haría es lanzar el Focus al formulario siempre después de ejecutar cada código. De esta manera solo tendrás que capturar el keypress del form. De lo contrario, deberías capturar también el keypress de cada uno de los botones y del cuadro de texto.
Un saludo
Hola Cron:
Veloz como el rayo... en responder a mi pregunta... Muchas gracias.
Pero... me lo podrias aclarar un "pelin" porque tal como lo he leido, "como que me quedo "en babia""... "Yo capturaría el evento keypress, keyup o keydown (dependiendo del tipo de funcionamiento que quieras..."
Me lo puedes poner con unas lineas de codigo para que capte la idea y luego trabaje en ella?
Que quieres que te diga... no doy para mas...
Saludos cordiales.
Jose Luis Casla
Jaja, claro.
VBA funciona con código que responde a eventos. Es decir, cuando se da una circunstancia (por ejemplo que haces click en un botón, o que se crea un formulario), se dispara un evento, y se ejecuta el código que haya dentro de ese evento.
En nuestro caso, yo lo que haría es lo siguiente:
Encima de la ventana de código tienes dos desplegables. El de la izquierda te permite elegir entre todos los objetos que tienes en el formulario, incluyendo el propio formulario. El de la derecha te permite elegir los eventos que pueden ocurrirle al objeto que has seleccionado.
Yo seleccionaría el userform a la izquierda, y keypress a la derecha. Se te creará un inicio y final de una rutina (ya sabes, Sub..... End Sub)
Ahí dentro es donde pondría el código. Ten en cuenta que al lanzar el evento keypress, hay una variable que se llama KeyAscii, que te dice el código Ascii de la tecla que has pulsado. Eso es lo que tienes que evaluar para saber si se ha pulsado la tecla a la que quieres reaccionar.
Al hacer lo que te digo, quedará algo así como:
Private Sub CommandButton1_Click()
TextBox1.Text = TextBox1.Text & "1"
End Sub
Private Sub CommandButton2_Click()
TextBox1.Text = TextBox1.Text & "2"
End Sub
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case 49 ' pulsado el 1
CommandButton1_Click
Case 50 ' pulsado el 2
CommandButton2_Click
Case Else
End Select
KeyAscii = 0
TextBox1.SetFocus
End Sub
Genial amigo Cron,
Ahora "hasta yo lo he entendido"... ja ja...
Muchas gracias.
Es mas. Gracias a estas explicaciones tuyas, y de otros, de hoy y de otas ocasiones, voy quitandome, poco a poco ignorancia... Quien sabe, si al final voy a terminar sabiendo algo...
Bromas aparte, la solución me ha parecido clara y comprensible.
La voy a aplicar en cuanto me pueda poner con ello.
Cuidate mucho amigo Cron, por la cuenta que me tiene... ja.. ja..
Saludos cordiales.
Jose Luis
La alegria no dura demasiado... jaja..
En cuanto a la introducción de los numeros desde el teclado, todo funciona sin problemas.
El problema "nuevo" viene ahora.
Si introduzco desde el teclado, o desde los botones la cantidad 100 y a continuación le doy a la tecla de dividir, y despues al 2... al darle al boton de "=" al que he asignado lo siguiente:
Private Sub CommandBotton 16_Click()
UserForm1.TextBox1 = Application.Evaluate(UserForm1.TextBox1.Value)
End Sub
me muestra en el TextBox1 el resultado 50. (Correcto)
A continuacion intoduzco el signo de dividir de nuevo seguido del 2... al darle de nuevo al signo de igualdad, me muestra de nuevo el resultado 25 (correcto)
Repito el proceso, y me muestra 12,5 (correcto)
Pero ahora con ese decimal, al repetir el proceso, ya no lo ejecuta, sino que me da error.
He hecho la prueba de empezar introduciendo un numero con decimales, como por ejemplo 7,5 y tratar de dividirleo entre 2 y... da el mismo error.
Es decir, en resumen: Application.Evaluate(TextBox1.Value) funciona bien siempre que no haya decimales en el TextBox.
Una vez que hay un decimal, ya no divide, ni suma, ni resta, ni multiplica.
¿Donde esta la causa? Y si se puede solucionar?
Saludos cordiales.
Jose Luis
Prueba a poner este código en el botón "="
UserForm1.TextBox1 = Application.Evaluate(Replace(UserForm1.TextBox1.Value,",","."))
Probablemente lo que ocurre es algo muy habitual en Excel. Aunque trabaje "en español" de cara al usuario, por detrás trabaja "en inglés". Cuando se trabaja con funciones integradas, como en tu caso Application.Evaluate, VBA espera puntos decimales, fechas en formato mes/día/año y cosas así.
Prueba lo que te he comentado y nos dices!!
Un saludo
Hola Cron:
¡¡¡ Si era muy facil !!!
Efectivamente he sustituido la linea anterior por la tuya, y todo se ha resuelto...
Eres una enciclopedia... y ademas, "super-rapido"... :) :) :)
Muchas gracias.
Jose Luis
Hola Cron,
Antes de que te vayas a dormir "en los laureles" una "ultima cuestion"...
Asigne este codigo, siguiendo tus instrucciones, al evento KeyPress del TextBox1
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case 49
CommandButton1_Click
Case 50
CommandButton2_Click
Case 51
CommandButton3_Click
Case 52
CommandButton4_Click
Case 53
CommandButton5_Click
etc. etc.
Con todos los numeros y signos matematicos, funciona "de cine"... Donde no acierto es al tratar de añadir el Case <Return>... para que me haga lo mismo que me hace el boton "=" del formulario.
Empece poniendo;
Case 13
CommandButton16_Click (el boton del signo "=")
Al ejecutar la calculadora y despues de escribir una operacion cualquiera en el TextBBox, como por ejemplo; 12/3 y darle al <Return> se me va a los boton del "+" y no hace nada...
Como que el ascii del Return esta "reservado"...
Saludos cordiales.
Jose Luis
Lo que ocurre es que Keypress no se dispara con ciertas teclas (Enter, Tab, y algunas otras)
Prueba a capturar la tecla 13 en el evento Keydown. Algo así como:
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Then
'Aquí lo que quieres que haga cuando se pulsa Enter
KeyCode = 0
TextBox1.SetFocus
End If
End Sub
Deja KeyCode = 0 dentro del If, de manera que solo se anule en caso de que se pulse esta tecla. Si se pulsa cualquier otra, se lanzará el siguiente evento, Keypress, y ya gestionamos ahí las teclas que producen contenido en el Textbox.
Yo sugiero hacerlo así porque estamos acostumbrados a que las teclas respondan en el momento en que se lanza Keypress. Si todo lo ponemos en KeyDown, vamos a tener una incómoda sensación de que el ordenador escribe más rápido de lo que nosotros pulsamos las teclas.
Un saludo
Hola Cron:
Genial. Ahora reconoce la tecla <Enter> sin problemas.
Muchas gracias.
Ya me diras donde hay que enviar la caja de puros...
Y una cuestion menor: (ja... ja...)
Como le digo al TextBox que solamente presente 4 decimales...? porque tiene "mania" de presentar "la tira de decimales" que ni siquiera caben en el espacio que le he dado...
Seguro que hay uno de esos parametros de decirle algo asi como (format, "#,##0.00")... pero no se como ni donde meterlo.
Saludos cordiales.
Jose Luis
No fumo
Prueba con esto:
Me.TextBox1 = format(Me.TextBox1 & "1","0.00")
Pero yo lo pondría solamente en el botón de resultado de cálculo, porque si no interfiere con la introducción de los números.
Un saludo
Hola Cron:
Lastima... por lo de la caja de puros...
Funciona a la perfeccion.
Con Me.TextBox1 = format(Me.TextBox1 & "1","0.00") obviamente muestra dos decimales.
Con Me.TextBox1 = format(Me.TextBox1 & "1","0.0000") muestras 4 decimales... etc.
Muchas gracias por las lecciones.
No sabes bien lo que he aprendido con tus respuestas.
Ojala que les haya servido tambien de ayuda a otros que aunque sea, "por curiosidad" se hayan acercado a este tema.
Como te dije en otra oportunidad: da gusto tener "ignorancias" asi, por la satisfaccion de encontrar ayudas como la tuya, amigo Cron.
Saludos cordiales.
Jose Luis
Hola Cron,
No. No hay mayor problema. Tranquilo.
En la instruccion para dar formato al TextBox1:
Me.TextBox1 = format(Me.TextBox1 & "1", "0.00")
he tenido que suprimir '& "1"' y ahora me queda asi:
Me.TextBox1 = format(Me.TextBox1 , "0.00")
porque con el 1 me falseaba el resultado. En cada operacion, suma, resta multiplicacion o division el resultado era ilogico, sin conseguir encontrar la explicacion de por que salia ese resultado.
Al final, he suprimido esa parte de la instruccion, y ahora queda bien.
Te lo digo, porque seguro que al leer este mensaje, sabes por qué... ja, ja..
Pero insisto, en que ahora está trabajando la calculadora sin problemas.
Me parecia obligado enviar esta ultima informacion, despues de lo que has tenido que sudarlo...
Con mi agradecimiento, saludos cordiales.
Jose Luis
Genial, gracias
Hola Cron, hice una calculadora con reconocimiento de teclas, gracias a esta explicación pero no puedo colocarle el separador de miles a los resultados del textbox resultado, porque me arroja el error -2477352571(80020005) y me dice que no se puede configurar la propiedad value, me imagino que es por la siguiente línea de código UserForm1.Txt_resultado = Application.Evaluate(Replace(UserForm1.Txt_resultado.Value, ",", ".")), el cual está reemplazando la coma por el punto. Me podrías indicar si existe otra línea de código que pueda usarse en el evento keydown por la que pueda sustituir la línea anterior, y que me permita poner la coma como separador de miles?
Cuando hago eso no lo pongo mientras el usuario escribe (keydown, keypress o similar), sino al terminar de escribir. Por ejemplo, en el evento Exit o en BeforeUpdate/AfterUpdate.
Lo que sí controlo con keydown es sustituir el punto por coma para que se pueda utilizar el punto del teclado numérico.