user3690217
user3690217

Reputation: 23

CSV Helper Multiple Same column Names

I have CSV file that has multiples columns with the same header name. I am using CsvHelper library. I want to collect their row values into one List but I am collecting first row value as many times I have header specified and not collecting from another index position. ex. COLUMN COLUMN Test1 Test2 Test3 Test4 I expect that my list has two elements first with value Test1,Test2 and second one with values Test3,Test4 but I first row has values Test1,Test1 and second Test3,Test3.

This is the mapping for this column

Map(m => m.COLUMN).ConvertUsing(row =>
                (row as CsvReader)?.FieldHeaders
                     .Where(header => header.StartsWith("COLUMN"))
                     .Select(header => row.GetField<string>(header))
                     .Where(value => !string.IsNullOrWhiteSpace(value))
                     .ToList()
            );

Can this be done with mapping? If I change Column names to COLUMN1 and COLUMN2 this works but that is not the solution for my problem.

Upvotes: 2

Views: 3368

Answers (1)

Josh Close
Josh Close

Reputation: 23373

There are many ways to do this. Here is one example.

void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name,List,List,List");
        writer.WriteLine("1,one,a,b,c");
        writer.WriteLine("1,two,d,e,f");
        writer.Flush();
        stream.Position = 0;

        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().Dump();
    }
}

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<string> List { get; set; }
}

public sealed class TestMap : CsvClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.List).ConvertUsing(row =>
        {
            var list = new List<string>();
            list.Add(row.GetField("List", 0));
            list.Add(row.GetField("List", 1));
            list.Add(row.GetField("List", 2));
            return list;
        });
    }
}

Also, version 3 has mapping to enumerables built in.

Map(m => m.List).Name("List");

Upvotes: 3

Related Questions