VBA Recordset过滤器通配符'结束'不工作 - 错误3001

问题描述 投票:3回答:1

我正在使用Microsoft.ACE.OLEDB.12.0将Excel文件读入ADO Recordset。根据snb在ADO上的优秀article,我一直在使用一些完美的过滤器,除了“Ends With”过滤器,我收到Error 3001: "Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another"。 “Ends With”过滤器本质上是一个通配符过滤器,就像在SQL中使用的那样,语法如下:

"[FieldName] LIKE '*searchterm'"

说我尝试了所有通配符(*, %)的组合而没有运气。 Recordset Filter属性上的microsoft documentation说明了以下关于LIKE运算符的使用:

“在LIKE子句中,您可以在模式的开头和结尾使用通配符。例如,您可以使用LastName Like'mit'。或者使用LIKE,您只能在模式的末尾使用通配符。例如,LastName喜欢'Smit *'。

以上似乎不清楚,但我相信他们说的如下:

开始和结束:LastName喜欢'mit'是合法的开始:LastName喜欢'Smit *'是合法的

结束于:姓氏'* t'是非法的???

如果是这种情况,那么我知道过滤器的Ends是不可能的,因为人们可能会直观地思考,我希望有人可以提供一种替代解决方案来模仿“Ends With”通配符过滤器。

如果没有,那么我希望有人能指出我所缺少的东西。非常感谢所有的建议,想法或答案。

以下是我的代码:

Option Explicit
Sub SheetToRecrdset()

 Dim strSourceFile As String
 Dim Conn As New ADODB.Connection
 Dim RcrdsetSheet As ADODB.Recordset

  strSourceFile = ThisWorkbook.FullName

    Set Conn = New ADODB.Connection
        With Conn
             .Provider = "Microsoft.ACE.OLEDB.12.0"
             .ConnectionString = "Data Source=" & strSourceFile & _
             ";Extended Properties='Excel 12.0;HDR=YES;IMEX=1'"
             .Open
        End With

    Set RcrdsetSheet = New ADODB.Recordset

     RcrdsetSheet.Open "SELECT * FROM [Data$] Where Not IsNull([Row_ID])", _
     Conn, adOpenKeyset, adLockOptimistic, adCmdText

        If RcrdsetSheet.EOF = True Or RcrdsetSheet.BOF = True Then
            MsgBox "For some reason the query did not return any data. Try closing" & _
            " and and opening the file again.", vbCritical, "Error: No Results Returned"
            Exit Sub
        End If

        'Example String to filter: "MRQ"

        'CONTAINS FILTER WORKS
        RcrdsetSheet.Filter = "[LOCATION] LIKE '*M*'"

        'BEGINS WITH FILTER WORKS
        RcrdsetSheet.Filter = "[LOCATION] LIKE 'M*'"


       'ENDS WITH FILTER DOESN'T WORK
       'RcrdsetSheet.Filter = "[LOCATION] LIKE '*Q'"     'Error 3001

       '@TinMan's Suggestions
       'RcrdsetSheet.Filter = "[LOCATION] LIKE '*Q''"    'Error 2147024809
       'RcrdsetSheet.Filter = "[LOCATION] LIKE '*Q'''"   'Error 3001
       RcrdsetSheet.Filter = "[LOCATION] LIKE ""*Q'"""   'Returns no Records

       Debug.Print RcrdsetSheet.RecordCount 'Returns 0

       Dim arrayOut As Variant

       arryOut = RcrdsetSheet.GetRows       'Error 3021


End Sub

示例数据示例:

enter image description here

另请注意,该字段的数据类型为adVarWChar,DataTypeEnum = 202,表示以null结尾的Unicode字符串。

excel vba ado recordset
1个回答
3
投票

新答案

我的原始答案有一些关于在查询中使用引号和单数的有价值的信息,但没有解决OP的问题。

虽然不是很清楚,但ADO » Recordset » Filter的这段摘录解释了这一点

如果使用LIKE运算符,还可以使用*或%通配符作为字符串中的最后一个字符,或者作为字符串中的第一个和最后一个字符。

将LIKE运算符与ADODB Recordset Filter属性一起使用时,如果Filter以通配符(*或%)开头,则它必须以通配符(*或%)结尾。 Filter字符串中间的通配符不起作用。

因为我们不能使用带有LIKE运算符的通配符使用ADO Recordset Filter而不使用通配符结束Filter并不意味着我们无法使其工作!

让我们破解系统!

  • 将计算字段添加到返回最后一个字符的查询中
  • 使用%作为ADO Recordset Filter的最后一个字符
  • 使用Like * somevalue%和计算字段=最后一个字符过滤原始字段

测试代码

Sub Test()
    TestFilter "(Location Like '*Q%') AND (LOCATIONLastChar = '''')"
End Sub

Sub TestFilter(Filter As String)
    Const BaseConnectionString = "Data Source=@FullName;Extended Properties='Excel 12.0;HDR=YES;IMEX=1'"
    Dim Conn As New ADODB.Connection, rs As New ADODB.Recordset
    Dim SQL As String

    Set Conn = New ADODB.Connection
    With Conn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .ConnectionString = Replace(BaseConnectionString, "@FullName", ThisWorkbook.FullName)
        .Open
    End With

    SQL = "SELECT *, Right(LOCATION,1) AS LOCATIONLastChar FROM [Data$] Where Not IsNull(Row_ID)"

    rs.Open SQL, Conn, adOpenKeyset, adLockOptimistic, adCmdText

    rs.Filter = Filter


    If Not rs.BOF Then
        Worksheets.Add
        Range("A1").CopyFromRecordset rs
    End If
    rs.Close
    Conn.Close
End Sub

原帖

当我在编写查询时遇到问题时,我使用Access Query Designer来帮助我编写它。

SELECT Table1.Field1
FROM Table1
WHERE (((Table1.Field1) Like "a'*"));

请注意,设计器使用过滤器字符串周围的引号。 SQL可以对字符串使用双引号或单引号。

如果对字符串值使用双引号,则双引号内的任何引号都需要加倍。

这是一个例子:

rs.Open "SELECT Table1.Field1 FROM Table1 WHERE (((Table1.Field1) Like ""a'*""));"

然而,这对于正确的颈部来说是一种痛苦。所以我所做的就是编写一些帮助函数,这些函数会使我的引号或单引号加倍。

Function getClipBoardText()
    With CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        .getFromClipBoard
        getClipBoardText = .getText
    End With
End Function

Sub PrintText()
    Dim s As String
    s = getClipBoardText
    Debug.Print Replace(s, Chr(34), String(2, 34))
End Sub

现在,我所要做的就是复制设计器的SQL并运行PrintText

enter image description here

简而言之,只需将单引号内的单引号加倍!

RcrdsetSheet.Filter = "[LOCATION] LIKE '*Q'''"

以下是如何使用双引号内的单引号

RcrdsetSheet.Filter = "[LOCATION] LIKE ""*Q'"""
© www.soinside.com 2019 - 2024. All rights reserved.