如何在c#中快速读取Excel电子表格

本文关键字:读取 Excel 电子表格 | 更新日期: 2023-09-27 18:10:13

我正在使用Microsoft.Office.Interop.Excel来读取内存中打开的电子表格。

gXlWs = (Microsoft.Office.Interop.Excel.Worksheet)gXlApp.ActiveWorkbook.ActiveSheet;
int NumCols = 7;
string[] Fields = new string[NumCols];
string input = null;
int NumRow = 2;
while (Convert.ToString(((Microsoft.Office.Interop.Excel.Range)gXlWs.Cells[NumRow, 1]).Value2) != null)
{
    for (int c = 1; c <= NumCols; c++)
    {
        Fields[c-1] = Convert.ToString(((Microsoft.Office.Interop.Excel.Range)gXlWs.Cells[NumRow, c]).Value2);
    }
    NumRow++;
    //Do my other processing
}

我有180,000行,这是非常慢的。我不确定"转换"是有效的。有什么办法能让我做得快一点吗?

月球

如何在c#中快速读取Excel电子表格

嗨,我发现了一个非常快的方法。

最好使用"get_range"一次读取整个数据。这将把数据加载到内存中,我可以像处理普通数组一样对其进行循环。

Microsoft.Office.Interop.Excel.Range range = gXlWs.get_Range("A1", "F188000");
object[,] values = (object[,])range.Value2;
int NumRow=1;
while (NumRow < values.GetLength(0))
{
    for (int c = 1; c <= NumCols; c++)
    {
        Fields[c - 1] = Convert.ToString(values[NumRow, c]);
    }
    NumRow++;
}

有几个选项-都涉及一些额外的库:

  • OpenXML 2.0(来自MS的免费库)可以用来读取/修改。xlsx文件的内容,这样你就可以随心所欲了

  • 一些(商业)第三方库带有网格控件,允许您在应用程序(无论是Winforms/WPF/ASP.NET…)中使用excel文件做更多的事情,如SpreadsheetGear, Aspose。细胞等。

我不确定"转换"是有效的。我能做点什么吗这快吗?

你怎么会相信这个?我向您保证,Convert.ToString()是您发布的代码中最有效的方法。您的问题是您在excel文档中循环使用180,000条记录…

你可以把工作分开,因为你知道行数,这是很简单的。

为什么要将Value2转换为字符串呢?

我发现了一种非常快速的阅读excel的方法。我需要得到一个二维字符串数组。用非常大的excel,用旧的方法花了大约一个小时。通过这种方式,我可以在20秒内得到我的值。

我正在使用这个块:https://reposhub.com/dotnet/office/ExcelDataReader-ExcelDataReader.html

下面是我的代码:

DataSet result = null;
//https://reposhub.com/dotnet/office/ExcelDataReader-ExcelDataReader.html
using (var stream = File.Open(path, FileMode.Open, FileAccess.Read))
{
    // Auto-detect format, supports:
    //  - Binary Excel files (2.0-2003 format; *.xls)
    //  - OpenXml Excel files (2007 format; *.xlsx)
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        result = reader.AsDataSet();
    }
}
foreach (DataTable table in result.Tables)
{
    if (//my conditions)
    {
        continue;
    }
    var rows = table.AsEnumerable().ToArray();
    var dataTable = new string[table.Rows.Count][];//[table.Rows[0].ItemArray.Length];
    Parallel.For(0, rows.Length, new ParallelOptions { MaxDegreeOfParallelism = 8 },
        i =>
        {
            var row = rows[i];
            dataTable[i] = row.ItemArray.Select(x => x.ToString()).ToArray();                                    
        });
    importedList.Add(dataTable);
}

我猜这不是转换"变慢"的来源…

实际上,检索单元格值非常慢。

我认为这种转换是没有必要的:

(Microsoft.Office.Interop.Excel.Range)gXlWs

没有这个应该也可以。

你可以直接问:

gXlWs.Cells[NumRow, 1].Value != null

尝试将整个范围或至少整个行移动到对象矩阵并使用它而不是范围本身。

使用OleDB方法。这是最快的如下;

string con =
  @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:'temp'test.xls;" + 
  @"Extended Properties='Excel 8.0;HDR=Yes;'";    
using(OleDbConnection connection = new OleDbConnection(con))
{
    connection.Open();
    OleDbCommand command = new OleDbCommand("select * from [Sheet1$]", connection); 
    using(OleDbDataReader dr = command.ExecuteReader())
    {
         while(dr.Read())
         {
             var row1Col0 = dr[0];
             Console.WriteLine(row1Col0);
         }
    }
}