Wiki

Clone wiki

CsvFileReader / Home

Welcome To the CsvFileReader Home Page

This wiki will highlight some of the features of using CsvFileReader. The Goal with this project was to utilize a CSV reader that would map to a defined Model. There is some extensibility that can be used to make this more robust and room for additionally type support but it is still very useful as is.

Features

Custom mapping via attributes or via a dictionary. Detailed exception handling

Supports the following types:

  • Int
  • String
  • Date
  • List
  • Custom type
  • List of all the above
  • Nullable int

To Do

More type support. There is room to add more support if need be. Additionally more Csv File options can be considered but I did not want to personally focus on this aspect as there may be many options that currently exist. The main focus was to reliably Define a model and pull out the collection from the CSV without any intervention

Usage

Assuming that we have a csv file as such

NameCategoryComment
Billyfun, niceI liked it and I had fun
AliceniceIt was nice
JohnunpleasantI hated it

1. Create your model

Some modifications that we want in this example is to first Call the class Comment and then map the comment column to the message property instead for more domain centric application.

Also columns map only to properties and not fields. Be default it will map to the name regardless of case unless you specify otherwise

public class Comment
{
  ///Map the Csv Collection
  [CsvListProperty("Name", ',')]
  public List<Categories> Category { get; set; }

  public string Name { get; set; }

  //Map the Comment Column to this property
  [CsvMapTo("Comment")]
  public string Message { get; set; }
}

public class Category
{
  public string Name { get; set; }
}

So what does the decorators mean ?

  • [CsvListProperty("Name", ',')] - The CsvListProperty is needed when mapping a collection. As an argument it takes the name of the property of the type when not a primitive and the delimiter to split on. If it is a primitive then you can ignore the Name part.
  • [CsvMapTo("Comment")] - The Map to Attribute allows you to map the column to the property

2. Retrieve your collection

  //Instantiate the CsvFile object with the path of the csv
  CsvFile csv = new CsvFile(path);

  //Get all the comments in the csv
  IEnumerable<Comment> comments = csv.Reader.RetrieveData<Comment>();

  comments.Foreach(Comment => Console.WriteLine(Comment.Name));
  //should Produce
  //Billy
  //Alice
  //John

Advanced Usage

using the modified Csv from above

NameCategoryCommentDateVotes
Billyfun, niceI liked it and I had fun04-20121
AliceniceIt was nice06-20123
JohnunpleasantI hated it07-20122
public class Comment
{
  public string Name { get; set; }

  ///Map the Csv Collection
  [CsvListProperty("Name", ',')]
  public List<Categories> Category { get; set; }  

  //Map the Comment Column to this property
  [CsvMapTo("Comment")]
  public string Message { get; set; }

  //Define the date format
  [CsvDate("MM-yyyy")]
  public DateTime Date { get; set; }

  public int Votes { get; set; }

  //ignore this entry as its not on the CSV
  [CsvIgnoreProperty]
  public int Enabled  { get; set; }
}

So what does the decorators mean ?

  • [CsvDate("MM-yyyy")] - this attribute is needed when working with Dates. A special note regarding dates is that you can optionally pass in a parameter called Try which will not throw an error if the format is not valid
  • [CsvIgnoreProperty] - this is used to ignore the this property

The last thing to Note is the scenario where you do not have a heading row predefined and you need to map by index. In this case you can actually use a Dictionary to store the index and the Property name to map to. Using the above class example we could use this approach as below

  Dictionary<int, string> mappings = new Dictionary<int, string>();
  mappings.Add(0, "Name");
  mappings.Add(1, "Category");
  mappings.Add(3, "Date");
  mappings.Add(4, "Votes");
  
  IEnumerable<Comment> comments = csv.Reader.RetrieveDataRemoveFirstRow<Comment>(this.mappings);
  //use the bottom option if you dont want to ignore the first row
  // IEnumerable<Comment> comments = csv.Reader.RetrieveData<Comment>(this.mappings);

This approach uses the Property names from the model so it will map the types for you. There are some specific Exceptions that get thrown which are useful for deciding to ignore or continue.

Have fun!

Updated