在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 '" &amp; CSql(-100) &amp; "%'" Else strMinGPFilter = " AND [G/P%] BETWEEN '" &amp; CSql(Me.cboSalesOVMinGP.Value * 100) &amp; "%'" End If If IsNull(Me.cboSalesOVMaxGP.Value) Then strMaxGPFilter = " AND '" &amp; CSql(100) &amp; "%'" Else strMaxGPFilter = " AND '" &amp; CSql(Me.cboSalesOVMaxGP.Value * 100) &amp; "%'" End If strSOFilter = Mid(strCRFilter &amp; strBRFilter &amp; strFDateField &amp; strTDateField &amp; strMinGPFilter &amp; strMaxGPFilter, 6) 您正在使用strMinGPFilter = " AND [G/P%] BETWEEN '" &amp; CSql(-100) &amp; "%'" 创建文本。应该是:strMinGPFilter = " AND [G/P%] BETWEEN " &amp; CSql(-1) &amp; "". 是的,我知道。我正在创建文本,因为当我将所有字符串组合在一起时,它给了我一个类型不匹配的错误。有可能解决这个问题吗? code strSOFilter = Mid(strCRFilter &amp; strBRFilter &amp; strFDateField &amp; strTDateField &amp; strMinGPFilter &amp; strMaxGPFilter, 6)

以上是关于在vba中使用多个字符串过滤访问报告,获取数据类型不匹配的主要内容,如果未能解决你的问题,请参考以下文章

访问报告字段截断为 255 个字符

VBA:如何从过滤后的数据中获取当前区域?

使用 VBA 访问查询和报告?

如何过滤 3 个文本框,然后在 MS Access VBA 中根据它们运行报告

使用 VBA 根据下拉选择过滤多个数据透视表

在access vba中输出多个报告会导致错误3014,打开的表太多