【问题标题】:Write csv file using CsvHelper, from excel in a dynamic way c#使用 CsvHelper 以动态方式从 excel 编写 csv 文件 c#
【发布时间】:2019-08-07 07:40:47
【问题描述】:

我正在尝试从 excel 文件生成 CSV 文件。我有不同的 Excel 文件,我想阅读它们并生成一个 CSV 文件。我想这一定很容易,但我遇到了一些麻烦。

这是我应该使用的库

https://www.nuget.org/packages/CsvHelper/.

我会很感激任何教程或任何关于我如何处理这个问题的东西。 这个想法是读取我的 Excel 文件的第一行(如标题),然后读取其他行作为值,这样我就可以编写 CSV。

【问题讨论】:

  • 到目前为止你尝试过什么?您的问题非常广泛,因此很难知道您坚持哪一部分。您是否卡在打开和阅读 Excel 文件?你还在坚持使用CsvHelper 库吗?您还遇到其他问题吗?我建议把你的问题分解成更小的部分。从读取 excel 文件开始,然后转到其他部分。如果您卡在某个地方,请回来再次询问,请务必提供minimal reproducible example。
  • 是的@pstrjds 我坚持以通用方式阅读 exel 文件,因为每个 exel 都是不同的。所以我希望 exel 的第一行始终是键(csv 的列名),而其他行是值。你明白吗?
  • 我明白,但请您告诉我们您的尝试。你到底在坚持什么? excel文件打不开?您无法解析excel文件吗?请更新您的问题,以便清楚您遇到的问题。就目前而言,它太宽泛了(通过获得与编写 CSV 文件相关的答案可以证明,但您现在在 cmets 中说该问题与读取 excel 文件有关)。

标签: c# .net csv export-to-csv csvhelper


【解决方案1】:
public class Program
{
    public static void Main()
    {
        string filePath = "C:\\Users\\{User}\\Desktop\\sample.xlsx";
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
        List<List<object>> rows = new List<List<object>>();
        List<object> row = new List<object>();
        // Excel Reader
        using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
        {
            using (var reader = ExcelReaderFactory.CreateReader(stream, new ExcelReaderConfiguration
            {
                FallbackEncoding = Encoding.GetEncoding(1252),

            }))
            {
                do
                {
                    while (reader.Read())
                    {
                        row.Clear();
                        for (int i = 0; i < reader.FieldCount; i++)
                        {
                            var field = reader.GetValue(i);
                            if (field is int valueInt)
                            {
                                row.Add(valueInt);
                            }
                            else if (field is bool valueBool)
                            {
                                row.Add(valueBool);
                            }
                            else if (field is DateTime valueDate)
                            {
                                //row.Add(valueDate); You can write any condition there
                                row.Add(valueDate.Year);
                            }
                            else if (field is TimeSpan valueTime)
                            {
                                row.Add(valueTime);
                            }
                            else if (field is string valueString)
                            {
                                row.Add(valueString);
                            }
                            else if (field is null)
                            {
                                row.Add(field);
                            }
                        }
                        if (row.Any())
                        {
                            rows.Add(row);
                        }
                    }
                } while (reader.NextResult());

            }
        }
        // CSV Writer
        using (var writer = new StreamWriter("C:\\Users\\{User}\\Desktop\\sample.csv"))
        using (var csv = new CsvWriter(writer))
        {
            foreach (var i in rows)
            {
                foreach (var field in i)
                {
                    csv.WriteField(field);
                }
                csv.NextRecord();
            }
        }
    }

}

此程序将 Excel (sample.xlsx) 文件转换为 CSV(sample.csv) 文件。

依赖关系:

【讨论】:

  • 我在使用这段代码时遇到了 2 个问题,尽管我认为它可能会起作用。第一个问题是我的 exel 中有不同的类型(字符串、int-s、日期时间等),它会引发异常:Unable to cast object of type 'System.DateTime' to type 'System.String'。我试过做:row.Add(Convert.ToString(reader.GetString(i)));,但还是不行。任何想法?虽然第二个问题是ResultsCount = 4 ,但我有 179 行和 19 个不同的列。知道为什么会这样吗?读取exel文件时可能会出现问题?谢谢:) @omansak
  • 我的坏ResultsCount returns the number of sheets in the current workbook。我正在做这个
  • @Pavel 好的,你可以使用了
  • 好的@omansak 这是另外几个问题。第一个是你给我的代码抛出了一个异常:`ExcelDataReader: Index was outside the bounds of the array.`所以我稍微修改了你的代码并添加了:for (int i = 0; i &lt;= reader.FieldCount -1; i++)。 xception 消失了,但问题是当我打开 csv 时,只写了一行。任何想法?我还删除了您添加的用于解析日期时间、int、bool 等的代码,因为我只将行存储为字符串,所以我使用了:row.Add(Convert.ToString(reader.GetValue(i)));。这是一个好习惯吗?谢谢你:)
  • 我还删除了 row.Clear()。它现在似乎起作用了。我会在 1 小时内接受你的答复。我还根据我的要求编辑了代码。你可以看看。谢谢你。 @omansak:D
【解决方案2】:

创建一个类文件,其中包含与您的 excel 列相同的属性。 解析您的 excel 文件并将其加载到您的类的实例中。写一个简单的程序如下

void Main()
{
    var records = new List<Foo>
    {
        new Foo { Id = 1, Name = "one" },
    };

    using (var writer = new StreamWriter("path\\to\\file.csv"))
    using (var csv = new CsvWriter(writer))
    {
        csv.WriteRecords(records);
    }
}

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}

其中 Foo 是类文件。 希望这会有所帮助

【讨论】:

  • No @sri 这没有帮助,因为每个 exel 都有不同的行,所以我不能写一个类 Foo 。我想以动态的方式阅读它们。例如,exel 的每一行都是键(或列名),其他行是值。
  • 你的意思是说每一行会有不同的列数吗?如果不是,您始终可以从第二行读取数据并将其转换为实体
  • @Sri,不,IMO OP 说“不同的文件”(每个 excel)会有不同的列标题,他想使用同一个类来读取这些不同的 excel 文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多