【问题标题】:Microsoft.Office.Interop.Excel or EPPlus for read a huge (or not) Excel fileMicrosoft.Office.Interop.Excel 或 EPPlus 用于读取巨大(或非)Excel 文件
【发布时间】:2013-04-25 18:19:56
【问题描述】:

我编写了一个代码来从 Excel 文件中读取一列。我在此使用 Microsoft.Office.Interop.Excel,首先读取整个 Range,然后写入 System.Array,然后对 System.Array 值进行一些操作,最后将其转换为 List,因为我填充了 ListBox 元素。这是代码(仅相关部分):

private List<string> bd = new List<string>();
private static System.Array objRowAValues;

private List<string> bl = new List<string>();
private static System.Array objRowBValues;

private List<string> cm = new List<string>();
private static System.Array objRowCValues;

private List<string> pl = new List<string>();
private List<string> bdCleanList;
private static Microsoft.Office.Interop.Excel.Application appExcel;

Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range rngARowLast, rngBRowLast, rngCRowLast;

long lastACell, lastBCell, lastCCell, fullRow;

private void btnCargarExcel_Click(object sender, EventArgs e)
    {
        if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
        {
            if (System.IO.File.Exists(openFileDialog1.FileName))
            {
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();
                Thread.Sleep(10000);

                filePath.Text = openFileDialog1.FileName.ToString();

                xlApp = new Microsoft.Office.Interop.Excel.Application();
                xlWorkBook = xlApp.Workbooks.Open(openFileDialog1.FileName, 0, true, 5, "", "", true,
                                                  Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false,
                                                  false, 0, true, 1, 0);
                xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

                fullRow = xlWorkSheet.Rows.Count;
                lastACell = xlWorkSheet.Cells[fullRow, 1].End(Excel.XlDirection.xlUp).Row;
                rngARowLast = xlWorkSheet.get_Range("A1", "A" + lastACell);
                objRowAValues = (System.Array)rngARowLast.Cells.Value;

                foreach (object elem in objRowAValues)
                {
                    if (elem != "")
                    {
                        bd.Add(cleanString(elem.ToString(), 10));
                    }
                }

                nrosProcesados.Text = bd.Count().ToString();
                listBox1.DataSource = bd;

                xlWorkBook.Close(true, null, null);
                xlApp.Quit();

                releaseObject(xlWorkSheet);
                releaseObject(xlWorkBook);
                releaseObject(xlApp);

                stopWatch.Stop();

                TimeSpan ts = stopWatch.Elapsed;
                executiontime.Text =
                    String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds,
                                  ts.Milliseconds / 10).ToString();
            }
            else
            {
                MessageBox.Show("No se pudo abrir el fichero!");
                System.Runtime.InteropServices.Marshal.ReleaseComObject(appExcel);
                appExcel = null;
                System.Windows.Forms.Application.Exit();
            }
        }
    }

我使用包含约 800 000 个单元格的 Excel 文件进行测试,用时不到 2 分钟。然后我从 EPPlus 测试样本并且比我的方法更快,所以我认为使用 EPPlus 而不是 Microsoft.Office.Interop.Excel 我认为也在使用 OpenXML SDK(但找不到任何适合我目标的示例,所以我离开现在)。在示例中,他们使用此代码从 Excel 文件中读取数据:

ExcelWorksheet sheet = package.Workbook.Worksheets[1];

var query1= (from cell in sheet.Cells["d:d"] where cell.Value is double && (double)cell.Value >= 9990 && (double)cell.Value <= 10000 select cell);

他们当然在这里使用 LINQ,但我对这个主题的问题是:

  • 您使用的是哪种方法?
  • 您对此有何建议?
  • 对使用 EPPlus 或 OpenXML SDK 编写相同的内容有何帮助?

我是来自 PHP 世界的 C# 世界的新手,这是我的第一个项目

【问题讨论】:

    标签: c# .net excel-interop epplus


    【解决方案1】:

    您使用了哪种方法? -EPPlus

    您对此有何建议? -我发现 EPPLus 的速度要快得多。在我看来,它也是一个更容易使用的 API。由于许多原因,其中一个原因是缺乏 COM 互操作性(无论是速度还是易用性)。要求也更少,尤其是在部署到服务器环境时:无需安装 Excel 垃圾。

    对使用 EPPlus 或 OpenXML SDK 编写相同的内容有何帮助? -EPPlus API 相当简单。尝试并针对您目前所尝试的内容发布更具体的问题。

    另一种循环单元格的方法:

    var firstColumnRows = sheet.Cells["A2:A"];
    
    // Loop through rows in the first column, get values based on offset
    foreach (var cell in firstColumnRows)
    {
        var column1CellValue = cell.GetValue<string>();
        var neighborCellValue = cell.Offset(0, 1).GetValue<string>();
    }
    

    【讨论】:

    • 谢谢,我检查了所有示例代码,但不足以让我了解我必须遵循哪些步骤才能使用 EPPlus 获得相同的结果,因为我在这里寻求帮助,我只是不知道我是否需要相同的逻辑来从 Excel 读取单元格并将它们写入 System.Array
    • 这就是你循环单元格的方式:codealoc.wordpress.com/2012/04/19/…
    • 更新了另一个例子。 EPPlus 中还有一个 Range 函数可能对您也有用。
    • 在我的情况下,我只有一列,所以看到你留下的代码我不需要循环来迭代槽列,现在这条线意味着object cellValue = workSheet.Cells[i, j].Value;我在那里创建什么?我可以使用Add() 方法将值添加到 List 吗?
    • Cell.Value 可以是stringint 或任何单元格类型。如果您知道单元格中的数据类型,您可以将其转换为(int)cell.Value,或改用cell.GetValue&lt;int&gt;()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多