我有一个名为qryAlloc_Source的查询,它在一个条件下有两个参数:
>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])
Run Code Online (Sandbox Code Playgroud)
A有一个单独的查询,最终引用qryAlloc_Source(中间有几个查询),当我在UI中双击它时该查询运行正常,但如果我尝试在VBA中打开它,我会收到错误.我的代码是:
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")
Run Code Online (Sandbox Code Playgroud)
我得到运行时错误3061,参数太少.预期2.我已经读过我可能需要使用表单参数在VBA中构建SQL,但鉴于链中存在一些查询,它将是相当复杂的SQL.
有关解决方法的任何建议吗?我考虑使用VBA从查询创建一个表,然后只引用该表 - 我讨厌做出额外的步骤.
当您尝试打开记录集时出现错误的原因是您的表单未打开,当您尝试访问[forms]![frmReportingMain]
它时为null,那么您尝试在该空引用上获取属性并且事情会爆炸.该OpenRecordset
函数无法弹出一个对话框来提示用户输入,如果它出现此错误,则会执行此操作.
您可以更改查询以使用未绑定到表单的参数
yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用此函数来获取该查询的记录集.
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
Run Code Online (Sandbox Code Playgroud)
这样做的缺点是,当你现在在绑定它的表单上调用它时,它不会动态地为你填充空白.
在这种情况下,您可以绑定表单qryAlloc_debts
并且在保存的查询上没有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
Run Code Online (Sandbox Code Playgroud)
小智 5
虽然当从 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
Run Code Online (Sandbox Code Playgroud)
如果引用的表单打开,则代码足够智能,可以使用表单上引用的控件。如果没有,它将使用提供给子例程的日期作为参数。这里的一个问题是,当我将参数设置为日期类型(#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
Run Code Online (Sandbox Code Playgroud)
对于 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
Run Code Online (Sandbox Code Playgroud)
这假设所有参数值都是可访问的 - 即表单打开并且控件具有值。
归档时间: |
|
查看次数: |
20874 次 |
最近记录: |