我正在使用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
样本数据示例:
此外,请注意该字段的数据类型为 adVarWChar,DataTypeEnum = 202,表示以空值结尾的Unicode字符串。
答案 0 :(得分:3)
我的原始答案包含有关在查询中使用引号和单打的一些有价值的信息,但未解决OP的问题。
尽管不清楚,但ADO » Recordset » Filter的摘录对此进行了解释
如果使用LIKE运算符,还可以将*或%通配符用作字符串中的最后一个字符或用作字符串中的第一个和最后一个字符。
在将LIKE运算符与ADODB Recordset Filter属性一起使用时,如果Filter以通配符(*或%)开头,则它必须以通配符(*或%)结尾。筛选器字符串中间的通配符不起作用。
因此,仅仅因为我们不能在不使用通配符结束过滤器的情况下,通过ADO Recordset过滤器将LIKE运算符与通配符一起使用,并不意味着我们无法使其工作!
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
长话短说,只需将单引号内的单引号加倍!
RcrdsetSheet.Filter = "[LOCATION] LIKE '*Q'''"
这是在双引号内使用单引号的方式
RcrdsetSheet.Filter = "[LOCATION] LIKE ""*Q'"""