none
string.format, como convertir variables string con valores de importes y decimales sin importar la cultura

    Question

  • tengo una dll externa que usa mi sistema, esta dll se comunica con un controlador fiscal
    mi sistema usa dicha dll pero puede trabajar con dos culturas, ingles o español
    y la seteo al inicializar mi sistema, independientemente de la configuracion reional de la pc
    yo adopto una cultura por ejemplo ingles para trabajar con separador decimal punto
    o español par atrabajar con separador decimal coma, asi funcioan mi sistema
     
    en la dll fiscal:
    recibo como parametro los importes en formato string, pero un cliente
    puede tener configurado la cultura inles y otro cliente español

    ejemplo

    en un string recibo un importe, que puede venir con separador decimal coma
    o punto segun su configuracion de cultura en el sistema ejemplos:
    1234.23
    1234,23

    esto se debe a que el sistema puede estar configurado con coma o punto como separador decimal


    Problema:

    estoy mandando el dato a un controlador fiscal y debo mandarlo siempre con punto
    como separador decimal y con un cierto formato de longitud
    completando con ceros los lugares restantes
    quiero usar la clase string.format para formatear los importes

    ejemplos:

    Si hago:
    valorRecibido="1234.23"
    
    valorFormateado = String.Format("{0:0.000}", valorRecibido);
    
    no me funciona y no hace nada el format sobre una variabel string en este caso valorRecibido
    si funciona si lo hacemos sobre un valor doble, entonces al parametro string valorRecibido
    lo convierto en doble antes de formatearlo:
    
    Si hago:
    valorRecibido="123,1234"
    valorFormateado = String.Format("{0:0.0000}", Convert.ToDouble(valorRecibido));
    queda bien el valor: 123,12340
    
    Si hago:
    valorRecibido="123.1234"
    valorFormateado = String.Format("{0:0.0000}", Convert.ToDouble(valorRecibido));
    queda mal el valor: 1231234,00000
    


    yo quiero poder transformar el parametro string recibido ya sea con punto o coma como
    separador decimal (1234.23 o 1234,23) a 123,12340 o sea un formato de 5 decimales
    pero evidentemente el problema esta que el Convert.ToDouble trabaja con la cultura regional

    hay alguna forma de usar el metodo String.Format para pasar una cadena string
    con el valor (1234.23 o 1234,23) y que funcione sin tener en cuenta la cultura regional

    porque sino no me queda otra que hacer algun algoritmo y cuando detecte coma o punto
    se que es el separador decimal y pasar todo a otro string para hacer lo
    que deseo, pero quiero evitar hacer procesos si ya existen clases como
    string.format

    la otra seria que establezca la misma cultura en la dll fiscal que en mi sistema
    pero no quiero llegar a eso

    que me aconsejan, gracias

     

    Saludos


    programador
    Friday, August 12, 2011 3:08 PM

Answers

  • hola

    lo que podrias hacer es usar el TryParse()

     

    textbox1.Text = "1.234,23";
    
    decimal valor = 0;
    
    if(!decimal.TryParse(textbox1.text, out valor)){ //convierte usando la cultura en-US
    
      NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
    
      CultureInfo culture = CultureInfo.CreateSpecificCulture("es-ES")
    
      decimal.TrayParse(textbox1.text, style, culture , out valor);
    
    }
    


    saludos

     


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, August 12, 2011 7:50 PM

All replies

  • no me funciona y no hace nada el format sobre una variabel string en este caso valorRecibido

    pero valorRecibido es un string es logico que no funcione, tiee que ser un valro numerico

    decimal valorRecibido= Convert.ToDecimal("1234.23");

    valorFormateado = String.Format("{0:0.000}", valorRecibido);

     

    yo quiero poder transformar el parametro string recibido ya sea con punto o coma como
    separador decimal (1234.23 o 1234,23) a 123,12340 o sea un formato de 5 decimales
    pero evidentemente

    el tema es que en cada momento tu tienes una cultura determianda definida en la pc, pro lo tanto deberias escribir la infromacion en base a esta

    si una pc el usuario tiene una cultura es-ES deberia usar la coma como separador decimal, si tiene una en-US deberia usar el punto

    pero no se deberia mezclar

    puede definir en la conversion una cultura determinada si esta es diferente a la establecida por defecto

    double val = Convert.ToDouble("1234.23", CultureInfo.CreateSpecificCulture("en-US"))

    en esa linea puede convertir sin problemas un numero con coma aunque tu cultura de la pc sea es-ES proque defines esta en la conversion

     

    pero el tema es que magicamente sepa como haceleo lo veo raro, ademas como detectarias la cultura con el punto porque que pasa si viene "1.234,23", si buscas si hay un punto o una cooma para determinar si es una u otra no puede porque no sabes que parte es decimal y cual marca los miles en el numero

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, August 12, 2011 3:27 PM
  • Hola Leandro, como estas, gracias por aclararme mi duda:

    es un string es logico que no funcione, pense que podia haber alguna forma de formatear un string a una mascara de decimales con puntos como separador decimal, sin que intervenga la cultura, pero ahora me queda claro, no se puede, isn manejar al cultura

    tambien podria establacer en la dll por default la cultura con la que quiero que trabaje independientemente de la configuracion regional de la pc

    haciendo esto en la dll:
    string pCulturaO = "en-US";
    System.Globalization.CultureInfo cultura1 = new System.Globalization.CultureInfo(pCulturaO);
    Thread.CurrentThread.CurrentUICulture = cultura1;
    Thread.CurrentThread.CurrentCulture = cultura1;

    en mi metodo de conversion puedo recibir importes en variables string
    con separador decimal coma  o punto, de ambas maneras siempre tendran que quedar
    con separador decimal punto porque el controlador recibe con punto,
    por eso establezco la cultura a ingles, no podria trabaajr con coma en cultura ingles


    ejemplo:

    asi, este es tu ejemplo me funciono ok: 
    this.textBox1.Text="123.1234"
    this.textBox2.Text="123,1234"
    
    //text1 a text3
    this.textBox3.Text = String.Format("{0:0.00000}", Convert.ToDouble(this.textBox1.Text.Trim()));
    //text2 a text4
    this.textBox4.Text = String.Format("{0:0.00000}", Convert.ToDouble(this.textBox1.Text.Trim()));
    
    o asi tambien anda, sin especificar la cultura al convert, porque no me toma la conf de
    la pc sino que en el main establezco la cultura inglesa:
    
    asi: 
    this.textBox1.Text="123.1234"
    this.textBox2.Text="123,1234"
    
    //text1 a text3
    this.textBox3.Text = String.Format("{0:0.00000}");
    //text2 a text4
    this.textBox4.Text = String.Format("{0:0.00000}");
    

    asi independientemente del otro lado si me llega
    "123.1234" o "123,1234" y si la pc tiene una cultura x, en la dll trabajo con cultura
    ingles que tiene separador decimal punto
    y me convierte correctamente el valor venag con coma o punto

    Ahora si me mandan los separadodres de miles y tengo el codigo de arriba de los ejemplos

    si mando  ejemplo"1.234,23" me da error "Input string was not in a correct format", aca como seteo la mascara para separadores de miles?, tendria que setear una mascara con separador de miles segun la cultura inglesa, el error es por la mascara?

    pero si lo mando asi 1,234.23 me queda bien 1234.23000

    Saludos


    programador
    Friday, August 12, 2011 7:01 PM
  • hola

    esta parte funciono

     

    this.textBox1.Text="123.1234"
    this.textBox2.Text="123,1234"
    
    //text1 a text3
    this.textBox3.Text = String.Format("{0:0.00000}", Convert.ToDouble(this.textBox1.Text.Trim()));
    //text2 a text4
    this.textBox4.Text = String.Format("{0:0.00000}", Convert.ToDouble(this.textBox1.Text.Trim()));
    

    porque has puesto dos veces el TextBox1imagino tienes una cultura que defien el punto comod ecimales or eso lo toma correctamente

     

     

    aqui

    this.textBox1.Text="123.1234"
    this.textBox2.Text="123,1234"
    
    //text1 a text3
    this.textBox3.Text = String.Format("{0:0.00000}");
    //text2 a text4
    this.textBox4.Text = String.Format("{0:0.00000}");
    


    no le has pasado ningun valor, o sea usas String.Format("{0:0.00000}"); pero el textbox1 y textbox2 dodne lo asignas ?

     

     

    Nota: no uses 0:0.00000 para formato usa N5


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, August 12, 2011 7:12 PM
  • disculpa Leandro copie cualquiera

    es asi:

    asigno text1= 1,234.23 ==============1234.23000
    asigno text2= 1.234,23===================== me da Input string was not in a correct format.
    
    
    cuando hago la conversion del text1 me lo hace bien porque la cultura del programa es ingles
    y el dato tiene como separador decimal el punto y separador de miles la coma
    
    //text1 a text3
    this.textBox3.Text = String.Format("{0:0.00000}", Convert.ToDecimal( this.textBox1.Text.Trim()));
    
    pero si quiero formatear el valor del text2 me da error en el formato de entrada 
    y es logico porque estoy mandando la coma como separador decimal y el punto
    como separador de miles
     //text2 a text4
     this.textBox4.Text = String.Format("{0:0.00000}", Convert.ToDecimal(this.textBox2.Text.Trim()));
    
    


    lo que yo quiero hacer es formatear el valor de entrada(text1 y text2) a decimal con punto
    para asignarlo a otro string, pero parece que si el valor al que quiero darle el formato
    no es adecuado da error de que el string no tiene un formato correcto

    creo que no me quedara otra que establecer que desde afuera se mande en un formato segun una cultura y
    en el drivers fiscal se setee la misma cultura para evitar permitir valores 
    como 1,234.23 o 1.234,23 segun al cultura del sistema que usa la dll

     

    Saludos


    programador
    Friday, August 12, 2011 7:41 PM
  • hola

    lo que podrias hacer es usar el TryParse()

     

    textbox1.Text = "1.234,23";
    
    decimal valor = 0;
    
    if(!decimal.TryParse(textbox1.text, out valor)){ //convierte usando la cultura en-US
    
      NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
    
      CultureInfo culture = CultureInfo.CreateSpecificCulture("es-ES")
    
      decimal.TrayParse(textbox1.text, style, culture , out valor);
    
    }
    


    saludos

     


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, August 12, 2011 7:50 PM
  • Hola Leandro, gracias por tu aporte, me anduvo el tryParse, entendi que que al convertir con la cultura ingles si el tryParse devuelve false es porque dio error entonces convertis con la cultura español :

    decimal valor = 0;
          
          //establezco que quiero convertir segun al cultura inglesa
          CultureInfo cultureDefault = CultureInfo.CreateSpecificCulture("en-US");
          NumberStyles styleDefault = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
          
          if (!decimal.TryParse(this.textBox1.Text, styleDefault, cultureDefault, out valor))
          {
            //si da error convierte usando la cultura Español
    
            NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
    
            CultureInfo culture = CultureInfo.CreateSpecificCulture("es-ES");
    
             decimal.TryParse(this.textBox1.Text, style, culture, out valor).ToString();
            this.textBox3.Text = valor.ToString();
          }
          else
          {
            this.textBox3.Text = valor.ToString();
          }
    

    Muchas Gracias, ya tengo una solcion para adoptar y validar los importes que me vienen en parametros string, uan ultima pregunta podria controlar que los separadores de miles y separador decimal sean distintos, ya que podrian mandarme 1,234,23 y me lo deja en 123423, o si me mandan  1.234.23 queda 123423, o sea me conviene tener alguna forma de validar el formato de se parametro string, si se que debe tenber un fomato de 5 enteros por ejemplo y dos decimales

     

    Saludos


    programador
    Friday, August 12, 2011 8:13 PM
  • hola

    Standard Numeric Format Strings

     

    luego de convertir puedes suar el formato F o N para desplegar la informacionm con F no tendras los separadores de miles

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, August 12, 2011 8:25 PM
  • gracias Leandro, ya voy a probar esto y te comento

    saludos


    programador
    Friday, August 12, 2011 8:44 PM
  • quiero dejar un aporte final en esto, renegue un rato con el tema de
    la cultura y el formato de importes y cantidades con decimales

    Resumen: tengo un valor cantidad o importe en un string y quiero darle un formato
    especifico(ejempo 00000.000)

    problemas:
    1- no puedo darle un formato de numero decimal a un string directamente, entonces debo convertirlo
    a decimal para poder aplicarle el formato
    2-no necesito tener en cuenta la cultura para el formato final, sino me mete al coma o el punto
    segun la conf regional


    Detalle:
    cuando me mandan los datos desde el sistema a la dll fiscal(esta se comunica con el ocx
    de epson), los importes y cantidades pueden venir con cultura inglesa o español
    segun este configurado el sistema, y vienen en parametros string

    ejemplo:
    el parametro cantidad en el metodo imprimir item
    "123,12" o "123.12" y vienen sin el formato que me pide el ocx paa cada caso


    la dll fiscal debe enviar este dato al ocx de un controlador fiscal Epson con un formato
    específico:
    por ejemplo 5 enteros y 3 decimales(00000000) sin el separador decimal, pero como lo recibo en formato string
    y el stringformat formatea un valor decimal, no me formatea directamente el string a decimal con formato
    entonces tengo que convertir el string a decimal para poder aplicarle luego el formato,
    con la funcion FormatNumero detallada abajo, recibo el parametro ya sea para cantidades o importes
    y lo convierto a decimal(en esto me ayudo leandro, usando el tryParse primero a ingles, si es false
    entonces lo hace con al cultura español y me devuelve el valor decimal a partir del string recibido)

    /// <summary>
        /// genera un valor decimal a partir de una cadena pasada como parametro
        /// sirve para cantidades o importes, luego en cada funcion se
        /// puede formatear el valor decimal devuelto a un formato especial con string.format
        /// </summary>
        /// <param name="ValorEntrada"></param>
        /// <returns></returns>
        public static decimal FormatNumero(string ValorEntrada)
        {
    
          decimal ValorSalida = 0;
          
          //cultura ingles
          CultureInfo cultureDefault = CultureInfo.CreateSpecificCulture("en-US");
          NumberStyles styleDefault = NumberStyles.AllowDecimalPoint;
         
          Boolean Convierte = decimal.TryParse(ValorEntrada, styleDefault, cultureDefault, out ValorSalida);
    
          if (Convierte==false)
          {
            //si da error convierte usando la cultura Español
    
            NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
    
            CultureInfo culture = CultureInfo.CreateSpecificCulture("es-ES");
    
            decimal.TryParse(ValorEntrada, style, culture, out ValorSalida);
          }
          
          return ValorSalida;
        }
    
    
    <strong>y para formatear al valor especifico, sin tener en cuenta la cultura
    hice</strong>:
    //quantity(cantidad): 5 enteros y 3 decimales
     string quantity = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:00000.000}", MetodoGeneral.FormatNumero(cCanti)).Replace( ".", "");
    

    formatear al valor especifico, sin tener en cuenta la cultura:
    aca si no ponemos InvariantCulture, me lo formatea con coma como separador decimal, si la cultura de la pc esta en español, si esta en ingles a punto, para que respete el formato
    ("{0:00000.000}") sin tener en cuenta la cultura de la pc lo hacemos asi con InvariantCulture

    el resultado seria "00123.120" que es el formato que espera el driver en ese parametro pero al final
    le saco el separador decimal, porque encima me lo pide sin el separador, en algunos otros parametros
    lo pide con el separador punto

    si no usamos InvariantCulture tendriamos al resultado por las dudas reemplazarle la coma por el punto
    que se daria en el caso de que la pc este configurada a español
     

    Saludos


    programador
    Monday, August 15, 2011 3:38 AM