使用csvHelper动态创建列

hyo*_*oma 10 c# export-to-csv xamarin csvhelper xamarin.forms

我有一个工作人员,从服务器获取各种字段.我正在使用CSVHelper包将此类转换为excel表.工人有像:

class Worker
{ 
string name;
string phone;
string age;
Dictionary<string,object> customerField;
}
Run Code Online (Sandbox Code Playgroud)

我可以映射姓名,电话,号码等

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

我通过以下方式生成地图:

csv.Configuration.RegisterClassMap<WorkerMap>();
Run Code Online (Sandbox Code Playgroud)

写下工人名单:

csv.WriteRecords(workerList);
Run Code Online (Sandbox Code Playgroud)

如何将customerField字典映射到Excel工作表,以便Key(字符串)是另一个列名,值(object)是列的值.

CSVHelper是否帮助我们在运行时执行此操作.我查看了文档.找不到任何对我有用的东西.

Mic*_*son 13

我不认为此时支持编写字典.首先,CsvHelper很难知道要写什么标题.幸运的是,手动使用CsvWriter并不是太复杂,一次写一个字段.如果我们假设每个Worker具有相同的密钥,customerField那么您的代码可能看起来像这样.

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();
}
Run Code Online (Sandbox Code Playgroud)

此代码未经测试,但应该让您非常接近所需的行为.如果列表中的customerField字典键不一致,那么代码会有点复杂,但仍然可以解决.


rob*_*obs 5

不支持字典,但支持ExpandoObject。

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

如果您点击上面的第一个链接,您会发现第50和57行使用的WriteDynamicHeader方法。

借助于扩展方法,我为每个记录创建一个ExpandoObject并使用CsvHelper写入该对象.name Dictionary<string, object>参数document是我希望从中创建CSV记录的参数。

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我可以像这样从字典中创建一个ExpandoObject

var csvObj = myDictonary.BuildCsvObject();
Run Code Online (Sandbox Code Playgroud)

因此,在上面链接中的Josh测试之后,我们需要与CsvHelper完美无缝地使用字典。我认为这不是迈克尔的更好解决方案,只是一种不同的方法。

功劳归功于字典代码中的基本ExpandoObject来自此处(这里有很多解释!)https://www.oreilly.com/learning/building-c-objects-dynamically