Dynamic creation of columns using csvHelper

走远了吗. 提交于 2019-12-12 09:36:15

问题


I have a worker with various fields that are fetched from server. I am using CSVHelper package to convert this class to an excel sheet. Worker has Fields like :

class Worker
{ 
string name;
string phone;
string age;
Dictionary<string,object> customerField;
}

I can map the name, phone, number like

class WorkerMap : CsvClassMap<Worker>
{
public WorkerMap()
{
Map(m => m.name);
Map(m => m.phone);
Map(m => m.age);
}
}

And I generate the map by :

csv.Configuration.RegisterClassMap<WorkerMap>();

Write the list of workers by :

csv.WriteRecords(workerList);

How can I map the customerField dictionary to the excel sheet such that the Key (string) is another column name and the value(object) is the value of the column.

Does CSVHelper help us do it at runtime. I looked through the documentation. Couldn't find anything that worked for me.


回答1:


I don't think that writing a dictionary is supported at this time. For one thing, CsvHelper would have a difficult time knowing what headers to write. Fortunately, it's not too complex to use CsvWriter manually, writing a field at a time. If we assume that each Worker has the same keys in customerField then your code might look something like this.

var firstWorker = workerList.First();
var keys = firstWorker.customerField.Keys.ToList();

var headers = new []{ "name", "phone", "age"}.Concat(keys).ToList();
var csv = new CsvWriter( textWriter );

// Write the headers
foreach( var header in headers )
{
    csv.WriteField(header);
}
csv.NextRecord();

// Write the rows
foreach( var item in workerList)
{
    csv.WriteField(item.name);
    csv.WriteField(item.phone);
    csv.WriteField(item.age);
    var dict = worker.customerField;
    foreach (var key in keys)
    {
        csv.WriteField(dict[key]);
    }
    csv.NextRecord();
}

This code is untested, but should get you pretty close to the behavior you need. If the customerField dictionary keys are not consistent in the list then the code would be a bit more complicated but it's still solvable.




回答2:


Dictionary isn't supported but ExpandoObject is supported.

https://github.com/JoshClose/CsvHelper/blob/48e70742e06007dae3a635c418b7e3358f667c4f/src/CsvHelper.Tests/Writing/MultipleHeadersTest.cs

https://github.com/JoshClose/CsvHelper/blob/b74a2f95a101158f4cdedd25fae6e8392b58855b/src/CsvHelper.Tests/Writing/DynamicTests.cs

If you follow the first link above you'll find the WriteDynamicHeader method in use on lines 50 & 57.

With help of an extension method I create an ExpandoObject for each record and use CsvHelper to write that object.The Dictionary<string, object> parameter named document is what I wish to create the CSV record from.

public static class DictionaryCsvExtentions
{
    public static dynamic BuildCsvObject(this Dictionary<string, object> document)
    {
        dynamic csvObj = new ExpandoObject();

        foreach (var p in document)
        {
            AddProperty(csvObj, p.Key, p.Value);
        }

        return csvObj;
    }

    private static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
    {
        var expandoDict = expando as IDictionary<string, object>;
        if (expandoDict.ContainsKey(propertyName))
        {
            expandoDict[propertyName] = propertyValue;
        }
        else
        {
            expandoDict.Add(propertyName, propertyValue);
        }
    }
}

Now I can create an ExpandoObject from my dictionary like this

var csvObj = myDictonary.BuildCsvObject();

and with that, following Josh's tests in the link above we have all we need to use a dictionary fairly seamlessly with CsvHelper. I don't think this is a better solution to Michael's, just a different approach.

credit where credit is due the basic ExpandoObject from dictionary code is from here (where there is a lot more explanation!) https://www.oreilly.com/learning/building-c-objects-dynamically



来源:https://stackoverflow.com/questions/42134421/dynamic-creation-of-columns-using-csvhelper

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!