如何将数据放置到CSV中的新列中使用.NET中的CsvWriter?

fzwojiic  于 12个月前  发布在  .NET
关注(0)|答案(2)|浏览(108)

我有一些数据被写入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();

这将产生如下输出fine:

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

有没有办法做到这一点?

ghhkc1vu

ghhkc1vu1#

这里是一个可行的解决方案,不需要修改很多代码。首先写入header(header指的是石油、天然气等),然后遍历header的数量,写入每个header的第一个数据值,之后您将添加一个新行并执行相同的操作,直到到达所有数据值的末尾。您还需要将ICollection更改为IList,以便可以使用索引。

using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture);
// HEADER WRITING:
// For each time series data (e.g., Oil, Gas, Water), we'll have two columns: 
// one for the timestamp and one for the value. 
// So, we iterate over the tags and write the headers accordingly.
foreach (DataTimeSeriesValues tag in tags)
{
    csvWriter.WriteField("Timestamp (UTC)"); // Write the timestamp header
    csvWriter.WriteField($"{tag.Name} ({tag.Unit})"); // Write the name of the tag with its unit (e.g., Oil (bbl))
}
csvWriter.NextRecord(); // Move to the next row after writing headers
    
// DATA WRITING:
// Determine the number of time series data available.(oil, gas)
// We are also assuming that for every header there is the same amount of data rows
int numberOfHeaders = tags[0].Values.Count;

// Loop through each header value.
for (int i = 0; i < numberOfHeaders; i++)
{
    // For each timestamp, loop through each tag (e.g., Oil, Gas, Water)
    foreach (DataTimeSeriesValues tag in tags)
    {
        csvWriter.WriteField(tag.Values[i].Timestamp); // Write the timestamp for the tag
        csvWriter.WriteField(tag.Values[i].Value);     // Write the corresponding value
    }
    csvWriter.NextRecord(); // Move to the next row after writing data for a particular Timeseries value
}
hwazgwia

hwazgwia2#

我建议你将series对象转换成一个简单对象的列表(flatten),并使用“WriteRecords”方法编写它。你可以使用dynamic objects来实现:

var records = new List<dynamic>();

dynamic record = new ExpandoObject();
record.Id = 1;
record.Name = "one";
records.Add(record);

using (var writer = new StringWriter())
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
    csv.WriteRecords(records);
    
    writer.ToString().Dump();
}

相关问题