在.NET5 中读取Excel文件,评估下参加神秘献祭会的几位子民

761 阅读7分钟

在很久很久之前,使用,NET代码打开Excel文件一直是一个痛苦的经历。在许多情况下,实际上您需要在目标/用户计算机上安装的Excel应用程序才能通过代码打开excel文件。如果您以前曾经使用过那些“ OLE DB Jet”查询,那么您就知道这不是一个很好的体验。幸运的是,现在有一些相当不错的开源解决方案,不需要在目标计算机上安装excel。这对Windows用户非常有用,这样您就不必在目标用户的计算机或Web服务器上安装excel,当然更适合Linux(甚至Mac / ARM)上托管.NET Core应用程序的人们–显然Excel并不是到处被待见!

1、评估序言

我的方法很简单。用几张纸,几个公式和几个特殊格式的情况创建一个标准化的Excel工作簿。在每个单独的库中读取相同的数据,看看哪个对我最有效。简单把!让我们走几步看看!

2、注意CSV格式

有一个特殊情况,先说为敬!如果您正在读CSV或更多内容,而单个excel表格中没有公式或任何“ excel”特效,则应使用标准CSV技术对其进行解析。那种方式是更简单的一种变种。有不同的CSV解析器非常适合获取表格数据并将其反序列化为对象,因此应在可能的地方使用,不必再往下看这些复杂的东东。

3、示例数据

我认为比较提供的不同库的最好方法是创建一个简单的电子表格,以比较我们可以读取数据的不同方法。电子表格将具有两个“工作表”,第二个工作表引用第一个工作表。

  • 工作表1,如下所示

在这里插入图片描述

注意,单元格A2只是数字“ 1”。然后在B2列中,有对单元格A2的引用。这是因为我们要检查库是否允许我们不仅从单元格获取“公式”,而且还应获取计算出的值。

我们还用红色字体样式设置了单元格A2的样式,而B2具有完整的边框(尽管在尝试显示公式时很难看到)。稍后,我们将尝试提取这些样式元素。

  • 工作表2,如下所示: 在这里插入图片描述 OK,我们正在做一个简单的“ SUM”公式,并参考第一个表。同样,这样我们可以测试是否同时获取公式和计算值,但这一次跨不同的工作表。对于一个曾经使用Excel的人来说并不复杂,但是让我们看看一些库是如何处理它的。

测试的结果应该满足某种神秘的,类似三星堆青铜器的仪式感和神秘感:

Sheet 1 Data
Cell A2 Value   : 
Cell A2 Color   :
Cell B2 Formula :
Cell B2 Value   :
Cell B2 Border  :

Sheet 2 Data
Cell A2 Formula :
Cell A2 Value   :

好吧,看完神秘的三星堆法老权杖,是时候让我们的子民来场献祭考核了。

3.1 EPPlus

当我第一次开始四处寻找.NET Core中的excel解析时,我记得很多月以前使用EPPlus进行了非常轻量级的excel解析。nuget包可以在这里找到:https ://www.nuget.org/packages/EPPlus/ 。它也是开源的,因此您可以在这里阅读源代码:https: //github.com/JanKallman/EPPlus

读取我们的excel电子表格的代码如下所示:

static void Main(string[] args)
{
    using(var package = new ExcelPackage(new FileInfo("Book.xlsx")))
    {
        var firstSheet = package.Workbook.Worksheets["First Sheet"];
        Console.WriteLine("Sheet 1 Data");
        Console.WriteLine($"Cell A2 Value   : {firstSheet.Cells["A2"].Text}");
        Console.WriteLine($"Cell A2 Color   : {firstSheet.Cells["A2"].Style.Font.Color.LookupColor()}");
        Console.WriteLine($"Cell B2 Formula : {firstSheet.Cells["B2"].Formula}");
        Console.WriteLine($"Cell B2 Value   : {firstSheet.Cells["B2"].Text}");
        Console.WriteLine($"Cell B2 Border  : {firstSheet.Cells["B2"].Style.Border.Top.Style}");
        Console.WriteLine("");

        var secondSheet = package.Workbook.Worksheets["Second Sheet"];
        Console.WriteLine($"Sheet 2 Data");
        Console.WriteLine($"Cell A2 Formula : {secondSheet.Cells["A2"].Formula}");
        Console.WriteLine($"Cell A2 Value   : {secondSheet.Cells["A2"].Text}");
    }
}

看完第一位位高权重的子民的表演,我能说什么呢?(字正腔圆,端庄秀丽)。

这是超级简单,中规中矩的一次献祭表演,以至于她献的血太少(好像穿的有点多),滴在碗里,几乎看不见。

然而她完美的解析了公式与文本!我们第一张表上的样式也很容易上手。边框解析有点烦人,因为您必须检查边框的“样式”,如果它是“无”样式,则表示没有边框(与“ HasBorder”或类似的布尔值相反)。

但是我认为可能是我太挑剔了,毕竟这是第一名来献祭表演的忠实子民,好吧,我宣布,EPPlus是很美的(可以正常工作)!

3.2、 NPOI

NPOI是另外一个带有Github的开源光环的库:https : //github.com/tonyqus/npoi和Nuget在这里:https : //www.nuget.org/packages/NP…

这位子民天生魅惑之力,虽然最近的花边新闻上表明她已经有几个月没有洗澡(发布)了,但总体还算不错,因为她并不像Excel本身一年四季都有面朝大海,春暖花开(大量更新),不过也惹得某些长老院长,忍受不住某些体味,老悄悄的打她小报告,所以如果看看Github上的Issues bug风评,列表好像有点长,我告诉自己“请谨慎评估,不要被风华绝代所迷倒。”

使用NPOI读取数据的代码如下所示:

…..

实际上你知道。我为此花了很多时间来尝试找出使用NPOI的最佳方法,但是文档太糟糕了,这位美人好像不是那么容易接近。

Wiki在这里:github.com/tonyqus/npo…,它有一些示例,但是大多数/全部都是关于创建excel工作簿的。我看到他们有一个指向如何读取Excel文件的教程的链接,该教程看起来很有希望,但实际上是在读电子表格,然后将文本转储出去。

使用EPPlus后,我只是没有任何理由继续进行此操作。几乎每个百度答案都会带建议使用NPOI的人们使用StackOverflow,这些NPOI这么古怪,看来我可能没走入她的内心,一句话: 打开方式不对

3.3、ExcelDataReader

第三名来了,它也是开源的:https : //github.com/ExcelDataReader/ExcelDataReader,在Nuget上是此处的:https ://www.nuget.org/packages/Ex…

在读取Excel时,好像也有些小问题,不过搜一搜总算能找到些蛛丝马迹。

可能是被第一名引导了,我忽然觉得:简单端庄,是一种美

我想做这个工作,但是…。只是看起来一点也不直观。ExcelDataReader的工作前提是您几乎以CSV方式依次读取“行”和“列”。这样的方式处理,如果您正在寻找一个特定的单元格,那简直就是地狱。

丑是丑了点,但丑媳妇总得见公婆,请看一些示例代码:

static void Main(string[] args)
{
    System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
    using (var stream = File.Open("Book.xlsx", FileMode.Open, FileAccess.Read))
    {
        using (var reader = ExcelReaderFactory.CreateReader(stream))
        {
            do
            {
                while (reader.Read()) //Each ROW
                {
                    for (int column = 0; column < reader.FieldCount; column++)
                    {
                        //Console.WriteLine(reader.GetString(column));//Will blow up if the value is decimal etc. 
                        Console.WriteLine(reader.GetValue(column));//Get Value returns object
                    }
                }
            } while (reader.NextResult()); //Move to NEXT SHEET

        }
    }
}

第一面(Hang)特别令人讨厌(没有它,很可能会爆炸)。

“哎,自带炸弹人,我不敢当着她的面说啥了,哼,等秋后再算账吧”。

但是您会注意到,我们正在逐行地尝试获取值。最重要的是,如果值是十进制,则调用“ GetString”之类的操作将不起作用(IMO最好使用隐式强制转换)。我也找不到任何方法来获取单元格的实际公式。以上仅返回计算结果。

我本来是想“路漫漫吾将上下而求索,但长得丑,实在不好下手,这不是我要的那个献祭者”。

3.4、Syncfusion

这位身价高昂,也许是不被大众喜欢的最主要的因素。

Syncfusion是,创建付费使用的库并将其上传到nuget的烦人公司之一,然后以小字体显示您需要购买许可证。

就我个人而言,我希望看到微软不允许付费库进入公共的Nuget仓库,这完全是搞坏大好的开放时代,就像你在抖音里看见某位博主很有料,等到了她的直播间,开始大肆收费一样。

好吧,我把价格公布下,有钱人还是能买得起的,每个开发人员的许可起价为每年995美元,因此,在大多数用例中,我没有太多理由使用它。nuget页面可以在这里找到www.nuget.org/packages/Sy…

好吧,表演就省略了,直接看评语吧。

“整体表现还是很不错的,毕竟是收费的,专业素质还是有的。 唯一的小缺憾就是对各类风格的解析不那么流畅。你懂得,毕竟是制式服务!”

4. 小结

看完各位献祭者的表演,我推荐使用 github.com/JanKallman/…

本次文风好像有些变化,也算是一种新尝试吧。反正看的人也不多,自娱自乐一乐。

写文章很累的!关注作者不迷路,一键三连你最棒!