I have a csv file with many columns that I want to read and then add a new column to CSV and write it back.
I can read it into a dynamic object, but how can I add a new column to it?
I am using CSVHelper.
I don't want to define a class to read the csv, since the number of columns is very high and also it may change.
The answer is what I was looking and it helped me to solve the problem.
Not sure what to add to this question as it explained the question properly some somebody answered it (The question may seem very basic, but that could not be the reason to close it)
dynamic records = null;
using (var sReader = new StringReader("Id,Name\n1,Test"))
using (var csvReader = new CsvHelper.CsvReader(sReader, CultureInfo.InstalledUICulture))
{
records = csvReader.GetRecords<dynamic>().ToList();
}
foreach (var record in records)
{
record.NewColumn = "New Item";
}
using (var csvWriter = new CsvWriter(Console.Out, CultureInfo.InvariantCulture))
{
csvWriter.WriteRecords(records);
}
If you need to add the column dynamically, you can add them like this.
foreach (var record in records)
{
var expandoDict = record as IDictionary<string, object>;
expandoDict.Add("NewColumn", "New Item");
}
Note:
Dynamics are really slow. If you're just adding a new field to the CSV, you can read and write directly and don't need to turn them into any sort of object. You can also use underlying classes directly.
void Main()
{
var s = new StringBuilder();
s.AppendLine("Id,Name");
s.AppendLine("1,one");
s.AppendLine("2,two");
using (var reader = new StringReader(s.ToString()))
using (var writer = new StringWriter())
using (var parser = new CsvParser(reader, CultureInfo.InvariantCulture))
using (var serializer = new CsvSerializer(writer, CultureInfo.InvariantCulture))
{
var row = parser.Read();
Array.Resize(ref row, row.Length + 1);
row[row.Length - 1] = "Header Name";
serializer.Write(row);
serializer.WriteLine();
while ((row = parser.Read()) != null)
{
Array.Resize(ref row, row.Length + 1);
row[row.Length - 1] = "Field Value";
serializer.Write(row);
serializer.WriteLine();
}
writer.Flush();
writer.ToString().Dump();
}
}
This example uses LINQPad and that is where the .Dump()
method comes from.