Существует ли собственный класс excel, который позволяет копировать диапазон и применять сортировку / фильтры? - PullRequest
1 голос
/ 13 января 2009

У меня есть диапазон, который я бы хотел произвольно отсортировать и отфильтровать, используя vba. Однако я не хочу, чтобы это влияло на рабочий лист. Я бы хотел скопировать диапазон в некоторый нативный класс, который поддерживает фильтрацию и сортировку (поэтому мне не нужно изобретать колесо), и использовать этот класс для возврата результата в вызывающий код.

Есть ли какие-либо классы, которые я могу использовать для этой цели? ListObject выглядел наиболее многообещающим, но для правильной работы он требует привязки к диапазону листа.

Ответы [ 5 ]

2 голосов
/ 14 января 2009

Вы можете использовать наборы записей. Вот некоторые заметки:

'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

Вы можете найти эту тему интересной: синхронизация двух списков с VBA

1 голос
/ 20 января 2009

Оказывается, я могу создать набор записей для этого. В отличие от ответа Ремо, хотя нам не нужно вызывать тяжелый процесс odbc на нашем листе.

Следующая функция (адаптированная из ответа Марка Нольда) создаст набор записей из предоставленного диапазона. Предполагается, что заголовки столбцов находятся в первом ряду предоставленного диапазона. Это можно сделать более надежным, но это хорошая отправная точка

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
1 голос
/ 20 января 2009

Если вы хотите читать и анализировать сложные наборы данных, вы можете использовать Microsoft ActiveX Data Objects Recordset 2.8 Library. При этом вы можете читать свои данные в набор записей, а затем фильтровать, сортировать, добавлять, удалять и передавать их другим функциям.

Я регулярно использую это, потому что мне часто приходится манипулировать и отображать большие наборы данных. Если он находится в наборе записей, я могу снова и снова использовать одни и те же процедуры манипуляции и представления.

См. Слияние таблиц Excel .... , где приведен пример сброса данных в набор записей. После того, как у вас есть данные в наборе записей, используйте r.filter = "ColumnA = 1" или r.sort = "ColumnC, ColumnA".

0 голосов
/ 14 января 2009

Вы хотите использовать класс Range (как говорит CasperOne). Вот пример кода VBA

Function SortAndFilter(rSource As Range) As Range</p> <pre><code>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

End Sub

0 голосов
/ 13 января 2009

Почему бы не скопировать данные на новый скрытый лист, выполнить там сортировку / фильтрацию, а затем скопировать данные обратно, когда закончите?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...