Csvhelper: Can CsvHelper store the CSV row number in the mapped object?

Created on 15 Nov 2017  路  7Comments  路  Source: JoshClose/CsvHelper

Hello!

I'm mapping my CSV records to a concrete object and I was wondering if there's a way to persist the row number in the concrete object?

I have a mapped object that looks like this:

public class CsvRowDto {
  public string FirstName {get; set;}
  public string LastName {get; set;}
}

And I'm trying to achieve something like this:

public class CsvRowDto {
  public int RowNumber {get; set;}
  public string FirstName {get; set;}
  public string LastName {get; set;}
}

The use case for this is to provide better error reporting. When my application detects a validation/business rule error I'd like to report the row number that had an error.

var records = csvReader.GetRecords<CsvRowDto>().ToList();

foreach(var person in records) {
  if(string.IsNullOrEmpty(person.FirstName)) {
    Console.WriteLine("First name is invalid: " + person.RowNumber);
  }
}

Most helpful comment

You'll want the file's line number then. A single CSV row may span many lines because a field could contain a '\r\n'.

void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name");
        writer.WriteLine("1,one");
        writer.WriteLine("2,two");
        writer.Flush();
        stream.Position = 0;

        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().ToList().Dump();
    }
}

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int RowNumber { get; set; }
}

public sealed class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.RowNumber).ConvertUsing(row => row.Context.RawRow);
    }
}

All 7 comments

Text file row number or CSV row number? Meaning, a CSV field may have a \r\n in it.

That's a quick response! :)

I think CSV row number?... I'm not certain on the differences between the two. The text file row number includes blank lines, right?

Let's say that you are a end user of my application and you upload a CSV. When my system detects an error it needs to tell you which row you should take a look at in the CSV file to find and fix the issue....

So... I think I need the CSV row number?

You'll want the file's line number then. A single CSV row may span many lines because a field could contain a '\r\n'.

void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name");
        writer.WriteLine("1,one");
        writer.WriteLine("2,two");
        writer.Flush();
        stream.Position = 0;

        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().ToList().Dump();
    }
}

public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int RowNumber { get; set; }
}

public sealed class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.RowNumber).ConvertUsing(row => row.Context.RawRow);
    }
}

Also, when an exception occurs, that information is available in the exception too.

Wonderful! @JoshClose That solved my question. Using Map(m => m.RowNumber).ConvertUsing(row => row.Context.RawRow); works like a charm.

Hi,
If the content of records span across multiples rows, the actual row number in the document is returned instead of record number, how do we get record number in csv in such a case
Thank you!

Use Row instead of RawRow.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

KuraiAndras picture KuraiAndras  路  5Comments

Wagimo picture Wagimo  路  4Comments

mabead picture mabead  路  3Comments

JoshClose picture JoshClose  路  5Comments

DmitryEfimenko picture DmitryEfimenko  路  3Comments