VBA函数从SQL查询返回记录集值

时间:2018-09-05 16:37:27

标签: vba ms-access dao recordset

我正在尝试从表中返回货币值,并且我需要将变量传递到包含查询的VBA定义函数中,以便获取正确的查询。我在表单的文本框中使用了该函数,但返回的是:

#Name?

感谢您的帮助。下面的代码:

Option Compare Database

Public Function payrollVar(dateVar As Date, roleidVar As String, typeVar As String) As DAO.Recordset

Dim dbs As DAO.Database
Dim rsSQL As DAO.Recordset
Dim strSQL As String

Set dbs = CurrentDb

'typeVar must either be ODE, Actual, or Forecast

If typeVar = "Actual" Or "Forecast" Then
    strSQL = "SELECT [Master Data].[*Quantity]" & _
             "FROM [Master Data]" & _
             "WHERE ((([Master Data].[*Category])='Payroll') AND (([Master Data].[*Date])= " & dateVar & ") AND (([Master Data].[*Role ID])= '" & roleidVar & "' ) AND (([Master Data].[*Type])= '" & typeVar & "' ));"
ElseIf typeVar = "ODE" Then
    strSQL = "SELECT [Master Data].[*Quantity]" & _
             "FROM [Master Data]" & _
             "WHERE ((([Master Data].[*Data Version])='Resource_Detail_Cost_Increase_Projections_Table') AND (([Master Data].[*Category])='Payroll') AND (([Master Data].[*Date])= " & dateVar & ") AND (([Master Data].[*Role ID])= '" & roleidVar & "' ));"
End If

Set rsSQL = dbs.OpenRecordset(strSQL)

payrollVar = rsSQL.GetRows(0)

End Function

2 个答案:

答案 0 :(得分:0)

考虑使用DLookUp函数,而不是DAO记录集检索,而DAO记录集检索不能直接用于文本框之类的表单控件。然后,将值直接分配给VBA中的文本框,并确保删除所有ControlSource,因为对于VBA分配,文本框应为空白。

在Access SQL和VBA中可用,DLookUp的 criteria 参数可以采用任何兼容的SQL WHERE条件。因此,您可以重用SELECT语句的一部分。另外,如果应返回多个值,该函数将返回查找的第一个实例。

Public Function payrollVar(dateVar As Date, roleidVar As String, typeVar As String)
    Dim val As Variant

    If typeVar = "Actual" Or typeVar = "Forecast" Then

        val = DLookUp("[*Quantity]", "[Master Data]", _
                      "[*Category] = 'Payroll' AND " _
                       & "[*Date] = #" & dateVar & "#) AND " _
                       & "[*Role ID] = '" & roleidVar & "' AND " _
                       & "[*Type] = '" & typeVar & "'")

    ElseIf typeVar = "ODE" Then

        val = DLookUp("[*Quantity]", "[Master Data]", _
                      "[*Category] = 'Resource_Detail_Cost_Increase_Projections_Table' AND " _
                       & "[*Date] = #" & dateVar & "#) AND  " _
                       & "[*Role ID] = '" & roleidVar & "' AND " _
                       & "[*Type] = '" & typeVar & "'")

    End If

    ' ASSIGN TO UNBOUND TEXTBOX 
    Me.[myTextbox] = val

End Function

然后在事件触发器OnClickOnOpenAfterUpdate等上调用非返回方法:

Call payrollVar(param1, param2, param3)

答案 1 :(得分:0)

首先,我也建议像Parfait建议的那样使用DLookup。我将更进一步,将其与IIF结合使用,以至于甚至没有必要使用函数,但这还取决于其他因素。但是,如果您确实想使用记录集并假设您的SQL是正确的,那么这就是您所缺少的:

代替

payrollVar = rsSQL.GetRows(0)

您需要:

rsSQL.MoveFirst
payrollVar=rsSQL![*Quantity]
rsSQL.Close

这通常是不够的!只有确保您的查询将返回一个值,这才足够好。如果有可能,它将找不到返回的记录,您需要将其包含在以下if语句中:

if rsSQL.EOF=False OR rsSQL.BOF=False Then
  rsSQL.MoveFirst
  payrollVar=rsSQL![*Quantity]
Else
  payrollVar=0 (or whatever value indicates no result found)
End If
rsSQL.Close

最后,为什么您会在列名上使用*?如果您在名称中不使用空格和符号,则SQL的工作和读取变得更加容易。