CSVHelper - 可以编写字典列表

问题描述 投票:0回答:3

我有一个字典列表,其键列表相同,但值不同。有没有办法使用 CSVHelper 将其写入 CSV 文件?我有下面的示例代码,但显然它不起作用。

       static void Main(string[] args)
        {

            List<Dictionary<String, String>> records = new List<Dictionary<string, string>>();
            Dictionary<String, String> data1 = new Dictionary<String, String>();
            data1.Add("Name1", "Value1");
            data1.Add("Name2", "Value2");
            records.Add(data1);

            Dictionary<String, String> data2 = new Dictionary<String, String>();
            data2.Add("Name1", "Value1");
            data2.Add("Name2", "Value2");
            records.Add(data2);

            using (var writer = new StreamWriter("e:\\temp\\test.csv"))
            using (var csv = new CsvWriter(writer))
            {

                csv.WriteRecords(records);
//GEtting exception here
//CsvHelper.Configuration.CsvConfigurationException: 'Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?'

            }
        }

有什么办法可以解决吗?

谢谢!

c# csvhelper
3个回答
9
投票

我相信唯一的方法就是用手写下来。

using (var writer = new StreamWriter("e:\\temp\\test.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
    var headings = new List<string>(records.First().Keys);

    foreach (var heading in headings)
    {
        csv.WriteField(heading);
    }

    csv.NextRecord();

    foreach (var item in records)
    {
        foreach (var heading in headings)
        {
            csv.WriteField(item[heading]);
        }

        csv.NextRecord();
    }
}


0
投票

假设您有字典。 关键是你的标题名称,字符串[]是标题下的值。

// Class to convert to CSV
public class LDAPRoles
    {
        public string[] LendingUser { get; set; }
        public string[] LendingUserViewOnly { get; set; }
        public string[] CreditManagement { get; set; }
        public string[] AssistantBranchManager { get; set; }
        public string[] BranchManager { get; set; }
        public string[] CreditStaff { get; set; }
        public string[] FraudStaff { get; set; }
        public string[] DistrictManager { get; set; }
        public string[] DigitalAdvisor { get; set; }
    }

在我的控制器中:

public IActionResult DownloadRoles()
        {
            // Get proprties from class
            var propertyInfos = _ldapOptions.Roles
                .GetType()
                .GetProperties();

            // Get header names from properties
            var headerNames = propertyInfos.Select(p => p.Name)
                .ToArray();

            // Create dictionary
            var dictionary = new Dictionary<string, string[]>();
            foreach (var header in headerNames)
            {
                foreach (var prop in propertyInfos)
                {
                    if (prop.Name == header)
                    {
                        var values = (string[])prop.GetValue(_ldapOptions.Roles);
                        dictionary.Add(header, values);
                    }
                }
            }

            // Calculate max rows
            var maxRows = dictionary.Max(c => c.Value.Length);

            // Write to temp file
            var file = Path.GetTempFileName();
            using (var writer = new StreamWriter(file))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                // Headers
                foreach (var heading in headerNames)
                {
                    csv.WriteField(heading);
                }

                csv.NextRecord();

                // Insert Rows
                for (int i = 0; i < maxRows; i++)
                {
                    foreach (var heading in headerNames)
                    {
                        var values = dictionary[heading];
                        if (i > values.Length - 1)
                        {
                            // empty row
                            csv.WriteField("");
                        }
                        else
                        {
                            // write value
                            csv.WriteField(values[i]);
                        }
                    }

                    // Next record
                    csv.NextRecord();
                }
            }

            // Read the stream as a string, and write the string to the console.
            string csvText;
            using (var sr = new StreamReader(file))
            {
                csvText = sr.ReadToEnd();
            }

            var csvBytes = Encoding.ASCII.GetBytes(csvText);

            // delete temp file
            System.IO.File.Delete(file);

            Response.Headers.Add("Content-Disposition", $"attachment; filename=\"Roles.csv\"");

            return File(csvBytes, "text/csv", $"Roles.csv");
        }

0
投票

简单的方法是编写自定义转换器

public class DictionaryConverter : DefaultTypeConverter
{
    public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
    {
        if (value is Dictionary<string, int> dictionary)
        {
            foreach (var item in dictionary)
            {
                row.WriteField(item.Value);
            }
            
        }
        return null;
    }
}

注册

  Map(s => s.MyDistionary).TypeConverter<DictionaryConverter>();

该缺陷仍然需要“丑陋”的标题代码:

var headings = new List<string>(records.First().Keys);

foreach (var heading in headings)
{
    csv.WriteField(heading);
}

文档在这里

© www.soinside.com 2019 - 2024. All rights reserved.