Как вернуть диапазон ячеек в VBA без использования цикла? - PullRequest
5 голосов
/ 11 ноября 2008

допустим, у меня есть таблица Excel, как показано ниже:

col1   col2
------------
dog1   dog
dog2   dog
dog3   dog
dog4   dog
cat1   cat
cat2   cat
cat3   cat

Я хочу вернуть диапазон ячеек (dog1, dog2, dog3, dog4) или (cat1, cat2, cat3) на основе "dog" или "cat"

Я знаю, что могу сделать цикл для проверки один за другим, но есть ли какой-либо другой метод в VBA, чтобы я мог "фильтровать" результат за один выстрел?

может быть Range.Find (XXX) может помочь, но я вижу примеры только для одной ячейки, а не диапазона ячеек.

Пожалуйста, совет

Привет

Ответы [ 6 ]

2 голосов
/ 12 ноября 2008

Вот несколько замечаний по использованию набора записей для возврата диапазона.

Sub GetRange()
Dim cn As Object
Dim rs As Object
Dim strcn, strFile, strPos1, strPos2

    Set cn = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")

    strFile = ActiveWorkbook.FullName

    strcn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
    & strFile & ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1';"

    cn.Open strcn

    rs.Open "SELECT * FROM [Sheet1$]", cn, 3 'adOpenStatic'

    rs.Find "Col2='cat'"
    strPos1 = rs.AbsolutePosition + 1
    rs.MoveLast
    If Trim(rs!Col2 & "") <> "cat" Then
        rs.Find "Col2='cat'", , -1 'adSearchBackward'
        strPos2 = rs.AbsolutePosition + 1
    Else
        strPos2 = rs.AbsolutePosition + 1
    End If
    Range("A" & strPos1, "B" & strPos2).Select
End Sub
1 голос
/ 12 ноября 2008

Забыли еще одну особенность XL2007: расширенная фильтрация. Если вы хотите это в VBA, я получил это из записанного макроса:

Range("A1:A1000000").AdvancedFilter Action:=xlFilterCopy, CopyToRange:= Range("F1"), Unique:=True

Я рассчитал время примерно на 0,35 с ...

По общему признанию, не много пользы, если у вас нет 2007.

1 голос
/ 11 ноября 2008

У этого парня хорошая функция FindAll:

http://www.cpearson.com/excel/findall.aspx

0 голосов
/ 12 ноября 2008

Если вы не используете старый старый компьютер или у вас есть рабочий лист XL2007 с базилией строк, цикл будет достаточно быстрым. Честное слово!

Не доверяешь мне? Посмотри на это. Я заполнил диапазон в миллион строк случайными буквами, используя это:

=CHAR(RANDBETWEEN(65,90))

Затем я написал эту функцию и вызвал ее из диапазона из 26 ячеек, используя Control-Shift-Enter:

=TRANSPOSE(UniqueChars(A1:A1000000))

Вот не очень оптимизированная функция VBA, которую я взломал за пару минут:

Option Explicit

Public Function UniqueChars(rng As Range)

Dim dict As New Dictionary
Dim vals
Dim row As Long
Dim started As Single

    started = Timer

    vals = rng.Value2

    For row = LBound(vals, 1) To UBound(vals, 1)
        If dict.Exists(vals(row, 1)) Then
        Else
            dict.Add vals(row, 1), vals(row, 1)
        End If
    Next

    UniqueChars = dict.Items

    Debug.Print Timer - started

End Function

На моем летнем ноутбуке Core 2 Duo T7300 (2 ГГц) это заняло 0,58 с.

0 голосов
/ 11 ноября 2008

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

0 голосов
/ 11 ноября 2008

Спасибо, DJ.

Это решение FindAll по-прежнему использует цикл VBA для выполнения задач.

Я пытаюсь найти способ без использования цикла уровня пользователя для фильтрации диапазона в Excel VBA.

Здесь я нашел решение. для этого нужен встроенный движок Excel.

(1) использование worksheetfunction.CountIf (, "Cat") для получения количества ячеек "cat"

(2) используйте .Find ("cat"), чтобы получить первый ряд "cat"

с количеством строк и первым рядом, я уже могу получить диапазон "кошка".

Хорошая часть этого решения: нет петли на уровне пользователя, это может улучшить производительность, если диапазон большой.

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