我正在使用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
示例数据示例:
另请注意,该字段的数据类型为adVarWChar,DataTypeEnum = 202,表示以null结尾的Unicode字符串。
我的原始答案有一些关于在查询中使用引号和单数的有价值的信息,但没有解决OP的问题。
虽然不是很清楚,但ADO » Recordset » Filter的这段摘录解释了这一点
如果使用LIKE运算符,还可以使用*或%通配符作为字符串中的最后一个字符,或者作为字符串中的第一个和最后一个字符。
将LIKE运算符与ADODB Recordset Filter属性一起使用时,如果Filter以通配符(*或%)开头,则它必须以通配符(*或%)结尾。 Filter字符串中间的通配符不起作用。
因为我们不能使用带有LIKE运算符的通配符使用ADO Recordset Filter而不使用通配符结束Filter并不意味着我们无法使其工作!
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'"""