VBA记录集筛选器通配符“结尾为”不起作用-错误3001

时间:2019-04-11 12:22:15

标签: excel vba ado recordset

我正在使用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子句中,您可以在模式的开头和结尾使用通配符。例如,您可以使用姓氏,例如' mit '。或者对于LIKE,可以使用通配符仅在模式末尾。例如,姓氏,例如“ Smit *”。

以上内容似乎不清楚,但我相信他们在说以下话:

开头和结尾:像' mit '这样的姓氏是合法的 开头:像'Smit *'这样的姓氏是合法的

但是

结尾为:像'* t'这样的姓是Illegall ???

如果是这种情况,那么我知道像一个人可能会凭直觉想到的那样,使用Ends with过滤器是不可能的,并且我希望有人可以提供一种替代方案,该方案将模仿“ 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,表示以空值结尾的Unicode字符串。

1 个答案:

答案 0 :(得分:3)

新答案

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

尽管不清楚,但ADO » Recordset » Filter的摘录对此进行了解释

  

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

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

因此,仅仅因为我们不能在不使用通配符结束过滤器的情况下,通过ADO Recordset过滤器将LIKE运算符与通配符一起使用,并不意味着我们无法使其工作!

让我们入侵系统!

  • 将计算所得的字段添加到查询中以返回最后一个字符
  • 将%用于ADO记录集过滤器的最后一个字符
  • 使用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'"""