Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write only selected class fields into CSV with CsvHelper?

I use CsvHelper to read and write CSV files and it is great, yet I don't understand how to write only selected type fields.

Say we had:

using CsvHelper.Configuration;

namespace Project
{
    public class DataView
    {
        [CsvField(Name = "N")]
        public string ElementId { get; private set; }

        [CsvField(Name = "Quantity")]
        public double ResultQuantity { get; private set; }

        public DataView(string id, double result)
        {
            ElementId = id;
            ResultQuantity = result;
        }
    }
}

and we wanted to exclude "Quantity" CsvField from resulting CSV file that we currently generate via something like:

using (var myStream = saveFileDialog1.OpenFile())
{
    using (var writer = new CsvWriter(new StreamWriter(myStream)))
    {
        writer.Configuration.Delimiter = '\t';
        writer.WriteHeader(typeof(ResultView));
        _researchResults.ForEach(writer.WriteRecord);
    }
}

What could I use to dynamically exclude a type field from the CSV?

If it is necessary we could process the resulting file, yet I do not know how to remove an entire CSV column with CsvHelper.

like image 245
myWallJSON Avatar asked Apr 16 '13 21:04

myWallJSON


2 Answers

I recently needed to achieve a similar result by determining what fields to include at runtime. This was my approach:

  1. Create a mapping file to map which fields I need at runtime by passing in an enum into the class constructor

    public sealed class MyClassMap : CsvClassMap<MyClass>
    {
        public MyClassMap(ClassType type)
        {
            switch (type)
            {
                case ClassType.TypeOdd
                    Map(m => m.Field1);
                    Map(m => m.Field3);
                    Map(m => m.Field5);                 
                    break;
                case ClassType.TypeEven:
                    Map(m => m.Field2);
                    Map(m => m.Field4);
                    Map(m => m.Field6);                 
                    break;
                case ClassType.TypeAll:
                    Map(m => m.Field1);
                    Map(m => m.Field2);
                    Map(m => m.Field3);
                    Map(m => m.Field4);
                    Map(m => m.Field5);
                    Map(m => m.Field6);                 
                    break;
            }
        }
    }
    
  2. Write out the records to using the mapping configuration

    using (var memoryStream = new MemoryStream())
    using (var streamWriter = new StreamWriter(memoryStream))
    using (var csvWriter = new CsvWriter(streamWriter))
    {
        csvWriter.Configuration.RegisterClassMap(new MyClassMap(ClassType.TypeOdd));
        csvWriter.WriteRecords(records);
        streamWriter.Flush();
        return memoryStream.ToArray();
    }
    
like image 175
Mark Erasmus Avatar answered Nov 15 '22 21:11

Mark Erasmus


Mark the field like this:

[CsvField( Ignore = true )]
public double ResultQuantity { get; private set; }

Update: Nevermind. I see you want to do this at runtime, rather than compile time. I'll leave this up as red flag for anyone else who might make the same mistake.

like image 25
Joel Coehoorn Avatar answered Nov 15 '22 20:11

Joel Coehoorn