【发布时间】:2013-08-20 03:40:15
【问题描述】:
我有一个范围,我想使用 vba 任意排序和过滤。但是,我不希望它影响工作表。我想基本上将范围复制到一些支持过滤和排序的本机类中(所以我不必重新发明轮子)并使用该类将结果返回给调用代码。
我可以为此使用任何课程吗? ListObject 看起来最有前途,但它似乎需要绑定到工作表范围才能正常工作。
【问题讨论】:
我有一个范围,我想使用 vba 任意排序和过滤。但是,我不希望它影响工作表。我想基本上将范围复制到一些支持过滤和排序的本机类中(所以我不必重新发明轮子)并使用该类将结果返回给调用代码。
我可以为此使用任何课程吗? ListObject 看起来最有前途,但它似乎需要绑定到工作表范围才能正常工作。
【问题讨论】:
您可以使用记录集。以下是一些注意事项:
'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
【讨论】:
如果您想读取和解析复杂的数据集,可以使用Microsoft ActiveX Data Objects Recordset 2.8 Library。有了它,您可以将数据读入记录集,然后过滤、排序、追加、删除并将其传递给其他函数。
我经常使用它,因为我经常需要操作和显示大型数据集。如果它在记录集中,我可以一遍又一遍地使用相同的操作和演示程序。
请参阅Merge Excel Sheets....,了解将数据放入记录集中的示例。将数据放入记录集中后,请使用 r.filter = "ColumnA = 1" 或 r.sort = "ColumnC, ColumnA"。
【讨论】:
原来我可以创建一个记录集来做到这一点。与 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
【讨论】:
Function CreateRecordSet(rSource As range) As recordSet 行中给出了错误“用户定义的类型未定义”。粘贴代码将大写的Recordset 更改为小写的recordset。我是否需要添加任何参考才能使其正常工作?
您想使用 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
结束子
【讨论】:
为什么不将数据复制到一个新的隐藏工作表,在那里执行排序/过滤,然后在完成后将数据复制回来?
【讨论】: