【问题标题】:Reading range by Microsoft.Office.Interop.ExcelMicrosoft.Office.Interop.Excel 的阅读范围
【发布时间】:2018-10-01 16:27:28
【问题描述】:

我想从 Excel 中读取大量单元格到 C# 中的二维数组。 使用 Microsoft.Office.Interop.Excel 并一一读取单元格太慢了。我知道如何将数组写入范围(Microsoft.Office.Interop.Excel really slow),但我想在相反的方向进行

        _Excel.Application xlApp = new _Excel.Application();
        _Excel.Workbook xlWorkBook;
        _Excel.Worksheet xlWorkSheet;
        object misValue = System.Reflection.Missing.Value;
        xlWorkBook = xlApp.Workbooks.Open(path);

        xlWorkSheet = xlWorkBook.Worksheets["Engineering BOM"];


        _Excel.Range range = (_Excel.Range)xlWorkSheet.Cells[1, 1];
        range = range.get_Resize(13000, 9);


        string[,] indexMatrix = new string[13000, 9];

        // below code should be much faster

        for (int i = 1; i < 1300; i++)
        {
            for (int j = 1; j < 9; j++)
            {
                indexMatrix[i, j] = xlWorkSheet.Cells[i, j].Value2;
            }
        }

因此,我希望在数组中获取单元格范围的值(范围大小与数组大小完全相同)。现在应用程序正在逐个单元格读取并将数据写入数组,但速度太慢。有什么方法可以直接将整个范围复制到单元格?

提前谢谢你:)

【问题讨论】:

  • 嗯什么?请说明问题所在。
  • 您知道如何从 Excel 的范围中获取值并将其粘贴到数组中吗?
  • 当然,但是您没有指定哪个范围,问题出在哪里,到目前为止您尝试了什么,您没有包含代码的 sn-p 以重新创建完整且可验证的例子。你没有发布你想要的结果。你什么都没做。这不是免费的编码服务。在再次询问之前,请阅读how to ask 以及如何重新创建complete and verifiable 示例。并编辑您的帖子以添加上述信息。
  • 是的,对不起。太多的心理捷径
  • 我同意@Simo。使用数据表。但是为了回答您的查询,MYARRAY = Rng.Value 将一次性将所有值存储到数组中。您不需要为此循环

标签: c# .net excel


【解决方案1】:

你可以试试这个,应该会更快,但是:

  • 您必须使用数据表(在这种情况下,最好使用数据表而不是 多维数组。)

  • 你不再需要关心范围了

那么我们要做什么呢?连接到excel并进行查询以选择所有数据并填写数据表。我们需要的?几行代码。

首先我们声明我们的连接字符串:

Excel 2007 或更高版本(*.XLSX 文件)

string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=No;IMEX=1\";", fullPath);

对于 Excel 2003*.XLS 文件)

string connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0; data source={0}; Extended Properties=\"Excel 8.0;HDR=No;IMEX=1\";", fullPath);

fullPath 是您的 excel 文件的完整文件路径


现在我们必须创建连接并填充数据表:

OleDbConnection SQLConn = new OleDbConnection(strConnectionString);
SQLConn.Open();
OleDbDataAdapter SQLAdapter = new OleDbDataAdapter();
string sql = "SELECT * FROM [" + sheetName + "$]";
OleDbCommand selectCMD = new OleDbCommand(sql, SQLConn);
SQLAdapter.SelectCommand = selectCMD;
SQLAdapter.Fill(dtXLS);
SQLConn.Close();

sheetName 是您的工作表名称,dtXLS 是您的数据表,其中填充了您的所有 excel 值。

这应该更快。

【讨论】:

  • 有效!但我为 *.XLS string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; Extended Properties=\"Excel 8.0;HDR=No;IMEX=1\";", fullPath); 做了一个调整
  • @jabol333,你也不需要为不同的excel文件使用不同的连接字符串,ACE适合所有人。 DataAdapter 还会根据需要打开和关闭连接。
【解决方案2】:

我猜这个范围在某种程度上定义了一个“数据表”。如果这是正确的,那么最快的方法是使用 OleDb 或 ODbc 将其读取为数据(甚至不需要安装 excel):

DataTable tbl = new DataTable();
using (OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;" +
        $"Data Source={path};" +
        @"Extended Properties=""Excel 12.0;HDR=Yes"""))
using (OleDbCommand cmd = new OleDbCommand(@"Select * from [Engineering BOM$A1:i13000]", con))
{
    con.Open();
    tbl.Load(cmd.ExecuteReader());
}

如果不是,那么你可以这样做:

Excel.Application xl = new Excel.Application();
var wb = xl.Workbooks.Open(path);

Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets["Engineering BOM"];

var v = ws.Range["A1:I13000"].Value;

(不确定excel本身是否可以做这么大的数组分配)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2023-01-24
    • 1970-01-01
    • 2020-02-01
    • 2012-12-16
    相关资源
    最近更新 更多