如何在 C# 中读取 excel 文件而不使用 Microsoft.Office.Interop.Excel 库

Posted

技术标签:

【中文标题】如何在 C# 中读取 excel 文件而不使用 Microsoft.Office.Interop.Excel 库【英文标题】:How to read an excel file in C# without using Microsoft.Office.Interop.Excel libraries 【发布时间】:2012-02-06 04:40:52 【问题描述】:

我有一个 C# 中的 .Net-Windows 应用程序。我需要打开一个excel并处理它。在不使用 Microsoft.Office.Interop.Excel 库的情况下如何做到这一点?

【问题讨论】:

【参考方案1】:

我强烈推荐 CSharpJExcel 阅读 Excel 97-2003 文件 (xls) 和 ExcelPackage 阅读 Excel 2007/2010 文件(Office Open XML 格式,xlsx)。

它们都工作得很好。他们绝对不依赖任何东西。

使用 CSharpJExcel 的示例:

Workbook workbook = Workbook.getWorkbook(new System.IO.FileInfo(fileName));
var sheet = workbook.getSheet(0);
...
var content = sheet.getCell(colIndex, rowIndex).getContents();
...
workbook.close();

使用 ExcelPackage 的示例:

using (ExcelPackage xlPackage = new ExcelPackage(existingFile))

  // get the first worksheet in the workbook
  ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets[1];
  int iCol = 2;  // the column to read

  // output the data in column 2
  for (int iRow = 1; iRow < 6; iRow++)
    Console.WriteLine("Cell(0,1).Value=2", iRow, iCol, 
      worksheet.Cell(iRow, iCol).Value);

  // output the formula in row 6
  Console.WriteLine("Cell(0,1).Formula=2", 6, iCol, 
    worksheet.Cell(6, iCol).Formula);

 // the using statement calls Dispose() which closes the package.

编辑

还有另一个项目ExcelDataReader,似乎能够处理这两种格式。就像我提到的其他方法一样,它也很容易。

还有其他库:

NPOI: Port of the Apache POI library to .NET: 非常强大、免费和开源。除了 Excel (97-2010),它还支持 Word 和 PowerPoint 文件。

ExcelLibrary: 它仅支持 Excel 97-2003 (xls) 文件。

EPPlus: ExcelPackage 的扩展。更容易使用(我猜)。

【讨论】:

这个 ExcelDataReader 非常棒,而且比 OLEDB 快得离谱。 ExcelDataReader 正在迁移到 GitHub:github.com/ExcelDataReader/ExcelDataReader【参考方案2】:
var fileName = @"C:\ExcelFile.xlsx";
var connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 12.0;IMEX=1;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text\""; ;
using (var conn = new OleDbConnection(connectionString))

    conn.Open();

    var sheets = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new object[]  null, null, null, "TABLE" );
    using (var cmd = conn.CreateCommand())
    
        cmd.CommandText = "SELECT * FROM [" + sheets.Rows[0]["TABLE_NAME"].ToString() + "] ";

        var adapter = new OleDbDataAdapter(cmd);
        var ds = new DataSet();
        adapter.Fill(ds);
    

【讨论】:

注意-当您的工作表受密码保护时,OLEDB 不起作用。 @Aleksandar ,这个解决方案也适用于 linux 吗? 需要什么命名空间?【参考方案3】:

我强烈反对使用 OleDB,尤其是当它要在服务器上运行时。从长远来看,它可能会让您付出更多代价——例如,我们有一个 SSIS 作业调用存储过程,而 OleDB 读取 sptroc 中的 excel 文件并不断使 SQL 框崩溃!我从存储过程中取出了 OleDB 的东西,它停止了服务器崩溃。

我发现的一种更好的方法是使用 Office 2003 和 XML 文件 - 关于Considerations for server-side Automation of Office。注意:Office 2003 是飞行的最低要求:

参考从 Excel 中读取:http://www.roelvanlisdonk.nl/?p=924(请进行更多研究以找到其他示例)

参考用于编写 Excel 电子表格:http://weblogs.asp.net/jgaylord/archive/2008/08/11/use-linq-to-xml-to-generate-excel-documents.aspx

public void ReadExcelCellTest()
        
            XDocument document = XDocument.Load(@"C:\BDATA\Cars.xml");
            XNamespace workbookNameSpace = @"urn:schemas-microsoft-com:office:spreadsheet";

            // Get worksheet
            var query = from w in document.Elements(workbookNameSpace + "Workbook").Elements(workbookNameSpace + "Worksheet")
                        where w.Attribute(workbookNameSpace + "Name").Value.Equals("Settings")
                        select w;
            List<XElement> foundWoksheets = query.ToList<XElement>();
            if (foundWoksheets.Count() <= 0)  throw new ApplicationException("Worksheet Settings could not be found"); 
            XElement worksheet = query.ToList<XElement>()[0];

            // Get the row for "Seat"
            query = from d in worksheet.Elements(workbookNameSpace + "Table").Elements(workbookNameSpace + "Row").Elements(workbookNameSpace + "Cell").Elements(workbookNameSpace + "Data")
                    where d.Value.Equals("Seat")
                    select d;
            List<XElement> foundData = query.ToList<XElement>();
            if (foundData.Count() <= 0)  throw new ApplicationException("Row 'Seat' could not be found"); 
            XElement row = query.ToList<XElement>()[0].Parent.Parent;

            // Get value cell of Etl_SPIImportLocation_ImportPath setting
            XElement cell = row.Elements().ToList<XElement>()[1];

            // Get the value "Leon"
            string cellValue = cell.Elements(workbookNameSpace + "Data").ToList<XElement>()[0].Value;

            Console.WriteLine(cellValue);
        

【讨论】:

OleDB 对你的服务器来说并不是一个风险;它通过存储过程在 SQL Server 外部运行任何东西,这真的很危险。【参考方案4】:

我最近发现这个库可以将 Excel 工作簿文件转换为 DataSet:Excel Data Reader

【讨论】:

【参考方案5】:

如果您需要打开 XLS 文件而不是 XLSX 文件,http://npoi.codeplex.com/ 是一个不错的选择。我们已经在我们的项目中使用了它,效果很好。

【讨论】:

【参考方案6】:

寻找 GSpread.NET。 它也是一个开源项目,不需要安装 Office。 您可以使用 Microsoft Excel 中的 API 来使用 Google 电子表格。 如果您想重新使用旧代码来访问 Google 电子表格,GSpread.NET 是最好的方法。 您需要添加几行:

Set objExcel = CreateObject("GSpreadCOM.Application")
// Name             - User name, any you like
// ClientIdAndSecret - `client_id|client_secret` format
// ScriptId         - Google Apps script ID
app.MailLogon(Name, ClientIdAndSecret, ScriptId);

其他代码保持不变。

http://scand.com/products/gspread/index.html

【讨论】:

【参考方案7】:

您可以尝试使用 OleDB 从 excel 文件中读取数据。请按照以下方式尝试..

DataSet ds_Data = new DataSet();
OleDbConnection oleCon = new OleDbConnection();

string strExcelFile = @"C:\Test.xlsx";
oleCon.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strExcelFile + ";Extended Properties=\"Excel 12.0;IMEX=1;HDR=NO;TypeGuessRows=0;ImportMixedTypes=Text\"";;

 string SpreadSheetName = "";

OleDbDataAdapter Adapter = new OleDbDataAdapter();
OleDbConnection conn = new OleDbConnection(sConnectionString);

string strQuery;
conn.Open();

int workSheetNumber = 0;

DataTable ExcelSheets = conn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new object[]  null, null, null, "TABLE" );

SpreadSheetName = ExcelSheets.Rows[workSheetNumber]["TABLE_NAME"].ToString();

strQuery = "select * from [" + SpreadSheetName + "] ";
OleDbCommand cmd = new OleDbCommand(strQuery, conn);
Adapter.SelectCommand = cmd;
DataSet dsExcel = new DataSet();
Adapter.Fill(dsExcel);
conn.Close();

【讨论】:

【参考方案8】:

我使用了 Excel.dll 库,它是:

开源 轻量级 快速 兼容 xls 和 xlsx

此处提供的文档: https://exceldatareader.codeplex.com/

强烈推荐。

【讨论】:

【参考方案9】:

我一直在寻找解决方案并遇到 Spreadsheetlight

这看起来很有希望。它是开源的,可作为 nuget 包使用。

【讨论】:

它很容易损坏现有的 XLSX 文件!小心。【参考方案10】:

如果您不想使用互操作,您可能想试试OfficeWriter。根据您真正需要对文件进行多少处理,这可能有点过头了。您可以申请免费试用。 documentation site 上有一个完整记录的 api。

免责声明:我是构建最新版本的工程师之一。

【讨论】:

【参考方案11】:

你也可以像我一样做商业控制: http://www.syncfusion.com/products/reporting-edition/xlsio

我多年来一直在苦苦挣扎,最后才找到一个商业解决方案。我首先尝试了 OLEDB 方法,该方法在我的开发环境中非常容易使用,但部署起来可能是个噩梦。然后我尝试了开源解决方案,但大多数都已过时并且支持不佳。

来自 syncfusion 的 xlsio 控件只是我使用且满意的控件,但还有其他控件。如果你能负担得起,不要犹豫,这是最好的解决方案。为什么?因为它与系统没有依赖关系,立即支持所有版本的office。除了其他优点之外,它真的很快。

不,我不为 synfusion 工作;)

【讨论】:

【参考方案12】:

如果有人需要,请在未安装 Office 的情况下使用 Interop.Excel 打开 excel。您可以使用 nuget 添加 Interop.Excel。

public DataTable ReadExcel(string fileName)
    
        Excel.Application FExcelObject = new Excel.Application();

        var FWorkbookObject = FExcelObject.Workbooks.Open(fileName,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing,
                Type.Missing);
        //var sheets = FWorkbookObject.Sheets[1];
        foreach (Excel.Worksheet sheets in FWorkbookObject.Sheets)
        
            System.Data.DataTable dt = new System.Data.DataTable(sheets.Name);
            DataRow dr;
            StringBuilder sb = new StringBuilder();
            int jValue = sheets.UsedRange.Cells.Columns.Count;
            int iValue = sheets.UsedRange.Cells.Rows.Count;
            for (int j = 1; j <= jValue; j++)
            
                dt.Columns.Add("column" + j, System.Type.GetType("System.String"));
            
            for (int i = 1; i <= iValue; i++)
            
                dr = dt.NewRow();
                for (int j = 1; j <= jValue; j++)
                
                    var oRng = (Microsoft.Office.Interop.Excel.Range)sheets.Cells[i, j];
                    string strValue = oRng.Text.ToString();
                    dr["column" + j] = strValue;
                
                dt.Rows.Add(dr);
            
            return dt;
        
        return new DataTable();
    

【讨论】:

以上是关于如何在 C# 中读取 excel 文件而不使用 Microsoft.Office.Interop.Excel 库的主要内容,如果未能解决你的问题,请参考以下文章

C#如何读取带密码的Excel文件

在 C# 2.0 中编写 excel 文件而不使用任何第三方 dlls/interop/sdk

[如何读取Excel文件而不将其第一行作为标题?熊猫,Python [重复]

使用 ExcelLibrary 在 C# 中读取 Excel .xlsx 文件时出现 OutOfMemoryException

c#如何使用ExcelPackage Plus读取excel(.xls和xlsx)中得数据

C#怎么读取Excel的数据