在vba中使用多个字符串过滤访问报告,获取数据类型不匹配
Posted
技术标签:
【中文标题】在vba中使用多个字符串过滤访问报告,获取数据类型不匹配【英文标题】:Filtering Access report with multiple strings in vba, getting data type mismatch 【发布时间】:2017-03-24 23:11:14 【问题描述】:在过去的几周里,我一直在自学 Access,并且在解决我遇到的许多编程难题方面做得很好。我终于碰壁了,无法让这个过滤器正常工作。
我正在尝试在表单上使用多个组合框来按多个条件过滤报表。它在按客户、分支机构和日期范围过滤时效果很好,但是我多次尝试添加 G/P% 范围过滤器非常令人沮丧。
我正在使用 vba 连接来自组合框的字符串以将它们转换为过滤器,但是我使用 G/P 范围函数得到数据类型不匹配错误或语法错误。基础查询的 [G/P%] 格式为百分比,组合框的来源是值列表(“0%”、“5%”、“10%”等),我肯定会省略单引号将值指定为数字而不是字符串。我已经在它上面尝试了很多小时,尝试对此代码进行变体,但没有任何效果。各个字符串似乎还可以,但我认为将它们组合成一个过滤器以用于打开报告是问题所在。
我尝试使用 Format() 来制作百分比值;我尝试将变量设置为字符串、整数和长整数;我尝试将所有文本移至最终字符串,因此 G/P 变量只是数字;在这一点上,我确信我犯的错误是我忽略的一些小而容易的错误,但我没有想法。
真正令人沮丧的是,我在表单的不同部分有一个类似的代码,它只使用客户名称和最大 G/P 进行过滤,而且效果很好!
Public Sub cmdSalesOVFilter_Click()
Dim strBRFilter As String
Dim strCRFilter As String
Dim strFDateField As String
Dim strTDateField As String
Dim strMinGPFilter As String
Dim strMaxGPFilter As String
Dim strSOFilter As String
If IsNull(Me.cboBranchSales.Value) Then
strBRFilter = " AND [BranchName] Like '*'"
Else
strBRFilter = " AND [BranchName] ='" & Me.cboBranchSales.Value & "'"
End If
If IsNull(Me.cboCustSalesOV.Value) Then
strCRFilter = " AND [CustName] Like '*'"
Else
strCRFilter = " AND [CustName] ='" & Me.cboCustSalesOV.Value & "'"
End If
If IsNull(Me.cboSalesOVDateFrom.Value) Then
strFDateField = " AND [OrderDate]>#" & Format("6/1/2016", "Short Date") & "#"
Else
strFDateField = " AND [OrderDate]>=#" & CDate(Me.cboSalesOVDateFrom.Value) & "#"
End If
If IsNull(Me.cboSalesOVDateTo.Value) Then
strTDateField = " AND [OrderDate]<#" & Format("1/1/2505", "Short Date") & "#"
Else
strTDateField = " AND [OrderDate]<=#" & CDate(Me.cboSalesOVDateTo.Value) & "#"
End If
If IsNull(Me.cboSalesOVMinGP.Value) Then
strMinGPFilter = " AND [G/P%]>=-100"
Else
strMinGPFilter = " AND [G/P%]>=" & Me.cboSalesOVMinGP.Value
End If
If IsNull(Me.cboSalesOVMaxGP.Value) Then
strMaxGPFilter = " AND [G/P%]<=100"
Else
strMaxGPFilter = " AND [G/P%]<=" & Me.cboSalesOVMaxGP.Value
End If
strSOFilter = Mid(strCRFilter & strBRFilter & strFDateField & strTDateField & strMinGPFilter & strMaxGPFilter, 6)
Call ReportFilter(strSOFilter)
DoCmd.OpenReport "rptYTDCustInvoices", acViewReport, strSOFilter
With Reports![rptYTDCustInvoices]
.Filter = strSOFilter
.FilterOn = True
End With
End Sub
【问题讨论】:
【参考方案1】:查询中使用的格式无关紧要,因此 5% 的值为 0.05。
但是,组合框总是返回字符串,所以 5% selected 返回“5%”。
您可以将其转换为数字:
TrueValue = Val("5%") / 100
现在,这必须与您的 SQL 正确连接,唯一安全的方法是使用 Str:
TrueTextValue = Str(Val("5%") / 100)
暂时忘记这一点,因为您的其他转换或多或少是松散的:
这应该是:
" And [OrderDate] >= #" & Format(CDate(Me.cboSalesOVDateFrom.Value), "yyyy\/mm\/dd") & "#"
一个固定的日期应该是文字:
" And [OrderDate] > #6/1/2016#" or " And [OrderDate] > #2016/6/1#"
或使用 DateSerial:
" And [OrderDate] >= #" & Format(DateSerial( 2016, 6, 1), "yyyy\/mm\/dd") & "#"
对于连接值的一般格式,您可以利用我的 CSql 函数。内联 cmets 列出了典型用法:
' Converts a value of any type to its string representation.
' The function can be concatenated into an SQL expression as is
' without any delimiters or leading/trailing white-space.
'
' Examples:
' SQL = "Select * From TableTest Where [Amount]>" & CSql(12.5) & "And [DueDate]<" & CSql(Date) & ""
' SQL -> Select * From TableTest Where [Amount]> 12.5 And [DueDate]< #2016/01/30 00:00:00#
'
' SQL = "Insert Into TableTest ( [Street] ) Values (" & CSql(" ") & ")"
' SQL -> Insert Into TableTest ( [Street] ) Values ( Null )
'
' Trims text variables for leading/trailing Space and secures single quotes.
' Replaces zero length strings with Null.
' Formats date/time variables as safe string expressions.
' Uses Str to format decimal values to string expressions.
' Returns Null for values that cannot be expressed with a string expression.
'
' 2016-01-30. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function CSql( _
ByVal Value As Variant) _
As String
Const vbLongLong As Integer = 20
Const SqlNull As String = " Null"
Dim Sql As String
Dim LongLong As Integer
#If Win32 Then
LongLong = vbLongLong
#End If
#If Win64 Then
LongLong = VBA.vbLongLong
#End If
Select Case VarType(Value)
Case vbEmpty ' 0 Empty (uninitialized).
Sql = SqlNull
Case vbNull ' 1 Null (no valid data).
Sql = SqlNull
Case vbInteger ' 2 Integer.
Sql = Str(Value)
Case vbLong ' 3 Long integer.
Sql = Str(Value)
Case vbSingle ' 4 Single-precision floating-point number.
Sql = Str(Value)
Case vbDouble ' 5 Double-precision floating-point number.
Sql = Str(Value)
Case vbCurrency ' 6 Currency.
Sql = Str(Value)
Case vbDate ' 7 Date.
Sql = Format(Value, " \#yyyy\/mm\/dd hh\:nn\:ss\#")
Case vbString ' 8 String.
Sql = Replace(Trim(Value), "'", "''")
If Sql = "" Then
Sql = SqlNull
Else
Sql = " '" & Sql & "'"
End If
Case vbObject ' 9 Object.
Sql = SqlNull
Case vbError ' 10 Error.
Sql = SqlNull
Case vbBoolean ' 11 Boolean.
Sql = Str(Abs(Value))
Case vbVariant ' 12 Variant (used only with arrays of variants).
Sql = SqlNull
Case vbDataObject ' 13 A data access object.
Sql = SqlNull
Case vbDecimal ' 14 Decimal.
Sql = Str(Value)
Case vbByte ' 17 Byte.
Sql = Str(Value)
Case LongLong ' 20 LongLong integer (Valid on 64-bit platforms only).
Sql = Str(Value)
Case vbUserDefinedType ' 36 Variants that contain user-defined types.
Sql = SqlNull
Case vbArray ' 8192 Array.
Sql = SqlNull
Case Else ' Should not happen.
Sql = SqlNull
End Select
CSql = Sql & " "
End Function
【讨论】:
感谢 Gustav 的建议和代码,我几乎可以正常工作了。根据我在组合框上设置最小/最大字段的方式,我遇到了奇怪的不一致,我需要引用我正在过滤的报告上的文本框还是直接查询数据?例如,当我将它们设置为 25-30% 时,我得到的数据大多很好,但由于某种原因,一些订单也有 3%。如果最小值为 0% 或更低,它也根本不起作用。 您应该在报告本身中应用任何排序,而不是在用作报告源的查询中;事实上,任何排序都应该从查询中删除。 仍然无法正常工作。你能说出这有什么问题吗?code strMinGPFilter = " AND [G/P%] BETWEEN '" & CSql(-100) & "%'" Else strMinGPFilter = " AND [G/P%] BETWEEN '" & CSql(Me.cboSalesOVMinGP.Value * 100) & "%'" End If If IsNull(Me.cboSalesOVMaxGP.Value) Then strMaxGPFilter = " AND '" & CSql(100) & "%'" Else strMaxGPFilter = " AND '" & CSql(Me.cboSalesOVMaxGP.Value * 100) & "%'" End If strSOFilter = Mid(strCRFilter & strBRFilter & strFDateField & strTDateField & strMinGPFilter & strMaxGPFilter, 6)
您正在使用strMinGPFilter = " AND [G/P%] BETWEEN '" & CSql(-100) & "%'"
创建文本。应该是:strMinGPFilter = " AND [G/P%] BETWEEN " & CSql(-1) & ""
.
是的,我知道。我正在创建文本,因为当我将所有字符串组合在一起时,它给了我一个类型不匹配的错误。有可能解决这个问题吗? code strSOFilter = Mid(strCRFilter & strBRFilter & strFDateField & strTDateField & strMinGPFilter & strMaxGPFilter, 6)
以上是关于在vba中使用多个字符串过滤访问报告,获取数据类型不匹配的主要内容,如果未能解决你的问题,请参考以下文章