Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.09.2012, 21:22   #1
gladius13
 
Регистрация: 11.05.2012
Сообщений: 6
По умолчанию Сравнение и сортировака двух и более столбцов данных (макрос)

Здравствуйте!

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

A - A - 5 - 4р.

В - B - 3 - 5р.

F - F - 1 - 6р.

Есть макрос, который сравнивает содержимое 2-х соседних столбцов на одинаковые значения и выводит на отдельном листе результат, сортируя одинаковые значения напротив друг друга и выделяя их цветом. Но при этом порядок значений в 1 столбце меняется.
Вот сам макрос:
_
Sub Main()

Dim i As Long, j As Long, a(), b(), x As Range, y As Range
Application.ScreenUpdating = False: Sheets(2).Activate: Cells.Delete
Sheets(1).Columns(1).Copy [A1]: Sheets(1).Columns(2).Copy [B1]: Columns(1).Copy [C1]
Range([B1], Cells(Rows.Count, 2).End(xlUp)).Copy Cells(Rows.Count, 3).End(xlUp).Offset(1)
[C:C].Sort Key1:=[C1], Order1:=xlAscending, Header:=xlGuess
a = Range([C1], Cells(Rows.Count, 3).End(xlUp)).Value: ReDim b(1 To UBound(a, 1), 1 To 2): i = 1: j = 1
Do
Set x = Columns("A").Find(a(i, 1))
If Not x Is Nothing Then
b(j, 1) = a(i, 1): x.Value = ""
End If
Set y = Columns("B").Find(a(i, 1))
If Not y Is Nothing Then
b(j, 2) = a(i, 1): y.Value = ""
End If
If Not x Is Nothing And Not y Is Nothing Then i = i + 2 Else i = i + 1
j = j + 1
Loop While i <= UBound(b, 1)
Range([D1], Cells(UBound(b, 1), 5)).Value = b: [A:C].Delete
For i = 1 To ActiveSheet.UsedRange.Rows.Count
If Cells(i, 1) = Cells(i, 2) Then Range(Cells(i, 1), Cells(i, 2)).Interior.ColorIndex = 6
Next
With ActiveSheet.UsedRange
.Borders(xlEdgeLeft).LineStyle = xlContinuous
.Borders(xlEdgeTop).LineStyle = xlContinuous
.Borders(xlEdgeBottom).LineStyle = xlContinuous
.Borders(xlEdgeRight).LineStyle = xlContinuous
.Borders(xlInsideVertical).LineStyl e = xlContinuous
.Borders(xlInsideHorizontal).LineSt yle = xlContinuous
End With

End Sub
_

Возможно ли доработать данный макрос так, чтобы он осуществлял 2 описанные выше задачи? Или может быть есть какие-либо другие решения?

Прикладываю файл содержащий данный макрос и пример.



--------- примечание модератора - вдруг кому пригодится --------------
Цитата:
Надстройка LOOKUP предназначена для сравнения и подстановки значений в таблицах Excel.

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


В настройках программы можно задать:
  • где искать сравниваемые файлы (использовать уже открытый файл, загружать файл по заданному пути, или же выводить диалоговое окно выбора файла)
  • с каких листов брать данные (варианты: активный лист, лист с заданным номером или названием)
  • какие столбцы сравнивать (можно задать несколько столбцов)
  • значения каких столбцов надо копировать в найденные строки (также можно указать несколько столбцов)

Скачать надстройку для сравнения таблиц Excel и копирования данных из одинаковых строк

Вложения
Тип файла: rar сравнение.rar (30.5 Кб, 114 просмотров)

Последний раз редактировалось EducatedFool; 30.09.2013 в 09:56.
gladius13 вне форума Ответить с цитированием
Старый 19.09.2012, 23:09   #2
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Т.е. первый столбец остаётся как есть, а второй со всеми своими "парами" (кстати, почему их нет?) распределяется рядом с первым? "Незадействованные" номера выкидываем?

Тогда заполните чем-нибудь столбцы C и D и выполните макрос:

Код:
Option Explicit


Sub compare()
    Dim a(), b(), c(), t&, x As Byte, iLastrow As Long, i As Long

    With Sheets(1)
        iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row
        a = Range(.[A1], .Range("A" & iLastrow)).Value
        iLastrow = .Cells(Rows.Count, 2).End(xlUp).Row
        b = Range(.[D1], .Range("B" & iLastrow)).Value

        ReDim c(1 To UBound(a), 1 To 3)

        With CreateObject("Scripting.Dictionary")

            For i = 1 To UBound(a)
                .Item(a(i, 1)) = i
            Next

            For i = 1 To UBound(b)
                If .exists(b(i, 1)) Then
                    t = .Item(b(i, 1))
                    For x = 1 To 3: c(t, x) = b(i, x): Next
                End If
            Next
        End With

        .[F1].Resize(UBound(c), 3) = c
        .Activate
    End With

End Sub
Выгрузка для сравнения в [F1], но можно выгружать и в [B1] - массив затрёт все данные рядом с данными столбца A.
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 19.09.2012 в 23:38.
Hugo121 вне форума Ответить с цитированием
Старый 20.09.2012, 07:22   #3
DiemonStar
Старожил
 
Регистрация: 08.02.2012
Сообщений: 2,173
По умолчанию

Цитата:
Выгрузка для сравнения в [F1], но можно выгружать и в [B1] - массив затрёт все данные рядом с данными столбца A.
правильнее перед выгрузкой сделать
Код:
.[B:D].ClearContents
иначе внизу останется куча мусора...
Правильно поставленная задача - три четверти решения.

Последний раз редактировалось DiemonStar; 20.09.2012 в 07:26.
DiemonStar вне форума Ответить с цитированием
Старый 20.09.2012, 09:23   #4
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

В этом конкретном примере не останется.
Если всегда первый столбец "выше" второго - то и никогда не останется. Поэтому зачем делать лишнюю работу?
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 20.09.2012, 10:40   #5
DiemonStar
Старожил
 
Регистрация: 08.02.2012
Сообщений: 2,173
По умолчанию

Цитата:
Если всегда первый столбец "выше" второго
с конечными пользователями нередко так не получается. так что это скорее один из элементов "защиты от дурака"
Правильно поставленная задача - три четверти решения.
DiemonStar вне форума Ответить с цитированием
Старый 20.09.2012, 21:35   #6
gladius13
 
Регистрация: 11.05.2012
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
Т.е. первый столбец остаётся как есть, а второй со всеми своими "парами" (кстати, почему их нет?) распределяется рядом с первым? "Незадействованные" номера выкидываем?

Тогда заполните чем-нибудь столбцы C и D и выполните макрос:

Код:
Option Explicit


Sub compare()
    Dim a(), b(), c(), t&, x As Byte, iLastrow As Long, i As Long

    With Sheets(1)
        iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row
        a = Range(.[A1], .Range("A" & iLastrow)).Value
        iLastrow = .Cells(Rows.Count, 2).End(xlUp).Row
        b = Range(.[D1], .Range("B" & iLastrow)).Value

        ReDim c(1 To UBound(a), 1 To 3)

        With CreateObject("Scripting.Dictionary")

            For i = 1 To UBound(a)
                .Item(a(i, 1)) = i
            Next

            For i = 1 To UBound(b)
                If .exists(b(i, 1)) Then
                    t = .Item(b(i, 1))
                    For x = 1 To 3: c(t, x) = b(i, x): Next
                End If
            Next
        End With

        .[F1].Resize(UBound(c), 3) = c
        .Activate
    End With

End Sub
Выгрузка для сравнения в [F1], но можно выгружать и в [B1] - массив затрёт все данные рядом с данными столбца A.
Да, первый столбец остаётся как есть, а второй выстраивается вместе другими столбцами напротив повторяющихся значений. "Незадействованные" номера можно просто оставлять внизу под распределенными номерами.

Макрос вроде работает как нужно! Спасибо!
Нельзя еще сделать чтобы второй столбец захватывал с собой при распределении больше 2 столбцов (хотя бы 4) и выводил результат на отдельном листе?
gladius13 вне форума Ответить с цитированием
Старый 20.09.2012, 21:51   #7
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Можно.
меняйте тут:
Код:
ReDim c(1 To UBound(a), 1 To 3)

                      For x = 1 To 3: c(t, x) = b(i, x): Next
а тут допишите впереди имя листа:
Код:
.[F1].Resize(UBound(c), 3) = c
Только не понял - зачем на другом листе "дырявый" второй столбец?
Не проще ли всё проделывать на копии?
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 24.09.2012, 23:07   #8
gladius13
 
Регистрация: 11.05.2012
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
Можно.
меняйте тут:
Код:
ReDim c(1 To UBound(a), 1 To 3)

                      For x = 1 To 3: c(t, x) = b(i, x): Next
а тут допишите впереди имя листа:
Код:
.[F1].Resize(UBound(c), 3) = c
Только не понял - зачем на другом листе "дырявый" второй столбец?
Не проще ли всё проделывать на копии?
Спасибо. Наверное проще, просто для удобства хотелось бы получать результат на отдельном листе.

Еще вопрос: воможна такая ситуация, что во втором столбце значения из 1 столбца встречаются 2 и более раз, но при этом в столбцах смежных со 2 столбцом (которые выстраиваются вместе с ним) по строкам значения разные. Макрос при этом выстраивает только одно значение, а остальные идут вниз как несовпадающие. Можно ли дополнить макрос так, чтобы он, при выстраивании значений 2 столбца и смежных столбцов напротив первого, суммировал значения в смежных столбцах ( то есть напротив совпадающего значения в 1 столбце стояло значение 2го столбца, а далее сумма из нескольких значений).
gladius13 вне форума Ответить с цитированием
Старый 24.09.2012, 23:34   #9
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,166
По умолчанию

Можно.
Но вникать сейчас некогда.
Что-то вроде
Код:
For x = 1 To 3: c(t, x) = c(t, x) + b(i, x): Next
посмотрите по месту.
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 24.09.2012 в 23:40.
Hugo121 вне форума Ответить с цитированием
Старый 27.09.2012, 09:10   #10
gladius13
 
Регистрация: 11.05.2012
Сообщений: 6
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
Можно.
Но вникать сейчас некогда.
Что-то вроде
Код:
For x = 1 To 3: c(t, x) = c(t, x) + b(i, x): Next
посмотрите по месту.
Работает, но при использовании этого кода кроме значений в смежных столбцах суммируются и значения столбца, в котором выстраиваются одинаковые значения. Например, если значение "3" встречается два раза, то макос ставит 6 и далее суммы по смежным столбцам( а нужно чтобы было 3 и суммы по смежным столбцам).
gladius13 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сравнение двух столбцов на одном листе jm2m Microsoft Office Excel 21 29.08.2012 21:53
Сравнение значений на двух листах, более 80 000 строк. Hoochara Microsoft Office Excel 3 15.06.2012 13:12
Сравнение двух столбцов mGm Microsoft Office Excel 1 15.02.2012 21:39
Номера столбцов в которых находиться более двух простых чисел andry-raser Общие вопросы C/C++ 1 19.12.2011 13:59
Сравнение данных из двух и более книг Excel 2003 Елена20.12.1987 Microsoft Office Excel 0 20.04.2010 18:56