Using MS Access 2016, I am copying a query I created in the query designer to VBA so I can dynamically change the WHERE clause based on some user selections on a form. This query is then set to the record source of a report.
On the form, the user has the option to configure three items: 1) the date, 2) System (all systems or a specific one), 3) a subsystem (all subsystems or a specific one). In VBA, I assemble the query statement using string concatenation and set up the WHERE clause based on the options selected.
The report was failing, so I started investigating. When I print out the string to the immediate window (debug.print) I could see what was wrong pretty quickly. The string gets rather lengthy at approximately 1138 characters (give or take based on the options selected). Around character 1027 VBA seems to automatically insert a carriage return.
Is this normal? Is there a way around this?
Here is my code:
'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
Here is the result of the print (line feed added for visibility of carriage return):
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 = #8/10/2016# )
AND ((Config_BaseData_Motors.EquipSystem Like "") ) AND ((Config_BaseData_Motors.EquipSubSystem Like ""));
I can shorten my query a bit and make it work in this instance, but what if I want to allow them to select more than one system or subsystem? Eventually I'll start using up characters again and run into the same issue.
Is there a better way to achieve my goal using concatenation? I have tried using one large concatenation statement and using a second string variable for the WHERE clause and then printing them out together debug.print ssql & ssql2
. They all produce the same result.
Alternatively, if there way a way to dynamically edit a MS Access query to change the where clause; that could be an option.
Thank you
Currentdb.QueryDefs("query_name").SQL = "new SQL"
– winghei