【问题标题】:How to read all Excel items to Listview without using looping?如何在不使用循环的情况下将所有 Excel 项目读取到 Listview?
【发布时间】:2020-06-24 02:00:01
【问题描述】:

是否可以在不使用循环的情况下读取 excel 项目中的所有项目?我的 Excel 中有将近 2 万行,将项目放入 Listview 需要很长时间。

这是我当前的代码:

 xlWorkBook = xlApp.Workbooks.Open(FileName)

 xlWorkSheet = xlWorkBook.Worksheets("ExportedFromDatGrid")
 xlApp.Sheets("ExportedFromDatGrid").activate()
 xlApp.Range("A2").Activate()

 Dim cCount As Integer
 Dim azr As Microsoft.Office.Interop.Excel.Range
 azr = xlWorkSheet.UsedRange

            For cCount = 2 To azr.Rows.Count
                Dim newitem As New ListViewItem()
                Dim excelvalue As String = (Format(azr.Cells(cCount, 2).value, "yyyy-MM-dd"))

                Dim fromdate As String

                fromdate = dtpFrom.Value.ToString("yyyy-MM-dd")
                Dim todate As String

                todate = dtpTo.Value.ToString("yyyy-MM-dd")

                'MessageBox.Show(fromdate & "FROM - <<  TO- >>>>" & todate)

                If ((excelvalue >= fromdate) And (excelvalue <= todate)) Then

                    newitem.Text = "CGC-" & azr.Cells(cCount, 1).value.ToString
                    newitem.SubItems.Add(Format(azr.Cells(cCount, 2).value, "yyyy-MM-dd HH:mm:00"))
                    newitem.SubItems.Add(azr.Cells(cCount, 3).value.ToString)
                    newitem.SubItems.Add(azr.Cells(cCount, 4).value.ToString)
                    newitem.SubItems.Add(azr.Cells(cCount, 5).value.ToString)

                    lvAll.Items.Add(newitem)

                End If

            Next
            xlWorkBook.Close()
            xlApp.Quit()

            System.Runtime.InteropServices.Marshal.ReleaseComObject(azr)

【问题讨论】:

  • 我敢打赌它确实需要太长时间;但是哪个用户会滚动浏览 20,000 条记录?
  • 这段代码真的有效吗,唯一的问题是它很慢?
  • @Mary 是的,代码可以运行,但速度很慢。在listview上放20k条记录大约需要10分钟,20k条记录是今年员工的出勤情况。

标签: vb.net office-interop


【解决方案1】:

您可以使用数组直接从 Excel 中读取数据范围,这比循环读取要快得多。

dim ValArray As Object(,)
ObjRange = xlWorkSheet.UsedRange

ValArray = ObjRange.Value2

然后,您将拥有一个 VB.NET 数组中的数据,该数组的循环速度要快得多。

然后你可以像这样循环遍历它

For i = 0 To valArray.GetUpperBound(0)
    Debug.print(valArray(i,0))
    Debug.print(valArray(i,1))
    'etc...
Next

相比之下,这应该相当快,可能是 10-20 倍。

【讨论】:

    【解决方案2】:

    这里的想法是加快用户界面的更新。

    创建ListViewItem 列表,并在循环的每次迭代中添加到其中。在循环外解析fromdatetodate。我们希望每次迭代都有一个新项目,所以我将newitemDim 移动到循环内。

    我认为最好将此日期数据保留为比较日期。假设这是一个日期值,它将为excelvalue 节省 20,000 次转换.ToString,但我不理会该代码。如果您的代码仍然太慢,请查看此内容。

    接下来,我们通过单个操作更新用户界面。 BeginUpdate...EndUpdate 防止 UI 在每次添加时重新绘制。 .AddRange 一次添加整个数组。

    一般来说,我认为使用ExcelOleDb 提供程序并使用ADO.net 将所有数据拉入DataTable 会更快。然后循环数据表的行。同样,如果您的代码仍然很慢,则需要考虑这一点。

    Dim lst As New List(Of ListViewItem)
    Dim fromdate = dtpFrom.Value.ToString("yyyy-MM-dd")
    Dim todate = dtpTo.Value.ToString("yyyy-MM-dd")
      For cCount = 2 To azr.Rows.Count
        Dim excelvalue As String = (Format(azr.Cells(cCount, 2).value, "yyyy-MM-dd"))
           If ((excelvalue >= fromdate) And (excelvalue <= todate)) Then
              Dim newitem As New ListViewItem()
              If ((excelvalue >= fromdate) And (excelvalue <= todate)) Then 
                  newitem.Text = "CGC-" & azr.Cells(cCount, 1).value.ToString
                  newitem.SubItems.Add(Format(azr.Cells(cCount, 2).value, "yyyy-MM-dd HH:mm:00"))
                  newitem.SubItems.Add(azr.Cells(cCount, 3).value.ToString)
                  newitem.SubItems.Add(azr.Cells(cCount, 4).value.ToString)
                  newitem.SubItems.Add(azr.Cells(cCount, 5).value.ToString)
                  lst.Add(newitem)
                End If
      Next
                xlWorkBook.Close()
                xlApp.Quit()
                lvAll.BeginUpdate()
                lvAll.Items.AddRange(lst.ToArray)
                lvAll.EndUpdate()
    

    在调用这个的代码中你需要添加

    GC.Collect()
    GC.WaitForPendingFinalizers()
    

    【讨论】:

    • 由于未显示值,我对您的代码进行了一些更改。 GC.Collect()GC.WaitForPendingFinalizers() 还有什么用?
    • 这里是关于 GC.Collect 和 GC.WaitForPendingFinalizers() 的链接。从本质上讲,它会让你摆脱 Excel 的幽灵副本。 stackoverflow.com/questions/10309365/…
    猜你喜欢
    • 2019-08-14
    • 2011-09-01
    • 2012-06-09
    • 1970-01-01
    • 2012-03-04
    • 2021-05-02
    • 1970-01-01
    • 2022-10-16
    • 2020-02-04
    相关资源
    最近更新 更多