Страницы: 1
RSS
сверка столбцов Макрос или формула
 
Требуется помощь!  
Можно ли создать макрос или формулу для сверки столбцов:  
1 таблица  
1 ст.   | 2 ст. | 3 ст.  | 4 ст.  | 5 ст.|  
Фамилия |  Имя  |Отчетс. | д/рожд.| счет |  
 
2 таблица  
1 ст.   | 2 ст. | 3 ст.  | 4 ст.  | 5 ст.| 6 ст. |  
Фамилия |  Имя  |Отчетс. | д/рожд.| счет |ДА/НЕТ |  
 
у первого таблиц 100 000 строк, у второго 500 000 строк...
 
Решение данного вопроса скорее всего нужно делать макросом, изза кол-ва строк, но опять же без примера, можно только поговорить.
Редко но метко ...
 
{quote}{login=Даулет}{date=25.10.2011 12:10}{thema=сверка столбцов Макрос или формула}{post}  
... Можно ли создать макрос или формулу для сверки столбцов... {/post}{/quote}  
Создавайте... ;) Или поищите готовое - все давно придумано до нас (есть "Приемы" и поиск не отключали)...  
-60781-
 
создаете в обеих таблицах доп.столбец, в котором через СЦЕПИТЬ создаете объединенные записи тех столбцов, которые надо сравнивать. Затем через ВПР сравниваете. В Приемах есть статься про ВПР: <EM>http://www.planetaexcel.ru/tip.php?aid=26</EM>  
 
и здесь: <EM>http://www.excel-vba.ru/chto-umeet-excel/kak-najti-znachenie-v-drugoj-tablice-ili-sila-vpr/</EM>
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Мне кажется, что 100000 ВПР() по 500000 значений подвесит XL.  
А наоборот ещё скорее...  
А если не подвесит - то с виду будет выглядь, что подвисло :(
 
Примерчик
 
Можно сделать быстрый код (и получить результат как в примере), если в одной из таблиц нет повторов по Ф+И+О.  
Но это вряд ли такое будет. Даже на этом примере такого нет.  
 
Думаю, нужно набирать в словарь по Ф+И+О+ДР (в итем счёт), и по по Ф+И+О+счёт (в итем ДР) и то вероятно будут повторы, и нужно предусмотреть ещё как их учесть.  
Может быть в Item поместить массив, куда собирать все данные этих повторов (счёт/ДР)  
Так пройтись по одному массиву данных (вероятно лучше по меньшему).  
Затем пройтись по второму массиву (сперва создать пустой массив под размер) и сверить по словарю текущие Ф+И+О+ДР и Ф+И+О+счёт.  
Если сошлось уже первое и в итем тоже есть соответствие - то всё ОК, проверяем следующее;  
если сошлось по Ф+И+О+ДР но в итем совпадений нет - то пишем "сошлось ДР, счёт другой", иначе:  
если сошлось по Ф+И+О+счёт но в итем совпадений нет - то пишем "сошлось счёт, ДР другой", иначе:  
пишем "не нашлось".  
Это пишем в пустой параллельный массив по индексу проверяемого массива.  
В конце выгружаем его рядом.  
Примерно вероятно так должно сработать, но есть вопрос - какие другие счёт и ДР вытягивать, если их будет несколько? Все? Тоже можно.  
Но мне сейчас реализовывать некогда, да и позже тоже вероятно некогда будет. И уже не интересно.  
Примите просто как подсказку :)  
А может кто попробует реализовать в порядке пробы сил... и проверит работоспособность алгоритма.
 
Hugo есть ли у Вас примерчик любой подходящий...
 
Вот что-то похожее, можно взять за основу и нарастить.
 
СПАСИБО HUGO!
 
Ну такое спасибо пока не заслужил, это только слова пока, кода-то рабочего нет. Пример не в счёт, пока Вы не разобрались :)  
Можно вероятно собирать в Item не в массив, а в строку с разделителями, и потом по Instr() искать совпадения.  
Вот только не знаю, какой длины строку можно собирать (может кто подскажет?). А на 100000 может быть много повторов, соответственно строка может вырасти длинная (ещё смотря какие данные в неё собирать).  
Надёжнее массив через Redim Preseve наращивать, но со строкой проще...
 
Ещё что подумал - в принципе можно эти таблицы подключить как внешние данные в Ацесс и делать дело в нём.  
Или в Экселе с помощью SQL/ADO/DAO  
Вот только не знаю, как создать запрос под именно такую задачу...  
Одинаковые или разные получить легко, а вот так частично разобрать - не делал.
 
Сегодня утром было чуть времени - реализовал алгоритм, работает.  
Думаю, тонкое место - запихнуть в ячейку перечисление расхождения. На 100000 может быть много, особенно если люди могут повторяться.  
Ну проверьте, как пойдёт.  
Таблицы разместил на двух листах - в принципе, можно скорректировать, чтоб брать из двух разных файлов - так не надо будет одну из них копипастить.  
Цветом расхождения не красил - геморой, и код затормозит раз так в... не знаю, может в 45...  
Т.е. вместо 10 секунд будет может быть часы работать.  Вам это нужно? И так всё видно, можно фильтром отобрать...
 
HUGO Спасибо!  
еще надо разобраться мне, ну нечего разберусь (макрос)...
 
HUGO спасибо! еще 1 вопрос а как можно переделать  
чтобы сверил    
Ф+И+О+ДР (в итем счёт) - "не совпало по счёту: " & Join(d, "|")  
место Ф+И+О+счёт (в итем ДР), этот счёт (в итем Ф+И+О+ДР) - "не совпало по Ф+И+О+ДР: " & Join(d, "|")
 
сверил по счету - результат Лист1 Ф+И+О+ДР
 
Не понял.  
Если нужно надписи заменить - то вроде Вы уже поняли, где это.  
Если нужно само сравнение иначе делать - не понял как и что хочется :)
 
Hugo переделал: можешь проверить?  
 
'в словарь счёт (в итем Ф+И+О+ДР)  
           temp = Trim(a(i, 5))  
           If Not .exists(temp) Then  
               ReDim d(0 To 0)  
               d(0) = Trim(a(i, 1)) & "|" & _  
                  Trim(a(i, 2)) & "|" & _  
                  Trim(a(i, 3)) & "|" & _  
                  Trim(a(i, 4))  
               .Item(temp) = d  
           Else  
               d = .Item(temp)  
               ReDim Preserve d(UBound(d) + 1)  
               d(UBound(d)) = Trim(a(i, 1)) & "|" & Trim(a(i, 2)) & "|" & Trim(a(i, 3)) & "|" & Trim(a(i, 4))  
               .Item(temp) = d  
           End If  
 
-------------------------  
 
f .exists(temp) Then  
                   d = .Item(temp)  
                   c(i, 1) = "не совпало по Ф+И+О+ДР: " & Join(d, "|")  
               Else  
 
**************************************************************************  
 
Вроде у меня работает...
 
{quote}{login=}{date=27.10.2011 08:28}{thema=}{post}Hugo переделал: можешь проверить?  
 
'в словарь счёт (в итем Ф+И+О+ДР)  
           temp = Trim(a(i, 5))  
           If Not .exists(temp) Then  
               ReDim d(0 To 0)  
               d(0) = Trim(a(i, 1)) & "|" & _  
                  Trim(a(i, 2)) & "|" & _  
                  Trim(a(i, 3)) & "|" & _  
                  Trim(a(i, 4))  
               .Item(temp) = d  
           Else  
               d = .Item(temp)  
               ReDim Preserve d(UBound(d) + 1)  
               d(UBound(d)) = Trim(a(i, 1)) & "|" & Trim(a(i, 2)) & "|" & Trim(a(i, 3)) & "|" & Trim(a(i, 4))  
               .Item(temp) = d  
           End If  
 
-------------------------  
 
f .exists(temp) Then  
                   d = .Item(temp)  
                   c(i, 1) = "не совпало по Ф+И+О+ДР: " & Join(d, "|")  
               Else  
 
**************************************************************************  
 
Вроде у меня работает...{/post}{/quote}
 
Т.е. это уже четвёртая ступень проверки - когда не прошли предыдущие проверки?  
Да, работает, на "Садыкововне" выводит разницу (в моём примере):  
 
Option Explicit  
 
Sub compare()  
   Dim temp$, a(), b(), iLastrow As Long, i As Long, el  
 
   '1.два диапазона в два массива  
   With Sheet1    'используется кодовое имя  
       iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row  
       a = Range(.[E2], .Range("A" & iLastrow)).Value
   End With  
 
   With Sheet2    'используется кодовое имя  
       iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row  
       b = Range(.[E2], .Range("A" & iLastrow)).Value
   End With  
 
   '2.создание массива для результатов  
   ReDim c(1 To UBound(b), 1 To 1)  
 
   '3.один перебор 100000*2 значений массива в словарь  
   With CreateObject("Scripting.Dictionary")  
       .CompareMode = vbTextCompare  
 
       For i = 1 To UBound(a)  
           'в словарь Ф+И+О+ДР (в итем счёт)  
           temp = Trim(a(i, 1)) & "|" & _  
                  Trim(a(i, 2)) & "|" & _  
                  Trim(a(i, 3)) & "|" & _  
                  Trim(a(i, 4))  
           If Not .exists(temp) Then  
               ReDim d(0 To 0)  
               d(0) = Trim(a(i, 5))  
               .Item(temp) = d  
           Else  
               d = .Item(temp)  
               ReDim Preserve d(UBound(d) + 1)  
               d(UBound(d)) = Trim(a(i, 5))  
               .Item(temp) = d  
           End If  
 
           'в словарь Ф+И+О+счёт (в итем ДР)  
           temp = Trim(a(i, 1)) & "|" & _  
                  Trim(a(i, 2)) & "|" & _  
                  Trim(a(i, 3)) & "|" & _  
                  Trim(a(i, 5))  
           If Not .exists(temp) Then  
               ReDim d(0 To 0)  
               d(0) = Trim(a(i, 4))  
               .Item(temp) = d  
           Else  
               d = .Item(temp)  
               ReDim Preserve d(UBound(d) + 1)  
               d(UBound(d)) = Trim(a(i, 4))  
               .Item(temp) = d  
           End If  
 
           'в словарь счёт (в итем Ф+И+О+ДР)  
           temp = Trim(a(i, 5))  
           If Not .exists(temp) Then  
               ReDim d(0 To 0)  
               d(0) = Trim(a(i, 1)) & "|" & _  
                      Trim(a(i, 2)) & "|" & _  
                      Trim(a(i, 3)) & "|" & _  
                      Trim(a(i, 4))  
               .Item(temp) = d  
           Else  
               d = .Item(temp)  
               ReDim Preserve d(UBound(d) + 1)  
               d(UBound(d)) = Trim(a(i, 1)) & "|" & Trim(a(i, 2)) & "|" & Trim(a(i, 3)) & "|" & Trim(a(i, 4))  
               .Item(temp) = d  
           End If  
 
 
       Next  
 
       '4.500000*2 проверок массива на наличие в словаре и заполнение массива результата  
       For i = 1 To UBound(b)  
           temp = Trim(b(i, 1)) & "|" & _  
                  Trim(b(i, 2)) & "|" & _  
                  Trim(b(i, 3)) & "|" & _  
                  Trim(b(i, 4))  
 
           If .exists(temp) Then  
               d = .Item(temp)  
               For Each el In d  
                   If el = Trim(b(i, 5)) Then  
                       c(i, 1) = "совпало"  
                       Exit For  
                   End If  
               Next  
               If c(i, 1) <> "совпало" Then c(i, 1) = "не совпало по счёту: " & Join(d, "|")  
           Else  
 
               temp = Trim(b(i, 1)) & "|" & _  
                      Trim(b(i, 2)) & "|" & _  
                      Trim(b(i, 3)) & "|" & _  
                      Trim(b(i, 5))  
 
               If .exists(temp) Then  
                   d = .Item(temp)  
                   c(i, 1) = "не совпало по дате: " & Join(d, "|")  
               Else  
                   temp = Trim(b(i, 5))  
                   If .exists(temp) Then  
                       d = .Item(temp)  
                       c(i, 1) = "не совпало по Ф+И+О+ДР: " & Join(d, "|")  
                   Else  
                       c(i, 1) = "не совпало вообще!!!"  
                   End If  
 
               End If  
           End If  
       Next  
   End With  
 
   '5.выгрузка результатов  
   With Sheet2    'используется кодовое имя  
       .[G2].Resize(i - 1) = c
   End With  
 
End Sub
 
"Т.е. это уже четвёртая ступень проверки - когда не прошли предыдущие проверки?  
Да, работает, на "Садыкововне" выводит разницу (в моём примере):"  
-------------------------------------------  
Да разница есть потому-что сверяет по счету:  
на 2 листе О=Садыкововна ;счет=129  
на 1 листе О=Садыковна ;счет=129  
 
пишет разницу "не совпало по Ф+И+О+ДР: Бакиева|Гульшан|Садыковна|28.08.1941"  
 
то что надо была !!!  
 
С помощью твоего макроса, хочу сделать чтобы только на одном листе проверял ...  
--------------------------------------------  
Огромное спасибо HUGO!!!
 
Так сделать для одного листа - это просто:  
изменить кодовое имя листа (или имя/номер прописать), определение последней строки, определение диапазона для массива, место выгрузки.  
И всё :)
Страницы: 1
Читают тему
Наверх