Страницы: 1
RSS
Двумерный ассоциативный массив VBA, Придумать оптимальный способ обращения с таблицей данных по принципу двумерного ассоциативного массива.
 
Друзья, на VBA писать только начинаю, пока не разобрался, но голову ломаю несколько дней  :)  

Мне необходимо производить манипуляции с таблицей данных, где в строках некий набор записей, а в столбцах различные подзаписи (типа "продавец", "продукт", "цена"...), то есть налицо двумерный массив. Очень хочется обращаться с этим массивом, как с ассоциативным.
Примерно так
Код
a[1][key1] = "abc"
a[1][key2] = 2
....
a[N][keyM] = "smth"

Таким образом к элементам массива удобно обращаться по ключам, складывать, вычитать и тд.
Наверняка в VBA есть решение, но для меня оно не открывается.

Что я изучил:
Collection, scripting.dictionary - не подходит, поскольку на один ключ там только одно значение (если я всё правильно понял)
Пользовательский тип данных - не подходит, поскольку набор колонок может меняться от раза к разу (как задавать тип данных динамически, я не нашёл)

Что приходит на ум:
1. Создать двумерный массив (просто скопировать таблицу в массив) вместе с названиями столбцов. Таким образом в первой строке массива у меня будет массив с названиями полей. И когда мне нужно будет обратиться к элементу a[345876]["Продукт"], то я буду искать в первой строке порядковый номер элемента с названием "Продукт"
примерно так
Код
for i=1 to a[1].Count
if aa == "Продукт" then exit For
Next' a[345876][i]      ' будет искомым элементом двумерного массива

2. Создать коллекцию массивов и проделать примерно тоже самое. Чем это лучше или хуже не знаю, то мне кажется, это будет одно и тоже.
3. Создать отдельную коллекцию типа ColNames(value='номер элемента' key='имя колонки'). Тогда к элементу a[345876]["Продукт"] можно будет обратиться таким образом a[345876][ColNames.Item("Продукт"  ;)  ]

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

Как вообще выглядит моя задача, точнее её часть:
1.У меня есть таблица, которую я копирую из другого файла. Строк в таблице десятки тысяч, столбцов - десятки (количество столбцов и их названия могут меняться от раза к разу)
Таблица примерно такого вида
Клиент продуктобъёмштукиСумма
k003382pr09878245-2094.4
k084982pr983769887-9837
k084982pr98346-34874.2-35
k084876pr983464576367736
2.Я формирую из комбинации значений нескольких столбцов столбец с ключом, который пока не является уникальным.
3. сортирую таблицу по пока не уникальному ключу
4. формирую массив уникальных ключей (убираю дубликаты)
5. далее нужно суммировать числовые столбцы по уникальному ключу. (это вполне решается прописыванием формул типа суммесли(...), но считает такой объем данных очень долго.
6. дальше нужно будет производить другие операции, но это уже другая история.

Возможно есть способ одновременного формирования списка уникальных ключей и суммирования строк с повторными ключами. Пока я формирую список ключей просто через .RemoveDuplicates

И так финальные вопросы:
1. Как создать такую структуру данных (массив, коллекцию... что угодно), чтобы можно было обращаться по принципу двухмерного ассоциативного массива.
2. Как удалить дубликаты в столбце "A" одновременным суммированием числовых значений в столбцах "D", "E"... там где значения столбца А повторяются.

Буду признателен за любые советы и конструктивную критику
Изменено: Alex - 07.01.2013 03:05:27
 
1) файлик приложите.
2) элементы коллекций и словарей могут иметь любые типы - в т.ч. массивы, структуры, словари и коллекции.
3) хотя бы примерный список того, зачем вам это надо - можете сформулировать?

upd а, ну и ООП ещё существует, говорят  :D  
upd-2 о!!! еще умное слово вспомнил - SQL. правда, насчет изменения (UPDATE/INSERT/DELETE) не уверен (не специалист), но, возможно, вам и SELECT'ов хватит?
upd-3 а еще в эксе есть сводные таблицы, и, особенно в последних версиях, достаточно мощные средства обработки больших массивов данных - OLAP, срезы и т.п....

в общем, понятно?  :D
умных слов много, но всё идёт от задачи - пути, способы, инструменты.
а задачи пока не видно (имхо).
Изменено: ikki - 07.01.2013 03:17:14
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
1. файлик приложил
На листе1 - начиная со столбца B - таблица в том виде как я её импортирую из исходного файла. Столбец А - это ключ, который нужно сделать уникальным и по которому просуммировать.
2. то что элементом коллекции может быть массив это я понял, но я пока не смог придумать структуру данных чтобы с ней удобно было обращаться.
3. Зачем мне нужно обращаться с таблицей как двумерным массивом.
У меня есть ещё некий "файл связи", в котором заданы правила преобразования числовых показателей, которые есть в исходной таблице
в файле связи примерно такой набор данных
param1 val
param2 val
param3 col
param4 val
param5 col
...
Что означате, что нужно сформировать новые числовые показатели val и col.
val = param1 + param2 + param4
col = param3 + param5...

Соответственно, чтобы обращаться к данным в исходной таблице и суммировать их в показатели другой системы координат, мне удобно к ним обращаться ассоциативно типа a[key1][param1] + a[key1][param2]..., а не высчитывать и не вводить какие-то индексы, которые потом интерпретировать и тд.
 
Alex, ваша задача как раз для сводных таблиц.
 
Цитата
upd а, ну и ООП ещё существует, говорят  :D  
upd-2 о!!! еще умное слово вспомнил - SQL...
upd-3 а еще в эксе есть сводные таблицы...
1. По поводу ООП, я не спец по VBA. Я знаю как задать пользовательский тип данных, но я не знаю как его менять автоматически в зависимости от входного файла. В одном случае мне может понадобиться 30 переменных в объекте, в другой 40. Если можно менять типы данных динамически или есть ещё какие-то решения, то буду признателен за ликбез.
2. По поводу SQL. Средствами SQL моя задача решалась бы очень просто. Но мы не ищем лёгких путей :)  Считаем, что Access-а у меня нет, у потенциального пользователя тоже. Как обращаться к таблице при помощи SQL запросов без БД? Если это возможно, то это будет супер
3. Сводные таблицы. Я пробовал, у меня не получилось. Загвоздка в том, что мне нужно просуммировать несколько столбцов. Я понял как в сводной таблице просуммировать один числовой столбец с учётом дублирования в ключевом столбце, считает отлично. А вот как просуммировать таким образом 30 столбцов, я не понял. Но я честно говоря в сводных таблицах пока слабоват.
 
Цитата
Alex пишет:
2. По поводу SQL. Средствами SQL моя задача решалась бы очень просто. Но мы не
ищем лёгких путей:) Считаем, что Access-а у меня нет, у потенциального
пользователя тоже. Как обращаться к таблице при помощи SQL запросов без БД? Если
это возможно, то это будет супер
на память не напишу - пользуюсь редко.
но драйвер ODBC может работать и с экселевскими таблицами. и с dbf-ками, и даже с текстовыми файлами.
для начала курим тему от разработчика: http://support.microsoft.com/kb/257819/ru
(ссылка на страницу, машинно-переведенную; если у вас всё в порядке с английским - лучше переключиться на оригинал)
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
ikki, Михаил С., ваши намёки про сводные таблицы уже дали результаты, я понял куда копать и, кажется, разобрался как просуммировать по разным столбцам. Думаю, что просуммировать и получить список уникальных ключей я смогу теперь.
Спасибо! Ваши мысли мне очень помогли копать в нужном направлении  :)  

Остался вопрос с двумерным ассоциативным массивом. Как организовать такую двухмерную структуру данных, которым будет удобно обращаться.

тему от разработчика пока не изучил
Цитата
тему от разработчика: http://support.microsoft.com/kb/257819/ru

upd: Начал читать, кажется, там есть кажется там есть возможность обращаться к таблице на языка SQL. Надеюсь для этого не нужны будут какие-то дополнительные модули офисные, которых может не быть у потенциального пользователя.
Изменено: Alex - 07.01.2013 11:26:17
 
пс. файл открыл, пока не понял...
Цитата
Что означате, что нужно сформировать новые числовые показатели val и col.
val = param1 + param2 + param4
col = param3 + param5...
это откуда и почему именно так?
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Цитата
Alex пишет:
Как организовать такую двухмерную структуру данных, которым будет удобно обращаться.
ну нет у меня заготовок  :(
вот, пример на скорую руку.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Цитата
Что означате, что нужно сформировать новые числовые показатели val и col.
val = param1 + param2 + param4
col = param3 + param5...
Ну это я к примеру так написал :)
Файл связи будет выглядеть примерно так (см. приложение)
Этот файл задаёт правила формирования новых числовых показателей.
В столбце "В" перечислены новые показатели, в столбце "А" - показатели из исходной таблицы. Если показателю из столбца "В" соответствует несколько показателей из столбца "А", то эти показатели в исходной таблице нужно суммировать, чтобы получить новый показатель. Такая задача преобразования. Может она тоже как-то просто решается без всяких заморочек, но я пока не нашёл как.  :)
 
ага...
т.е. в исходной таблице у вас может быть разное кол-во столбцов (с показателями)
и каждый из показателей приндлежит какой-либо группе...
и вам нужны суммы именно по группам. но в разрезе покупателей-продуктов?
да?

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

а объем таблицы (по максимуму) какой может быть?
Изменено: ikki - 07.01.2013 05:06:09
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
и вообще  :D
я понимаю, что это "например".
но, имхо, какой-то небрежный.
вот у вас в таблице заголовки
  1. Volume (Piece)
  2. GSV
  3. Order Quantity
  4. Off Invoice
  5. Centralised delivery
  6. Centralised delivery

последние два заголовка одинаковые - это нормально?
не для каждого заголовка есть соответствующее значение во второй таблице - это что?
есть "похожие" значения - с "припиской" on invoice
а для первого элемента ("Volume (Piece)") я вообще ничего не нашёл
или он общий и не входит в "группируемые"?

задачка более-менее интересная, но столько вопросов...
:(
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
для очистки совести:
Цитата
...понадобится предварительная обработка по нормализации.
пример во вложении.
запускаете макрос - Лист2 заполнится данными в виде, пригодном для сводной.
сводная делается в три щелчка
Цитата
...но столько вопросов...
сделал как понял  :D  
надеюсь, разберетесь  ;)
Изменено: ikki - 07.01.2013 11:29:24
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Я так делал словари в словаре - думаю так код проще и короче:

Код
Sub PereborFailov2() ' словарь в словаре
    Dim a, i&, t$, Dic As Object, Dic2 As Object
    Dim el, col
    
    a = Range("C3", Cells(Rows.Count, "A").End(xlUp)).Value
    Set Dic = CreateObject("Scripting.Dictionary")
    With Dic
        .CompareMode = 1
        For i = 1 To UBound(a)
            t = a(i, 1)
            If Not .exists(t) Then .Add t, CreateObject("Scripting.Dictionary")
            .Item(t).Item(a(i, 2) & "|" & a(i, 3) & "|" & i) = 0&
            
        Next
    End With
    
    For Each el In Dic.keys
        Debug.Print "Открываем файл " & el
        Set Dic2 = Dic.Item(el)
        For Each col In Dic2.keys
            Debug.Print "Ищем данные " & col '& "|" & Dic2.Item(col)
        Next
        Debug.Print "Закрываем файл " & el
    Next

End Sub


Суть в одной строке - если ключа нет, добавляем его с словарём в Item.
Затем в следующей строке дополняем словарь словаря - он в любом случае уже есть.

Задачу/файлы не смотрел, но кажется, что словари тут бы пригодились...
 
Цитата
Alex пишет:
2. По поводу SQL. Средствами SQL моя задача решалась бы очень просто.
Вот самый простейший пример, изучайте
Спасибо
 
пару вопросов:
  • когда и для чего вы используете sql?
  • sql в excel?
книжки для тех, кто хочет освоить sql
Изменено: nerv - 07.01.2013 14:18:55
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Друзья, я не пропал, я просто перевариваю... :)
Цитата
Михаил С. пишет:
Alex,  ваша задача как раз для сводных таблиц.
Михаил С. Спасибо за наводку на правильный путь.
Цитата
ikki пишет:
для очистки совести:
Цитата
...понадобится предварительная обработка по нормализации.
пример во вложении.
запускаете макрос - Лист2 заполнится данными в виде, пригодном для сводной.
сводная делается в три щелчка
Цитата
...но столько вопросов...
сделал как понял  :D  
надеюсь, разберетесь  ;)
ikki спасибо большое за такую оперативную готовность помочь не только словом, но и делом. Макрос конечно делает не совсем то что нужно, но это просто я так криво задачу, видимо, описал. Но логику я понял, это как раз то от чего я хотел уйти. Вы там просто переименовываете столбцы... В общем это не совсем ассоциативная логика. Но в сводных таблицах похоже можно обращаться по именам полей, мне кажется я найду в этом решение.
Цитата
R Dmitry пишет:
Цитата
Alex пишет:
2. По поводу SQL. Средствами SQL моя задача решалась бы очень просто.
Вот самый простейший пример, изучайте
R Dmitry Спасибо большое. Я потратил пару часов, чтобы понять подключены у меня драйвера ODBC или ещё что-то, а с вашим примером я быстро понял, что всё у меня работает. Способ отличный! Сейчас я похоже обойдусь сводными таблицами, но на будущее, я обязательно запомню.

Как допишу, отпишусь, как в итоге решил свою задачу. Ещё раз все спасибо, честно, не ожидал такой мощной поддержки, был приятно удивлён! Всем удачи
Страницы: 1
Читают тему
Наверх