2016-08-11 101 views
0

使用的MS Access 2016年,我复制我在查询设计器创建VBA查询,所以我可以动态改变基于窗体上的一些用户选择的WHERE子句。这个查询然后被设置为报告的记录源。的MS Access VBA字符串连接会自动添加回车

在窗体上,用户可以选择配置三个项目: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 [总容量],Reliability_MotorMasterList.EquipmentName AS设备,Config_BaseData_Motors.EquipSystem,Config_BaseData_Motors.EquipSubSystem,Motor_GetSystemName([Config_BaseData_Motors] [EquipSystem])AS系统,Motor_GetSubSystemName([Config_BaseData_Motors ] [EquipSubSystem])AS [子系统],IIF(Motor_GetServiceStatus([Reliability_MotorData] [MotorID],[SelectDate]。)= - 1, “OOS”,IIF(Motor_GetServiceStatus([Reliability_MotorData] [MotorID],[SelectDate ])= 0, “以服务”, “未知”))AS [服务模式],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 =#7/10/2016年#)

AND((Config_BaseData_Motors.EquipSystem像 “”))AND(( Config_BaseData_Motors.EquipSubSystem Like“”));

我可以缩短我的查询了一下,并使其在这种情况下工作,但如果我想让他们选择多个系统或子系统呢?最终我会再次使用字符并遇到同样的问题。

有没有更好的方式使用级联实现我的目标是什么?我已经尝试过使用一个大的并置语句,并为WHERE子句使用第二个字符串变量,然后将它们一起打印出来debug.print ssql & ssql2。他们都产生相同的结果。

可替换地,如果存在方法的方式来动态地修改MS Access查询改变where子句;这可能是一个选择。

谢谢

+0

您是否尝试过使用别名,某事。像这样SELECT fieldname AS f FROM tablename t WHERE t.f = 1.这将是一个简单的方法来缩短您的查询。另一种方法是将查询保存在视图中,并使用where子句,即select * from view where ... –

+0

您可以使用'Currentdb.QueryDefs(“query_name”)更改查询定义。SQL =“new SQL“' – winghei

回答

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 
+0

谢谢!我最终使用了你的答案和上面@winghei的评论的组合。我没有想过添加到现有查询的querydef。我最终的目标是允许用户从每个列表中选择多个项目,并且'LIKE'运算符不会接受逗号分隔列表。最后,我使用VBA在现有的querydef的末尾组装并添加一个自定义的'WHERE'子句。 – DaveJM