En anteriores ocasiones ya he tratado el tema de la localización de aplicaciones en Xojo, enfocada en textos, fechas y números. Sin embargo, una gran parte de las consultas que recibo por parte de los recién llegados a Xojo tiene que ver con el modo correcto de formatear los números que deseamos incluir en controles como TextField o ListBox. A continuación veremos las opciones disponibles, y los matices de cada caso.
En muchos casos lo primero que necesitamos tener en cuenta es el tipo de dato que utilizaremos para trabajar con valores numéricos con parte decimal. Recuerda que si te interesa contar con la máxima precisión deberás de utilizar el tipo de dato Currency mediante el cual nos aseguramos una precisión de cuatro decimales sin los efectos de redondeo que se aplican en el caso de expresar el mismo valor como tipo de dato Double. Probablemente si vas a trabajar con datos numéricos correspondientes a moneda… querrás utilizar Currency.
Ahora bien, ¿cuál es el mejor modo de expresar posteriormente dicho valor numérico con el formato correcto? Si tienes pensado desplegar tu aplicación en varios países, entonces lo más aconsejable es utilizar el tipo Locale. Esta clase nos permitirá obtener y aplicar sin complicaciones el formato regional correcto que tenga defnido el usuario en su equipo a la hora de ejecutar la aplicación.
Así, el siguiente ejemplo mostrará el valor numérico de moneda correctamente en euros, empleando el punto como separador de miles y la coma como separador de decimales:
Dim moneda As Currency = 1000.2345
Dim t As Text = moneda.ToText(Xojo.Core.Locale.Current) // t = 1000,23 €
Como puedes observar, el problema en este caso es que si bien siempre nos va a tomar y aplicar correctamente el formato regional… perdemos dos decimales por el camino que no podremos recuperar posteriormente para guarar nuevamente el valor sobre una base de datos o bien a la hora de realizar cálculos. En cualquier caso, si con dos decimales (que no se ven modificados por redondeo) tenemos suficiente, este es el camino a seguir.
Posteriormente podemos aplicar la operación inversa, de modo que podamos asignar a una variable de tipo Currency el valor resultante de una cadena con formato regional aplicado:
Dim monedaConvertida As Currency = Currency.FromText(t,Xojo.Core.Locale.Current) // monedaConvertida = 1000.23
Lógicamente, en este caso la variable monedaConvertida
sólo cuenta con dos posiciones decimales.
Format, decide el formato a aplicar
A diferencia del anterior, el método Format nos va de perlas para indicar y personalizar en todo momento el formato del valor numérico convertido a texto, además de conservar cuanta precisión deseemos sobre el valor original. Eso sí, en este caso no contamos con el automatismo de que el formateado se ajuste sobre las preferencias regionales de cada país sobre el cual se esté ejecutando la aplicación.
Partiendo del mismo valor Currency empleado en el ejemplo anterior, utilizaremos la cadena de formato para conservar cuatro posiciones decimales sin incluir el símbolo de moneda (algo que no siempre necesitamos mostrar, probablemente):
Dim moneda As Currency = 1000.2345
Dim formateado As String = Format(moneda, "######,###.####") // formateado = 1.000,2345
CDbl, de texto a número… con formato internacional
¿Cómo podemos recuperar el valor numérico de una cadena de texto? Una opción sería mediante Val si bien el principal inconveniente es que dicho método trata el valor numérico de las cadenas de texto bajo notación inglesa (norteamericana, en concreto). Esto es un serio problema, dado que el punto, nuestro separador de miles, sería interpretado como separador decimal.
Para mantener en todo momento el sentido en la conversión desde el texto de nuevo a su representación numérica hemos de utilizar la versión del método que está especialmente preparada para tener en cuenta el uso de punto y coma realizado en cada país. Se trata de CDbl. Así, para recuperar nuevamente el mismo valor a partir de la cadena generada en el ejemplo anterior con Format utilizaremos:
Dim monedaConvertida As Currency = CDbl(formateado) // monedaConvertida = 1000.2345
Y en este caso, además, puedes observar como se mantiene en todo momento la máxima precisión del valor original; esto es, los cuatro decimales.
Formatear decimales, cuando faltan… y cuando sobran
Personalmente creo que la documentación proporcionada por Xojo para el método Format es suficiente para saber de qué modo podemos utilizar los caracteres especiales que indican el formato que se aplicará en la cadena resultante de la conversión. Sin embargo, continúan siendo muchos los casos en los que no sabemos cuando debemos aplicar la almohadilla (#) o bien el número cero (0) en la expresión de formato. De forma resumida:
- Utilizamos almohadilla (#) para indicar la posición que ocupará un dígito. Si la cifra a formatear no contiene una posición coincidente con la posición de la almohadilla, entonces no se imprimirá nada en la cadena formateada resultante y, lo que puede ser malo, se redondeará el valor.
- Utilizamos cero (0) para indicar la posición que rellenaremos con cero si la cifra a formatear no proporciona un dígito para dicha posición. Este es probablemente el caracter que desees utilizar a la hora de unificar todos los valores para que muestren la misma cantidad de posiciones decimales.
Para verlo en la práctica mediante un ejemplo concreto:
Dim cantidad As Double = 100.23 // El valor original tiene dos posiciones decimales
Dim otraCantidad As Double = 200.4 // El valor original tiene una posición decimal
Dim cantidadFormateada As String = Format(cantidad, "###,###.00") // La variable cantidadFormateada = 100,23
Dim cantidadFormateada As String = Format(otraCantidad, "###,###.00") // La variable otraCantidad = 200,40
Como puedes ver, en el segundo caso el valor numérico gana en uniformidad visual al añadir una segunda posición decimal que no tenía originalmente (el cero). Esto nos proporcionará listados visualmente más ordenados, por ejemplo o bien la uniformidad de la información mostrada en los diferentes controles.
En conclusión
Como puedes ver, Xojo nos proporciona una gran cantidad de métodos y tipos de datos en su Framework de modo que podamos mostrar y trabajar correctamente en todo momento con valores numéricos atendiendo a los diferentes formatos regionales, y también para unificar o mantener siempre la máxima precisión que necesitemos.
Hola Javier. Hace poco comenzé a probar Xojo y tu foro me ha sido de mucha utilidad. Sin embargo estoy “atrapado” en algo posiblemente trivial. Necesito rescatar la parte entera de un número con decimales. en Basic existe la función FIX, pero no la encuentro con ese nombre en Xojo. He tratado de “simular” la función con un método, pero no he podido por un comportamiento irregular de Xojo al buscar la coma decimal. Ojalá me puedas ayudar. Atte. Alejandro
Hola, tienes varias formas de hacerlo. La más trivial es asignando el número en coma flotante a una variable de tipo entero: la conversión es automática y se desprecia la parte decimal del valor. Si quieres “redondear” el número entero teniendo en cuenta los decimales, utiliza la función Round(), y si quieres hacer la aproximación hacia el próximo entero sin tener en cuenta la “proximidad inferior/superior” de la parte decimal, utiliza la función Ceil(). Por ejemplo:
Dim d As Double = 1.5634
Dim n As Integer = d
Dim n1 As Integer = Round(d)
Dim n2 As Integer = Ceil(d)
MsgBox n.ToText + EndOfLine + n1.ToText + EndOfLine + n2.ToText
Gracias Javier. Muy útil tu respuesta.