26

I have a csv file with 40 columns and I want to load it to a datatable using csvhelper. After installing the library, I did this:

using (TextReader reader = File.OpenText(fileName)) {
   var csv = new CsvReader(reader);
   while (csv.Read()) {
       var farmID = csv.GetField(0);
       Console.WriteLine(farmID);
   }
}

and as you see, I have a console statement and it works perfectly.

However, the csvReader has a constructor that takes a custom class to load the data directly to it.

I tried this:

var record = csv.GetRecord<CSVFileDefinition>();

but I got this exception

No properties are mapped for type 'MyProjectName.CSVFileDefinition'.

because the CSVFileDefinitionis an empty class.

my question is how to fill that class.

This is the library:

http://joshclose.github.io/CsvHelper/

Many thanks

Update 2

The solution that works for me is:
sealed class CSVFileDefinitionMap : CsvClassMap<CSVFileDefinition>
{
   public CSVFileDefinitionMap()
   {
      Map(m => m.FRM_ID).Name("FARM ID");
      Map(m => m.FRM_OWNER).Name("FARM OWNER ");
   }
}

class CSVFileDefinition
{
    public string FRM_ID { get; set; }
    public string FRM_OWNER { get; set; }
}

using (TextReader reader = File.OpenText(fileName)) {
    var csv = new CsvReader(reader);
    csv.Context.RegisterClassMap<CSVFileDefinitionMap>();
    while (csv.Read()) {
       var record = csv.GetRecord<CSVFileDefinition>();
    }
}
Enrique Avina
  • 973
  • 7
  • 20
Agnieszka Polec
  • 1,471
  • 6
  • 20
  • 26
  • 1
    Isn't it right there in the docs at: http://joshclose.github.io/CsvHelper/#mapping ? – Kirk Woll Jul 29 '14 at 13:48
  • @KirkWoll maybe I don't know. I couldn't understand it. I just need form guys here who have worked with this library to give me a simple example with just one filed as a starting point and I can do the rest – Agnieszka Polec Jul 29 '14 at 13:50
  • But the docs are clear; there are even examples in the tests here: https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper.Tests/CsvReaderMappingTests.cs – Kirk Woll Jul 29 '14 at 13:52
  • @KirkWoll you write. However, it is not easy to me. Anyway, I will try the same way as your link did and I will update you. – Agnieszka Polec Jul 29 '14 at 13:55
  • I am a good c# developer, If it was a python issue, I would solve it quickly. you know guys. everyone has a default language :P – Agnieszka Polec Jul 29 '14 at 13:55
  • @KirkWoll I did as the below answer and I wrote the exception in that answer, could you check please ? – Agnieszka Polec Jul 29 '14 at 14:48
  • If your 'Update 2' edit is the working solution for you, better post it as an answer to your question. It would be clearer and easier for who will find your question and need your solution. – Frédéric Jan 29 '16 at 09:01
  • 5
    The docs don't state that you need to register the class map in the Mapping section, I suspect the op wouldn't have needed to ask if the docs were more clear. – reggaeguitar Mar 14 '17 at 15:30
  • 3
    Update for 2020: per [this question](https://stackoverflow.com/questions/44313515/csvclassmap-not-found-error-in-visual-studio-2015) current syntax is to use ClassMap instead of CsvClassMap. Need to add a ```using CvsHelper.Configuration;``` as well. – user8675309 Jul 14 '20 at 03:47
  • Just faced the same issue code from Update 2 works fine with: ClassMap instead of CsvClassMap – Lia Apr 12 '21 at 19:27

2 Answers2

6

It seems that all you need to do is to add a property to the CSVFileDefinition class for each column name you expect to find in the CSV file, and the auto mapping should take care of the rest.

For example, this should pull in the farm ID column providing that the property name matches the column name in the CSV:

public class CSVFileDefinition
{
    public int FarmId { get; set; }

    //... add other columns here...
}
  • 3
    I got this exception `Fields 'FRM_ID' do not exist in the CSV file.` – Agnieszka Polec Jul 29 '14 at 14:48
  • 2
    I have used this method successfully, but got a problem when the properties are not strings and the data cell is empty. For example, I had a decimal property and it's not working. – Vasily Hall Nov 09 '16 at 22:27
  • when property name is different from column header please use Class Map like the update added to the question. – hatem87 Jun 13 '17 at 12:14
4

The CsvHelper API is like the weather: if you don't like it, wait five minutes and it will change :-)

Version 20.0.0 moved RegisterClassMap from the Configuration object to the Context object that's part of the writer itself: I don't believe you can attach it to a general configuration.

// Note: CsvConfiguration takes CultureInfo starting in (I think) v23.0.0
var Config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
    HasHeaderRecord = true,
    Delimiter = ","
};

var outputStream = new StreamWriter("myfile.csv");
var Writer = new CsvWriter(outputStream, Config);

Writer.Context.RegisterClassMap<MyType>(mymap);  // 20.0.0

It's always wise to check the changelog; it calls out breaking changes (which are very, very common).

Ref: https://joshclose.github.io/CsvHelper/change-log/

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30