【问题标题】:Reading Excel files from C#从 C# 读取 Excel 文件
【发布时间】:2010-09-06 03:52:11
【问题描述】:

是否有免费或开源库可以直接从 C# 程序读取 Excel 文件 (.xls)?

不需要太花哨,只需选择一个工作表并将数据读取为字符串即可。到目前为止,我一直在使用 Excel 的导出到 Unicode 文本功能,并解析生成的(制表符分隔的)文件,但我想消除手动步骤。

【问题讨论】:

    标签: c# .net excel ms-office


    【解决方案1】:

    您可以编写一个 excel 电子表格来加载给定的 excel 电子表格并将其保存为 csv(而不是手动执行)。

    然后你可以从 c# 中自动化。

    一旦它在 csv 中,c# 程序就可以理解它。

    (另外,如果有人让你用excel编程,最好假装你不知道)

    (编辑:是的,rob 和 ryan 都是对的)

    【讨论】:

      【解决方案2】:

      我知道人们一直在为此目的制作 Excel“扩展”。
      您或多或少在 Excel 中制作了一个“导出到程序 X”按钮,然后以程序可以读取的格式导出和发送数据。

      http://msdn.microsoft.com/en-us/library/ms186213.aspx 应该是一个不错的起点。

      祝你好运

      【讨论】:

        【解决方案3】:

        如果我在这里跑题了,请原谅我,但这不是Office PIA's 的用途吗?

        【讨论】:

        • 是的,但这将涉及创建 Excel.Application 实例、加载 xls 文件等。如果要求纯粹是从文件中读取一些数据,那么使用起来会更容易、更轻量级其他答案中描述的 ADO.NET 方法之一。
        • 太慢了,使用 Office PIA 作为基线,其他一切都更快 - 即使只是使用从 .Value2 属性传递的对象数组。仍在使用 PIA。
        【解决方案4】:

        如果只是 Excel 文件中包含的简单数据,您可以通过 ADO.NET 读取数据。请参阅此处列出的连接字符串:

        http://www.connectionstrings.com/?carrier=excel2007 要么 http://www.connectionstrings.com/?carrier=excel

        -瑞恩

        更新:那么您可以通过 select * from [Sheet1$] 之类的方式阅读工作表

        【讨论】:

        • 这种方式是目前最快的。
        • 这当然不是真的,Stingy。您必须筛选所有数据并编写糟糕的数据库代码(手工制作模型,将列映射到属性,yadda yadda)。最快的方法是让其他可怜的 SOB 为你做这件事。这就是为什么人们使用框架而不是自下而上编写所有内容的原因。
        • 没用的方法!读取时将文本列截断为 255 个字符。谨防!请参阅:stackoverflow.com/questions/1519288/… ACE 引擎做同样的事情!
        • 请注意,使用 ADO.NET 从 exel 读取数据需要安装 Microsoft Access 或 Microsoft Access Database Engine Redistributable。
        • 驱动程序还将根据前几行猜测列类型。如果您有一列在第一行中看起来像整数,那么当您遇到非整数(例如浮点数、字符串)时会遇到错误
        【解决方案5】:

        不是免费的,但在最新的 Office 中,有一个非常很好的自动化 .Net API。 (很久以前就有一个 API,但它是讨厌的 COM)你可以在代码中做你想要/需要的一切,而 Office 应用程序仍然是一个隐藏的后台进程。

        【讨论】:

        • @Anonymous-type 我确实阅读了这个问题,并为所需的 OSS 实现提供了一个有用的替代方案......因为,我很确定没有任何可用的东西。而且,从接受的答案来看,安装 Office 的要求不是问题。
        【解决方案6】:

        刚刚做了一个需要管理一些 excel 文件的快速演示项目。 GemBox 软件的 .NET 组件足以满足我的需要。它有一个免费版本,但有一些限制。

        http://www.gemboxsoftware.com/GBSpreadsheet.htm

        【讨论】:

        • 仅供参考:我试过了,但它不能满足我读取加密文件的需要。
        【解决方案7】:

        这是我几年前使用 .NET 1.1 用 C# 编写的一些代码。不确定这是否正是您所需要的(并且可能不是我最好的代码:))。

        using System;
        using System.Data;
        using System.Data.OleDb;
        
        namespace ExportExcelToAccess
        {
            /// <summary>
            /// Summary description for ExcelHelper.
            /// </summary>
            public sealed class ExcelHelper
            {
                private const string CONNECTION_STRING = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=<FILENAME>;Extended Properties=\"Excel 8.0;HDR=Yes;\";";
        
                public static DataTable GetDataTableFromExcelFile(string fullFileName, ref string sheetName)
                {
                    OleDbConnection objConnection = new OleDbConnection();
                    objConnection = new OleDbConnection(CONNECTION_STRING.Replace("<FILENAME>", fullFileName));
                    DataSet dsImport = new DataSet();
        
                    try
                    {
                        objConnection.Open();
        
                        DataTable dtSchema = objConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
        
                        if( (null == dtSchema) || ( dtSchema.Rows.Count <= 0 ) )
                        {
                            //raise exception if needed
                        }
        
                        if( (null != sheetName) && (0 != sheetName.Length))
                        {
                            if( !CheckIfSheetNameExists(sheetName, dtSchema) )
                            {
                                //raise exception if needed
                            }
                        }
                        else
                        {
                            //Reading the first sheet name from the Excel file.
                            sheetName = dtSchema.Rows[0]["TABLE_NAME"].ToString();
                        }
        
                        new OleDbDataAdapter("SELECT * FROM [" + sheetName + "]", objConnection ).Fill(dsImport);
                    }
                    catch (Exception)
                    {
                        //raise exception if needed
                    }
                    finally
                    {
                        // Clean up.
                        if(objConnection != null)
                        {
                            objConnection.Close();
                            objConnection.Dispose();
                        }
                    }
        
        
                    return dsImport.Tables[0];
                    #region Commented code for importing data from CSV file.
                    //              string strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +"Data Source=" + System.IO.Path.GetDirectoryName(fullFileName) +";" +"Extended Properties=\"Text;HDR=YES;FMT=Delimited\"";
                    //
                    //              System.Data.OleDb.OleDbConnection conText = new System.Data.OleDb.OleDbConnection(strConnectionString);
                    //              new System.Data.OleDb.OleDbDataAdapter("SELECT * FROM " + System.IO.Path.GetFileName(fullFileName).Replace(".", "#"), conText).Fill(dsImport);
                    //              return dsImport.Tables[0];
        
                    #endregion
                }
        
                /// <summary>
                /// This method checks if the user entered sheetName exists in the Schema Table
                /// </summary>
                /// <param name="sheetName">Sheet name to be verified</param>
                /// <param name="dtSchema">schema table </param>
                private static bool CheckIfSheetNameExists(string sheetName, DataTable dtSchema)
                {
                    foreach(DataRow dataRow in dtSchema.Rows)
                    {
                        if( sheetName == dataRow["TABLE_NAME"].ToString() )
                        {
                            return true;
                        }   
                    }
                    return false;
                }
            }
        }
        

        【讨论】:

        • 完全同意 Cherian。这段代码已有很多年历史了......在我精通 Resharper 之前:)
        • 代码很难看,但它显示了如何获取工作表名称,太棒了!
        【解决方案8】:
        var fileName = string.Format("{0}\\fileNameHere", Directory.GetCurrentDirectory());
        var connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=Excel 8.0;", fileName);
        
        var adapter = new OleDbDataAdapter("SELECT * FROM [workSheetNameHere$]", connectionString);
        var ds = new DataSet();
        
        adapter.Fill(ds, "anyNameHere");
        
        DataTable data = ds.Tables["anyNameHere"];
        

        这是我通常使用的。这有点不同,因为我通常在表格的编辑处粘贴一个 AsEnumerable():

        var data = ds.Tables["anyNameHere"].AsEnumerable();
        

        因为这让我可以使用 LINQ 从字段中搜索和构建结构。

        var query = data.Where(x => x.Field<string>("phoneNumber") != string.Empty).Select(x =>
                        new MyContact
                            {
                                firstName= x.Field<string>("First Name"),
                                lastName = x.Field<string>("Last Name"),
                                phoneNumber =x.Field<string>("Phone Number"),
                            });
        

        【讨论】:

        • 如果这种方法中的 Select 似乎试图猜测列的数据类型并强制该猜测的数据类型。例如,如果您有一个主要包含双值的列,它不会喜欢您传递 x.Field,但需要 x.Field。这是真的吗?
        • 刚在 MSDN 上查了一下。看起来 只是用于尝试将列中的内容转换为类型。在此示例中,只是将列中的数据转换为字符串。如果您想要双精度,则需要调用 double.Parse(x.Field("Cost") 或类似的方法。Field 是 DataRow 的扩展方法,看起来没有非通用版本。
        • 向 Linq 查询添加 double.Parse 是否会减慢速度?
        • 请注意,如果您正在阅读xlsx,则需要使用此连接字符串:string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=Excel 12.0;", fileName)
        • 遗憾的是 Jet.OLEDB 驱动程序不兼容 64 位;您将需要切换到目标 x86 而不是 Any CPU(如果您仍想继续使用此方法)。或者安装 64 位 ACE 驱动程序并更改连接字符串以使用此驱动程序(如 Andreas 所示) - microsoft.com/en-us/download/…
        【解决方案9】:

        ADO.NET 方法既快速又简单,但它有一些您应该注意的怪癖,尤其是关于如何处理 DataTypes。

        这篇优秀的文章将帮助您避免一些常见的陷阱: http://blog.lab49.com/archives/196

        【讨论】:

        • 你回答了我的问题(以上面评论的形式)。
        【解决方案10】:

        前段时间,我用 C# 从 Excel 文件中读取了很多内容,我们使用了两种方法:

        • COM API,您可以在其中直接访问 Excel 的对象并通过方法和属性对其进行操作
        • 允许像数据库一样使用 Excel 的 ODBC 驱动程序。

        后一种方法要快得多:通过 COM 读取具有 20 列和 200 行的大表需要 30 秒,而通过 ODBC 则需要半秒。因此,如果您只需要数据,我会推荐数据库方法。

        干杯,

        卡尔

        【讨论】:

          【解决方案11】:

          虽然您确实特别要求 .xls,暗示较旧的文件格式,但对于 OpenXML 格式(例如 xlsx),我强烈推荐 OpenXML SDK (http://msdn.microsoft.com/en-us/library/bb448854.aspx)

          【讨论】:

            【解决方案12】:

            我推荐 FileHelpers 库,它是一个免费且易于使用的 .NET 库,用于从 EXCEL 导入/导出数据,文件、字符串或流中的固定长度或分隔记录 + 更多。

            Excel 数据链接文档部分 http://filehelpers.sourceforge.net/example_exceldatalink.html

            【讨论】:

            • 我不会让你失望的,但我最近开始使用 FileHelpers 并且对它的糟糕程度感到震惊。例如,将 csv 中的列映射到属性的唯一方法……对不起,FIELDS,模型是按列的顺序创建字段。我不了解你,但我不会依赖编译器的怪癖来作为我的 f8king 框架的最核心设计考虑因素之一。
            【解决方案13】:

            最近,部分是为了在 LINQ 方面做得更好......我一直在使用 Excel 的自动化 API 将文件保存为 XML 电子表格,然后使用 LINQ to XML 处理该文件。

            【讨论】:

            • 我怀疑你可以保护它免受 Excel 的影响,但不能保护它免受带有编译器的人的影响......就像任何东西......它只是字节。
            • @gsvirdi,发布一个关于 Excel 文件安全性的单独问题,这个问题是关于性能的。
            【解决方案14】:

            这是我用于 Excel 2003 的:

            Dictionary<string, string> props = new Dictionary<string, string>();
            props["Provider"] = "Microsoft.Jet.OLEDB.4.0";
            props["Data Source"] = repFile;
            props["Extended Properties"] = "Excel 8.0";
            
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, string> prop in props)
            {
                sb.Append(prop.Key);
                sb.Append('=');
                sb.Append(prop.Value);
                sb.Append(';');
            }
            string properties = sb.ToString();
            
            using (OleDbConnection conn = new OleDbConnection(properties))
            {
                conn.Open();
                DataSet ds = new DataSet();
                string columns = String.Join(",", columnNames.ToArray());
                using (OleDbDataAdapter da = new OleDbDataAdapter(
                    "SELECT " + columns + " FROM [" + worksheet + "$]", conn))
                {
                    DataTable dt = new DataTable(tableName);
                    da.Fill(dt);
                    ds.Tables.Add(dt);
                }
            }
            

            【讨论】:

            • 工作表未定义...在明确定义其他所有内容后,我觉得有点奇怪。
            【解决方案15】:

            Koogra 是一个用 C# 编写的开源组件,用于读写 Excel 文件。

            【讨论】:

            • 与 NPOI 相比,看起来不再特别活跃
            【解决方案16】:

            SpreadsheetGear for .NET 是一个与 Excel 兼容的 .NET 电子表格组件。您可以在我们的product page 右侧看到我们的客户对性能的评价。您可以通过免费、功能齐全的evaluation 自己尝试。

            【讨论】:

              【解决方案17】:

              ExcelMapper 是一个开源工具 (http://code.google.com/p/excelmapper/),可用于将 Excel 工作表作为强类型对象读取。它同时支持 xls 和 xlsx 格式。

              【讨论】:

                【解决方案18】:

                我刚刚使用ExcelLibrary 将 .xls 电子表格加载到数据集中。对我来说效果很好。

                【讨论】:

                  【解决方案19】:

                  SmartXLS是另一个excel电子表格组件,支持excel图表、公式引擎的大部分功能,可以读写excel2007 openxml格式。

                  【讨论】:

                    【解决方案20】:

                    Excel Package 是一个开源 (GPL) 组件,用于读取/写入 Excel 2007 文件。我在一个小项目上使用它,API 很简单。仅适用于 XLSX (Excel 200&),不适用于 XLS。

                    源代码也似乎组织良好且易于使用(如果您需要像我一样扩展功能或修复小问题)。

                    起初,我尝试了 ADO.Net(Excel 连接字符串)方法,但它充满了讨厌的 hack——例如,如果 second 行包含一个数字,它将返回所有整数下方列中的字段,然后悄悄删除任何不适合的数据。

                    【讨论】:

                      【解决方案21】:

                      您可以尝试使用这个开源解决方案,让处理 Excel 变得更加简洁。

                      http://excelwrapperdotnet.codeplex.com/

                      【讨论】:

                        【解决方案22】:

                        SpreadsheetGear 很棒。是的,这是一笔费用,但与玩弄这些其他解决方案相比,这是值得的。它快速、可靠、非常全面,我不得不说,在我的全职软件工作中使用该产品一年半之后,他们的客户支持非常棒!

                        【讨论】:

                        • 当有这么多简单有效的方法(免费)读取和写入 Excel 时,很难证明其合理性。
                        【解决方案23】:

                        Excel 数据阅读器怎么样?

                        http://exceldatareader.codeplex.com/

                        我在生产环境中使用 anger 将大量数据从各种 Excel 文件中提取到 SQL Server Compact 中。它工作得很好,而且相当健壮。

                        【讨论】:

                        • 我将第二个 Excel 数据阅读器;它还导致了非常有用的 Excel 数据驱动测试库,它使用 NUnit 2.5 的 TestCaseSource 属性使使用 Excel 电子表格的数据驱动测试变得非常容易。请注意 Resharper 尚不支持 TestCaseSource,因此您必须使用 NUnit 运行器。
                        • 不幸的是,我们刚刚遇到了这个库的一些问题。首先,我们有一些货币字段作为日期出现。其次,如果工作簿中有任何空工作表,它就会崩溃。所以,虽然它很容易集成,但我们现在正在重新评估是否继续使用这个库。它似乎没有被积极开发。
                        • 它还假设 xlsx 文件中存在一些可选元素,如果它们不存在,则导致它无法读取数据。
                        • 我们遇到了来自 SQL Server Reporting Services 的 Excel 文件的问题。它们只是不起作用,除非您打开它们并保存它们(即使是未经编辑的)。 @RichieHindle:你在说什么可选元素(希望这对我的 SSRS Excel 文件有帮助)?
                        • @Peter:我认为&lt;worksheet&gt; 中缺少&lt;dimension&gt; 元素给我带来了麻烦。
                        【解决方案24】:

                        Excel 数据阅读器是最佳选择!

                        它是开源的,位于http://exceldatareader.codeplex.com/ 并积极开发。

                        几年来,我们一直在使用它来阅读表格(有时不是表格)工作表(在财务应用程序中)。

                        从人类可读的表格中读取单元测试数据就像一个魅力。

                        请避免尝试返回 DateTime 的功能,因为对于 Excel,DateTime 只是双数字。

                        【讨论】:

                        【解决方案25】:

                        .NET 组件 Excel Reader .NET 可以满足您的要求。阅读 XLSX 和 XLS 文件已经足够好了。所以尝试一下:

                        http://www.devtriogroup.com/ExcelReader

                        【讨论】:

                          【解决方案26】:

                          我们使用的解决方案需要:

                          • 允许读取/写入 Excel 生成的文件
                          • 性能快速(不像使用 COM)
                          • 成为 MS Office 独立(需要在没有安装 MS Office 的客户端的情况下可用)
                          • 免费开源(但积极开发)

                          有多种选择,但我们发现 NPoi(Java 长期存在的 Poi 开源项目的 .NET 端口)是最好的: http://npoi.codeplex.com/

                          它还允许使用 .doc 和 .ppt 文件格式

                          【讨论】:

                            【解决方案27】:

                            如果您在同一个工作表中有多个表,您可以为每个表指定一个对象名称并使用 OleDb 方法读取该表,如下所示:http://vbktech.wordpress.com/2011/05/10/c-net-reading-and-writing-to-multiple-tables-in-the-same-microsoft-excel-worksheet/

                            【讨论】:

                              【解决方案28】:

                              如果它只是表格数据。我会推荐 Marcos Melli 的文件数据助手,可以下载 here

                              【讨论】:

                                【解决方案29】:

                                Take.io电子表格将为您完成这项工作,而且不收取任何费用。看看this吧。

                                【讨论】:

                                • 这是一个非常棒的小图书馆。它只是将所有内容转换为字符串列表列表,这对于我需要它的工作来说很好。
                                【解决方案30】:

                                我想展示一个使用 .NET 读取 xls/xlsx 文件的简单方法。希望以下内容对您有所帮助。

                                私有 DataTable ReadExcelToTable(字符串路径) { //连接字符串 string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';"; //同名 //string connstring = Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + path + //";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';"; 使用(OleDbConnection conn = 新 OleDbConnection(connstring)) { conn.Open(); //获取所有工作表名称 DataTable sheetName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,new object[]{null,null,null,"Table"}); //获取第一个工作表名称 字符串 firstSheetName = sheetName.Rows[0][2].ToString(); //请求参数 string sql = string.Format("SELECT * FROM [{0}]",firstSheetName); OleDbDataAdapter ada =new OleDbDataAdapter(sql,connstring); 数据集集 = 新数据集(); ada.Fill(set); 返回 set.Tables[0]; } }

                                代码来自文章:http://www.c-sharpcorner.com/uploadfile/d2dcfc/read-excel-file-with-net/。您可以从中获得更多详细信息。

                                【讨论】:

                                • 很有帮助,尤其是关于阅读工作表名称的部分。
                                猜你喜欢
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多