使用ADO记录集获取已过滤项目的补充

时间:2013-08-28 14:56:09

标签: vba filter ado recordset

我有一个包含产品表的ADO Recordset。 我有一个用于过滤表的产品列表 - 动态构建像这样的过滤器(但更长):

rs.Filter = "productType = 'product A' " _
+ "or productType = 'product B' " _
+ "or productType = 'product C' "

这对我来说很好,我将过滤后的行复制到一个单独的工作表中,一切正常。

然后新项目要求意味着我还需要获取排除的项目。很好,我做了一些布尔代数,并使用相反的过滤器运行相同的查询:

rs2.Filter = "productType <> 'product A' " _
+ "and productType <> 'product B' " _
+ "and productType <> 'product C' "

这也很好。我将排除的项目复制到另一个工作表中,所以现在我同时包含已包含和已排除的项目。

但是新要求意味着我必须应对特殊情况 - 产品B仅包含在特定日期。现在,这适用于正面过滤器,可以找到包含项目:

rs.Filter = "productType = 'product A' " _
+ "or (productType = 'product B' and expiry = 16/08/2013) " _
+ "or productType = 'product C' "

但是我遇到了负面过滤器(找到排除项目的问题)的问题。由于restriction on nested OR's in ADO Recordset Filter

,不允许以下内容
rs2.Filter = "productType <> 'product A' " _
+ "and (productType <> 'product B' or expiry <> 16/08/2013) " _
+ "and productType <> 'product C' "

有替代解决方案吗? 例如。某种方式来获得过滤器的补充(即只是它排除的行)?

我应该强调 - 要包含的产品列表是动态构建的,在编写代码时我无法使用。

1 个答案:

答案 0 :(得分:0)

我与ADO合作很多,我发现只有两种解决方案可以解决ADO中的这种限制。

第一种解决方案通常是最好的解决方案。只需将此过滤器/ where构建到SQL语句中并再次查询数据源。

第二个选项效率低,但在较小的记录集上运行正常。这是我写的一个返回Filtered记录集的函数。你需要做的就是多次调用它,每次调试一次(如果有意义的话),这样你最终得到你想要的结果。我不知道这对连接的记录集有什么用处。我只使用断开连接的记录集。

Public Function GetFilteredRecordset(ByRef rsSource As ADODB.Recordset, _
                                        ByVal sWhere As String, _
                                        Optional ByVal sOrderBy As String, _
                                        Optional ByVal LockType As ADODB.LockTypeEnum = adLockUnspecified) As ADODB.Recordset

    Dim sOriginalOrderBy As String
    sOriginalOrderBy = rsSource.Sort

    rsSource.Filter = sWhere
    If sOrderBy <> "" Then
        If Left(LCase(sOrderBy), 8) = "order by" Then sOrderBy = Trim(Right(sOrderBy, Len(sOrderBy) - 8))
        rsSource.Sort = sOrderBy
    End If

    Dim objStream As ADODB.Stream
    Set objStream = New ADODB.Stream
    rsSource.Save objStream, adPersistXML

    Dim rsF As ADODB.Recordset
    Set rsF = New ADODB.Recordset
    rsF.Open objStream, , , LockType

    rsSource.Filter = ""
    rsSource.Sort = sOriginalOrderBy

    objStream.Close
    Set objStream = Nothing
    Set GetFilteredRecordset = rsF

End Function