VBA OpenRecordset生成的参数太少。预期2。错误

VBA OpenRecordset生成的参数太少。预期2。错误,vba,ms-access,Vba,Ms Access,我有一个名为qryAlloc_Source的查询,在一个条件下有两个参数: >=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd]) 我得到运行时错误3061,参数太少。预期2。我已经读到,我可能需要使用表单参数在VBA中构建SQL,但是考虑到链中有一些查询,这将是非常复杂的SQL 关于解决办法有什么建议吗?我考虑过使用VBA从查询中创建一个表,然后只引用

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

>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])
我得到运行时错误3061,参数太少。预期2。我已经读到,我可能需要使用表单参数在VBA中构建SQL,但是考虑到链中有一些查询,这将是非常复杂的SQL


关于解决办法有什么建议吗?我考虑过使用VBA从查询中创建一个表,然后只引用该表——不过我不想做额外的步骤。

当您尝试打开记录集时出现错误的原因是您的表单未打开,并且当您尝试访问[forms]时![frmReportingMain]它为null,然后您尝试获取该null引用的属性,结果会发生爆炸。OpenRecordset函数无法弹出对话框来提示用户输入,就像用户界面在出现此错误时所做的那样

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

yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd
这样做的缺点是,当您现在在绑定到它的表单上调用它时,它不会为您动态地“填充空格”

在这种情况下,您可以绑定表单QRYALLOCU,并且在保存的查询中没有where子句,然后使用表单过滤器生成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

而一个[表格]!。。。当从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时,参数不喜欢,即使字段是日期。只有当我将参数设置为字符串时,它才能正常工作。但是,当将值直接从表单上的控件中取出时,这似乎不是一个问题。

我知道这篇文章发布已经有一段时间了,但我想投入我的一便士,因为我一直在搜索这个问题:

可以解析存储的查询:

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

这假设所有参数值都是可访问的,即窗体是打开的,控件有值。

'我的记录集中有两个参数,但得到的参数太少。在MS Access vba中使用OpenRecordset时,预期会出现2'错误,这就是我如何解决它的方法,它可以正常工作!请参阅以下子程序:

'专用子显示ID\u单击

"一,。我为两个参数字段xEventID和xExID创建了变量,如下所示:

Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer 
Dim xExId As Integer  
Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
"二,。将变量设置为参数字段,如下所示:

Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer 
Dim xExId As Integer  
Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
"三,。将rst设置为OpenRecordSet,并将变量集分配给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

'End Sub

我需要重新阅读此文件以完全消化它,但我确实想注意,我的表单已打开,并且输入了日期范围。实际上,我是用同一表单上的按钮启动代码的。这才是真正让我困惑的地方——我可以手动打开查询,但不能使用代码。非常感谢您的输入,我现在将再次查看。因此,我的主要问题是,这些参数不是我需要的查询的一部分。它们是按日期筛选原始数据的源数据查询的一部分。我需要的查询是一个链上的几个查询,它进行大量的分组和合并。很遗憾,我无法将参数直接应用于此查询。查询定义选项仍然适用。这些参数将沿着链向上运行。您甚至可以在表单加载时像这样填充此记录集,并将其设置为表单的记录集。或者,一旦您的一大组查询正常工作,将其合并回一个查询。啊,我现在明白了——我不知道我可以使用qdef参数,即使这些参数在该查询中不是特别的。谢谢谢谢@VBlades这真的帮了大忙!我只是根据时间给了布拉德正确的答案,但看到这两个答案确实有助于澄清问题。我很感激。太棒了,很高兴能帮上忙。