timyrik20
timyrik20

Reputation: 77

How write header of not flat class using CSVHelper?

public class Class1
{
    [CsvField(Name = "Field1")]
    public int Field1 { get; set; }

    [CsvField(Name = "Field2")]
    public int Field2 { get; set; }

    [CsvField(Ignore = true)]
    public Class2 Class2 { get; set; }

    [CsvField(Ignore = true)]
    public Class3 Class3 { get; set; }
}

public class Class2
{
    [CsvField(Name = "Field3")]
    public int Field3 { get; set; }

    [CsvField(Name = "Field4")]
    public int Field4 { get; set; }
}

public class Class3
{
    [CsvField(Name = "Field5")]
    public int Field5 { get; set; }

    [CsvField(Name = "Field6")]
    public int Field6 { get; set; }
}

I'm using CSVHelper to write data into CSV file. I need write Class1 with header like this:

Field1, Field2, Field3, Field4, Field5, Field6

How I can do this?

Upvotes: 2

Views: 3904

Answers (2)

Awais akhtar
Awais akhtar

Reputation: 1

look at this

    foreach (var item in Collection)
    {
        csv.WriteField(item.Field1);
        csv.WriteField(item.Field2);
        csv.WriteField(item.Class2.Field3);
        csv.WriteField(item.Class2.Field4);
        csv.WriteField(item.Class3.Field5);
        csv.WriteField(item.Class3.Field6);

        // Write out end line
        csv.NextRecord();
    }
}

}

Upvotes: 0

drneel
drneel

Reputation: 2907

This is an old question, so you likely already have an answer. You have a few options.

Option 1 (that I know will work) Documentation

You just need to manually write out the contents of the CSV, below is some code that will get you started, but you'll need to modify based on how the contents of your objects are stored.

using (var stream = new MemoryStream())
{
    using (var streamWriter = new StreamWriter(stream))
    using (var csv = new CsvWriter(streamWriter))
    {
        // Write out header
        csv.WriteField("Field1");
        csv.WriteField("Field2");
        csv.WriteField("Field3");
        csv.WriteField("Field4");
        csv.WriteField("Field5");
        csv.WriteField("Field6");

        // Write out end line
        csv.NextRecord();

        //Pseudocode
        foreach (var item in Class1Collection)
        {
            csv.WriteField(item.Field1);
            csv.WriteField(item.Field2);
            csv.WriteField(item.Class2.Field3);
            csv.WriteField(item.Class2.Field4);
            csv.WriteField(item.Class3.Field5);
            csv.WriteField(item.Class3.Field6);

            // Write out end line
            csv.NextRecord();
        }
    }
}

Option 2 (have used, but not like this) Documentation

Your second option is to write a custom CSVMap that tells the CSVWriter how to handle the nested classes. I'm not sure how to deal with the name, so you might have to work through that.

public sealed class Class1CSVMap : CsvClassMap<RemittanceFormModel>
{
    public Class1CSVMap()
    {
        Map(m => m.Field1).Name("Field1");
        Map(m => m.Field2).Name("Field2");
        Map(m => m.Class2).Name("Field3,Field4").TypeConverter<Class2Converter>();
        Map(m => m.Class3).Name("Field5,Field6").TypeConverter<Class3Converter>();
    }
}

Then you have your converter, one for Class2 and one for Class3

public class Class2Converter : DefaultTypeConverter
{
    public override string ConvertToString(TypeConverterOptions options, object model)
    {
        var result = string.Empty;

        var classObject = model as Class2;

        if (classObject != null)
        {
            result = string.Format("{0},{1}", classObject.Field3, classObject.Field4);
        }

        return result;
    }
}

Option 3 (have never used) Documentation

You can do an inline converter instead of creating a separate class. I've never tried this, but it should work.

public sealed class Class1CSVMap : CsvClassMap<Class1>
{
    public Class1CSVMap()
    {
            Map(m => m.Field1).Name("Field1");
            Map(m => m.Field2).Name("Field2");
            Map(m => m.Class2).Name("Field3,Field4").ConvertUsing(row =>  string.Format("{0},{1}", row.Field3, row.Field4); );
            Map(m => m.Class3).Name("Field5,Field6").ConvertUsing(row =>  string.Format("{0},{1}", row.Field5, row.Field6); );
    }
}

Upvotes: 5

Related Questions