【问题标题】:Is there a native excel class which allows a range to be copied and sorts/filters applied?是否有允许复制范围和应用排序/过滤器的本机 excel 类?
【发布时间】:2013-08-20 03:40:15
【问题描述】:

我有一个范围,我想使用 vba 任意排序和过滤。但是,我不希望它影响工作表。我想基本上将范围复制到一些支持过滤和排序的本机类中(所以我不必重新发明轮子)并使用该类将结果返回给调用代码。

我可以为此使用任何课程吗? ListObject 看起来最有前途,但它似乎需要绑定到工作表范围才能正常工作。

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    您可以使用记录集。以下是一些注意事项:

    'Reference: Microsost ActiveX n.n Object Library '
    
    Dim rs As ADODB.Recordset
    Dim cn As ADODB.Connection
    
    'From: http://support.microsoft.com/kb/246335 '
    
    strFile = Workbooks(1).FullName
    strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strFile _
        & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"
    
    Set cn = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")
    
    cn.Open strCon
    
    'Must have client-side cursor for sorting '
    rs.CursorLocation = adUseClient
    
    'Substitute a name range for [Sheet1$] '
    'or include a range of cells : [Sheet1&A1:C7] '
    
    strSQL = "SELECT * FROM [Sheet1$] " _
           & "WHERE TransID>2 ORDER BY MyTime"
    
    rs.Open strSQL, cn, 3, 3
    
    rs.Filter = "TransID=3"
    rs.Sort = "Mytime"
    
    'Write out to another sheet '
    Worksheets(2).Cells(2, 1).CopyFromRecordset rs
    

    你可能会觉得这个话题很有趣:syncing two lists with VBA

    【讨论】:

      【解决方案2】:

      如果您想读取和解析复杂的数据集,可以使用Microsoft ActiveX Data Objects Recordset 2.8 Library。有了它,您可以将数据读入记录集,然后过滤、排序、追加、删除并将其传递给其他函数。

      我经常使用它,因为我经常需要操作和显示大型数据集。如果它在记录集中,我可以一遍又一遍地使用相同的操作和演示程序。

      请参阅Merge Excel Sheets....,了解将数据放入记录集中的示例。将数据放入记录集中后,请使用 r.filter = "ColumnA = 1" 或 r.sort = "ColumnC, ColumnA"。

      【讨论】:

        【解决方案3】:

        原来我可以创建一个记录集来做到这一点。与 Remou 的回答不同,尽管我们不必在工作表上调用重量级的 odbc 进程。

        以下函数(改编自 Mark Nold 的回答)将从提供的范围创建一个记录集。它假定列标题位于所提供范围的第一行。这可以变得更健壮,但它是一个很好的起点

        Function CreateRecordSet(rSource As range) As Recordset
            ' Constants
            Const MAX_CHARS = 1200
        
            ' Declarations
            Dim rs As Recordset
            Dim c As Long
            Dim r As Long
            Dim colCount As Long
            Dim rowCount As Long
            Dim fldName As String
        
            colCount = rSource.Columns.Count
            rowCount = rSource.rows.Count
        
            ' Setup record set
            Set rs = New Recordset
            r = 1 ' assume first row contains headers
            For c = 1 To colCount
                fldName = rSource.Cells(r, c).Value
                rs.Fields.Append fldName, adVarChar, MAX_CHARS
            Next c
        
            ' Fill record set
            rs.Open
            r = 2 ' skip header row
            For r = 2 To rowCount
                rs.AddNew
                Debug.Print "row "; r & " of " & rowCount & " created"
                For c = 1 To colCount
                    rs.Fields(c - 1) = CStr(rSource.Cells(r, c).Value)
                    Debug.Print "-- row(" & r; "): added col " & c & " of " & colCount
                Next c
            Next r
        
            Set CreateRecordSet = rs
        End Function
        Sub TestCreateRecordSet()
            Dim r As range
            Dim rs As Recordset
        
            Set r = range("A1:B4")
            Set rs = CreateRecordSet(r)
        End Sub
        

        【讨论】:

        • 请参阅 Mark Nolds 回答,了解使用记录集背后的原因
        • 出色的工作,很好的一点是这是轻量级的做事方式:)
        • 我在 Excel Office 2010 文件中复制了您的代码,它在 Function CreateRecordSet(rSource As range) As recordSet 行中给出了错误“用户定义的类型未定义”。粘贴代码将大写的Recordset 更改为小写的recordset。我是否需要添加任何参考才能使其正常工作?
        【解决方案4】:

        您想使用 Range 类(就像 CasperOne 所说的那样)。这是一些示例 VBA 代码

        Function SortAndFilter(rSource As Range) As Range

        Dim rResult As Range
        Dim vaTemp As Variant
        Dim wsTemp As Worksheet
        Dim wbTemp As Workbook
        
        vaTemp = rSource.Value
        
        Set wbTemp = Workbooks.Add
        Set wsTemp = wbTemp.Sheets(1)
        
        Set rResult = wsTemp.Range("A1").Resize(UBound(vaTemp, 1), UBound(vaTemp, 2))
        rResult.Value = vaTemp
        
        rResult.Sort rResult.Cells(1), xlDescending
        
        Set SortAndFilter = rResult
        

        结束函数

        Sub Testit()

        Dim rTest As Range
        
        Set rTest = SortAndFilter(Selection)
        
        'Do stuff with your range object
        
        rTest.Parent.Parent.Close False 'close temp workbook
        

        结束子

        【讨论】:

        • 我遇到了 rResult.Value = vaTemp 行的问题。 VBA 似乎不允许我从函数中设置 rResult 的值。我读过其他地方 VBA 不会让你在函数内设置范围值 - 只有 subs。你确定这段代码有效吗?再次感谢您的帮助。
        【解决方案5】:

        为什么不将数据复制到一个新的隐藏工作表,在那里执行排序/过滤,然后在完成后将数据复制回来?

        【讨论】:

        • 这可能就足够了。我去看看。泰
        • 你能举一个例子来说明你在 vba 中用来做这一切的代码吗?
        猜你喜欢
        • 2017-01-17
        • 1970-01-01
        • 1970-01-01
        • 2018-02-28
        • 2021-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-19
        相关资源
        最近更新 更多