Home > Blockchain >  .NET Csv Helper - Type Conversion to Double
.NET Csv Helper - Type Conversion to Double

Time:07-12

In one of the columns, regarding price, the data is in a weird format when the price starts with 0. Example : instead of 0,60 the format would be ,60. I tried to use the CsvHelper library from .NET nuget packages, and i would receive, of course an exception when reaching a line with this kind of values, because it could not convert this to double.

This library has a documentation regarding mapping, but i could not find anything documente on how to custom config my situation :

https://joshclose.github.io/CsvHelper/examples/configuration/class-maps/type-conversion/

Can someone give me a hint/tip for this situation ?

Here is my class setup:

public class Article
{
    public int Id { get; set; }
    public int ItemID { get; set; }
    public string? Barcode { get; set; }
    public double Price{ get; set; }
   
}

public class ArticleClassMap : ClassMap<Article>
{
    public ArticleClassMap()
    {
        Map(m => m.ItemID).Name("itemID");
        Map(m => m.Barcode).Name("barcode");
        Map(m => m.Price).Name("price");
    }
}

Here is how my file row with issues would look like : 1234|9999| ,60

Where 1234 would be the ItemId, 9999 EAN, and ,60 would represent a price of 0,60.

Here is how the CsvReader is setup :

   using (var reader = new StreamReader(stream, Encoding.UTF8))
            {
                using (var csv = new CsvReader(reader, config))

                {
                    csv.Context.RegisterClassMap<ArticleClassMap>();
                    var records = csv.GetRecords<Article>().ToList();
                    return records;
                }
            }

CodePudding user response:

I think you problem comes form ',' in your price normaly it should be '.' One solution is custom convert commas to periods and then parse to double like this:

Map(m => m.ItemID).Name("itemID");
Map(m => m.Barcode).Name("barcode");
Map(m => m.Price).Convert(row =>
{
    return Double.Parse(row.Row.GetField<string>("price").Replace(',', '.'));
});

CodePudding user response:

After hours of trying, I found a working solution in my case :

I've created a customer converter:

public class PriceConverter : DefaultTypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {

        double result;

        //replace space with 0 in position 5 of string text, if position 5 is an empty character
        if (text.Length > 5 && text[5] == ' ')
        {
            text = text.Remove(5, 1).Insert(5, "0");
        }

        result = double.Parse(text);
        
        return result;

    }

    public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        return value?.ToString();
    }
}

This works in the case, because in the .csv file the positions are fixed! So, before the comma, we always have the whole value.

Then I applied it to the mapping like this :

 public ArticleClassMap()
    {
        Map(m => m.Price).Name("price").TypeConverter<PriceConverter>();
    }

  • Related