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

时间:2014-06-20 21:41:51

标签: vba ms-access

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

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

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

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

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

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

4 个答案:

答案 0 :(得分:6)

当您尝试打开记录集时出现错误的原因是您的表单未打开,当您尝试访问[forms]![frmReportingMain]它为null时,您尝试获取该空引用和属性的属性爆炸。 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 clause ,然后使用表单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

答案 1 :(得分:4)

虽然从GUI运行QueryDef时,[Forms]!...引用默认为表单引用,但它实际上只是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#)时参数不喜欢,即使该字段是日期。如果我将params设置为字符串,它似乎只能正常工作。但是,当将值直接从表单上的控件中拉出来时,这似乎不是一个问题。

答案 2 :(得分:3)

我知道自从发布以来已经有一段时间了,但是我想提高我的价值,因为我总是在寻找这个问题:

可以解析存储的查询:

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

这假设所有参数值都是可访问的 - 即表单是打开的,控件具有值。

答案 3 :(得分:0)

&#39;我的记录集中有两个参数,我得到的参数太少了。预计2&#34;在MS Access vba中使用OpenRecordset时出现错误,这就是我如何解决它并且工作正常的方法!见下面的子程序:

&#39;私人子显示ID_Click()

&#39; 1。我为我的两个参数字段xEventID和xExID创建了变量,如下所示:

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

&#39; 2。将变量设置为参数字段,如下所示:

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

&#39; 3。将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

&#39; End Sub