【问题标题】:Excel throws Exception from HRESULT: 0x800AC472 when preforming list.Contains()Excel 在执行 list.Contains() 时从 HRESULT 引发异常:0x800AC472
【发布时间】:2021-10-22 03:53:10
【问题描述】:

我正在 VS2019 上编写一个 Windows 窗体应用程序,它将打开一个 excel 文件并执行嵌套循环。

基本上,有两个整数列表。代码将遍历每一行以检查单元格 A 的值是否存在于任何列表中,然后将字符串分配给单元格 B。

原始代码中的列表大约有 400 个元素,但我将其删减到此处发布。然后有趣的事情发生了。当我使用 400 多个元素运行原始代码时,它会循环该行并中途停止,然后它给了我“HRESULT 异常:0x800AC472”。但是,当我运行下面的代码时,它没有错误。

所以我想如果是庞大的列表是问题所在。我想知道你们中是否有人遇到过这种情况以及如何解决它。

[更新] 我已向列表中添加了更多元素并尝试运行它。它确实抛出了同样的异常。我还尝试减少元素的数量并再次运行,它没有错误地工作。所以我猜是因为元素的数量。

Private Sub generateZone(ByVal worksheet As Object)
    'Initialise Excel Object
    xlsApp = New Excel.Application
    'Open file
    xlsWorkBook = xlsApp.Workbooks.Open("File location")
    'Open worksheet(according to the spreadsheet)
    xlsWorkSheet = xlsWorkBook.Worksheets("sheet1")

    'Excel interaction setting
    With xlsApp
        .Visible = True
        .Application.Visible = True
        .DisplayAlerts = False
        .EnableEvents = False
    End With        

    Dim emZone1 As New List(Of Integer)(New Integer() {87371, 87390, 94614, 92000, 82898, 96500, 99124, 93260, 82496, 97858, 90323, 88083, 80770, 84186, 86318, 91922, 85987, 80635, 84079, 96691, 85578, 83108, 96081, 87642, 96703, 96692, 99193, 93039, 97003, 89374, 99252, 82305, 87907, 90966, 80517, 88471, 92395, 86109, 87112, 92849, 93853, 91136, 90512, 97143, 96105, 93966, 81136, 97218, 97816, 82525, 97714, 98175, 94940, 97262, 81750, 92075, 98905, 96199, 94072, 83841, 88243, 98375, 84142, 92818, 83527, 97446, 88632, 86542, 84768, 86283, 84910, 88986, 92802, 99145, 81487, 84729, 80010, 90896, 99418, 87545, 95937, 89904, 88073, 85255, 87285, 88442, 86325, 90223, 92048, 85160, 98768, 80283, 91273, 92077, 91043, 81409, 96042, 82536, 92726, 91980})


    Dim emZone2 As New List(Of Integer)(New Integer() {86634, 92330, 95970, 95577, 87510, 89481, 94248, 93860, 81857, 82810, 93228, 80095, 94437, 84887, 88766, 92706, 92264, 88109, 91992, 82751, 94767, 95397, 96066, 91667, 94059, 89419, 82796, 82310, 86961, 85681, 93969, 81736, 81009, 97445, 80741, 92154, 84923, 86182, 91660, 90665, 81388, 87722, 94031, 94678, 84074, 80550, 82953, 81317, 95132, 92163})


    'get last row
    Dim lastRow As Integer
    lastRow = worksheet.UsedRange.Rows.Count


    'loop through every row
    For i As Integer = 1 To lastRow
        'get pronvice from column J
        Dim province As String = worksheet.Range("J" & i).Value
        If province = "Sabah" Or province = "Sarawak" Then

            'check zone1
            For Each zone1 As Integer In emZone1
                If emZone1.Contains(worksheet.Range("L" & i).Value) Then
                    worksheet.Range("M" & i).Value = "Zone 1"

                Else
                    'check zone2
                    For Each zone2 As Integer In emZone2
                        If emZone2.Contains(worksheet.Range("L" & i).Value) Then
                            worksheet.Range("M" & i).Value = "Zone 2"
                            ' Exception from HRESULT: 0x800AC472 shows here

                        Else
                            'if not in both zone
                            worksheet.Range("M" & i).Value = "EM"
                        End If
                    Next
                End If
            Next

        Else
            'if not sabah and sarawak
            worksheet.Range("M" & i).Value = "WM"
        End If

    Next

    'releaseObject(xlsWorkSheet)
    'releaseObject(xlsWorkBook)
    'releaseObject(xlsApp)

End Sub

【问题讨论】:

  • 你的逻辑有点奇怪。您正在循环emZone1emZone2,但在每个中重复一组固定的逻辑(未使用索引变量zone1zone2)。看起来您可能最初是在实现自己的 Contains 逻辑,但是当您切换到使用 Contains 时忘记取出循环?
  • @Craig 我的意图是先循环遍历 emZone1,如果 emZone1 中不存在“L & i”值,则继续循环遍历 emZone2,如果该值仍然不存在,它将显示“EM”。这是我在我的知识水平上设法产生的:')
  • 我做了很多这样的 Excel 交互,我发现最好将数据加载到 customObject 列表中并尽快处理 Excel。然后在列表而不是文档上执行您的逻辑。它可以帮助解决这些异常,并加快您的代码速度。
  • 为了扩展 @djv 的评论,我推荐 EPPlus(通过 NuGet 在 Visual Studio 中添加参考)。它比 Office Interop 好多了。

标签: excel vb.net visual-studio-2019


【解决方案1】:

不确定这是否相同,但另一个具有相同错误的 SO post 已通过以下答案解决:

“在我的情况下,抛出异常是因为我的 excel 互操作工具正在显示一个模式对话框(与过期的许可证密钥相关联 - 我真丢脸)。如果我关闭了对话框(它显示在后台)然后在 Visual Studio 中点击“继续”,程序能够连接到 xlsx 文件并成功检索数据。” -mbmihura

您是否确认没有出现任何弹出窗口或任何内容?

您的 excel 是否也获得许可?

如果不是这样,

我会为你的循环添加一个限制,并尝试找出在错误之前是否有固定的迭代次数,如果是,那么就会施加一些默认限制。

最后一个想法,

我在很多示例中看​​到这些互操作 excel 调用没有得到正确处理,这导致许多 excel 卡在后台运行。

检查您的任务管理器并确保没有发生这种情况。如果是这样,请将它们关闭并再次尝试测试。

【讨论】:

  • 我使用的是授权的 excel,所以没有弹出窗口。我有点觉得这个列表导致代码太庞大,但正如你提到的那样,它也可能是由某些数字引起的。
  • 每次都在同一行抛出错误吗?无论如何将所有数据加载到excel之外的数据源中?我总是对 excel 的东西有奇怪的错误行为。
【解决方案2】:

我认为您只需要在读取值之前检查空单元格。当单元格为空并且您尝试将其解析为字符串时,Excel 会抛出异常

Dim xlsRange As Excel.Range = Nothing

    ' In your loop
    xlsRange = DirectCast(xlsWorkSheet.Cells("J" & i), Excel.Range)
    If xlsRange.Value IsNot Nothing Then
        Dim province = xlsRange.Value.ToString()
    End If
    ' /Loop

' always release it at the end

If xlsRange IsNot Nothing Then Marshal.ReleaseComObject(xlRange)

我还是更喜欢把所有的东西都加载到对象中,并在释放所有 Excel 对象后对它们进行操作

【讨论】:

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