The case is that I'm parsing a file, that looks something like this.
Name | Account |
---|---|
Foo client | 123 |
Bar client | 456,789 |
In the real data I do some more stuff, to clean up account, etc, but the main point is the ,
in the Account column. I now get an IEnumerable with 2 records, I'd like to get an IEnumerable with 3 records, by splitting records on the comma in the Account column.
Like this.
Name | Account |
---|---|
Foo client | 123 |
Bar client | 456 |
Bar client | 789 |
Is this possible to achieve through CSV Helper?
void Main()
{
using (var sReader = new StringReader("Name,Account\nFoo client,123\nBar client,\"456,789\""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Read();
csvReader.ReadHeader();
var records = new List<Foo>();
while (csvReader.Read())
{
var name = csvReader.GetField("Name");
var account = csvReader.GetField("Account");
var splitAccounts = account.Split(",");
foreach(var item in splitAccounts)
{
records.Add(new Foo { Name = name, Account = int.Parse(item)});
}
}
records.Dump();
}
}
public class Foo
{
public string Name { get; set; }
public int Account { get; set; }
}
Update:
Each row is a record, so you really can't create a new record with your ClassMap
outside of the row. What you might be able to do is wrap your class in another class that contains a List<MyClass>
of the records you are trying to create and then combine them back into a single List<MyClass>
. If Account
can be type string
in MyClass
you could get away without the separate MyClassMap
and just let it AutoMap()
your class.
void Main()
{
using (var sReader = new StringReader("Name,Account\nFoo client,123\nBar client,\"456,789\""))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InvariantCulture))
{
csvReader.Configuration.RegisterClassMap<FooMap>();
csvReader.Configuration.RegisterClassMap<MyClassMap>();
var wrappedRecords = csvReader.GetRecords<Foo>();
var records = wrappedRecords.SelectMany(r => r.Clients).ToList();
records.Dump();
}
}
public class FooMap : ClassMap<Foo>
{
public FooMap()
{
Map(x => x.Clients).ConvertUsing(x =>
{
var records = new List<MyClass>();
var record = x.GetRecord<MyClass>();
var splitAccounts = x.GetField("Account").Split(",");
foreach (var item in splitAccounts)
{
records.Add(new MyClass { Name = record.Name, Account = int.Parse(item) });
}
return records;
});
}
}
public class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
Map(x => x.Name);
}
}
public class Foo
{
public List<MyClass> Clients { get; set; }
}
public class MyClass
{
public string Name { get; set; }
public int Account { get; set; }
}