【问题标题】:Read large excel sheet using Interop in C#在 C# 中使用 Interop 读取大型 Excel 工作表
【发布时间】:2020-04-09 23:06:38
【问题描述】:

我知道我的问题可能看起来很常见。这个论坛本身就有很多知识共享。但我无法为我的特定需求找到解决方案。

就我而言,我有一个 excel 工作簿(2016 版),其中包含 10 张工作表,每张 1500 行。每张纸中的列可能从 15 到 20 不等。我想从所有工作表中读取所有数据并验证它们的数据类型并将其插入到 sql server 数据库表中。

但我尝试使用 2 张,每张 100 行。

Excel.Worksheet ofWs;
Excel.Range range;
ofWs = (Excel.Worksheet)ofShe.get_Item("Sales");
range = ofWs.UsedRange;
for (int i = 2; i <= range.Rows.Count; i++)
{
    string var1 = "";
    double var2 = 0;

    //validation for column1
    if ((ofWs.Cells[i, 1] as Excel.Range).Value2 != null)
    {
        if ((ofWs.Cells[i, 1] as Excel.Range).Value2.GetType().ToString() == "System.String")
            var1 = (string)(ofWs.Cells[i, 1] as Excel.Range).Value2;
        else
        {
            sale_comm_column += "COLUMN A, ";
            sale_errFlag = false;
        }
    }
    else
    {
        sale_comm_column += "COLUMN A, ";
        sale_errFlag = false;
    }

    //validation for column2
    if ((ofWs.Cells[i, 2] as Excel.Range).Value2 != null)
    {
        if ((ofWs.Cells[i, 2] as Excel.Range).Value2.GetType().ToString() == "System.Double")
            var2 = (double)(ofWs.Cells[i, 2] as Excel.Range).Value2;
        else
        {
            sale_comm_column += "COLUMN B, ";
            sale_errFlag = false;
        }
    }
    else
    {
        sale_comm_column += "COLUMN B, ";
        sale_errFlag = false;
    }

}

这个 for 循环将遍历所有行,我正在验证“if”语句中的每一列。在这里,我只展示了第一张纸的 2 列的验证部分。对于 100 行本身来说,它花费了太多时间。但是,如果我删除所有这些“如果”,则需要更少的时间。如果我想在实际要求 10 张每张 1500 行的情况下尝试此操作,最好的方法是什么??

【问题讨论】:

  • 文件格式是什么:.xls 还是 .xlsx?后者可以在没有 (t)rusty Office COM 互操作的情况下进行处理,这要好得多。
  • 尝试不使用 Value2。 Value2 是文本比较,应该使用 string.Empty
  • @Christopher,版本是 .xlsx(Excel 2016)..
  • @jdweng,你的意思是,只要有 Value2 就用 Value 替换它???我无法得到“应该使用 string.Empty”
  • @jdweng,我尝试将 Value2 替换为 Value。读取和验证 100 行和 22 列的每个单元格也需要花费太多时间。

标签: c# excel excel-interop


【解决方案1】:

这主要是一个速度问题,所以speed rant 值得一读。您可以跳过第 1 部分。

将数据库操作保留在数据库中

当您将这些东西插入数据库时​​,您应该在数据库中执行此操作。每个值得它的 Diskspace 的 DBMS,都可以选择进行批量插入。您不会通过在客户端中完成它来击败那个。这只会增加通过网络传输数据的需要。

CSV 支持是有保证的,而且 Excel 格式很常见。如有疑问,您可以将 Excel 文件另存为 CSV,如果您不需要格式化和类型提示。但是,您可能需要进行一些解析。

OpenXML 与 Office 互操作

在 .NET 中使用 Office 格式有 3 个选项:

  1. 如果您只需要新格式 (.xlsx),请使用 OpenXML SDK。或者人们围绕它制作的任何包装纸。甚至只是 ZipArchive 和 XMLReader 类 - 它是开放格式,基于在 .zip 容器中拥有一堆 XML 文件。
  2. 如果您还需要支持旧格式 (.xls),则必须使用 (t)rusty Office Interop。那个有 COM 互操作的所有常见问题,除了它还需要安装程序并需要交互式会话。这意味着它不能从服务中运行,包括大多数 WebServer 都作为一个服务运行。
  3. 对于任何给定的问题、任何给定的语言和任何给定的格式,都可能有第三种方法。但这些很少而且相距甚远。我什至计算了 DBMS 方式(如果可用)。

虽然我没有进行任何测量,但我愿意用真金白银打赌 OpenXML 在速度上会击败 OfficeInterop。一种是通过 XML 解析和 Zip 文件解压来做基本的文件操作。另一个具有 COM 互操作的开销远程处理工作的不可见 Office 实例。谁会以速度取胜甚至都不是问题。唯一的问题是它是否足够快。

【讨论】:

    【解决方案2】:

    您的方法会花费很多时间,因为每次更新单元格时,都会对 excel 实例进行一次 RPC 调用。

    考虑到你的excel文件格式是.xlsx

    我会向您推荐以下内容:

    1. 如果你用Hex-editor打开一个excel文件,你会注意到文件签名是PK(zip文件格式),这意味着它基本上是压缩的XML文件。
    2. 解压 excel 文件,然后在 '\xl\worksheets' 文件夹中,您将看到 'sheet[1~10].xml' 文件
    3. 编写读取/验证 XML 文件并将其插入数据库的代码。

    上述过程可以很容易地自动化,并且应该比使用 excel 互操作要快得多。

    【讨论】:

      猜你喜欢
      • 2019-01-14
      • 2015-09-20
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多