Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Separador decimal y de miles, problemas con distintas configuraciones (https://www.clubdelphi.com/foros/showthread.php?t=55408)

kuan-yiu 16-04-2008 10:44:44

Separador decimal y de miles, problemas con distintas configuraciones
 
Tengo instalada una aplicación en diferentes equipos, que están por toda España y que cada uno tiene una configuración regional distinta y tengo el típico problema con los separadores decimales y de miles porque cada ordenador está configurado de un modo diferente y en la mayoría de los casos no puedo cambiar esa configuración.

Ya he revisado los hilos sobre este tema y:
Código Delphi [-]
  ThousandSeparator  := ',';
  DecimalSeparator := '.';
No me funciona correctamente (tal vez lo estoy poniendo en el lugar incorrecto), ahora mismo lo tengo en el onCreate de mi formulario principal, el del menú.
También he probado a "hacerlo a mano", pasando cada número por funciones que sacan los puntos, pero como unos usan la coma y otros el punto como separador decimal y nunca sé en que caso me encuentro... tampoco funciona bien.
Encontré también en el foro que en torry.net hay algún tEdit que sólo permite introducir números y la idea me pareció perfecta... pero la página sigue caída :(

Mi problema con cantidades como: 1.627,63 o su otra versión 1,627.63, o esta 1627,63, o esta 1627.63; escritas tal cual en un edit, con el teclado numérico o con el otro o incluso copiadas desde un documento excel (ya he visto de todo en el manejo de la aplicación).

¿Cómo proceso esto? "strToFloat" no admite como números los que tienen ambos separadores o los transforma mal...
¿Cómo detecto cual es la configuración de un ordenador?
¿Alguien tiene los componentes de torry.net para que pueda ver si me sirven?

...¿Alguna sugerencia? :confused:

kuan-yiu 16-04-2008 10:46:15

¡Me olvidaba!

Gracias a todos de antemano :)

defcon1_es 16-04-2008 11:17:05

Cita:

Empezado por kuan-yiu (Mensaje 280398)
Mi problema con cantidades como: 1.627,63 o su otra versión 1,627.63, o esta 1627,63, o esta 1627.63; escritas tal cual en un edit, con el teclado numérico o con el otro o incluso copiadas desde un documento excel (ya he visto de todo en el manejo de la aplicación).

Yo usaría TMaskEdit en vez de edits normales. Estos componentes validan los datos introducidos mediante una máscara que defines tu, con lo que te evitas ese tipo de errores.
Cita:

Empezado por kuan-yiu (Mensaje 280398)
¿Cómo proceso esto? "strToFloat" no admite como números los que tienen ambos separadores o los transforma mal...

Código Delphi [-]
type TConjuntoDigitosValidos = Set of Char;

function LimpiarFormatoNumero(Numero:String):String;
var contador :Integer;
    CadenaAuxiliar :String;
    ConjuntoValido :TConjuntoDigitosValidos;
begin
// Función que  devuelve el número de moneda sin
// separador de  miles ni espacios
  if Numero = ''
  then Result := '0'
  else begin
    ConjuntoValido := ['0','1','2','3','4','5','6','7','8','9','-'];
    ConjuntoValido := ConjuntoValido + [SysUtils.DecimalSeparator];
    CadenaAuxiliar := '';
    try
      for contador := 1 to length(Numero) do
      begin
        if (Numero[Contador] in ConjuntoValido)
        then begin
          CadenaAuxiliar := CadenaAuxiliar + Numero[Contador];
        end;
      end;
      if (CadenaAuxiliar = '') then CadenaAuxiliar := '0';
      Result := CadenaAuxiliar;
    except
      Result := '0';
    end;
  end;
end;
Cita:

Empezado por kuan-yiu (Mensaje 280398)
¿Cómo detecto cual es la configuración de un ordenador?

Basta con comprobar los datos de las variables
SysUtils.ThousandSeparator
SysUtils.DecimalSeparator

Lepe 16-04-2008 14:07:37

En hilos relacionados tienes el "dichoso separador decimal" que tiene varias cositas en cuenta:
- cambiar el punto del teclado numérico por la coma (para usarlo como separador decimal)
- cambiar los sysutils.decimalSeparator en controles ad-aware.

Otra solución es heredar tú misma de TEdit, añadiendo un par de propiedades (como lo hace el DBEdit):
- DisplayFormat
- EditFormat (quizás más complicada)
- AsValue:Extended

Saludos

kuan-yiu 16-04-2008 15:42:20

Lo que he hecho por el momento pero aún no he probado es:
* Añadir el cambio del punto del teclado decimal por una coma, tal como sale en el hilo "dichoso separador decimal"
* Modificar una rutina propia que uso en las operaciones con dinero para eliminar el separador de miles antes de nada.

Ahora toca instalarlo en los 3 sitios que me han avisado de los problemas y esperar. Os mantendré informados.

jcarteagaf 17-04-2008 19:08:20

Punto decimal
 
estare al tanto de tu avance, ya que ese tema tambien me afectara a futuro. Por favor no te olvides publicar como te fue.

Gracias de antemano.

kuan-yiu 14-05-2008 11:40:10

Por el momento ha bajado considerablemente el número de avisos de error del tipo "invalid floating point value", pero aún me llegan algunos. Estoy revisando si son por otra causa nueva o por un error.

BlueSteel 14-05-2008 16:18:59

Cita:

Empezado por kuan-yiu (Mensaje 286550)
Por el momento ha bajado considerablemente el número de avisos de error del tipo "invalid floating point value", pero aún me llegan algunos. Estoy revisando si son por otra causa nueva o por un error.

Hola Kuan

yo he solucionado en parte ese problema con el componente JvValidateEdit de la JVC (Jedi)...

lo bueno del componente es que puedes decir que tome solo numeros.... además el mismo tiene las sgtes caracteristicas

.text
.AsCurrency
.AsFloat

por lo cual, cuando tengo un texto y debo pasarle el valor al componente solo lo uso en el .text... si tengo un valor de punto flotante (decimales) lo hago con el .AsFloat... y si el valor viene con formato de pesos (moneda)... utilizo el .AsCurrency...

Código Delphi [-]
vTot.AsCurrency := vCtd.AsFloat*vUni.AsCurrency;

Salu2:p:D

Faust 15-05-2008 04:36:31

Hace poco pedí ayuda sobre TFormatSettings y como usarlo con algunas funciones como FloatToSTrF, pero solo BlueSteel me respondió y no era exactamente lo que buscaba, he hecho algunas pruebas y parece que se puede hacer esto, GetLocaleFormatSettings recupera de la configuración del sistema operativo que uses ciertas configuraciones para mostrar valores, ojalá te sirva de algo.

mlara 15-05-2008 06:35:17

¿Por qué no cambias la configuración regional desde tu programa?
 
Pues yo me evité muchos inconvenientes haciéndolo... claro, ojalá tus clientes no se enojen porque cada vez que inician tu aplicación su config. regional cambia :D (aunque podrías recomponerla al finalizar... digo).

Código:

SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, '.');
SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, ',');
SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONDECIMALSEP, '.');
SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHOUSANDSEP, ',');


kuan-yiu 15-05-2008 09:06:32

Cita:

Empezado por mlara (Mensaje 286781)
Pues yo me evité muchos inconvenientes haciéndolo... claro, ojalá tus clientes no se enojen porque cada vez que inician tu aplicación su config. regional cambia :D (aunque podrías recomponerla al finalizar... digo).

Código:

SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, '.');
SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, ',');
SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONDECIMALSEP, '.');
SetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SMONTHOUSANDSEP, ',');


Eso no puedo hacerlo de ningún modo. Mientras usan mi programa tienen que poder usar otros que dependen de esa configuración.

kuan-yiu 15-05-2008 09:44:47

Precisamente lo que inicialmente buscaba era un componente que solucionase parte del problema BlueSteel, pero no quiero bajarme todo lo que hay en Jedi para usar sólo una cosa. También quería probar un componente que está en Torry pero justo cuando me surgió este problema la página no funcionaba.
Si alguien sabe de dónde puedo descargar algo así que me lo diga.

Gracias por la referencia Faust, pero ya tenía implementado algo así y no era suficiente, por eso hice la consulta y ahora estoy informando de los progresos, como dije que haría.

BlueSteel 15-05-2008 19:24:17

Cita:

Empezado por kuan-yiu (Mensaje 286802)
pero no quiero bajarme todo lo que hay en Jedi para usar sólo una cosa.

Creo que la Jedi te permite seleccionar que componente deseas instalar... me parece que uno de los hilos esta.... si bien yo instalé todos... despues de buscar he encontrado algunos que me han servidor muchos... como tablas de memoria, el tab por enter, trabajar con imagenes, progresbar, y muchos otros...

Salu2:p:D

mlara 18-05-2008 01:56:13

Cita:

Empezado por kuan-yiu (Mensaje 280398)
...
Código Delphi [-]
ThousandSeparator  := ',';
DecimalSeparator := '.';
Mi problema con cantidades como: 1.627,63 o su otra versión 1,627.63, o esta 1627,63, o esta 1627.63; escritas tal cual en un edit, con el teclado numérico o con el otro o incluso copiadas desde un documento excel (ya he visto de todo en el manejo de la aplicación).

¿Cómo proceso esto? "strToFloat" no admite como números los que tienen ambos separadores o los transforma mal...[/b]

Cuando asignas el valor a DecimalSeparator y ThousandSeparator, StrToFloat convierte una cadena numérica que use el separador decimal asignado a tipo número, pero no toma el separador de miles; ¿por qué? Por esta razón: Qué pasa si tu cliente escribe: 150,000.83? La coma está bien situada, pero si escribe: 1500,00.83? mmm ahí está. Esto no sucedería si usaras un TMaskEdit. Pero suponiendo que no lo usas, pues por qué no usas esta función:

Código:

function CustomStrToFloat(S: string): Extended;
var
  SWTS: string; // S sin separador de miles (S Without Thousand Separator)
begin
  SWTS := S;
  while Pos(ThousandSeparator, SWTS) > 0 do
    SWTS := AnsiReplaceStr(SWTS, ThousandSeparator, '');

  Result := StrToFloat(SWTS)
end;

Observa que se usa la misma variable ThousandSeparator a la cual le abrás asignado su valor en el OnCreate de la forma principal, según nos habías contado. Así queda solucionado tu problema.

Una variante de la función puede ser esta:

Código:

function CustomStrToFloat(S: string): Extended;
var
  Fmt: TFormatSettings;
  SWTS: string; // S sin separador de miles (S Without Thousand Separator)
begin
  GetLocaleFormatSettings(GetSystemDefaultLCID, Fmt);
  Fmt.DecimalSeparator := DecimalSeparator;
  Fmt.ThousandSeparator := ThousandSeparator;

  SWTS := S;
  while Pos(ThousandSeparator, SWTS) > 0 do
    SWTS := AnsiReplaceStr(SWTS, ThousandSeparator, '');

  Result := StrToFloat(SWTS, Fmt)
end;

Observa que la función StrToFloat ahora se ejecuta incluyendo el formato mediante la variable Fmt de tipo TFormatSettings. En verdad, así como está funciona igual que la anterior función, pero si en vez de usar las variables DecimalSeparator y ThousandSeparator, usas '.' y ',' según tu necesidad, pues tendrías un control total. Incluso hasta podrías pasar los caracteres como parámetro.

Por otra parte leí que querías usar como alternativa un TEdit que permitiera únicamente registrar números. Bueno, pues esto es muy sencillo, pues únicamente es necesario escribir el evento OnKeyPress:

Código:

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if ((Key < '0') or (Key > '9')) and (Key <> #8) then
    Key := #0;
end;

Espero que ahora sí esta ayuda te sirva.

Saludos.

cascarrabias 18-05-2008 11:21:21

Lo siento...me equivoque de post, saludos!

chopin_fev 01-10-2008 23:49:16

Perfecto.........
 
Mismo problema de Conf. Regional..........
Con todas las opciones que discutian llegue a la conclusion de modificar el ed.text en la propiedad keypress....solo numeros y decimales in '0'..'9' or ',' '.' y con el ThousandSeparator..... entrega si es coma o punto y con strtofloat funciona para cualquier conf.regional..........
Gracias a todos y al foro...........


La franja horaria es GMT +2. Ahora son las 17:24:27.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi