【问题标题】:Better Way of Getting the Text Value of Cells in an Excel (*.xls) File获取 Excel (*.xls) 文件中单元格文本值的更好方法
【发布时间】:2010-12-13 17:14:23
【问题描述】:

我正在尝试编写一个导入函数来从 Excel 文件中获取数据。我目前的做法如下:

Private Sub ReadExcel(ByVal childform As PhoneDiag.frmData, ByVal FileName As String)

        Dim xlApp As Excel.Application
        Dim xlWorkBook As Excel.Workbook
        Dim xlWorkSheet As Excel.Worksheet

        xlApp = New Excel.ApplicationClass
        xlWorkBook = xlApp.Workbooks.Open(FileName)
        xlWorkSheet = xlWorkBook.Worksheets(1)
        Dim columnrange = xlWorkSheet.Columns
        Dim therange = xlWorkSheet.UsedRange

        ''Add rows by column
        For rCnt = 2 To therange.Rows.Count

            Dim rowArray(therange.Columns.Count) As String

            For cCnt = 1 To therange.Columns.Count

                Dim Obj = CType(therange.Cells(rCnt, cCnt), Excel.Range)
                Dim celltext As String
                celltext = Obj.Value.ToString
                rowArray((cCnt - 1)) = celltext

            Next

            childform.datagridSample.Rows.Add(rowArray)

        Next

        '' make sure we close the excel.exe service after use
        xlWorkBook.Close()
        xlApp.Quit()
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet)
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)

    End Sub

当然,问题在于它运行得非常糟糕。据我所知,很可能归结为这一行:

Dim Obj = CType(therange.Cells(rCnt, cCnt), Excel.Range)

我只需要来自单元格的文本,而不是为每个单元格创建一个对象(然后不将它们发送到垃圾收集)。有没有更简单的方法来获取文本?

理想情况下,如果我能获得获取单元格文本值的方法,我希望将多个 rowArray() 添加到主数组并稍后更新程序的值。

如果您看到任何其他性能提示,请告诉我。将不胜感激。 =b

编辑:我也意识到如果我要创建一个主数组(比如 mArr)来保存所有数据,我有两个选择。让 mArr 大而子阵列小,还是 mArr 小而子阵列容纳更多信息,在性能方面会更好吗?

我问是因为将要导入的文件的行数多于列数,所以我想知道是否有任何“设置”的方法。

【问题讨论】:

    标签: vb.net excel import ctypes


    【解决方案1】:

    这是一个 C# 版本(但你明白了要点),它将把数据放入数据表中......

    con = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+SpreadsheetLocation+";Extended Properties=\"Excel 8.0;IMEX=1;HDR=NO\"");
    OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM ["+Worksheet+"$]", con);
    DataTable dt = new DataTable();
    da.Fill(dt);
    

    其中“SpreadSheetLocation”和“Worksheet”分别是文件路径和工作表名称。然后,您可以根据需要将数据表行转换为数组。

    更新:对于此解决方案,您也不需要在机器中安装 Excel...

    【讨论】:

      【解决方案2】:

      为了简单阅读,我会使用 CodePlex 上的Excel Data Reader

      使用该组件的机器不需要安装 Excel,而且非常易于使用。您可以将 Worksheet 读入 DataSet。

      【讨论】:

        【解决方案3】:

        单独阅读单元格内容是一个巨大的性能杀手。我的建议是首先将整个范围读入对象数组,然后从该数组中检索数据。我不是用 VB.NET 编写的,但在 C# 中,代码看起来像这样:

        Excel.Range firstCell = excelWorksheet.get_Range("A1", Type.Missing);
        Excel.Range lastCell = excelWorksheet.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
        object[,] cellValues;
        Excel.Range worksheetCells = excelWorksheet.get_Range(firstCell, lastCell);
        cellValues = worksheetCells.Value2 as object[,];
        

        此示例将工作表的全部内容读入 cellValues(注意空值)。同样的建议也适用于写入工作表 - 一次完成所有操作,使用一个数组。
        如果你有兴趣,我在这个there有一个更长的帖子@
        哦,顺便说一句,替换

        xlApp = New Excel.ApplicationClass
        

        通过

        xlApp = New Excel.Application
        

        【讨论】:

        • 只是出于好奇,为什么要用 Application 代替 ApplicationClass?
        • 来自 MSDN:“此类支持 .NET Framework 基础结构,不打算直接从您的代码中使用。” msdn.microsoft.com/en-us/library/… 我不知道使用它是否会出错,但应用程序接口正是为此而生的。这很有趣,因为 ApplicationClass 出现在互联网上的很多地方,我想肯定有一个代码 sn-p 被一遍又一遍地复制......
        【解决方案4】:

        SpreadshsetGear for .NET 将允许您打开工作簿并访问单元格的原始值(数字、文本、逻辑或错误)或获取单元格的格式化文本。由于 SpreadsheetGear 作为应用程序的一部分运行,而不是像 Excel 那样作为 COM Interop 运行,因此运行速度会更快(请参阅this page 上的 cmets,了解我们的一些客户对性能的评价)。

        您可以查看实时示例here 并下载免费试用版here

        免责声明:我拥有 SpreadsheetGear LLC

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多