Во втором листе список, его нужно сравнить с первым столбцом в первом листе и того, что в первом листе нет перенести в третий лист. Для наглядности: в файле на третьем листе то, что должно получиться. Желательно сделать макросом, по возможности комментируя код. Файл создал для примера, а так есть разные файлы с разными форматами, хотелось бы самому разобраться в вопросе, чтобы изменять код. Excel 2007. И можете посоветовать материал для изучения, чтобы в общих чертах разбираться с макросо-, формулописанием? Спасибо.
Во втором листе список, его нужно сравнить с первым столбцом в первом листе и того, что в первом листе нет перенести в третий лист. Для наглядности: в файле на третьем листе то, что должно получиться. Желательно сделать макросом, по возможности комментируя код. Файл создал для примера, а так есть разные файлы с разными форматами, хотелось бы самому разобраться в вопросе, чтобы изменять код. Excel 2007. И можете посоветовать материал для изучения, чтобы в общих чертах разбираться с макросо-, формулописанием? Спасибо.
Добрый день. Для начала посмотрите файл, код из которого можно использовать для Вашей задачи. Там совсем немного нужно переделать. Если хочется почитать про использование словарей - Dictionary - это совсем не сложно!
А вот вариант этого кода для Вашей задачи - всего лишь поменял имена листов, добавил в одном месте Not и в одном месте поменял присваиваемое в цикле массиву значение.
Code
Option Explicit
'Макросом - '1.два диапазона в два массива '2.создание массива для результатов '3.один перебор 300 значений массива в словарь '4.100 000 проверок массива на наличие в словаре и заполнение данными массива результата '5.выгрузка результатов (тут нет предварительной очистки диапазона)
Sub compare() Dim a(), b(), iLastrow As Long, i As Long, ii As Long
'1. With Лист1 'используется кодовое имя iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row a = Range(.[c1], .Range("A" & iLastrow)).Value End With
With Лист2 'используется кодовое имя iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row b = Range(.[A1], .Range("A" & iLastrow)).Value End With
'2. ReDim c(1 To UBound(a), 1 To 3)
With CreateObject("Scripting.Dictionary")
'3. For i = 1 To UBound(b) .Item(b(i, 1)) = i Next
'4. For i = 1 To UBound(a) If Not .exists(a(i, 1)) Then ii = ii + 1 c(ii, 1) = a(i, 1) c(ii, 2) = a(i, 2) c(ii, 3) = a(i, 3) End If Next End With
'5. With Лист3 'используется кодовое имя .[A1].Resize(ii, 3) = c .Activate End With
End Sub
Как применить код на вашем файле - домашнее задание P.S. Как недавно выяснил - кодовые имена листов могут иногда сами меняться в зависимости от того, на какой версии Экселя открывается файл. Если вдруг у кого-то имена листов в файле не совпадут с тем, что написано в коде - это тот случай Решение - поменять их назад вручную. Или в коде, или в файле. Но кодовое имя - это не то, что написано на корешке листа, а то, что видно в редакторе VBA. Меняется вручную в свойствах листа в графе (Name) или кодом.
P.S. Я думаю, что Вам всё же нужно было не ПЕРЕНОСИТЬ, а КОПИРОВАТЬ. Если переносить - тогда ещё один массив нужно создавать...
Добрый день. Для начала посмотрите файл, код из которого можно использовать для Вашей задачи. Там совсем немного нужно переделать. Если хочется почитать про использование словарей - Dictionary - это совсем не сложно!
А вот вариант этого кода для Вашей задачи - всего лишь поменял имена листов, добавил в одном месте Not и в одном месте поменял присваиваемое в цикле массиву значение.
Code
Option Explicit
'Макросом - '1.два диапазона в два массива '2.создание массива для результатов '3.один перебор 300 значений массива в словарь '4.100 000 проверок массива на наличие в словаре и заполнение данными массива результата '5.выгрузка результатов (тут нет предварительной очистки диапазона)
Sub compare() Dim a(), b(), iLastrow As Long, i As Long, ii As Long
'1. With Лист1 'используется кодовое имя iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row a = Range(.[c1], .Range("A" & iLastrow)).Value End With
With Лист2 'используется кодовое имя iLastrow = .Cells(Rows.Count, 1).End(xlUp).Row b = Range(.[A1], .Range("A" & iLastrow)).Value End With
'2. ReDim c(1 To UBound(a), 1 To 3)
With CreateObject("Scripting.Dictionary")
'3. For i = 1 To UBound(b) .Item(b(i, 1)) = i Next
'4. For i = 1 To UBound(a) If Not .exists(a(i, 1)) Then ii = ii + 1 c(ii, 1) = a(i, 1) c(ii, 2) = a(i, 2) c(ii, 3) = a(i, 3) End If Next End With
'5. With Лист3 'используется кодовое имя .[A1].Resize(ii, 3) = c .Activate End With
End Sub
Как применить код на вашем файле - домашнее задание P.S. Как недавно выяснил - кодовые имена листов могут иногда сами меняться в зависимости от того, на какой версии Экселя открывается файл. Если вдруг у кого-то имена листов в файле не совпадут с тем, что написано в коде - это тот случай Решение - поменять их назад вручную. Или в коде, или в файле. Но кодовое имя - это не то, что написано на корешке листа, а то, что видно в редакторе VBA. Меняется вручную в свойствах листа в графе (Name) или кодом.
P.S. Я думаю, что Вам всё же нужно было не ПЕРЕНОСИТЬ, а КОПИРОВАТЬ. Если переносить - тогда ещё один массив нужно создавать...Hugo
А что делать, если в первом листе более 3х значений? Во второй части я вставил "1 to 6", чтобы столбцов в массиве было 6, но появилась ошибка, которая гласит, что массив А выходит за рамки, но не могу понять где в описании массива А изменить параметр... и как автоматизировать последний столбец? Чтобы был iLastRow и iLastColumn? Хотя первый вопрос выяснил, внес нужные изменения.. Проблема была в том, что почему-то изменения не сразу вступали в силу..
А что делать, если в первом листе более 3х значений? Во второй части я вставил "1 to 6", чтобы столбцов в массиве было 6, но появилась ошибка, которая гласит, что массив А выходит за рамки, но не могу понять где в описании массива А изменить параметр... и как автоматизировать последний столбец? Чтобы был iLastRow и iLastColumn? Хотя первый вопрос выяснил, внес нужные изменения.. Проблема была в том, что почему-то изменения не сразу вступали в силу..DieMust
Сообщение отредактировал DieMust - Среда, 07.12.2011, 01:49
Кроме 1 to 6 ещё и массив a нужно брать с бОльшего диапазона:
Code
a = Range(.[c1], .Range("A" & iLastrow)).Value
Тут берётся от C1 до конца A (можно иначе написАть -я так написАл ) Причём конец A можно определить ранее по любому столбцу (iLastrow ) Ну и тут тогда продлжить:
Специально не сокращал код циклом, чтоб можно было столбцы как угодно тасовать, если нужно (или пропускать лишние).
Про iLastColumn понял - сделать можно, но поздно уже сегодня...
Кроме 1 to 6 ещё и массив a нужно брать с бОльшего диапазона:
Code
a = Range(.[c1], .Range("A" & iLastrow)).Value
Тут берётся от C1 до конца A (можно иначе написАть -я так написАл ) Причём конец A можно определить ранее по любому столбцу (iLastrow ) Ну и тут тогда продлжить:
Sub ertert() Dim str$, x, y(), i&, j&, k& str = Join(WorksheetFunction.Transpose(Sheets("Лист2").Columns(1).SpecialCells(2)), ",")
x = Sheets("Лист1").Range("A1").CurrentRegion.Value ReDim y(1 To UBound(x, 1), 1 To UBound(x, 2)) For i = 1 To UBound(x) If InStr(str, x(i, 1)) = 0 Then k = k + 1 For j = 1 To UBound(x, 2) y(k, j) = x(i, j) Next j End If Next i
Sheets("Лист3").Range("A1").Resize(k, UBound(x, 2)).Value = y() End Sub
Для разнообразия
Code
Sub ertert() Dim str$, x, y(), i&, j&, k& str = Join(WorksheetFunction.Transpose(Sheets("Лист2").Columns(1).SpecialCells(2)), ",")
x = Sheets("Лист1").Range("A1").CurrentRegion.Value ReDim y(1 To UBound(x, 1), 1 To UBound(x, 2)) For i = 1 To UBound(x) If InStr(str, x(i, 1)) = 0 Then k = k + 1 For j = 1 To UBound(x, 2) y(k, j) = x(i, j) Next j End If Next i
Sheets("Лист3").Range("A1").Resize(k, UBound(x, 2)).Value = y() End Sub