VBA OpenRecordset Producing 参数太少。预期 2. 错误

Posted

技术标签:

【中文标题】VBA OpenRecordset Producing 参数太少。预期 2. 错误【英文标题】:VBA OpenRecordset Producing Too few parameters. Expected 2. Error 【发布时间】:2022-01-07 12:24:04 【问题描述】:

我有一个名为 qryAlloc_Source 的查询,它在一个条件下有两个参数:

>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])

A 有一个单独的查询,它最终引用 qryAlloc_Source(中间有几个查询),当我在 UI 中双击它时,该查询运行良好,但如果我尝试在 VBA 中打开它,我得到一个错误.我的代码是:

Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")

我收到运行时错误 3061,参数太少。预期 2。我读过我可能需要使用表单参数在 VBA 中构建 SQL,但鉴于链中有一些查询,这将是非常复杂的 SQL。

关于解决方法的任何建议?我考虑过使用 VBA 从查询中创建一个表,然后只是引用该表——不过我讨厌做额外的步骤。

【问题讨论】:

【参考方案1】:

当您尝试打开记录集时出现错误的原因是您的表单未打开,当您尝试访问 [forms]![frmReportingMain] 时它为空,然后您尝试获取该空引用的属性并且事情爆炸了. OpenRecordset 函数无法弹出一个对话框来提示用户输入,就像 UI 遇到此错误时所做的那样。

您可以更改查询以使用未绑定到表单的参数

yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd

然后你可以使用这个函数来获取那个查询的记录集。

Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset

    Dim db As DAO.Database
    Dim qdef As DAO.QueryDef
    Set db = CurrentDb
    Set qdef = db.QueryDefs("qryAlloc_Debits")
    qdef.Parameters.Refresh
    qdef.Parameters("pAllocStart").Value = pAllocStart
    qdef.Parameters("pAllocEnd").Value = pAllocEnd
    Set GetQryAllocDebits = qdef.OpenRecordset

End Function

这样做的缺点是,当您现在在绑定到它的表单上调用它时,它不会为您动态地“填写空白”。

在这种情况下,您可以绑定表单 qryAlloc_debts 并在已保存的查询上设置 no where 子句,然后使用表单 Filter 来创建 where 子句。在这种情况下,您可以完全按照您的编写方式使用 where 子句。

如果你还想打开一个记录集,你可以这样做

Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset

    Dim qdef As DAO.QueryDef
    Set qdef = New DAO.QueryDef
    qdef.SQL = "Select * from qryAlloc_Debits where AllocStart >= pAllocStart and pAllocEnd <= pAllocEnd"
    qdef.Parameters.Refresh
    qdef.Parameters("pAllocStart").Value = pAllocStart
    qdef.Parameters("pAllocEnd").Value = pAllocEnd
    Set GetQryAllocDebits = qdef.OpenRecordset

End Function

【讨论】:

我需要重新阅读以完全消化它,但我确实想注意我的表单是打开的,并且输入了一个日期范围。我实际上是用同一个表单上的一个按钮来启动代码的。这才是真正让我困惑的地方——我可以手动打开查询,但不能使用代码。非常感谢您的意见 - 我现在会再次审查它。 所以我的主要问题是这些参数不是我需要的查询的一部分(qryAlloc_Debits)......它们是按日期过滤原始数据的源数据查询的一部分。我需要的查询是执行大量分组和合并的链中的几个查询。所以很遗憾,我无法将参数直接应用于此查询。 那么查询 def 选项仍然适用。参数将沿着链向上运行。您甚至可以在表单加载时像这样填充此记录集并将其设置为表单的记录集。 或者,一旦您的大量查询工作正常,将其合并回一个查询。 啊,我现在明白了——我想念我可以使用 qdef 参数,即使这些参数不是专门在那个查询中。谢谢!【参考方案2】:

虽然 [Forms]!... 当从 GUI 运行 QueryDef 时引用默认为表单引用,但它实际上只是 VBA 查询中的另一个参数。结果是您根本不必重新编码查询/创建新查询。此外,正如@Brad 所提到的,无论参数是否在查询链的最终查询中,您都可以像在最终查询的集合中一样引用该参数。既然如此,你应该可以使用类似这样的代码:

Sub GetQryAllocDebits(dteAllocStart As Date, dteAllocEnd as Date)

    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim rst As DAO.Recordset

    Set db = CurrentDb()
    Set qdf = db.QueryDefs("qryAlloc_Debit")

    If CurrentProject.AllForms("frmReportingMain").IsLoaded Then
        qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = [forms]![frmReportingMain]![txtAllocStart]
        qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = [forms]![frmReportingMain]![txtAllocEnd]
    Else
        qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = CStr(dteAllocStart)
        qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = CStr(dteAllocEnd)
    End If

    Set rst = qdf.OpenRecordset

    Do Until rst.EOF
        '...do stuff here.
    Loop

    Set rst = Nothing
    Set qdf = Nothing
    Set db = Nothing

End Function

如果引用的表单是打开的,则代码足够智能,可以使用表单上的引用控件。如果不是,它将使用提供给子例程的日期作为参数。这里的一个问题是,当我将它们设置为日期类型 (#xx/xx/xx#) 时,即使该字段是日期,参数也不喜欢。如果我将参数设置为字符串,它似乎只能正常工作。不过,直接从表单上的控件中提取值似乎不是问题。

【讨论】:

感谢@VBlades——这真的很有帮助!我只是根据时间给了布拉德正确的答案,但是看到这两个答案确实有助于澄清它。我很感激。 太棒了,很高兴它有帮助。【参考方案3】:

我知道这已经有一段时间没有发布了,但我想投入我的 tuppence 价值,因为我一直在寻找这个问题:

可以解析存储的查询:

Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
    prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset

对于 SQL:

Set db = CurrentDb
Set qdf = db.CreateQueryDef("", "SELECT * FROM MyTable " & _
    "WHERE ID = " & Me.lstID & _
    " AND dWeekCommencing = " & CDbl(Me.frm_SomeForm.Controls("txtWkCommencing")) & _
    " AND DB_Status = 'Used'")
For Each prm In qdf.Parameters
    prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset

这假定所有参数值都可以访问 - 即表单是打开的并且控件具有值。

【讨论】:

【参考方案4】:

'我的记录集中有两个参数,并且在 MS Access vba 中使用 OpenRecordset 时出现“参数太少。预期为 2”'错误,这就是我解决它的方法,它可以工作!见下面的子程序:

'Private Sub DisplayID_Click()

'1.我为我的两个参数字段 xEventID 和 xExID 创建了变量,如下所示:

Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer 
Dim xExId As Integer  

'2.将变量设置为参数字段,如下所示:

Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID

'3.将 rst 设置为 OpenRecordSet 并将 Set the variables 分配给 WHERE 子句。确保完全按照其显示方式包含所有引号、& 和空格。否则代码将中断!完全如下所示:

Set rst = db.OpenRecordset("SELECT tblInfo_Exhibitor.EventID,tblInfo_Display.ExID, tblMstr_DisplayItems.Display " _
& "FROM tblInfo_Exhibitor INNER JOIN (tblMstr_DisplayItems INNER JOIN tblInfo_Display ON tblMstr_DisplayItems.DisplayID = tblInfo_Display.DisplayID) ON tblInfo_Exhibitor.ExID = tblInfo_Display.ExID " _
& "WHERE (((tblInfo_Exhibitor.EventID) =" & xEventID & " ) and ((tblInfo_Exhibitor.ExID) =" & xExId & " ));")

rst.Close
Set rst = Nothing
db.Close

'结束子

【讨论】:

以上是关于VBA OpenRecordset Producing 参数太少。预期 2. 错误的主要内容,如果未能解决你的问题,请参考以下文章

OpenRecordSet 的数据类型不匹配错误

MS Access VBA 更新组合框表字段

填充集合VBA MS Access - 参考问题

excel vba 调用ADODB 问题?

挂在特定记录上的 VBA 记录集更新

VBA将参数添加到新查询def