Números, decimales y millares

Pregunta Sin Miedo no te cortes cualquier cosa para empezar - Autoit se comienza facilmente.Para Ordenes o Comandos sueltos. Ver nota como preguntar.
Responder
jamaro
Hacker del Foro
Mensajes: 253
Registrado: 03 Nov 2010, 23:04

Números, decimales y millares

Mensaje por jamaro »

Hola de nuevo:

Vuelvo con una pregunta, después de haber buscado en el foro y la ayuda de Autoit sobre cadenas (strings) y números.

Tengo varios programitas en los que tengo algunos datos numéricos con decimales. En los input del formulario introduzco los números normalmente con el teclado numérico, saliendo de la siguiente manera: "12345.67"
Con esos números opero y no hay problema, pero luego, el resultado que obtengo, en ocasiones lo deseo con el formato que utilizamos aquí, punto para separar millares y coma para separar decimales. Trabajando con el resultado y con las cadenas, convierto el número "12345.67" a "12345,67" (todavía no me he puesto a pelear con los millares, pero con la coma tengo suficiente, de momento).

La razón de este mensaje es saber si existe alguna manera de:
1º Configurar un control input (o el teclado) para que al introducir un número con decimales desde el teclado numérico se utilice "," en lugar de "."
2º Operar con números que se hayan escrito con "," en lugar de "."
3º En algunos programas (no de Autoit) tienen una opción en su configuración para indicarles cuál será el separador de decimales que se utilizará. ¿Hay alguna manera de hacerlo en Autoit?

Agradezco vuestra ayuda y sigo buscando soluciones por la red.
Avatar de Usuario
adrmil
Mensajes: 4
Registrado: 09 Dic 2010, 08:00

Re: Números, decimales y millares

Mensaje por adrmil »

y si remplazas , por . usando

Código: Seleccionar todo

StringReplace("h o l a ", " ", "-")
? :smt019
jamaro
Hacker del Foro
Mensajes: 253
Registrado: 03 Nov 2010, 23:04

Re: Números, decimales y millares

Mensaje por jamaro »

adrmil escribió:y si remplazas , por . usando

Código: Seleccionar todo

StringReplace("h o l a ", " ", "-")
? :smt019
Hola adrmil:
Seguramente no me expliqué bien. Lo que comentas ya lo hago con los resultados de las casillas que tengo con punto como separador de decimales, pero lo que pregunto en el mensaje anterior es si existe posibilidad de que al introducir los datos, cuando pulso 'punto' en el teclado numérico, realmente salga una 'coma'. Y además, si es posible en Autoit operar con números con los decimales separados por 'coma'.

Se da el caso también, de que tengo datos en una base de SQLite, cuyos números tienen decimales separados por 'coma'. De momento, salvo que exista otra manera, lo que debo hacer es convertir la 'coma' a 'punto' para poder operar con ellos.

En definitiva, las cuestiones que hago, son sobre la posibilidad de configurar un programa de Autoit para que los números tengan el formato de aquí (decimales con 'coma', y millares con 'punto').

Un saludo y gracias

EDITO: Adjunto código obtenido del foro en inglés, al que he hecho unas pequeñas modificaciones para indicar distintos separadores de millares, decimales e indicar el número de decimales que se desea. De todos modos, mis preguntas son otras y siguen en el aire ;-)
Enlace al foro inglés: http://www.autoitscript.com/forum/topic ... rmat-udfs/

Código: Seleccionar todo

;example
$oldnum=8555425 + 100 + 900.50 + 3.1415
$Price = _StringFormatPict($oldnum,"€ ",".",",",5)
MsgBox(64,"",$price)
$Price = _StringFormatPict($oldnum)
MsgBox(64,"",$price)

#include-once

;==============================================================================
; ToDo: Decimal test, search for & strip AlphaChars,
;       syntax like @J$ 999.99
;
; Function Name:    _StringFormatPict()
; Description:      Formats a numeric string or number to a given picture using
;                   user specified precision, width, thousands separators, and
;                   prefixes ($ sign, etc)
;
; Syntax:           _StringFormatPict($string, $prefix, $kSep)
;					* _stringFormatPict($string, $prefix="", $kSep=".", $dSep=",", $ndecimales=2)
;
; Parameter(s):     $string     = string or number to format
;                   $prefix     = leading character to insert
;                   $kSep       = thousands separartor
;                                 (ie: "," for 1,000.00 vs. 1000.00)
;					* $dSep		= Separador de decimales				
;					* $ndecimales	= Cifras decimales
;
; Requirement(s):   None
;
; Return Value(s):  On Success - Returns the string formatted as specified
;                   On Failure - -1  and sets @ERROR = 1
;
; Author(s):        ResNullius
; * Modificaciones:	jamaro
;===============================================================================
;
Func _stringFormatPict($string, $prefix="", $kSep=".", $dSep=",", $ndecimales=2)

  local $pict = ""
  ;$string = String(StringFormat("%.2f",$String))
  $string = String(StringFormat("%." & $ndecimales & "f",$String))
  $pict = StringSplit($string,".")

  $int = $pict[1]
  $count=0

  If StringLen($int) = 3 OR (StringLen($int) = 4 AND StringLeft($int,1) == "-" ) then
    $int = $int

  Else
    For $i = 1 to StringFormat("%d",(StringLen($pict[1])-1)/3)
      $int = StringReplace($int,StringRight($int,3*$i+$count),$kSep & StringRight($int,3*$i+$count))
      $count += 1
    Next
  EndIf
  $int = $prefix & $int
  ;$pict = $int & "," & $pict[2] ; Decimales
  $pict = $int & $dSep & $pict[2] ; Decimales

  return $pict

Endfunc
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Números, decimales y millares

Mensaje por Chefito »

Lo de cambiar la una tecla al ser pulsada se debe hacer con hook (ganchos) al teclado. Es algo complicado, pero por fortuna en el foro ya tenemos varios códigos hecho de esto. El funcionamiento es que al detectar que el input tiene el foco, mira si as pulsado la tecla punto ( . ) del teclado numérico. Si la pulsas, envía una coma al input y anula el envío del punto.

Código: Seleccionar todo

#include <Misc.au3>
#include <GUIConstantsEx.au3>

OnAutoItExitRegister("OnAutoItExit")   ;si te da error esta línea, es porque tienes una versión anterior de AutoIt. Coméntala y el script funcionará sin problemas.
Global $codigo=0
Global $dll = DllOpen("user32.dll")
Global Const $WH_KEYBOARD_LL = 13
Global $hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
Global $hmod = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
Global $hHook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", _
      $WH_KEYBOARD_LL, "ptr", DllCallbackGetPtr($hStub_KeyProc), "hwnd", $hmod[0], "dword", 0)
Global $gui=GUICreate("My GUI Button")
$input = GUICtrlCreateInput("", 10, 100, 300, 20)
$Button = GUICtrlCreateButton("Boton", 10, 30, 100)

GUISetState()
While 1
   Sleep(10)
        $msg = GUIGetMsg()
        Select
            Case $msg = $GUI_EVENT_CLOSE
                ExitLoop
        EndSelect
WEnd

Func _KeyProc($nCode, $wParam, $lParam)
    Local $ret, $KEYHOOKSTRUCT, $posmouse
      If ControlGetFocus($gui)="Edit1" Then   ;Entra en la condición si el foco lo tiene el control input (clase Edit1).

         If $wParam = 256 Then   ;cuando pulsas, o mantienes pulsada una tecla, entra en este bloque.
            $KEYHOOKSTRUCT = DllStructCreate("dword;dword;dword;dword;ptr", $lParam)
            $codigo=DllStructGetData($KEYHOOKSTRUCT, 1)
;~             ;ConsoleWrite($codigo & @CRLF)   ;<<<<<=== aquí te dice el código de tecla que pulsas. Esto solamente es informativo. Quitalo.
;~             ConsoleWrite("El codigo de la tecla que has pulsado es " & $codigo & "  puede que sea la tecla " & chr($codigo) &@CRLF)   ;<<<<<=== aquí te dice el código de tecla que pulsas. Esto solamente es informativo. Quitalo.
            If $codigo=110 Then		;entra en la condición si pulsas el punto del teclado numérico.
				  send(",")		;envia la coma al control activo, en este caso el input.
				  Return -1		;anula la tecla pulsada. En este caso el punto.
			EndIf
		EndIf
      EndIf   ;final de la condición que dice "si está activa la ventana del programa, ejecuta la anulación de teclas."

EndFunc  ;==>_KeyProc

Func OnAutoItExit()
   DllClose($dll)
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hHook[0])
    DllCallbackFree($hStub_KeyProc)
EndFunc  ;==>OnAutoItExitm
Lo de operar con la coma en vez de con el punto creo que te lo vas a tener que currar tu. Simplemente haz una función que te cambie la coma por un punto para operar y ya está. Si luego quieres devolver el resultado con una coma en vez de con un punto, pues haces el cambio contrario y ya está. Bastante facil.

Te recuerdo que en Windows muchas veces se puede definir el caracter separador de decimales. Suele ponerse según el teclado y el pais. Lo que pasa que no veo bien cambiar cosas del sistema, pero bueno. Seguro que hay apis por ahí para hacerlo directamente por código.

También te puedes currar unos filtros (con condiciones) para que solamente acepte números (negativos o positivos). O solamente la coma y dígitos. Lo que necesites. Eso es muy facil.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
jamaro
Hacker del Foro
Mensajes: 253
Registrado: 03 Nov 2010, 23:04

Re: Números, decimales y millares

Mensaje por jamaro »

Chefito: Muchas gracias por el código y las ideas. Como habéis comentado alguna vez, casi todo se puede hacer en Autoit, sólo hace falta saber cómo ;-) Y vosotros lo tenéis todo muy claro. Gracias.

La verdad que utilizaré el código "a ciegas" puesto que cuando entra con los DllCall, me pierdo y no sé el por qué hace las cosas. Pero bueno, el resultado es el deseado.
Responder