【问题标题】:Importing an excel file to existing DataGridView in VB.Net将 excel 文件导入到 VB.Net 中的现有 DataGridView
【发布时间】:2019-02-26 07:45:33
【问题描述】:

我的下面代码有问题,它在运行时冻结并且什么也不做。

基础设施: 视觉工作室 2017 .NET 框架 4.7.2 操作系统:Windows 7

目标: 我有一个包含 3 列的 DataGridView,我在这个 DataGridView 中列出了来自另一个来源的一些信息,以填充第一行和第二行。

第一行是参数名称,第二行是这个参数的当前值。

第三列不在此过程中填写,我将从我的数据库 Excel 文件中填写第三列,以将参数的当前值与 Excel 中存储的数据库值进行比较。这就是我的问题开始的地方。

我正在尝试使用以下代码从我正在使用数据库的 Excel 表中填充 DataGridView 参数值;

有些参数没有存储在 Excel 表格中,所以实际上我需要一个类似 vlookup 的函数来将数据与参数名称进行映射。

在excel中,A列是我的参数名称,B列是参数的数据库值。

我正在尝试导入此 excel 并尝试匹配 DataGridView 和 Excel 中的参数名称,如果参数名称相同,则应将 Excel 参数值写入 DataGridView 中的第三列。

Public Class BuildImportExcel
    Public Shared Sub NewMethod(ByVal dgv As DataGridView)
        Dim ofd As OpenFileDialog = New OpenFileDialog With {
            .Filter = "Excel |*.xlsx",
            .Title = "Import Excel File"
        }
        ofd.ShowDialog()

        Try
            If ofd.FileName IsNot "" Then
                Dim xlApp As New Excel.Application
                If xlApp Is Nothing Then
                    MessageBox.Show("Excel is not properly installed!")
                Else
                    Dim xlBook As Excel.Workbook = xlApp.Workbooks.Open(ofd.FileName)
                    Dim xlSheet As Excel.Worksheet = CType(xlBook.ActiveSheet, Excel.Worksheet)

                    For i = 0 To dgv.Rows.Count
                        If dgv.Rows(i).Cells(0).Value IsNot "" Then
                            Dim look As Boolean = True
                            Dim found As Boolean = False
                            Dim rowLook As Integer = 2
                            Dim rowFound As Integer = 0
                            While look = True
                                If xlSheet.Range("A" & rowLook).Value IsNot "" Then
                                    If xlSheet.Range("A" & rowLook).Text Is dgv.Rows(i).Cells(0).Value Then
                                        found = True
                                        rowFound = rowLook
                                    End If
                                Else
                                    look = False
                                End If
                                rowLook = rowLook + 1
                            End While
                            If found = True Then
                                dgv.Rows(i).Cells(2).Value = xlSheet.Range("B" & rowFound).Text
                            End If
                        End If
                    Next
                    xlApp.Quit()
                    Release(xlSheet)
                    Release(xlBook)
                    Release(xlApp)
                End If
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
    Private Shared 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 Class

但问题是它无法冻结我认为参数列表大约有 200 行,所以它会导致冻结并尝试使用 5 个参数等小部分,但仍然相同。好像有问题,我找不到。

将它们与该方法匹配是否也是逻辑方式,或者您是否建议使用 OLEDB 连接之类的方法?

编辑: 我关闭 Option Strict 然后将 IsNot 更改为 operator 然后它开始工作,但我想使用 Option Strict 我如何处理这个运算符?

【问题讨论】:

  • 请查看Comparing Objects。你希望Option Strict On 很好,因为它强制执行的严格类型可以防止许多逻辑错误。此外,请注意 Excel Range.Text 属性返回 Range 值的 as display(格式化)文本表示形式。如果单元格宽度不足以显示该值,则 Text 属性将返回一个空字符串或适合该宽度的“#”字符字符串。

标签: excel vb.net datagridview


【解决方案1】:

你让这变得比它必须的更困难。一个有问题和有问题的领域是While look = True 循环。这假设很多,并且在我的测试中,会导致代码经常冻结。这里的主要问题是代码(有点)循环遍历 Excel 文件中的行。这里的问题是你不知道有多少行!没有对此进行检查,代码将在线失败......

  If xlSheet.Range("A" & rowLook).Value IsNot "" Then

当您到达给定 Excel 文件的底部时,它永远找不到匹配项。

另一个问题是线路……

If xlSheet.Range("A" & rowLook).Text Is dgv.Rows(i).Cells(0).Value Then 

这总是会失败,永远不会是真的。我的理解……

Is 运算符确定两个对象引用是否指向同一个 目的。但是,它不执行值比较。

鉴于此,我建议您稍微简化一下。最重要的是通过 Excel 工作表的循环是“昂贵的”,如果有很多行,您可能会遇到性能问题。当我说很多行时,我的意思是数万行……。 200 行应该没问题。

如果我们能知道工作表中有多少行是从……返回的,事情就不会复杂化了。

 Dim xlSheet As Excel.Worksheet = CType(xlBook.ActiveSheet, Excel.Worksheet)

这基本上是一个 Excel Range,正是从这个Range,我们可以得到这个 excel 范围内的行数……

   Dim totalExcelRows = xlSheet.UsedRange.Rows.Count

现在,我们可以用一个简单的for 循环代替复杂且有问题的While 循环。这将消除一些变量,并将循环索引保持在 excel 文件中的行范围内。

我希望这是有道理的……下面是上述内容的一个示例。

Public Shared Sub NewMethod(ByVal dgv As DataGridView)
    Dim ofd As OpenFileDialog = New OpenFileDialog With {
        .Filter = "Excel |*.xlsx",
        .Title = "Import Excel File",
        .InitialDirectory = "D:\\Test\\ExcelFiles"
    }
    ofd.ShowDialog()
    Try
        If ofd.FileName IsNot "" Then
            Dim xlApp As New Excel.Application
            If xlApp Is Nothing Then
                MessageBox.Show("Excel is not properly installed!")
            Else
                Dim xlBook As Excel.Workbook = xlApp.Workbooks.Open(ofd.FileName)
                Dim xlSheet As Excel.Worksheet = CType(xlBook.ActiveSheet, Excel.Worksheet)
                Dim totalExcelRows = xlSheet.UsedRange.Rows.Count
                For i = 0 To dgv.Rows.Count
                    If dgv.Rows(i).Cells(0).Value IsNot Nothing Then
                        For excelRow = 1 To totalExcelRows
                            If xlSheet.Range("A" & excelRow).Text.ToString() = dgv.Rows(i).Cells(0).Value.ToString() Then
                                dgv.Rows(i).Cells(2).Value = xlSheet.Range("B" & excelRow).Text
                                Exit For
                            End If
                        Next
                    Else
                        Exit For
                    End If
                Next
                xlApp.Quit()
                Marshal.ReleaseComObject(xlSheet)
                Marshal.ReleaseComObject(xlBook)
                Marshal.ReleaseComObject(xlApp)
            End If
        End If
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
End Sub

【讨论】:

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