Страницы: 1
RSS
VBA Уникальные строки из массива
 
Приветствую,

Не получается доработать код макроса под себя, может кто-то из опытных поможет в этом деле!?))

Исходная задача такова: На входе уже есть массив данных из которого надо выбрать уникальные значения.

В процессе, нашел на просторах инета нужный код, но (для меня) проблема в том, что нужная функция принимает в параметре переменную-диапазон, а мне надо передавать i-й элемент массива. Вот сам код макросса:

Код
'Массив  FirstArr() определяется выше по коду и содержит 100 элементов

 Sub UnikArr()
 
    Dim MyData As Range: Set MyData = Range([A1], Range("A" & Rows.Count).End(xlUp))
    Dim ArrRng() As Variant

    ArrRng = UniqueValuesFromArray(MyData.Value, 1) 'Тут нужен цикл For и вместо MyData.Value, 1 подставить FirstArr(0, i)

    Range("B1").Resize(UBound(ArrRng)).Value = ArrRng


End Sub

Function UniqueValuesFromArray(ByVal ArrTmp, ByVal col As Long) As Variant
Dim i As Long


    If Not IsArray(ArrTmp) Then MsgBox "Это не массив!", vbCritical: Exit Function
    If col > UBound(ArrTmp, 2) Then MsgBox "Нет такого столбца в массиве!", vbCritical: Exit Function
    If col < LBound(ArrTmp, 2) Then MsgBox "Нет такого столбца в массиве!", vbCritical: Exit Function

    On Error Resume Next: Dim coll As New Collection, txt$
    
    For i = LBound(ArrTmp) To UBound(ArrTmp)
        txt$ = Trim(ArrTmp(i, col)): coll.Add txt$, txt$
    Next i
    ReDim MyArr(1 To coll.Count, 1 To 1)
    For i = 1 To coll.Count: MyArr(i, 1) = coll(i): Next i
    UniqueValuesFromArray = MyArr
End Function



Заранее, благодарю
Изменено: prostor - 10.06.2017 13:19:01
 
Цитата
2.3. Приложите файл(ы) с примером (общим весом не более 100 Кб) в реальной структуре и форматах данных того, что есть сейчас и того, что хотелось бы на выходе.

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
Код
 Sub UnikArr()
  
    Dim MyData As Range
    Dim ArrRng As Variant
    
    Set MyData = Range([A1], Range("A" & Rows.Count).End(xlUp))
    With Sheets.Add
        With .Range("A1").Resize(MyData.Count)
            .Value = MyData.Value
            .RemoveDuplicates Array(1)
        End With
        ArrRng = .Range("A1").CurrentRegion
        Application.DisplayAlerts = False
        .Delete
        Application.DisplayAlerts = True
    End With
     
    Range("B1").Resize(UBound(ArrRng)).Value = ArrRng
 
End Sub
There is no knowledge that is not power
 
Код

Sub start()
Dim arr
arr = Selection
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
Dim el
For Each el In arr
    If Not dic.exists(el) Then dic.Add el, el
Next
arr = dic.keys()
End Sub

Вместо arr может быть любой нужный вам массив.
С уважением,
Федор/Все_просто
 
JayBhagavan,Сорри, добавил файл макроса с примечаниями....
 
SuperCat,Надо вообще отвязаться от диапазона MyData As Range. Добавил в первый пост файл с комментариями.
 
Все_просто,спасибо. Все получилось!

Правильно ли я понимаю, что: CreateObject("Scripting.Dictionary") используется только для подключения метода .exists - который удаляет дубли?
У массивов такого метода нет? Верно?
 
Код
For Each el In arr
    If Not dic.exists(el) Then dic.Add el, el
Next
можно упростить до:
Код
For Each el In arr
    dic(el) = el
Next
There is no knowledge that is not power
 
Отобрать уникальные из массива можно и при помощи коллекции.
 
Юрий М,у коллекции есть такой метод ? или это как то по-особому делается? ибо в справке не нашел такого https://msdn.microsoft.com/ru-ru/library/yb7y698k(v=vs.90).aspx

Киньте пример, если не сложно.
 
Код
Sub TestUniq()
Dim Uniq As New Collection, Arr(), x
    Arr = Selection.Value
    For Each x In Arr
        On Error Resume Next
        Uniq.Add x, CStr(x)
    Next
End Sub
 
Детально прочитал справку по всем элементам из вашего примера, не понял как именно отбираются уникальные значения:((
Изменено: prostor - 10.06.2017 20:46:37
 
Коллекция просто не позволит добавить в себя уже существующий элемент - это вызвало бы ошибку. Но строка On Error Resume Next приходит на помощь: разрешает продолжить выполнение программы )
 
Юрий М,Это офигенно круто!:)) Засяду ка и изучу этот объект!

Я так понимаю, что элементы коллекции (например строки), можно так же обрабатывать (регулярками, например) как и элементы массива?
 
Есть строка - нет разницы, чем её обрабатывать ))
А с коллекцией есть один немаловажный момент: раньше я всегда перебирал элементы готовой коллекции обычным циклом For-Next. Заметил, что при большом количестве данных скорость катастрофически падает с каждым элементом. По совету ZVI стал использовать For Each-Next - тормоза пропали!  
 
Юрий М,что посоветуете почитать/посмотреть по Коллекциям? А то я штудирую msdn, но там как-то ограниченная инфа очень...
 
Котяра, тогда On Error Resume Next лучше в начала процедуры поставить
There is no knowledge that is not power
 
Цитата
SuperCat написал:
Котяра, тогда On Error Resume Next лучше в начала процедуры поставить
За пределами цикла?
 
Ничего не могу посоветовать (
И Вы показали ссылку на справку по VB - это ведь не совсем VBA )
 
Цитата
Юрий М написал:
И Вы показали ссылку на справку по VB - это ведь не совсем VBA )
Это да. Так нагуглилось просто:))

Благодарю за помощь. Пошел учится...
 
По поводу словарей. Это, можно сказать, основной мой инструмент в работе. Чуть ли не каждый второй мой макрос для заказчиков использует именно словари/многократно вложенные словари (привычка из Python). Для меня словари намного легче громоздких отвлекающих конструкций с "редим презервами". Словари тем более удобны, что методы keys() и items() дают на выходе одномерные массивы, которые потом очень легко выводить в диапазоны. С помощью вложенных словарей очень просто реализуется программируемая сводная таблица.
Коллекции - другая опера. По возможности стараюсь использовать как можно реже (хотя иногда и лень). Для некоторых целей не совсем подходит. Только write-once/read-only (название - мое изобретение) чего стоит (в словарях можно менять уже внесенные значения, хотя для вложенных словарей нужно добавлять дополнительную переменную). Это свойство коллекций очень ограничивает.

До сих пор, словари меня не подводили. Надеюсь и не будут.
С уважением,
Федор/Все_просто
 
Да, словари (объект Scripting.Dictionary из WSH) - это, по идее, обязательная тема изучения, для тех, кому требуется массовая обработка данных. Простые коллекции VBA всё же менее функциональны, а для многих задач функционал запросов (сводные/Power*/sql) излишний.
 
Коллеги, тема про извлечение уникальных значений из массива, а не про словари v/s коллекции ))
 
Цитата
prostor написал:
За пределами цикла?
Да
There is no knowledge that is not power
 
Вопрос, конечно уже выходит за рамки этой темы, но все же (не могу нагуглить) - каково исходное назначение словарей и коллекций? Ведь не зря они существуют как самостоятельные инструменты, и с разными "свойствами", методами....
 
Про словари
Согласие есть продукт при полном непротивлении сторон
Страницы: 1
Читают тему
Наверх