I\'m using CsvHelper. To write to a .csv
file, I need a header based off of a class.
I write the header manually and it works, but I need to be done aut
You may be confused how CSVHelper works. This code handles the write aspect of your read in-write out loop:
List<Employee> empList = new List<Employee>();
empList.Add(new Employee { FirstName = "Ziggy", LastName = "Walters", Wage = 132.50F });
empList.Add(new Employee { FirstName = "Zoey", LastName = "Strand", Wage = 76.50F });
using (StreamWriter sw = new StreamWriter(@"C:\Temp\emp.csv"))
using (CsvWriter cw = new CsvWriter(sw))
{
cw.WriteHeader<Employee>();
foreach (Employee emp in empList)
{
emp.Wage *= 1.1F;
cw.WriteRecord<Employee>(emp);
}
}
CSVWriter
implements IDisposable
, so I put it into a using block as well.Result:
FirstName,LastName,Wage
Ziggy,Walters,145.75
Zoey,Strand,84.15
Write header just writes the first line - the names of the columns/items. Notice that the wages listed are different than what I used to create each one.
For what you are doing, I would read in a typed object in place of iterating the empList
. For the error listed in the edit, that means that it could not find a column by that name in the input file (probably because you didnt use the Types overload). The class property names should match the column names exactly (you may also want to configure CSVHelper).
The full in-out loop is only slightly more complex:
using (StreamReader sr = new StreamReader(@"C:\Temp\empIN.csv"))
using (StreamWriter sw = new StreamWriter(@"C:\Temp\empOUT.csv"))
using (CsvWriter cw = new CsvWriter(sw))
using (CsvReader cr = new CsvReader(sr))
{
cw.WriteHeader<Employee>();
var records = cr.GetRecords<Employee>();
foreach (Employee emp in records)
{
emp.Wage *= 1.1F;
cw.WriteRecord<Employee>(emp);
}
}
Results using the output from the first loop as input:
FirstName,LastName,Wage
Ziggy,Walters,160.325
Zoey,Strand,92.565
If there is no header record in the incoming CSV it wont know how to map data to the class. You need to add a map:
public class EmployeeMap : CsvHelper.Configuration.CsvClassMap<Employee>
{
public EmployeeMap()
{
Map(m => m.FirstName).Index(0);
Map(m => m.LastName).Index(1);
Map(m => m.Wage).Index(2);
}
}
Mine is nested inside the Employee
class. Then give CSVHelper that map:
... before your try to read from the incoming CSV:
cr.Configuration.RegisterClassMap<Employee.EmployeeMap>();
cw.WriteHeader<Employee>();
...
Now it knows how to map csv columns to the properties in your class.
I believe this exception is from the CsvReader and not the CsvWriter. Default CsvConfiguration expects a header and uses AutoMap to generate a PropertyName_to_Index mapping.
From the documentation you may need to define a map see mapping