Страницы: 1
RSS
Сравнить два больших файла на уникальные значения в строках
 
Доброго всем времени суток.  
 
Сразу скажу, практически впервые пользуюсь пакетом MS Office, поэтому прошу снисходительно отнестись. Опишу задачу: Есть два файла Excel 2010, в каждом порядка 300-500 тысяч строк, нужно сравнить эти два файла по значениям одного из столбцов (скажем по столбцу B, можно заранее привести файлы к одному виду). Теоретически значения в файле 1 и файле 2, этого столбца, должны быть одинаковы, на практике возможны расхождения, которые и требуется обнаружить. Т.е. нужно найти все уникальные значения в файле 1, которых нет в файле 2 и, соответственно, наоборот. (если будет проще или быстрее работать, то можно разместить данные не в разных файлах, а на страницах одной книги).  
Пробовал решить данную задачу следующим способом: объединял обе таблицы в один файл одну под другой, потом делал Условное форматирование-Правила выделения ячеек-Повторяющиеся значения и далее в этой колонке фильтр по цвету заливки. На файле в 8Мб данный способ занимает около часа (да даже само открытие окна фильтра в этой колонке занимает около 20 минут, думаю потому что в 500000 строк каждое значение повторяется максимум дважды), на файле более 50Мб у меня комп повесился :(  
Данные можно разместить на листах в одной книге, это не принципиально, привести таблицы к одинаковому виду тоже, вся проблема в объеме файлов. Подскажите пожалуйста какой нибудь алгоритм, который не сутки будет работать.  
 
P.S. поиском по форуму воспользовался как смог, опробовал то что нашел, но не смог быстро разобраться с VBA, а решение нужно срочно. Заранее признателен.
 
Обращайтесь. Адрес в подписи.
Я сам - дурнее всякого примера! ...
 
Можете оставлять значения и в разных файлах, но код проще написать, когда значения рядом на разных листах (или в одном, без разницы) - так писанины меньше.  
 
Тут на форуме таких кодов полно - искать нужно по scripting.dictionary  
Можно и написать - только вот что делать с обнаруженными?  
Только не говорите, что нужно их красить :)
 
Кстати, я недавно уже ссылку давал на файлик:  
ibay.narod.ru/other/DoublesRemoveTwoColumns_v6.rar  
Можете сразу открыть два своих файла и обработать этим.  
Думаю, должно отработать быстро. Если попробуете - расскажите :)
 
Объясните пожалуйста логику процесса, для чего выделять по две ячейки? Мне нужно сравнить в двух файлах (ну или на двух листах книги) одну колонку и скопировать уникальные значения в другой файл (либо на другой лист).  
По запросу Вашей обработки я выделил 1 ячейку нужного мне столбца в первом файле, и 1 ячейку во втором. По второму запросу 2-ую ячейку в том же столбце в первом файле и 2-ую во втором. Получил результат: Данные stf_ctf2_01082012-31082012.xlsx Суммы stf_ctf2_01082012-31082012.xlsx Данные stf_ctf2_01082012-31082012.xlsx Суммы stf_ctf2_01082012-31082012.xlsx  
ЧЯДНТ?
 
Ещё раз попробовал запустить предложенную обработку, выбрал в первом диапазоне первую ячейку нужной колонки в первом файле, во втором диапазоне пустую ячейку в первом файле. В третьем диапазоне первую ячейку во втором файле, во втором пустую ячейку во втором файле. Получил на выходе колонку со всеми значениями из двух файлов (не проверял, но по виду так, судя по количеству, просто расхождений должно быть не более 100-500, а в выходном файле более 500000 строк).
 
Тот файл разарабатывался для сверки платёжек, поэтому там нужно выделять по две ячейки в каждом файле.  
Т.е. в одном цену и дату платежа(или ID платежа), и во втором аналогично.  
В Вашем случае - оба раза кликайте по одному столбцу. Т.е. два раза укажите на данные в одном листе, затем два раза на данные во втором.
 
Проверил - можно выделять вместо ID ячейку в пустом столбце.  
Т.е. выделяете ячейку с данными одного файла, затем пустую ячейку рядом с данными, затем аналогично данные и пустую во втором файле.
 
Привел файлы к одному виду, т.е. колонка с требуемыми данными для отбора - столбец А, затем столбец Б пустой. Выделяю в первом файле первую ячейку из стобца А и первую из столбца Б. Во втором файле так же. Результат обработки - пустая таблица. Хотя визуально видно, что расхождения в файлах есть.
 
Алгоритм работы Вашего модуля объясните пожалуйста.
 
а, ещё, пардонте, забыл уточнить, значения в ячейках по которым нужен отбор строковые
 
Ну а на Вашем приложенном файле расхождение показывает? У меня находит - и если два раза данные указывать, и если данные и пустой столбец.  
Алгоритм точно уже не помню, но там исключаются все парные значения (с учётом даты или ID), оставшиеся собираются в новую книгу.  
Т.е. если в одном столбце будет  
1  
2  
3  
а во втором  
1  
1  
3  
то расхождение будет  
2 в первом файле и 1 во втором.
 
То, что там строки - роли не играет.  
Ну а пустой столбец лучше не выбирать - выбирайте оба раза столбец с данными, так надёжнее :)
 
Согласен, с приведенным мной файлом примера обработка выполняется и выдает результат, видимо дело в том, что в ячейках по которым нужно делать отбор не числовые значения, а строковые. И мне не совсем подходит то, что в результате выводится только значения из колонок отбора, мне нужны строки полностью.  
Тем не менее весьма благодарен за помощь, возможно мне Ваша обработка поможет достичь требуемого результата, попробую разобраться в коде. Спасибо.  
Если кто то ещё что нибудь может посоветовать в плане решения данной задачи, так же буду признателен.
 
Для строк полностью нужно писать другой код - этот такой какой есть.  
Но в Вашем примере ведь нет строк полностью :)  
А без реального примера (на 10 строк например) полностью рабочий код вряд ли получите.  
Ну и если вытянутых данных немного - то ведь по ним можно формулами подтянуть остальное из тех строк.  
С помощью ВПР() или индекса с поискпозицией :)  
 
То, что там строки - роли не играет. Должно всё равно находить отличия - может быть их нет (позиция роли не играет)?  
А в коде не разберётесь - он закрыт :(
 
Для проверки попробуйте поменять в одном файле пару значений - в итоге должно найтись по два отличия на каждой стороне.
 
Steel Rain!  
Если вопрос актуален, укажите E-mail для отправки файла.
 
Мне интересно, как там дела...
 
Игорь, судя по количеству однотипных тем, пора завести "Уголок Hugo - сравнение двух столбцов/файлов". :-)
 
Ну тут я ни строчки кода не написал :)  
Но интересно, как сравнилось - но боюсь тема ушла за предел отображаемых :(  
Я с работы её уже не видел, и по страницам не пройдёшь - остаётся толлько хромой поиск... :(
 
Потренировался, попробуйте, может быть подойдет.  
ПыСы первый раз объявил словарь, тяжело. Hugo, не посмотришь файл, что то много у меня переходных массивов получилось. Не понял как по заданному значению Item вытащить Key.
 
{quote}{login=Igor67}{date=06.09.2012 11:15}{thema=}{post}первый раз объявил словарь, тяжело. {/post}{/quote}А я ещё и не подступался. :-)
 
Вот тут не понял:  
 
For i = 1 To UBound(arrB)  
           If .exists(arrA(i, 1)) Then  
 
Что-то не то :(  
Вообще я сейчас в деталях не помню тот код, но там я как-то делал за много проходов по словарям, чтоб из кучи совпадений осталось одно без пары.  
Например, если в одном списке две единицы, а во втором одна, то код покажет, что не совпадает одна единица первого списка.    
 
Ну а по итему думаю кей не получить без перебора. Мне никогда такое и не надо было :)
 
Тем более что итемы могут быть одинаковые у разных ключей!
 
Спасибо за отклики. Игорь, там где не понял это просто косяк:) Вчера не смог перебрать пары ключ-значение в словаре. Сегодня получилось. Кажется делал то же что и вчера, но... Код должен быть рабочим, без проверок на ошибочные данные или их отсутствие.  
Sub getUniq() 'извлечение только уникальных записей (повторяются по 1 разу)  
   Dim arrA(), arrB(), arrRezalt(), p&, i&, x  
   'забираем данные в массив для обработки  
   arrA = Worksheets("file1").Range("b2:b" & Worksheets("file1").Cells(Rows.Count, 2).End(xlUp).Row).Value  
   arrB = Worksheets("file2").Range("b2:b" & Worksheets("file2").Cells(Rows.Count, 2).End(xlUp).Row).Value  
   'создаем словарь для извлечения уникальных  
   With CreateObject("scripting.dictionary")  
       For i = 1 To UBound(arrA)  
           If .exists(arrA(i, 1)) Then 'если значение ключ есть в словаре  
               'считаем количество повторных значений  
               .Item(arrA(i, 1)) = .Item(arrA(i, 1)) + 1  
               p = p + 1 'если значение повторилось, то можно будет уменьшить конечный массив уникальных  
           Else: .Add key:=arrA(i, 1), Item:=1 'заносим значение в словарь и указываем на первое повторение  
           End If  
       Next i  
 
       For i = 1 To UBound(arrB) 'данные другого столбца  
           If .exists(arrB(i, 1)) Then  
               .Item(arrB(i, 1)) = .Item(arrB(i, 1)) + 1  
               p = p + 1  
           Else: .Add key:=arrB(i, 1), Item:=1  
           End If  
       Next i  
       'вычисляем размер итогового массива  
       p = .Count - p '+ 1  
       'определяем его  
       ReDim arrRezalt(1 To p, 1 To 1)  
       i = 0  
       For Each x In .keys 'начинаем перебор данных в словаре по ключам  
           If .Item(x) = 1 Then 'если данный ключ повторился 1 раз, заносим номер в итоговый массив  
               i = i + 1  
               arrRezalt(i, 1) = x  
           End If  
       Next x  
   End With  
   'выгружаем данные на лист  
   Лист3.[d1].Resize(p).Value = arrRezalt()
End Sub
 
Да, так должно сработать.  
p можно не считать - просто объявляем массив размером со словарь, а после его заполнения выгружаем по количеству i (это ведь всё равно считается i = i + 1).  
Т.е. пустой низ остаётся невыгруженным - чуть больше расход памяти, зато код проще.  
 
Но таким кодом отберутся только значения, встреченные 1 раз. А если 3?
 
Посмотрите. Два диапазона по 500000 строк, у меня посчиало за 67 сек. Зависит от скорости машины и к-ва отобранных. Можно еще ускорить, но лень экспериментировать:-)
Я сам - дурнее всякого примера! ...
Страницы: 1
Читают тему
Наверх