У меня есть столбцы столбцов в файле, которые будут иметь такие значения, как «000120000», которые необходимо преобразовать в «1200.00» с помощью CsvHelper ClassMap. В настоящее время я использую тип Decimal для этих столбцов и имею NumberStyle в ClassMap, которое обрезает ноль в начале. Таким образом, я получаю значение как «120000». Я попытался использовать «TypeConverterOption.Format (« 0.00 »)», но безуспешно. Поэтому хотелось бы знать, есть ли способ преобразовать значение «120000» в «1200.00» с помощью ClassMap. Я могу даже разделить на 100, но не хочу делать это везде, где я использую поле, поэтому мне нужно выполнить эту логику в ClassMap. Заранее благодарим вас за помощь в этом.

В ClassMap у меня есть следующий код: csvConfig.TypeConverterOptionsCache.GetOptions <десятичный?> (). NumberStyle = NumberStyles.Number | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent;

Пример: «000120000» -> «1200.00» (сейчас я получаю значение как «120000»)

1
Sai Krishna 13 Июл 2020 в 15:21

1 ответ

Лучший ответ

Это один из способов сделать это. С кастомным конвертером.

public class Program
{
    static void Main(string[] args)
    {
        using (var stream = new MemoryStream())
        using (var writer = new StreamWriter(stream))
        using (var reader = new StreamReader(stream))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
            writer.WriteLine("1,000120000,000120000");
            writer.Flush();
            stream.Position = 0;

            csv.Configuration.RegisterClassMap<FooClassMap>();

            var records = csv.GetRecords<Foo>().ToList();
        }
    }
}

public class Foo
{
    public int Id { get; set; }
    public decimal MoveDecimalPoint { get; set; }
    public decimal NoMoveDecimalPoint { get; set; }
}

public class FooClassMap : ClassMap<Foo>
{
    public FooClassMap()
    {
        AutoMap(CultureInfo.InvariantCulture);
        Map(m => m.MoveDecimalPoint).TypeConverter<MoveDecimalConverter>();
    }
}

public class MoveDecimalConverter : DecimalConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        var numberStyle = memberMapData.TypeConverterOptions.NumberStyle ?? NumberStyles.Number;

        if (decimal.TryParse(text, numberStyle, memberMapData.TypeConverterOptions.CultureInfo, out var d))
        {
            return d / 100;
        }

        return base.ConvertFromString(text, row, memberMapData);
    }
}

Если вы хотите, чтобы ВСЕ десятичные значения перемещались на два десятичных разряда, вы можете добавить MoveDecimalConverter в конфигурацию.

public class Program
{
    static void Main(string[] args)
    {
        using (var stream = new MemoryStream())
        using (var writer = new StreamWriter(stream))
        using (var reader = new StreamReader(stream))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
            writer.WriteLine("1,000120000,000120000");
            writer.Flush();
            stream.Position = 0;

            csv.Configuration.TypeConverterCache.AddConverter<decimal>(new MoveDecimalConverter());

            var records = csv.GetRecords<Foo>().ToList();
        }
    }
}

Вы также можете использовать ConvertUsing()

public class Program
{
    static void Main(string[] args)
    {
        using (var stream = new MemoryStream())
        using (var writer = new StreamWriter(stream))
        using (var reader = new StreamReader(stream))
        using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
        {
            writer.WriteLine("Id,MoveDecimalPoint,NoMoveDecimalPoint");
            writer.WriteLine("1,000120000,000120000");
            writer.Flush();
            stream.Position = 0;

            csv.Configuration.RegisterClassMap<FooClassMap>();

            var records = csv.GetRecords<Foo>().ToList();
        }
    }
}

public class Foo
{
    public int Id { get; set; }
    public decimal MoveDecimalPoint { get; set; }
    public decimal NoMoveDecimalPoint { get; set; }
}

public class FooClassMap : ClassMap<Foo>
{
    public FooClassMap()
    {
        AutoMap(CultureInfo.InvariantCulture);
        Map(m => m.MoveDecimalPoint).ConvertUsing(row =>
        {
            if (decimal.TryParse(row["MoveDecimalPoint"], NumberStyles.Number, row.Configuration.CultureInfo, out var d))
            {
                return d / 100;
            } 
            else
            {
                return 0;
            }
        });
    }
}
0
David Specht 14 Июл 2020 в 17:29