Bhav
Bhav

Reputation: 2195

Mapping and writing a custom class to csv

I'm trying to output some data to a CSV file using CsvHelper. One row for each instance of CSVExport below. Each row could have varying number of columns as the length on Stores could be different. The mapping works for the first three properties (CurrencyCode, StoreCode, OutletTradingName) but I'm having issues with the List<Stores> Stores.

I currently get the following error message with the below code:

{"Converting IEnumerable types is not supported for a single field. If you want to do this, create your own ITypeConverter and register it in the TypeConverterFactory by calling AddConverter."}

Any suggestions on how to resolve this?

C# code to write to csv file:

var memoryStream = new System.IO.MemoryStream();
var streamWriter = new System.IO.StreamWriter(memoryStream);
using (var csvWriter = new CsvWriter(streamWriter))
{
    csvWriter.Configuration.RegisterClassMap<CSVExportMap>();
    csvWriter.WriteRecords(csvExport);
    streamWriter.Flush();
}

mapping:

public sealed class CSVExportMap : CsvClassMap<CSVExport>
{
    public CSVExportMap()
    {
        Map(m => m.CurrencyCode).Name("Outlet Currency").Default("Not available.");
        Map(m => m.StoreCode).Name("Store No.").Default("Not available.");
        Map(m => m.OutletTradingName).Name("Outlet Trading  Name").Default("Not available.");

        // if I comment this line out, I get no error but no list of stores
        Map(m => m.Stores).ConvertUsing( row => new List<Stores> { row.GetRecord<Stores>() } );
    }
}

Class I'm trying to output to CSV file:

public class CSVExport
{
    public string StoreCode { get; set; }
    public string OutletTradingName { get; set; }
    public string CurrencyCode { get; set; }
    public List<Stores> Stores { get; set; }
}

public class Stores
{
    public string Name { get; set; }
    public string StoreCode { get; set; }
    public string ID { get; set; }
}

Upvotes: 0

Views: 1621

Answers (1)

MRK
MRK

Reputation: 316

Make sure you have latest version of CsvHelper. (currently v7.1.1) I tried your code and replaced this line:

Map(m => m.Stores).ConvertUsing( row => new List<Stores> { row.GetRecord<Stores>() } );

with this:

Map(m => m.Stores).ConvertUsing(row =>
{
    var list = new List<Store>();
    list.Add(row.GetField<Store>(2));
    return list;
});

Or shorter (One Liner):

Map(m => m.Stores).ConvertUsing(row => new List<Store> {row.GetField<Store>(2)});

and program worked without problem. Index in GetField<Store>(2) is zero-based and your Store class have 3 members. I just rename your Stores class to Store (Only for naming convention! It was confusing with Stores list property! Sorry)

I used this tip: Writing a collection that contains collections

Upvotes: 2

Related Questions