使用MS Access 2016,我将我在查询设计器中创建的查询复制到VBA,因此我可以根据表单上的某些用户选择动态更改WHERE子句。然后将此查询设置为报告的记录源。
在表单上,用户可以选择配置三个项目:1)日期,2)系统(所有系统或特定系统),3)子系统(所有子系统或特定子系统)。在VBA中,我使用字符串连接来组装查询语句,并根据所选的选项设置WHERE子句。
报告失败了,所以我开始调查。当我将字符串打印到即时窗口(debug.print)时,我很快就能看到错误。字符串变得相当冗长,大约1138个字符(根据所选的选项给出或取出)。在角色1027周围,VBA似乎会自动插入一个回车。
这是正常的吗?有办法解决这个问题吗?
这是我的代码:
'Procedure to execute report
Private Sub cmdExecReport_Click()
On Error GoTo ErrHandler
Dim ssql As String
Dim ssql2 As String
Dim StartDate As Date
Dim System As Long
Dim SubSystem As Long
'Step 1: Acquire data from form
'Acquire start date
StartDate = Me.txtReportDate_Start.Value
'Acquire System
System = Me.cboSystem.Value
'Acquire SubSystem
SubSystem = Me.cboSubSystem.Value
'Step 2: Configure record source
'Assemble the record source string based on the selected items
ssql = "SELECT Reliability_MotorData.DateStamp, Config_BaseData_Motors.Service, Config_BaseData_Motors.SysCapacity_Pct AS [Total Capacity], "
ssql = ssql & "Reliability_MotorMasterList.EquipmentName AS Equipment, Config_BaseData_Motors.EquipSystem, Config_BaseData_Motors.EquipSubSystem, "
ssql = ssql & "Motor_GetSystemName([Config_BaseData_Motors].[EquipSystem]) AS System, Motor_GetSubSystemName([Config_BaseData_Motors].[EquipSubSystem]) AS [Sub System], "
ssql = ssql & "IIf(Motor_GetServiceStatus([Reliability_MotorData].[MotorID],[SelectDate])=-1," & """" & "OOS" & """" & ",IIf(Motor_GetServiceStatus([Reliability_MotorData].[MotorID],"
ssql = ssql & "[SelectDate])=0," & """" & "In Service" & """" & "," & """" & "Unknown" & """" & ")) AS [Service Mode], Motor_GetCurrentMotorCapacity([Reliability_MotorData].[MotorID],[SelectDate]) AS [Current Capacity] "
ssql = ssql & "FROM (Config_BaseData_Motors RIGHT JOIN Reliability_MotorMasterList ON Config_BaseData_Motors.MotorID = Reliability_MotorMasterList.MotorID) "
ssql = ssql & "INNER JOIN Reliability_MotorData ON Reliability_MotorMasterList.MotorID = Reliability_MotorData.MotorID "
'Configure the Where clause
ssql = ssql & "WHERE ((Reliability_MotorData.DateStamp = #" & StartDate & "#) "
'Configure the System list
ssql = ssql & "AND ((Config_BaseData_Motors.EquipSystem "
'Check the system selected
If System = -1 Then 'all systems
ssql = ssql & "Like " & """" & "*" & """" & ") "
Else 'specific one
ssql = ssql & "= " & System
End If
'Add closing paren
ssql = ssql & ") "
'Configure the SubSystem list
ssql = ssql & "AND ((Config_BaseData_Motors.EquipSubSystem "
'Check the subsystem selected
If SubSystem = -1 Then 'all subsystems
ssql = ssql & " Like " & """" & "*" & """" & ")"
Else 'specific one
ssql = ssql & "= " & SubSystem
End If
'Add closing paren & ;
ssql = ssql & ");"
Debug.Print ssql
'Step 3: Launch Report
' DoCmd.OpenReport "Motor Capacity 4", acViewPreview, , , , ssql
Exit Sub
ErrHandler:
'Write to event log
Call WriteWinEventLog(Error, Now() & " - " & "Execution error on form " & CurrentFormName & " in routine cmdExecReport_Click" & vbCrLf _
& "Error Number: " & Err.Number & vbCrLf & "Source: " & Err.Source & vbCrLf & "Description: " & Err.Description)
End Sub
以下是打印结果(为了回车的可见性而添加了换行符):
SELECT Reliability_MotorData.DateStamp,Config_BaseData_Motors.Service,Config_BaseData_Motors.SysCapacity_Pct AS [Total Capacity],Reliability_MotorMasterList.EquipmentName AS Equipment,Config_BaseData_Motors.EquipSystem,Config_BaseData_Motors.EquipSubSystem,Motor_GetSystemName([Config_BaseData_Motors]。[EquipSystem])AS System,Motor_GetSubSystemName( [Config_BaseData_Motors]。[EquipSubSystem])AS [Sub System],IIf(Motor_GetServiceStatus([Reliability_MotorData]。[MotorID],[SelectDate])= - 1," OOS",IIf(Motor_GetServiceStatus([Reliability_MotorData]) 。[MotorID],[SelectDate])= 0," In Service"," Unknown"))AS [Service Mode],Motor_GetCurrentMotorCapacity([Reliability_MotorData]。[MotorID],[SelectDate ])AS [当前容量] FROM(Config_BaseData_Motors RIGHT JOIN Reliability_MotorMasterList ON Config_BaseData_Motors.MotorID = Reliability_MotorMasterList.MotorID)INNER JOIN Reliability_MotorData ON Reliability_MotorMasterList.MotorID = Reliability_MotorData.MotorID WHERE ((Reliability_MotorData.DateStamp =#8/10/2016#)
AND((Config_BaseData_Motors.EquipSystem赞" "))AND((Config_BaseData_Motors.EquipSubSystem Like" "));
我可以稍微缩短我的查询并使其在这个实例中工作,但是如果我想允许他们选择多个系统或子系统呢?最终我会再次开始使用角色并遇到同样的问题。
使用连接是否有更好的方法来实现我的目标?我已经尝试使用一个大的连接语句,并为WHERE子句使用第二个字符串变量,然后将它们一起打印debug.print ssql & ssql2
。它们都产生相同的结果。
或者,如果有办法动态编辑MS Access查询以更改where子句;这可能是一种选择。
谢谢
答案 0 :(得分:0)
最佳做法是不要在代码中构建SQL查询。只需保存您构建的查询,然后使用参数化的querydef来调用它。例如。保存查询:
SELECT Reliability_MotorData.DateStamp,
Config_BaseData_Motors.Service,
Config_BaseData_Motors.SysCapacity_Pct AS [Total Capacity],
Reliability_MotorMasterList.EquipmentName AS Equipment,
Config_BaseData_Motors.EquipSystem,
Config_BaseData_Motors.EquipSubSystem,
Motor_GetSystemName([Config_BaseData_Motors].[EquipSystem]) AS System,
Motor_GetSubSystemName([Config_BaseData_Motors].[EquipSubSystem]) AS [Sub System],
IIf(Motor_GetServiceStatus([Reliability_MotorData].[MotorID], [SelectDate])=-1,
"OOS",
IIf(Motor_GetServiceStatus([Reliability_MotorData].[MotorID],[SelectDate])=0,
"In Service",
"Unknown")) AS [Service Mode],
Motor_GetCurrentMotorCapacity([Reliability_MotorData].[MotorID],[SelectDate]) AS [Current Capacity]
FROM (Config_BaseData_Motors
RIGHT JOIN Reliability_MotorMasterList
ON Config_BaseData_Motors.MotorID = Reliability_MotorMasterList.MotorID)
INNER JOIN Reliability_MotorData
ON Reliability_MotorMasterList.MotorID = Reliability_MotorData.MotorID
WHERE ((Reliability_MotorData.DateStamp = [SearchDate])
AND ((Config_BaseData_Motors.EquipSystem Like [SearchSystem]))
AND ((Config_BaseData_Motors.EquipSubSystem Like [SearchSubSystem]));
并查询它:
Private Sub cmdExecReport_Click()
On Error GoTo ErrHandler
Dim qdf As QueryDef
Dim StartDate As Date
Dim System As Long
Dim SubSystem As Long
'Step 1: Acquire data from form
StartDate = Me.txtReportDate_Start.Value 'Acquire start date
System = Me.cboSystem.Value 'Acquire System
SubSystem = Me.cboSubSystem.Value 'Acquire SubSystem
'Step 2: Acquire QueryDef
Set qdf = CurrentDB.QueryDefs("qryMyParameterQuery") ' EDIT THIS
'Step 3: Substitute Parameters
'Substitute date
qdf.Parameters("SearchDate") = "#" & StartDate & "#"
'Substitute system
If System = -1 Then
qdf.Parameters("SearchSystem") = """*"""
Else
qdf.Parameters("SearchSystem") = """" & System & """" ' format as String
End If
'Substitute subsystem
If SubSystem = -1 Then
qdf.Parameters("SearchSubSystem") = """*"""
Else
qdf.Parameters("SearchSubSystem") = """" & SubSystem & """" ' format as String
End If
' Step 4: Open report, recordset, etc.
' Example:
'Dim rst As Recordset
'Set rst = qdf.OpenRecordset()
'...
End Sub