Страницы: 1
RSS
Сравнение двух таблиц
 
Добрый утро!

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

Задача такова. Есть две таблицы в них значения ФИО, Ставка, должность, ЗП одинаковые, но стоят в разных столбцах, их необходимо сравнить и в таблице номер один записать Название отдела в соответствующе строке. А если есть ошибка то помечать ячейку, которая отличается цветом.

Файл оригинал и что должно получиться прикрепляю.
 Любые идеи рассмотрю и приму с огромной благодарностью.

Заранее огромное спасибо за помощь!
 
Написать макрос несложно. Проблема в организации данных - в двух таблицах нет единого ключевого поля. Только не нужно рассказывать, что последовательность сотрудников в обеих таблицах всегда будет совпадать - в реальность Вы столкнётесь когда в них будет даже разное количество строк. Вот если бы во второй таблице был бы табельный номер... Фамилия в качестве ключевого поля не подходит, бывает встречаются однофамильцы, кстати на одном из моих предыдущих мест работы их четырёхсот работников было пять Ивановых, причём у троих совпадали инициалы, а двое были полными тёзками. Так же одну фамилию можно написать по разному, например Семёнов и Семенов - для макроса это будут разные фамилии.
Так что сначала подумайте как избежать подобных неоднозначностей, а заодно и что делать если в таблицах будет разное количество строк (оба варианта),так же что делать если в первой таблице есть сотрудники, которых вообще нет во второй и наоборот.
Не стреляйте в тапера - он играет как может.
 
Davidov.p.v, здравствуйте!
Если возможно построчно сцепить столбцы, то ТУТ лучшая (на мой взгляд, конечно) программа для сравнения двух списков.
Ещё можете взглянуть СЮДА, автор, кажется, Hugo (местный умный планетянин)
Изменено: Jack Famous - 18.06.2016 10:34:40
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Цитата
Ts.Soft написал: Проблема в организации данных - в двух таблицах нет единого ключевого поля
В таблице уникальное поле это ФИО, абсолютно точно нет совпадений.

Цитата
в реальность Вы столкнётесь когда в них будет даже разное количество строк.
Количество строк действительно разное.

Цитата
Фамилия в качестве ключевого поля не подходит
Фамилию можно взять как ключевое слово однофамильцев точно нет.

Цитата
Так же одну фамилию можно написать по разному, например Семёнов и Семенов
Вот это может быть я не представляю как это можно исправить. Если только сравнить столбцы фамилии сначала и вывести не совпадении одной либо двух букв как вариант.

Цитата
так же что делать если в первой таблице есть сотрудники, которых вообще нет во второй и наоборот.
Как вариант после сравнения каждой строки помечать ее цветом.

Jack Famous, спасибо это я уже видел я нашел похожий на то что мне надо не большой макрос но он не информативный в плане ошибок в строке.
Макрос привожу.
Код
Sub Макрос1()
'' Макрос1 сравнение двух таблиц с использованием макроса VBA
' ссылка на первый лист книги

Dim sheet1 As Worksheet
Set sheet1 = ActiveWorkbook.Sheets(1)
' ссылка на второй лист книги
Dim sheet2 As Worksheet
Set sheet2 = ActiveWorkbook.Sheets(2)
 
' строка для хранения идентификатора строки первой таблицы
Dim str1 As String
' строка для хранения идентификатора строки второй таблицы
Dim str2 As String
 
' позиция курсора (номер строки) в первой таблице
Dim i As Integer
i = 3
Dim last_i As Integer
last_i = 3
' позиция курсора (номер строки) во второй таблице
Dim j As Integer
j = 3
Dim last_j As Integer
last_j = 3
 
' определяем последнюю значимую строку первой таблицы (последняя строка, в первой колонке которой есть значение)
For Each Cell In sheet1.Range("A:A")
    If Cell.Row > 2 Then
        If Cell.Value > "" Then
            last_i = Cell.Row
        Else
            Exit For
        End If
    End If
Next Cell
 
' определяем последнюю значимую строку второй таблицы (последняя строка, в первой колонке которой есть значение)
For Each Cell In sheet2.Range("A:A")
    If Cell.Row > 2 Then
        If Cell.Value > "" Then
            last_j = Cell.Row
        Else
            Exit For
        End If
    End If
Next Cell
 
' пробегаем по строкам второй таблицы (внешний цикл)
For j = 3 To last_j
    ' определяем идентификатор текущей строки
    str2 = sheet2.Cells(j, 5).Value & "-" & sheet2.Cells(j, 2).Value & "-" & sheet2.Cells(j, 4).Value & "-" & sheet2.Cells(j, 6).Value
    ' пробегаем по строкам первой таблицы (внутренний цикл)
    For i = 3 To last_i
        ' определяем идентификатор текущей строки
        str1 = sheet1.Cells(i, 2).Value & "-" & sheet1.Cells(i, 4).Value & "-" & sheet1.Cells(i, 8).Value & "-" & sheet1.Cells(i, 9).Value
        ' сравниваем идентификаторы строк первой и второй таблицы
        If str2 = str1 Then
            ' если совпадение найдено, то записываем покупателя из второй таблицы в первую в строку с соответствующей ему квартирой
            sheet1.Cells(i, 10).Value = sheet2.Cells(j, 1).Value
            ' прекращаем внутренний цикл, переходим к следующей итерации внешнего цикла
            ' (к следующей записи второй таблицы)
            Exit For
        End If
    Next i
Next j 
End Sub
Изменено: Davidov.p.v - 18.06.2016 22:47:05
 
Davidov.p.v, как Вы думаете, зачем давным-давно для идентификации сотрудников придумали табельный номер? Это сегодня у Вас нет однофамильцев, а завтра кто-то уволился, кто-то устроился... Или Вы при приёме на работу будете отказывать однофамильцам уже существующих сотрудников? Так это нарушение Трудового кодекса - вот в инспекции по  труду посмеются...
Так что лучше заранее всё предусмотреть и использовать для идентификации старый добрый табельный номер.
Кстати креме е/ё возможно ещё много вариантов: Иванов И.И., Иванов ИИ, Иванов И. И. - для программы разные люди. А бывают и орфографические ошибки...

А вообще это постоянная проблема при постановке задачи - никто не думает о том что может быть завтра. Я уже не сосчитаю сколько раз мне говорили: "такого у нас нет, не было и никогда не будет", проходило какое-то время, что-то менялось и ко мне прибегали с криком "программа не работает!!!" или "нам надо так, а программа это не позволяет", полностью забыв свои слова "такого у нас нет, не было и никогда не будет".
Не стреляйте в тапера - он играет как может.
 
Ts.Soft, я согласен но тут одноразовая проверка 2000 сотрудников. И проверять 2000 записей руками как то не очень есть хорошо, когда век компьютерных технологий..
 
Доброе время суток
Цитата
Davidov.p.v написал: когда век компьютерных технологий..
О, это да, и в школе информатика, а в институте программирование. Тогда где ваши попытки? А то пока
Цитата
Davidov.p.v написал: И проверять 2000 записей руками как то не очень есть
 
Davidov.p.v, ну если временно, то смотрите что получилось.
При запуске снимается всё цветовое выделение и очищается список структурных подразделений.
Дополнительно сделал пометку на втором листе просмотренных строк. Если при сравнении ошибок нет, то фамилия помечается зелёным, иначе - красным. Если фамилия никак не помечена, значит на первом листе такой фамилии нет.

Кстати, у Вас сразу выскакивают ошибки в должностях: на одном листе "продавец-консультант", а на другом уже "продавец-консультант запчастей"
Изменено: Ts.Soft - 18.06.2016 14:07:01
Не стреляйте в тапера - он играет как может.
 
Цитата
Андрей VG написал: в школе информатика, а в институте программирование
Не верю. Я видел молодых экономистов/бухгалтеров и т.п. - они даже аккаунт в одноклассниках без посторонней помощи создать не могут...
Да и если всех обучают программированию, тогда зачем нужны программисты?
Не стреляйте в тапера - он играет как может.
 
Цитата
Ts.Soft написал:
Не верю. Я видел молодых экономистов/бухгалтеров и т.п. - они даже аккаунт в одноклассниках без посторонней помощи создать не могут
И на этом основании можно сделать вывод, что программирование в (непрофильных) вузах не преподают? ))
 
Ts.Soft, Огромное СПАСИБО. Все работает как я и хотел. ЕЩЕ РАЗ СПАСИБО. Вы меня спасли от очень муторной и кропотливой работы которую я бы выполнял месяц.
Изменено: Davidov.p.v - 19.06.2016 21:24:27
 
Цитата
Ts.Soft написал: Кстати, у Вас сразу выскакивают ошибки в должностях
Так как один, это выгрузка из 1С, а второй это пишет другой сотрудник.
 
Помогите, пож-ста, доработать код:
Две таблицы на одном листе, первый столбец является ключом данных (уникальное значение, идентификатор), кол-во столбцов в двух таблицах неизменно, а количество строк может меняться (удаляться и прибавляться)).
Мой код сравнивает построчно, что нужно чтобы сравнение было по массивам?
Код
Sub CompareArrays()

    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Сравнение")

    Dim arr1 As Variant, arr2 As Variant
    Dim keyCol1 As Integer, keyCol2 As Integer
    Dim dict1 As Object, dict2 As Object
    Dim key As Variant
    Dim r As Long, c As Long
    Dim rowIndex As Variant

    ' Определяем массивы данных
    arr1 = ws.Range("A2:I300").Value ' Замените на диапазон вашей первой таблицы
    arr2 = ws.Range("J2:R300").Value ' Замените на диапазон вашей второй таблицы

    ' Определяем столбцы ключей (1 - это первый столбец в массиве)
    keyCol1 = 1
    keyCol2 = 1

    ' Создаем словари для хранения ключей и индексов
    Set dict1 = CreateObject("Scripting.Dictionary")
    Set dict2 = CreateObject("Scripting.Dictionary")

    ' Заполняем словари данными из массивов
    For r = 1 To UBound(arr1, 1)
        key = arr1(r, keyCol1) & arr1(r, keyCol1 + 1)
        dict1(key) = r
    Next r

    For r = 1 To UBound(arr2, 1)
        key = arr2(r, keyCol2) & arr2(r, keyCol2 + 1)
        dict2(key) = r
    Next r

    ' Сравниваем массивы и выделяем изменения
    For Each key In dict1.Keys
        If Not dict2.exists(key) Then
            ' Удаленные данные - синим цветом
            rowIndex = dict1(key)
            For c = 1 To UBound(arr1, 2)
                ws.Cells(rowIndex + 1, c).Interior.Color = RGB(0, 0, 255)
            Next c
        Else
            rowIndex = dict1(key)
            For c = 1 To UBound(arr1, 2)
                If arr1(rowIndex, c) <> arr2(dict2(key), c) Then
                    ' Измененные данные - красным цветом
                    ws.Cells(rowIndex + 1, c).Interior.Color = RGB(255, 0, 0)
                    ws.Cells(dict2(key) + 1, c + 9).Interior.Color = RGB(255, 0, 0)
                End If
            Next c
            ' Строка с изменениями - желтым цветом
            ws.Rows(rowIndex + 1).Interior.ColorIndex = 6
            dict2.Remove key
        End If
    Next key

    ' Новые данные - зеленым цветом
    For Each key In dict2.Keys
        rowIndex = dict2(key)
        For c = 1 To UBound(arr2, 2)
            ws.Cells(rowIndex + 1, c + 9).Interior.Color = RGB(0, 255, 0)
        Next c
    Next key

    MsgBox "Сравнение завершено.", vbInformation
End Sub

 
V P, что Вы подразумеваете под "сравнение по массивам"?
Что не устраивает в этом коде?
 
Сейчас код сравнивает построчно точное совпадение, а у меня строки могут менять своё местоположение, сортировка не помогает, под сравнением массивов я имею ввиду что должен быть поиск строк по ключу(индексу) , и уже потом сравнение ячеек, сейчас сравнение построчно.  
 
Hugo, есть идеи как поправить?  
 
Хочу узнать у знатоков, данный код логичный, правильный?
Код
Sub CompareArrays()

    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Сравнение")

    Dim arr1 As Variant, arr2 As Variant
    Dim keyCol1 As Integer, keyCol2 As Integer
    Dim dict1 As Object, dict2 As Object
    Dim key As Variant
    Dim r As Long, c As Long
    Dim rowIndex As Variant

    ' Определяем массивы данных
    arr1 = ws.Range("A2:I300").Value ' Замените на диапазон вашей первой таблицы
    arr2 = ws.Range("J2:R300").Value ' Замените на диапазон вашей второй таблицы

    ' Определяем столбцы ключей (1 - это первый столбец в массиве)
    keyCol1 = 1
    keyCol2 = 1

    ' Создаем словари для хранения ключей и индексов
    Set dict1 = CreateObject("Scripting.Dictionary")
    Set dict2 = CreateObject("Scripting.Dictionary")

    ' Заполняем словари данными из массивов
    For r = 1 To UBound(arr1, 1)
        key = arr1(r, keyCol1) & arr1(r, keyCol1 + 1)
        dict1(key) = r
    Next r

    For r = 1 To UBound(arr2, 1)
        key = arr2(r, keyCol2) & arr2(r, keyCol2 + 1)
        dict2(key) = r
    Next r

    ' Сравниваем массивы и выделяем изменения
    For Each key In dict1.Keys
        If Not dict2.exists(key) Then
            ' Удаленные данные - синим цветом
            rowIndex = dict1(key)
            For c = 1 To UBound(arr1, 2)
                ws.Cells(rowIndex + 1, c).Interior.Color = RGB(0, 0, 255)
            Next c
        Else
            rowIndex = dict1(key)
            For c = 1 To UBound(arr1, 2)
                If arr1(rowIndex, c) <> arr2(dict2(key), c) Then
                    ' Измененные данные - красным цветом
                    ws.Cells(rowIndex + 1, c).Interior.Color = RGB(255, 0, 0)
                    ws.Cells(dict2(key) + 1, c + 9).Interior.Color = RGB(255, 0, 0)
                End If
            Next c
            ' Строка с изменениями - желтым цветом только первый столбец
            ws.Cells(rowIndex + 1, 1).Interior.ColorIndex = 6
            dict2.Remove key
        End If
    Next key

    ' Новые данные - зеленым цветом
    For Each key In dict2.Keys
        rowIndex = dict2(key)
        For c = 1 To UBound(arr2, 2)
            ws.Cells(rowIndex + 1, c + 9).Interior.Color = RGB(0, 255, 0)
        Next c
    Next key

    MsgBox "Сравнение завершено.", vbInformation
End Sub
Страницы: 1
Читают тему
Наверх