Страницы: 1 2 След.
RSS
VBA Маркировка элементов в массиве (или словаре, или коллекции)
 
Приветствую,

На входе имею два массива ArrBase() и ArrMarker(), оба массива - строки.
_ ArrBase() содержит 100500 номенклатур;
_ ArrMarker() содержит 3 маркера.
_ InStr() делаю поиск подстроки ArrMarker в ArrBase, если больше 0 то надо как то ставить метку ArrMarker....

Например:
'.....
ArrBase(0, 0) = "Велосипед Apollo Aspire 20"
ArrBase(0, 1) = "Велосипед Apollo Aspire 30"
ArrBase(0, 2) = "Велосипед Apollo Aspire 40"
ArrBase(0, 3) = "Велосипед Ghost MISS 1100"
ArrBase(0, 4) = "Велосипед Ghost MISS 1200"
ArrBase(0, 5) = "Велосипед Ghost MISS 1300"
ArrBase(0, 6) = "Велосипед Orbea MX 10"
ArrBase(0, 7) = "Велосипед Orbea MX 20"
'....
ArrMarker(0, 0) = "Apollo"
ArrMarker(0, 1) = "Ghost"
ArrMarker(0, 2) = "Orbea"

Вопрос в том, что не могу понять какой Объект лучше использовать: Массивы, Коллекции или Словари, так, что бы получить две колонки : "Велосипед Apollo Aspire 20" | "Apollo"
При этом, не хотелось бы выводить это все на лист в текущей книге, а сразу сохранить в CSV/XML (типа готовая структура).

Направьте плз, а то вообще сбился с пути, в голове каша :) Благодарю
Изменено: prostor - 17.06.2017 02:12:44 (UPD: Добавил файл)
 
Если наименования все должны быть уникальные - то словарь однозначно.
Если могут быть повторения - двумерный массив.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Цитата
The_Prist написал:
Если наименования все должны быть уникальные - то словарь однозначно.
В случае со словарем - уникальное значение "Номенклатура" это (Items), а ключи (keys) это "Маркер" ?

А если понадобится добавить 3, 4... колонки, то надо будет создать новый Словарь. И эти два словаря можно будет связать по полю ключи (keys) ?

Верно понимаю?
Изменено: prostor - 16.06.2017 13:01:55
 
Сделайте такой массив:
[ [Марка1,[Модель1,Модель2, Модель3]],  [Марка2,[Модель1,Модель2, Модель3]],  [Марка3,[Модель1,Модель2, Модель3]]]
Изменено: kavaka08 - 16.06.2017 13:05:43
 
Что вы понимаете под?
Цитата
prostor написал:
И эти два словарю можно будет связать по полю ключи (keys) ?
И на сколько я понимая по моему уникальное значение это "Key" а "Item" это элемент который может повторяться!!
Изменено: Nordheim - 16.06.2017 13:08:40
"Все гениальное просто, а все простое гениально!!!"
 
Провокация кучи воды. Нет чтобы файл приложить...
Цитата
2.3. Приложите файл(ы) с примером (общим весом не более 100 Кб) в реальной структуре и форматах данных того, что есть сейчас и того, что хотелось бы на выходе.
ОФФ
Изменено: JayBhagavan - 16.06.2017 13:09:48

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
kavaka08,тот же вопрос: Если на одну номенклатуру надо поставить больше одной метки, например "Бренд:Apollo" | "Цвет:Синий" и "Бренд:Apollo" | "Цвет:Красный"

Придется создавать новый массив? Типа ArrBaseBrand(), ArrBaseColor()  и т.д.
Хочу понять, есть ли в VBA такой Объект для хранения значений, который можно "расширить вправо" (извиняюсь, если как то выразился не верно).
 
Цитата
JayBhagavan написал:
Провокация кучи воды. Нет чтобы файл приложить...
Файл не приложил, т.к. нет его - понять не могу с чего начать писать код.
Обязательно приложу, как проясню для себя с чего начать:)
 
prostor, массивы можно изменять по размеру
Код
Redim preserve
https://msdn.microsoft.com/ru-ru/library/office/gg251578.aspx
 
Цитата
prostor написал: Хочу понять, есть ли в VBA такой Объект для хранения значений, который можно "расширить вправо"
Есть - массив. Расширяйте вправо через Redim Preserve. Но, опять же, не видя файла мы продолжаем в гадалок играть.

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
Цитата
Nordheim написал:
И на сколько я понимая по моему уникальное значение это "Key" а "Item" это элемент который может повторяться!!
Наоборот: (Keys) - может повторятся, (Items) - должно быть уникальным. В этом и есть подвох.
 
Ключи не могут повторятся.
 
Key это ключ он уникальный, Item - элемент который может повторяться.
Думаю стоит сначала почитать про словари а затем макросы писать:)
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
prostor написал:
(Keys) - может повторятся, (Items) - должно быть уникальным
это разрыв логики какой-то. На каком этапе разработки алгоритма Вы пришли к решению, что ключи должны быть не уникальными?
Совет: определите, какой нужен результат(а то сначала два столбца, теперь это может быть и 4 и 6). Нужны ли вообще проверки значений на уникальность. если нужны - зачем? Должны ли от этого зависеть значения для уникального ключа? Если да - то как?
И вот тогда придет понимание как должно работать.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
описание объекта Dictionary
Согласие есть продукт при полном непротивлении сторон
 
The_Prist, Да, Вы правы. Что то меня переклинило....:(

Добавил файл с макросом, который делает "что надо", но не уверен что "как надо". Ниже код макроса из файла. Буду рад советам по улучшению:) Благодарю
---
1. Создаю одномерный массив ArrTmp и заполняю из диапазона в книге, чисто для примера. Поэтому эту часть можно пропустить:)
2. Все остальное ждет вашей критики:)
Код
Option Explicit

Sub MyItemMarker()

'Создаём и Наполняем Словари----------------------------------------------------

'Объявляем переменные для словарей Маркеров
Dim DictType
Dim DictBrand
Dim DictColor

Dim row As Integer ' Создаём переменную счетчик строк
Dim key As String, item As String ' Создаём переменные для Ключа и Элемента словарей

    'Создаём словари
    Set DictType = CreateObject("Scripting.Dictionary")
    Set DictBrand = CreateObject("Scripting.Dictionary")
    Set DictColor = CreateObject("Scripting.Dictionary")
    
    ' Наполняем словари из диапазона
    With Sheets("test_data").Range("D3:E5") ' Словарь DictType
        For row = 1 To .Rows.Count
            key = CStr(.Cells(row, 1).Value) ' Получаем Key - ключ
            item = CStr(.Cells(row, 2).Value) ' Получаем Item - значение
            DictType.Add key, item ' Добавляем новую пару в Словарь
        Next row
    End With

    With Sheets("test_data").Range("F3:G7") 'Словарь DictBrand
        For row = 1 To .Rows.Count
            key = CStr(.Cells(row, 1).Value) ' Получаем Key - ключ
            item = CStr(.Cells(row, 2).Value) ' Получаем Item - значение
            DictBrand.Add key, item ' Добавляем новую пару в Словарь
        Next row
    End With
    
    With Sheets("test_data").Range("H3:I7") 'Словарь DictColor
        For row = 1 To .Rows.Count
            key = CStr(.Cells(row, 1).Value) ' Получаем Key - ключ
            item = CStr(.Cells(row, 2).Value) ' Получаем Item - значение
            DictColor.Add key, item ' Добавляем новую пару в Словарь
        Next row
    End With

'Создаём и Наполняем Результирующий Массив---------------------------------------------

Dim ArrTmp As Variant ' Временный массив
    With Sheets("test_data").Range("A3", Cells(Rows.Count, 1).End(xlUp))
        ArrTmp = WorksheetFunction.Transpose(.Value) ' Наполняем временный одномерный массив из диапазона
    End With

    Dim ArrResult() ' Результирующий массив
        ReDim ArrResult(0 To UBound(ArrTmp, 1) - 1, 0 To 3) As Variant

Dim n As Long, k As Long, d As Long, sStr As String

    ' Переносим в массив ArrResult Наменклатуру из временного массива ArrTmp
    For n = LBound(ArrResult, 1) To UBound(ArrResult, 1)
        k = n + 1
        ArrResult(n, 0) = ArrTmp(k)
    Next n
    
    ' Заполняем массив ArrResult маркерами по Словарям
    ' Парсим каждый первый элемент второго уровня в массиве ArrResult
    For n = LBound(ArrResult, 1) To UBound(ArrResult, 1)
        
        ' Проставляем маркер Типа намеклатуры по словарю DictType
        For d = 0 To DictType.Count - 1
            key = DictType.Keys()(d)
            item = DictType.Items()(d)
            sStr = ArrResult(n, 0)
            
            If InStr(1, sStr, key, vbTextCompare) > 0 Then
                ArrResult(n, 1) = item
            End If
        Next d
        
        ' Проставляем маркер Бренда намеклатуры по словарю DictBrand
        For d = 0 To DictBrand.Count - 1
            key = DictBrand.Keys()(d)
            item = DictBrand.Items()(d)
            sStr = ArrResult(n, 0)
            
            If InStr(1, sStr, key, vbTextCompare) > 0 Then
                ArrResult(n, 2) = item
            End If
        Next d
        
        ' Проставляем маркер Цвета намеклатуры по словарю DictColor
        For d = 0 To DictColor.Count - 1
            key = DictColor.Keys()(d)
            item = DictColor.Items()(d)
            sStr = ArrResult(n, 0)
            
            If InStr(1, sStr, key, vbTextCompare) > 0 Then
                ArrResult(n, 3) = item
            End If
        Next d
    Next n

Stop ' Остановка по требыванию:)))

End Sub
 
Я бы заменил:
Код
' Наполняем словари из диапазона
    With Sheets("test_data").Range("D3:E5") ' Словарь DictType
        For row = 1 To .Rows.Count
            key = CStr(.Cells(row, 1).Value) ' Получаем Key - ключ
            item = CStr(.Cells(row, 2).Value) ' Получаем Item - значение
            DictType.Add key, item ' Добавляем новую пару в Словарь
        Next row
    End With
 
    With Sheets("test_data").Range("F3:G7") 'Словарь DictBrand
        For row = 1 To .Rows.Count
            key = CStr(.Cells(row, 1).Value) ' Получаем Key - ключ
            item = CStr(.Cells(row, 2).Value) ' Получаем Item - значение
            DictBrand.Add key, item ' Добавляем новую пару в Словарь
        Next row
    End With
     
    With Sheets("test_data").Range("H3:I7") 'Словарь DictColor
        For row = 1 To .Rows.Count
            key = CStr(.Cells(row, 1).Value) ' Получаем Key - ключ
            item = CStr(.Cells(row, 2).Value) ' Получаем Item - значение
            DictColor.Add key, item ' Добавляем новую пару в Словарь
        Next row
    End With
 


на
Код
With Sheets("test_data").Range("D3:E5") ' Словарь DictType
   For row = 1 To .Rows.Count
       DictType.item(CStr(.Cells(row, 1).Value)) = CStr(.Cells(row, 2).Value)
   Next row
End With
With Sheets("test_data").Range("F3:G7") 'Словарь DictBrand
   For row = 1 To .Rows.Count
       DictBrand.item(CStr(.Cells(row, 1).Value)) = CStr(.Cells(row, 2).Value)
   Next row
End With
With Sheets("test_data").Range("H3:I7") 'Словарь DictColor
   For row = 1 To .Rows.Count
       DictColor.item(CStr(.Cells(row, 1).Value)) = CStr(.Cells(row, 2).Value)
   Next row
End With


Это исключает ошибку при повторении ключа, без использования
Код
On Error Resume Next
"Все гениальное просто, а все простое гениально!!!"
 
Код
    For n = LBound(ArrResult, 1) To UBound(ArrResult, 1)
        k = n + 1
        ArrResult(n, 0) = ArrTmp(k)
    Next n

В данной инструкции переменная k как бы и не нужна можно записать так:
Код
    For n = LBound(ArrResult, 1) To UBound(ArrResult, 1)
        ArrResult(n, 0) = ArrTmp(n+1)
    Next n
Изменено: Nordheim - 17.06.2017 10:17:13
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, спасибо, исправил.
 
prostor, Посмотрел файл, по моему в вашем случае использование словарей не имеет смысла, потому как у вас идет циклический перебор, а словарь подразумевает поиск по ключу, в этом преимущество словарей. и соответственно прирост в скорости
Изменено: Nordheim - 17.06.2017 13:18:23
"Все гениальное просто, а все простое гениально!!!"
 
Код
With Sheets("test_data").Range("A3", Cells(Rows.Count, 1).End(xlUp))
        ArrTmp = WorksheetFunction.Transpose(.Value) ' Наполняем временный одномерный массив из диапазона
    End With

Данную инструкцию не стоит использовать потому как перед
Код
Cells(Rows.Count, 1).End(xlUp)
не прописано  
Код
Sheets("test_data")
и если во время выполнения макроса будет открыт другой лист, то возможна ошибка или неправильный пересчет. Я бы сделал так:
Код
With Sheets("test_data")
       With .Range("A3", .Cells(Rows.Count, 1).End(xlUp))
             ArrTmp = WorksheetFunction.Transpose(.Value) ' Наполняем временный одномерный массив из диапазона
       End With
End With

вот эта инструкция отработает корректно
Изменено: Nordheim - 17.06.2017 13:34:12
"Все гениальное просто, а все простое гениально!!!"
 
Nordheim, по поводу актуальности исп словарей в этом макросе - я сам не уверен. Первый раз исп словари (только учусь).
На что эффективней заменить словарь в данном случае? Может двумерный массив?
планирую сделать наполнение Маркер:Значение из текстового файла, что б можно было исп многократно в других модулях.  
 
В модуле 1 файла макрос работает аналогично вашему.
Проверяйте!
Это код макроса:

Код
Option Explicit

Sub MyItemMarker1()
Dim DictType()
Dim n&, k As Byte, i As Byte
Dim ArrResult()
DictType = Application.Transpose(Sheets("test_data").Range("D3:F7").Value)
With Sheets("test_data")
    With .Range("A3", .Cells(Rows.Count, 1).End(xlUp))
        ArrResult() = .Value
    End With
End With
ReDim Preserve ArrResult(1 To UBound(ArrResult), 1 To 4)
For n = LBound(ArrResult, 1) To UBound(ArrResult, 1)
   For k = LBound(DictType, 1) To UBound(DictType, 1)
        For i = LBound(DictType, 2) To UBound(DictType, 2)
            If Not IsEmpty(DictType(k, i)) Then
                If InStr(1, ArrResult(n, 1), DictType(k, i), vbTextCompare) > 0 Then ArrResult(n, k + 1) = DictType(k, i)
            End If
 Next i, k, n
Range("h1").Resize(UBound(ArrResult, 1), UBound(ArrResult, 2)) = ArrResult
Stop
End Sub
Изменено: Nordheim - 17.06.2017 15:51:32
"Все гениальное просто, а все простое гениально!!!"
 
Еще немного упростил :)

Код
Option Explicit
Sub MyItemMarker1()
Dim DictType()
Dim n&, k As Byte, i As Byte
Dim ArrResult()
DictType = Application.Transpose(Sheets("test_data").Range("D3:F7").Value)
ArrResult() = Sheets("test_data").Range("A3", Sheets("test_data").Cells(Rows.Count, 1).End(xlUp)).Value
ReDim Preserve ArrResult(1 To UBound(ArrResult), 1 To 4)
For n = LBound(ArrResult, 1) To UBound(ArrResult, 1)
   For k = LBound(DictType, 1) To UBound(DictType, 1)
        For i = LBound(DictType, 2) To UBound(DictType, 2)
            If Not IsEmpty(DictType(k, i)) Then
                If InStr(1, ArrResult(n, 1), DictType(k, i), vbTextCompare) > 0 Then ArrResult(n, k + 1) = DictType(k, i)
            End If
 Next i, k, n
Stop
End Sub
Изменено: Nordheim - 17.06.2017 19:08:22
"Все гениальное просто, а все простое гениально!!!"
 
Раз уж зашла речь о
Цитата
Nordheim написал:
Данную инструкцию не стоит использовать потому как
есть небольшое уточнение- Rows.Count тоже будет браться не от листа Sheets("test_data"), а от активного листа. В данном коде это не важно, т.к. книга используется одна (да и лист тоже всего один), но бывают ситуации когда в работе участвует несколько книг, и не факт что они все одного вида.
 
Hugo, Совершенно согласен,
Код
Rows.Count
упустил :)
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
Nordheim написал:
Еще немного упростил
Сорри, не смог ответить сразу. Код супер! Еще раз убеждаюсь, что не достаточно знать только синтаксис в программировании, а и уметь мыслить "глубоко":) Спасибо за помощь!
---
В последнем примере вы исп только массивы, без словарей. Массив DictType наполняется только "ключами", а значение опустили. В конкретном случае это оправдано. Интересует момент такой: если потребуется все таки использовать пару "ключ:значение" - то это только Словари?

Возможна такая ситуация, когда исходная строка может содержать разные обозначения цвета, а метку надо поставить всем одинаковую, например: "красн:Красный" или "red:Красный" или "#FF0000:Красный"

Благодарю
 
При использовании словарей желательно что бы массив содержал значения равные ключам, в этом случае будет производиться поиск значения в списке ключей и возвращать элемент принадлежащий ключу.
пример: в словаре DicObj под индексом №1  Key = "Test", Item = "Пример", Массив MyArr(1,1) = "Test" MyArray(1,2) = "Empty"
Код
MyArray(1,2) = DicObj.Item(Cstr(MyArray(1,1))

В приведенном примере  части массива MyArray(1,2) будет присвоено значение "Пример" без всякого перебора циклом. Это случай который мне известен как преимущество словаря перед массивами.
"Все гениальное просто, а все простое гениально!!!"
 
Цитата
prostor написал: если потребуется все таки использовать пару "ключ:значение" - то это только Словари?
Есть ВСТРОЕННЫЙ инструмент VBA - Коллекции (Collection). Без необходимости подключения внешних библиотек. Несомненным плюсом является возможность указания порядка добавления пары (ключ-значение) (Before/After), что упрощает (при прочих равных) сортировку.
Не помню где 'стянул' это файл и кто автор
Согласие есть продукт при полном непротивлении сторон
 
Цитата
Sanja написал:
Без необходимости подключения внешних библиотек.
Вы имеете ввиду раннее/позднее связывание?

Или как то можно хранить "укомплектованную" коллекцию НЕ в текстовом файле?
Страницы: 1 2 След.
Читают тему
Наверх