如何使用vb.net更快地将excel导入datagridview

时间:2016-04-07 07:34:44

标签: vb.net excel winforms datagridview

目前我有一个包含1500行和9列的excel文件。每次加载winform时,我都希望excel文件中的记录加载到datagridview中。我正在使用Microsoft office interop将记录导入datagridview,但速度太慢了。

所以我的问题是,我还有什么方法可以加快这个过程?我该怎么办?

Dim xlApp As Microsoft.Office.Interop.Excel.Application
Dim xlWorkBook As Microsoft.Office.Interop.Excel.Workbook
Dim xlWorkSheet As Microsoft.Office.Interop.Excel.Worksheet

xlApp = New Microsoft.Office.Interop.Excel.Application
xlWorkBook = xlApp.Workbooks.Open("C:\Install\Data.xlsx")
xlWorkSheet = xlWorkBook.Sheets("sheet1")

Dim countRows As Integer = xlWorkSheet.UsedRange.Rows.Count()

For i As Integer = 2 To countRows
    newVersionRow = VersionDBDataSet.IEVersion.NewIEVersionRow()
    newVersionRow.PC_Name = xlWorkSheet.Cells(i, 1).value.ToString()
    newVersionRow.PC_Status = xlWorkSheet.Cells(i, 2).value.ToString()
    newVersionRow.svcKBNumber = xlWorkSheet.Cells(i, 3).value.ToString()
    newVersionRow.svcVersion = xlWorkSheet.Cells(i, 4).value.ToString()
    newVersionRow.Last_Updated = DateTime.Parse(xlWorkSheet.Cells(i, 5).value.ToString())
    newVersionRow.Patches = Integer.Parse(xlWorkSheet.Cells(i, 6).value)
    newVersionRow.Uptime = Integer.Parse(xlWorkSheet.Cells(i, 7).value)
    newVersionRow.Count = Integer.Parse(xlWorkSheet.Cells(i, 8).value)
    newVersionRow.Offline = Integer.Parse(xlWorkSheet.Cells(i, 9).value)

    VersionDBDataSet.IEVersion.Rows.Add(newVersionRow)

    If newVersionRow.PC_Status = "Online" Then
        numofOnline += 1
        lblOnlinePC.Text = numofOnline
    Else
        numofOffline += 1
        lblOfflinePC.Text = numofOffline
    End If

Next

xlWorkBook.Close()
xlApp.Quit()

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

1 个答案:

答案 0 :(得分:1)

一种可能的方法是将所有使用过的单元格读入数组,迭代数组并将单元格数据放入DataTable的行中。以下设置为读取三列数据,如果工作表中有更多列,我们在此演示中忽略它们。因此,为您创建九个数据列并使用相同的逻辑。

注意函数HasHeader的最后一个参数如果传递为True,则数组中的第一行将被视为列名,传递False则表示第一行中的数据。有了这个说代码假设我们很可能从第一行开始,但即便如此,如果我们从第4行开始并且第4行有列标题,这可能是一个问题,因为上面的行也被收集并且会甩开因此,这里的魔力可能不适合你。

编辑:刚看到您使用代码更新了您的问题,以下内容可能无法接受,因为看起来您不是从第一行开始,但您可以跳过数组中的前几个元素得到你想要的东西。

示例用法

Dim fileName As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Customers.xlsx")
Dim sheetName As String = "Customers"
Dim dtCustomers As DataTable = UsedRowsToDataTable(fileName, sheetName, True)
DataGridView1.DataSource = dtCustomers

将数据读入DataTable的代码

Option Strict On
Option Infer Off

Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office
Imports System.Runtime.InteropServices
Module ExcelIterataingData_DataTable
    Public Function UsedRowsToDataTable(
        ByVal FileName As String,
        ByVal SheetName As String,
        ByVal HasHeader As Boolean) As DataTable

        Dim dtSheetData As New DataTable

        If IO.File.Exists(FileName) Then

            Dim Proceed As Boolean = False
            Dim xlApp As Excel.Application = Nothing
            Dim xlWorkBooks As Excel.Workbooks = Nothing
            Dim xlWorkBook As Excel.Workbook = Nothing
            Dim xlWorkSheet As Excel.Worksheet = Nothing
            Dim xlWorkSheets As Excel.Sheets = Nothing
            Dim xlCells As Excel.Range = Nothing

            xlApp = New Excel.Application
            xlApp.DisplayAlerts = False
            xlWorkBooks = xlApp.Workbooks
            xlWorkBook = xlWorkBooks.Open(FileName)

            xlApp.Visible = False

            xlWorkSheets = xlWorkBook.Sheets

            For x As Integer = 1 To xlWorkSheets.Count
                xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)

                If xlWorkSheet.Name = SheetName Then
                    Proceed = True
                    Exit For
                End If

                Marshal.FinalReleaseComObject(xlWorkSheet)
                xlWorkSheet = Nothing

            Next
            If Proceed Then

                dtSheetData.Columns.AddRange(
                    New DataColumn() _
                    {
                        New DataColumn With
                        {
                            .ColumnName = "CompanyName",
                            .DataType = GetType(String)
                        },
                        New DataColumn With
                        {
                            .ColumnName = "ContactName",
                            .DataType = GetType(String)
                        },
                        New DataColumn With
                        {
                            .ColumnName = "ContactTitle",
                            .DataType = GetType(String)
                        }
                    }
                )

                Dim xlUsedRange As Excel.Range = xlWorkSheet.UsedRange

                Try

                    Dim ExcelCells(,) As Object =
                        CType(xlUsedRange.Value(
                                Excel.XlRangeValueDataType.xlRangeValueDefault),
                            Object(,))

                    If ExcelCells IsNot Nothing Then
                        ' Get bounds of the array.
                        Dim RowCount As Integer = ExcelCells.GetUpperBound(0)

                        For row As Integer = 1 To RowCount

                            If (ExcelCells(row, 1) IsNot Nothing) AndAlso (ExcelCells(row, 2) IsNot Nothing) Then
                                dtSheetData.Rows.Add(New Object() _
                                    {
                                        ExcelCells(row, 1),
                                        ExcelCells(row, 2),
                                        ExcelCells(row, 3)
                                    }
                                )
                            End If
                        Next

                    End If
                Finally
                    Release(xlUsedRange)
                End Try

            End If

            xlWorkBook.Close()
            xlApp.UserControl = True
            xlApp.Quit()

            Release(xlCells)
            Release(xlWorkSheets)
            Release(xlWorkSheet)
            Release(xlWorkBook)
            Release(xlWorkBooks)
            Release(xlApp)

            If Not Proceed Then
                Throw New Exception("Failed to locate " & SheetName)
            End If
        Else
            Throw New Exception("Failed to locate " & FileName)
        End If

        If HasHeader Then
            If dtSheetData.Rows.Count > 0 Then
                dtSheetData.Rows(0).Delete()
            End If
        End If

        Return dtSheetData

    End Function
    Private Sub Release(ByVal sender As Object)
        Try
            If sender IsNot Nothing Then
                Marshal.ReleaseComObject(sender)
                sender = Nothing
            End If
        Catch ex As Exception
            sender = Nothing
        End Try
    End Sub

End Module

另一种选择是通过OleDb数据提供者阅读,你可以看到MSDN code samples here中的例子,看一下项目Demo1_VB是一个简单的例子,而其他的则更复杂。