Страницы: 1
RSS
Использование словарей как альтернативу Vlookup
 
Здравствуйте, пробую разобраться с созданием словарей в Excel VBA. Не могу понять их принцип.

Задача такая - Имеется таблица на листе ("Data") с огромным колличеством строк и коллонок: (сверху A,B это буква коллонки; слева номер строки)
AB…..CB
1
……
11Код продуктаНомер продуктаФотография
124001Yes
1341021No
1442013Yes
15430222Yes
1644033No
Нужно добавить в словарь только те значения, у которых в коллонке А номер = 440, и добавить на другой лист ("Foto") эти значения, где:
AB….E
1Номер продуктаФото
2
3
Через Select Case сделал, но скорость обработки не самая быстрая получилась, хочу научиться через словари это делать или через SQL запросы.
 
вложение Dictionary_Coll.xls по ссылке посмотрите Dictionary - это совсем не сложно! очень полезная шпаргалка по словарю
Работать надо не 12 часов, а головой.
 
alessandro2981, запросом будет просто и быстро, но надо учитывать Ваши хотелки и структуру данных. Файлик дадите с пояснениями? :)
Код
SELECT * FROM [Дата$] WHERE [Код продукта] = 440
Изменено: Smiley - 30.06.2015 15:45:55
Учусь программировать :)
 
Как раз готовил файлик с примерами и комментариями)) Все подробно рассписал и разукрасил  :)

Лист ("Foto") собирает данные с двух других листов
 
alessandro2981, так в чем сложность? :) Пишите запрос или используйте словари.  
Учусь программировать :)
 
Сложность в том, что я еще пока не понимаю принцип работы запросов и словарей) Запрос может и смогу написать как-то, хоть и коряво но может и будет работать, а словари пробовал понять по статьям в интернете, вообще мимо, смысл не могу уловить, как все происходит...  :D
 
alessandro2981, если не пропускать столбец:
Код
Sub SQLconn()
    Set objConnection = CreateObject("ADODB.Connection")
    Set rs = CreateObject("ADODB.Recordset")
    objConnection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
    "Data Source=" & ActiveWorkbook.Path & "\" & ActiveWorkbook.Name & ";" & _
    "Extended Properties=""Excel 12.0;HDR=NO"";"
    sqlStr1 = "SELECT D.F1, D.F2, AD.F10, D.F80 FROM [Data$A11:CB20] AS D LEFT JOIN [AnotherData$C1:L3] AS AD ON D.F2 = AD.F1 WHERE D.F1 = 440"
    rs.Open sqlStr1, objConnection, 3, 3
    Sheets("Foto").Cells(2, 1).CopyFromRecordset rs
 End Sub
Обратите внимание на [Data$A11:CB20] и [AnotherData$C1:L3]
Изменено: Smiley - 30.06.2015 16:45:20
Учусь программировать :)
 
alessandro2981, на словари я почти год медитировал пока до меня дошло, что всё очень просто. Спасибо уважаемому Hugo за примеры на словарях.
В двух словах словарь состоит из двух частей - ключ и содержимое. Допустим, что ключ - это контейнер с уникальным номером, а содержимое может быть каким угодно, т.е., как правило, не уникальное. Словарь не позволит в себя запихнуть ещё один контейнер с номером (идентификатором), который уже в нём есть - словарь просто заменить значение контейнера (если вы просто присваиваете). Наверное не очень понятно... Тогда практика, практика и ещё раз практика. :)

Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori
 
ваш словарь
Код
Sub certain_ID_dic()
Dim a(), i&, lr&
With Sheets("Data")
    lr = .Cells(.Rows.Count, "A").End(xlUp).Row
    a = .Range("a11:cb" & lr).Value
End With

    With CreateObject("Scripting.Dictionary")
        '.CompareMode = 1    ' если в массиве только числа, то можно без этой строки
        For i = 1 To UBound(a)
   'условие на конкретный ID
        If a(i, 1) = 440 Then      
            ID = a(i, 1)
   'сбор ключей и значений под каждый ключ
            If Not .exists(a(i, 2)) Then .Item(a(i, 2)) = a(i, UBound(a, 2))
        End If
        Next i
   'выгрузка
        Sheets("Foto").Range("B2").Resize(.Count, 1).Value = Application.Transpose(Array(.keys))
        Sheets("Foto").Range("E2").Resize(.Count, 1).Value = Application.Transpose(Array(.items))
        Sheets("Foto").Range("A2").Resize(.Count, 1).NumberFormat = "000000"
        Sheets("Foto").Range("A2").Resize(.Count, 1).Value = ID
    End With
End Sub
Изменено: JeyCi - 30.06.2015 16:47:42
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Smiley, А можно ли как-то вытягивать таким способом значения из разных книг Excel, не открывая их?
Допустим, что есть 3 рабочих книги, с такими же названиями как и у листов, только теперь они содержат по 1 листу:

Foto.xlsm - открыт и содержит макрос

Эти нет смысла открывать, так как много времени уходит на их открытие и закрытие (файлы по 60мб):
Data.xlsx
AnotherData.xlsx  
 
alessandro2981, мне кажется, держать очень много данных в Excel, как минимум, неудобно. Могу только предложить засунуть эти книги в виде таблиц в Access и подключаться к нему.
Изменено: Smiley - 30.06.2015 16:51:02
Учусь программировать :)
 
Smiley, Думал по поводу Access, было бы супер, но тут не все так просто  :)

1. На рабочих копьютерах нету Access, нужно будет каждый раз загружать с флешки Portable версию.
2. Один из файлов подгружаю с сайта, в день по 300 записей.
3. Другой файл это под заказ выбранные поля из огромной базы данных сервера, который находится в другой стране. Генерируется и приходит по э-майлу в csv формате. С ним работает весь офис для подготовки отчетов и анализа данных, продаж.
4. Данные вводятся на сервер путем ввода через консоль PuTTY, где каждое значение вбивается отдельно, никакого импорта из excel и прочего там не предусмотренно.
5. Где-то раз в неделю запрашиваем новый отчет, приходит новый csv файл.

Не думаю, что можно как-то в access сделать постоянное обновление базы данных из новых сгенерированных excel файлов.
Изменено: alessandro2981 - 30.06.2015 17:14:10
 
Цитата
alessandro2981 написал: значения из разных книг Excel, не открывая их?
в случае с запросами в них можно дополнить sql-код UNION  - заглядывайте в Приёмы...(перед таблицей прописать полный путь к файлу) ...  хотя можно и открыть поочерёдно и кодом от Smiley выгрузить др за др данные из Rs...
но в общем и целом, когда надо определить диапазон книги, который нужен для работы - её нужно открыть (можно открывать в скрытом режиме) - например через GetObject, - или см вариант - Сборка листов из разных книг в одну - и далее - там, где
Код
    'проходим по всем выбранным файлам
    x = 1
    While x <= UBound(FilesToOpen)
        Set importWB = Workbooks.Open(Filename:=FilesToOpen(x))
        'выполняем свой код
   'нужное вставляем в первую строку после последней заполненной в Thisworkbook
        x = x + 1
    Wend
p.s. хотя это тема уже др ветки  ;)
Изменено: JeyCi - 03.07.2015 13:43:49
чтобы не гадать на кофейной гуще, кто вам отвечает и после этого не совершать кучу ошибок - обратитесь к собеседнику на ВЫ - ответ на ваш вопрос получите - а остальное вас не касается (п.п.п. на форумах)
 
Цитата
alessandro2981 написал:
Не думаю, что можно как-то в access сделать постоянное обновление базы данных из новых сгенерированных excel файлов.
ну в 2010 точно можно связать таблицу в Access с Excel-данными через "Внешние данные", причем при изменении в Excel будут меняться и данные в Access. Останется просто связать 3 таблицы в 1 Access файле с 3 Excel файлами, а потом запросом из Access вытаскивать необходимую информацию. Вам ведь это нужно?
Изменено: Smiley - 30.06.2015 17:40:38
Учусь программировать :)
 
Smiley, Если это один и тот же файл, то все должно быть впорядке. А как быть, если этот файл каждую неделю новый? Не думаю что сработает просто переименовать заменить файл, где стоит к нему ссылка в Access. Или этот способ работает в данном случае?
 
Цитата
alessandro2981 написал: Не думаю что сработает просто переименовать заменить файл
срабатывало. Я как-то просто подменял содержимое файла (т.е. давал другой файл с тем же названием).
 
alessandro2981, ну это в любом случае удобнее, чем работать с 3 файлами Excel по 60 мб и функциями ВПР... Кстати, такой размер файла только с данными или с формулами внутри? Перелинковать 3 файла на 3 таблицы в БД каждую неделю займет минут 10, наверное :)
Учусь программировать :)
 
вообще для вашей задачи словарь не нужен, тут быстрее будет просто загружать в массивы и обрабатывать их циклом
в словарях же чаще всего используют отработанные методы поиска соответствия( ключ-данные), проверки уникальности(ключа) и динамическое  добавление/удаление элементов
если ничего из этого не требуется(а для вашей задачи не требуется), то массивы предпочтительнее по скорости, а так же массивы быстро загружаются/выгружаются с/на лист(а)
Живи и дай жить..
 
файл должен находиться C:\1\
изменяете значение в "желтой" ячейке - обновляется таблица ниже, либо на таблице - правой кнопкой - Обновить.
Неизлечимых болезней нет, есть неизлечимые люди.
 
Здравствуйте, снова столкнулся с похожей проблемой из-за непонимания работы словарей и массивов. Попробовал применить здесь предыдущие способы, все без результатно.

Все расписал в файле примера:

1.Лист CRRATYLV и DATA добавляются с помощью макроса из другой книги, это я сделал.
2. Нужно создать макрос, который берет все значения из листа CRRATYLV только из коллонок перечисленных в Sheets("MACRO").Range("A2:A" & Lastrow)
3. Выбирает только те строки, где Produkta kods = 430 и 440
4. Сравнивает, были ли такие уже записи на Листе DATA, сравнивает по Polises numurs
5. Если в  Sheets("MACRO").Range("B2:B" & Lastrow) стоит U, тогда обновляет эти коллонки новым значением из Листа CRRATYLV в Листе DATA
6. Если на листе DATA не было найдено строки с таким Polises numurs, то макрос добавляет эту строку
7. Коллонки FLEET, FLEET DATE на листе DATA не должны затрагиваться

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