使用CsvHelper导出dynamic动态记录时如何自定义列顺序
解决CsvHelper导出dynamic列表时的列顺序控制问题
因为dynamic类型的对象本质是ExpandoObject(实现了IDictionary<string, object>),直接用WriteRecords会按字典默认的键顺序导出,无法自定义。你可以通过手动指定列顺序,逐个写入字段值的方式实现需求,具体修改如下:
修改后的完整代码
// Requirements: // input file structure is like: Id, TradeId, Date, Value1, value2 // need to remove TradeId, Date and write like in that order : value2, Id, value1 var fileName = @"whatever path"; var configuration = new CsvConfiguration(CultureInfo.InvariantCulture) { Encoding = Encoding.UTF8, // Our file uses UTF-8 encoding. Delimiter = "," // The delimiter is a comma. }; // reading input file, removing 2 columns TradeId and Date List<dynamic> records; using (var fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var textReader = new StreamReader(fs, Encoding.UTF8)) using (var csv = new CsvReader(textReader, configuration)) { records = csv.GetRecords<dynamic>().ToList(); foreach (var record in records) { var dict = (IDictionary<string, object>)record; dict.Remove("TradeId"); dict.Remove("Date"); } } } // 定义要导出的列顺序(注意字段名大小写要和实际字典中的键一致) var exportColumnOrder = new[] { "value2", "Id", "value1" }; CsvConfiguration conf = new CsvConfiguration(CultureInfo.InvariantCulture); conf.HasHeaderRecord = false; // do not write headers using (var writer = new StreamWriter("whatever output file name")) using (var csvw = new CsvWriter(writer, conf)) { // 遍历每个记录,按指定顺序写入字段 foreach (var record in records) { var dict = (IDictionary<string, object>)record; foreach (var column in exportColumnOrder) { // 写入对应列的值,若字段不存在可加判断避免报错 csvw.WriteField(dict.TryGetValue(column, out var value) ? value : string.Empty); } // 写完当前记录,切换到下一行 csvw.NextRecord(); } }
关键说明
- 先定义
exportColumnOrder数组,明确你需要的导出顺序,注意字段名的大小写要和读取后字典中的键完全匹配(比如原文件的Value1和value2要对应准确)。 - 不再使用
csvw.WriteRecords(records),而是遍历每个记录,再按顺序遍历列名,用WriteField逐个写入值,最后调用NextRecord()换行。 - 加入
TryGetValue判断是为了避免因字段缺失导致的异常,可根据实际情况调整。
内容的提问来源于stack exchange,提问作者user1998535
相关产品推荐
相关产品推荐

