.NET中如何使用CsvWriter实现CSV多列横向写入时间序列数据?
问题:如何将多组时间序列数据按横向多列格式写入CSV?
我有一些写入CSV文件的数据,在Excel中打开时显示为2列。我想添加多个表头并将值写入对应的列中,实现横向排列多组时间序列的格式。
数据定义
public class DataTimeSeriesValues { public string Name { get; set; } public string Unit { get; set; } public ICollection<DataValue> Values { get; set; } public static List<DataTimeSeriesValues> Get() { var tags = new List<DataTimeSeriesValues>(); var random = new Random(); var oil = new DataTimeSeriesValues { Name = "Oil", Unit = "bbl", Values = new List<DataValue>() }; var gas = new DataTimeSeriesValues { Name = "Gas", Unit = "mmscf", Values = new List<DataValue>() }; var water = new DataTimeSeriesValues { Name = "Water", Unit = "bbl", Values = new List<DataValue>() }; for (int i = 0; i < 2; i++) { oil.Values.Add(new DataValue { Timestamp = DateTime.UtcNow.AddMinutes(i), Value = random.Next(1, 100).ToString() }); gas.Values.Add(new DataValue { Timestamp = DateTime.UtcNow.AddMinutes(i), Value = random.Next(1, 100).ToString() }); water.Values.Add(new DataValue { Timestamp = DateTime.UtcNow.AddMinutes(i), Value = random.Next(1, 100).ToString() }); } tags.Add(oil); tags.Add(gas); tags.Add(water); return tags; } } public class DataValue { public DateTime Timestamp { get; set; } public string Value { get; set; } }
当前写入CSV的代码
string csvPath = Path.Combine(folderPath, $"{task.Name}_{DateTime.UtcNow:ddMMyyyyHHmmss}.csv"); var streamWriter = new StreamWriter(csvPath); var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture); List<DataTimeSeriesValues> tags = DataTimeSeriesValues.Get(); foreach(DataTimeSeriesValues tag in tags) { csvWriter.WriteField("Timestamp (UTC)"); csvWriter.WriteField($"{tag.Name} ({tag.Unit})"); csvWriter.NextRecord(); foreach(DataValue value in tag.Values) { csvWriter.WriteField(value.Timestamp); csvWriter.WriteField(value.Value); csvWriter.NextRecord(); } } streamWriter.Flush(); streamWriter.Close();
当前输出
Timestamp UTC,Oil (bbl) 09/12/2023 05:52:03,72 09/12/2023 05:53:03,98 Timestamp UTC,Gas (mmscf) 09/12/2023 05:52:03,21 09/12/2023 05:53:03,20 Timestamp UTC,Water (bbl) 09/12/2023 05:52:03,37 09/12/2023 05:53:03,45
期望输出
Timestamp UTC,Oil (bbl),Timestamp UTC,Gas (mmscf),Timestamp UTC,Water (bbl) 09/12/2023 05:52:03,72,09/12/2023 05:52:03,21,09/12/2023 05:52:03,37 09/12/2023 05:53:03,98,09/12/2023 05:53:03,20,09/12/2023 05:53:03,45
解决方案
可以实现这种格式,核心思路是先一次性生成完整的表头行,再按时间序列的索引逐行拼接所有标签对应位置的数据。修改后的代码如下:
string csvPath = Path.Combine(folderPath, $"{task.Name}_{DateTime.UtcNow:ddMMyyyyHHmmss}.csv"); using var streamWriter = new StreamWriter(csvPath); using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture); List<DataTimeSeriesValues> tags = DataTimeSeriesValues.Get(); // 写入表头行 foreach (var tag in tags) { csvWriter.WriteField("Timestamp (UTC)"); csvWriter.WriteField($"{tag.Name} ({tag.Unit})"); } csvWriter.NextRecord(); // 按索引逐行写入所有标签的数据 // 假设所有标签的Values数量一致,取第一个标签的长度作为循环次数 int rowCount = tags.First().Values.Count; for (int i = 0; i < rowCount; i++) { foreach (var tag in tags) { var dataValue = tag.Values.ElementAt(i); csvWriter.WriteField(dataValue.Timestamp); csvWriter.WriteField(dataValue.Value); } csvWriter.NextRecord(); } // using语句会自动处理Flush和Close,无需手动调用
说明
- 表头处理:遍历所有标签,依次写入每个标签的时间戳表头和数值表头,形成横向的完整表头。
- 数据行处理:通过索引循环,每次取出每个标签对应位置的
DataValue,将时间戳和值写入同一行的对应列。 - 注意事项:代码假设所有标签的时间序列长度相同,如果存在长度不一致的情况,需要额外处理(比如补空值或截断到最短长度)。
内容的提问来源于stack exchange,提问作者tangel
相关产品推荐
相关产品推荐

