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

50
我有一个用C#编写的.Net-Windows应用程序,需要打开并处理Excel文件。如何在不使用Microsoft.Office.Interop.Excel库的情况下完成这一操作?
12个回答

74

我强烈推荐使用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:Apache POI库的.NET端口
    非常强大、免费且开源。除了Excel(97-2010)外,它还支持Word和PowerPoint文件。

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

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


5
这个 ExcelDataReader 真是太棒了,比 OLEDB 快得多。 - c-sharp
2
ExcelDataReader正在迁移到GitHub:https://github.com/ExcelDataReader/ExcelDataReader - Dude Pascalou

49
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);
    }
}

3
注意:当您的工作表受到密码保护时,OLEDB 无法使用。 - Sangram Nandkhile
@Aleksandar,这个解决方案在Linux上也适用吗? - Dalton Cézane
命名空间是必需的吗? - Lorenzo Bassetti
在使用此功能时,请注意平台。如果您安装了 Office x64 提供程序,则您的应用程序只能作为 x64 运行,32 位同理。如果您安装了 Office 32 位提供程序,则您的应用程序只能作为 32 位 (x86) 运行。 - midspace
这需要在计算机上安装Excel应用程序吗? - justanotherguy

3
我建议不要使用OleDB,特别是如果它将在服务器上运行。从长远来看,这可能会使您付出更多的代价 - 例如,我们有一个SSIS作业调用存储过程,其中OleDB读取Excel文件,在sptroc中并且导致SQL框架崩溃!我将OleDB从sproc中移除,就停止了服务器崩溃的问题。
我发现更好的方法是使用Office 2003和XML文件 - 关于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);
        }

3
不是 OleDB 对您的服务器构成风险,而是通过存储过程运行任何外部 SQL Server 的东西才真正危险。 - philu

3

我最近发现了这个库,它可以将Excel工作簿文件转换成DataSetExcel Data Reader

(说明:该库可以帮助将Excel文件转换为DataSet格式,方便IT技术人员处理数据)

2

寻找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

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

1
你可以尝试使用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();

1
我使用了Excel.dll库,该库具有以下特点:
  • 开源
  • 轻量级
  • 快速
  • 兼容xls和xlsx格式
文档可以在这里找到: https://exceldatareader.codeplex.com/ 强烈推荐使用。

1
我刚刚在寻找解决方案时发现了 Spreadsheetlight,这看起来非常有前途。它是开源的并且可以作为NuGet软件包使用。

它很容易破坏现有的XLSX文件!请小心。 - Lorenzo Bassetti

0

你也可以像我一样购买商业控件,比如这个: http://www.syncfusion.com/products/reporting-edition/xlsio

我曾经苦苦挣扎多年,最终选择了商业解决方案。我首先尝试了OLEDB方法,在我的开发环境中非常容易使用,但是部署起来可能会很麻烦。然后我尝试了开源解决方案,但大多数都已经过时且支持不佳。

Syncfusion的xlsio控件正是我使用并感到满意的控件,但还有其他选择。如果你能负担得起,不要犹豫,这是最好的解决方案。为什么?因为它没有与系统的依赖关系,并立即支持所有版本的Office。除此之外,它还非常快速。

不,我不是Syncfusion的员工 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接