为啥我的脚本字典函数在 access vba 中只返回键?

Posted

技术标签:

【中文标题】为啥我的脚本字典函数在 access vba 中只返回键?【英文标题】:Why does my scripting dictionary function in access vba only return keys?为什么我的脚本字典函数在 access vba 中只返回键? 【发布时间】:2019-07-22 20:09:59 【问题描述】:

我有一个 Access 2016 函数,该函数根据历史值数据库检查脚本字典的值,并返回不属于计算的错误范围内的键/项对的字典。但是,该函数仅返回键,并且对该项目的调用会导致运行时错误 3420 - 对象无效或不再设置。

我在函数末尾调试字典,它打印正常,但是当函数返回时,它会出错。

这是对该函数的简化调用:

sub Verify(index as long, frm as form)
  dim badComps as object
  dim comp as variant

  Set badComps = Check_History(INDEX, custID, Station)

    For Each comp In badComps.Items
        Debug.Print "'" & comp & "'"
    Next
End Sub

这是函数本身:(编辑:该函数有效,所以我对其进行了简化。最后的调试语句打印了我需要返回到验证子的所有内容)

Function Check_History(INDEX As Long, ByVal frmCust As String, ByVal frmStat As String) As Scripting.dictionary
    Dim avgs As Object, mPercents As Object, dict As Object
    Dim rst As DAO.Recordset, rst2 As DAO.Recordset
    Dim db As DAO.Database
    Dim compName As Variant, badKeys As Variant
    Dim i As Long

    Set db = CurrentDb
    Set mPercents = CreateObject("Scripting.Dictionary")
    Set dict = CreateObject("Scripting.Dictionary")

    'pull history for the passed station
    Set rst = db.OpenRecordset("SELECT * FROM [tblCalculated_Values] WHERE [INDEX] = " & INDEX)
    rst.MoveLast


    'pull history for the passed station.
    Set rst2 = db.OpenRecordset("SELECT * FROM [Sample History] WHERE [INDEX] = '" & frmCust & frmStat & "'")
    If rst2.RecordCount = 0 Then GoTo nohist
    rst2.MoveLast
    rst2.MoveFirst

    'calculate the average historical value for each component
    For i = 0 To rst2.RecordCount - 1
        For Each compName In mults.keys
            If avgs.Exists(compName) Then
                avgs.Item(compName) = avgs.Item(compName) + rst2.fields(compName)
            Else
                avgs.Add compName, rst2.fields(compName)
            End If
        Next
        rst2.MoveNext
    Next
    rst2.MoveFirst

    For Each compName In mults.keys
        If avgs.Exists(compName) Then
            If IsNull(avgs.Item(compName)) Then avgs.Item(compName) = 0
            avgs.Item(compName) = avgs.Item(compName) / rst2.RecordCount
        End If
    Next

        'If sample falls outside the range of avg +- 1, add error to dictionary

        If mPercents.Item(compName) > 0 And avgs.Item(compName) > 0 Then
            If mPercents.Item(compName) < WorksheetFunction.Max(0.001, Round(avgs.Item(compName) - 1, 3)) Or _
                mPercents.Item(compName) > Round(avgs.Item(compName) + 1, 3) Then dict.Add compName, mPercents.Item(compName)
            If dict.Exists(compName) Then Debug.Print compName, dict.Item(compName)            
        End If
    Next

    badKeys = dict.keys
    'if no errors, add key = "clean" & item = 0, else return dictionary of component, avg value

    If UBound(badKeys) = -1 Then dict.Add "clean", 0

    Set Check_History = dict

nohist:
End Function

任何帮助/见解/提示都会让我的一天变得更加美好。蒂亚!

【问题讨论】:

“它出错了”具体是什么意思?另外,如果引用了Scripting 库,为什么要声明您的字典As Object 并用= CreateObject("Scripting.Dictionary") 而不是= New Scripting.Dictionary 分配它们?让你的生活更轻松,不要针对早期绑定的引用编写后期绑定的代码...... 您在check_History 的哪个位置为返回的字典dict 提供任何值(除了单行If UBound(badKeys) = -1 Then dict.Add "clean", 0?请提供minimal reproducible example,强调“最小”。 另外nohist 标签也没有分配返回引用,所以badcomps 很可能是Nothing - 在这种情况下,Verify 中会出现错误 91。 在函数中创建字典不是问题。最后一个 For 循环中的调试语句为我提供了函数应该传递的所有数据。但是,当我回到验证子时,For...Each 循环会抛出帖子开头提到的错误 3420。 在您发布的代码中您在dict 中没有设置任何键。请查看您发布的代码。 【参考方案1】:

忽略您发布的代码的其他问题,这个:

avgs.Add compName, rst2.fields(compName)

有点模棱两可:你的意思是添加 Field 对象本身,还是字段的 Value ?

看起来你打算做后者,但实际上你正在做前者。因此,当您的字典从函数返回时,它可能包含对您(现已关闭)记录集的引用。

您的Debug.Print 输出可能没问题,因为会调用默认的Value 属性来创建Print 输出

avgs.Add compName, rst2.fields(compName).Value

应该解决这个问题。

【讨论】:

以上是关于为啥我的脚本字典函数在 access vba 中只返回键?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Access VBA 在 Excel 中添加小计在一个数据库中工作,但在另一个数据库中出现错误 1004?

使用拼写检查时使用 VBA 切换字典 (MS Access)

access 2010找不到我的VBA函数?

为啥在 Access 中返回 835 条记录的查询会在 VBA 代码中返回一个空记录集?

Access 2010 VBA:为啥这个表单打开和关闭序列不起作用?

如何在 vba(access) 中将变量设置为我的表单列表框之一?