Страницы: 1
RSS
-=Выделение совпадений с помощью 2х массивов=-
 
Всем привет!  
С массивами очень редко работаю, но сейчас нужно, т.к. перебор циклом на большом объеме очень долгий.  
Суть задачи: есть два листа с номерами, если номера совпадают на листе1 с номерами, которые на листе2 - их нужно выделить font.bold (на 1м листе).  
Два макроса во вложении, цикл работает как надо, а вот с массивом проблема :(  
 
Подскажите, пожалуйста, что не правильно делаю?  
Заранее благодарю.
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
Привет. Прикольно Богдан, ты значению в массиве пытаешься присвоить жирность шрифта:-) Это значение в памяти, в виде нулей и единиц у него нет шрифта. Вариант поскорей:  
Public Sub www()  
   Dim a, i&, lr&  
   a = Sheets(2).Range("a2").CurrentRegion.Value  
   With CreateObject("scripting.dictionary")  
       For i = 1 To UBound(a)  
           If Not .exists(a(i, 1)) Then .Item(a(i, 1)) = a(i, 1)  
       Next  
       For i = 1 To Sheets(1).[e1].End(xlDown).Row
           If .exists(Sheets(1).Cells(i, 5)) Then Sheets(1).Cells(i, 5).Font.Bold = True  
       Next  
   End With  
End Sub  
Можно еще существенно ускорить за счет допстолбца.
Я сам - дурнее всякого примера! ...
 
Исправь:  
If .exists(Sheets(1).Cells(i, 5).Value)
Я сам - дурнее всякого примера! ...
 
Если нет повторов в первом листе ещё быстрее:  
 
Public Sub iMass()  
   Dim tm!: tm = Timer  
   Dim a(), b(), i&, lr&, t&  
   Application.ScreenUpdating = False  
   a = Sheets(1).Range("e1").CurrentRegion.Value  
   b = Sheets(2).Range("a1").CurrentRegion.Value  
   With CreateObject("scripting.dictionary")  
       For i = 1 To UBound(a): .Item(a(i, 1)) = i: Next  
       For i = 1 To UBound(b)  
           t = b(i, 1)  
           If .exists(t) Then Sheets(1).Cells(.Item(t), 5).Font.Bold = True  
       Next  
   End With  
   Application.ScreenUpdating = True  
   Debug.Print Format((Timer - tm) / 24 / 60 / 60, "nn:ss") & "  мин:сек"  
End Sub  
 
Т.к. в словаре запоминается значение и его позиция на листе (в данном случае совпадает с позицией в массиве, но если есть сдвиг - его можно позже при покраске учесть).  
Далее при повторе красим конкретную ячейку.  
Но если в первом листе будут повторы - первое значение покрашено не будет.  
Хотя это тоже можно учесть - собирать в итем в строку (или массив) все адреса, потом циклом их извлекать.
 
Я чуть поэкономней:  
Public Sub www()  
   Dim a, i&  
   a = Sheets(2).Range("a2").CurrentRegion.Value  
   With CreateObject("scripting.dictionary")  
       For i = 1 To UBound(a)  
           If Not .exists(a(i, 1)) Then .Item(a(i, 1)) = a(i, 1)  
       Next  
       a = Sheets(1).Range("e1", [e1].End(xlDown))
       For i = 1 To UBound(a)  
           If .exists(a(i, 1)) Then Sheets(1).Cells(i, 5).Font.Bold = True  
       Next  
   End With  
End Sub
Я сам - дурнее всякого примера! ...
 
Еще была мысль в union по 100 строк собирать, набралось больше - закрасили, очистили, набираем по новой. Думаю, Богдан сам сообразит. А нет, так спросит.
Я сам - дурнее всякого примера! ...
 
{quote}{login=KukLP}{date=24.03.2012 05:52}{thema=}{post}Прикольно Богдан, ты значению в массиве пытаешься присвоить жирность шрифта:-){/post}{/quote}  
Не смейся :) Меня Саша (Nerv), когда-то пытался научить работать с массивами, но я уже всё забыл (т.к. на работе их не использую), помню только "азы".  
С виду вроде бы всё понятно, а вот если придется написать ещё раз - наверное не напишу...  
Спасибо, сейчас буду разбираться. ;)
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
В массив берутся только данные - далее они живут отдельно от листа. Ту книгу можно вообще закрыть.  
Поэтому "красить жирным" нечего - это не set r = range.
 
Привет, Богдан. Для сравнения/сопоставления по списку используют коллекцию (с обработкой ошибок) или словарь.  
 
 http://msdn.microsoft.com/ru-ru/library/yb7y698k%28v=vs.90%29.aspx  
http://msdn.microsoft.com/en-us/library/x4k5wbx4%28v=vs.85%29.aspx  
http://msdn.microsoft.com/en-us/library/aa164502%28v=office.10%29.aspx
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Спасибо
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
Ребят, подскажите, пожалуйста, ещё разок.  
Как с помощью массивов выделить на Листе2 те данные, которых нет на Листе1?  
Опять таки - циклом слишком долго.  
В примере выделил цветом.  
 
Желательно подкорректировать код:  
   Dim a, i&, lr&  
   a = Sheets(2).Range("a2:a" & Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row)  
   With CreateObject("scripting.dictionary")  
       For i = 1 To UBound(a)  
           If Not .exists(a(i, 1)) Then .Item(a(i, 1)) = a(i, 1)  
       Next  
       For i = 1 To Sheets(1).[e1].End(xlDown).Row
           If .exists(Sheets(1).Cells(i, 5).Value) Then Sheets(1).Cells(i, 5).Font.Bold = True  
       Next  
   End With
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
примерно так... вроде...  
Sub www()  
Dim tm!: tm = Timer  
   Dim a, i&, lr&, s&  
   a = Sheets(1).Range("e1:e" & Sheets(1).Cells(Rows.Count, 5).End(xlUp).Row)  
   With CreateObject("scripting.dictionary")  
       For i = 1 To UBound(a)  
           If Not .exists(a(i, 1)) Then .Item(a(i, 1)) = a(i, 1)  
       Next  
         
       For i = 1 To Sheets(2).[a1].End(xlDown).Row
           If .exists(Sheets(2).Cells(i, 1).Value) = False Then Sheets(2).Cells(i, 1).Font.Bold = True  
       Next  
         
   End With  
       Debug.Print Format((Timer - tm) / 24 / 60 / 60, "nn:ss") & "  мин:сек"  
End Sub
Excel 2007
 
Спасибо, а у меня чет не выходило
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
и ещё разок подскажите, пожалуйста, по массивам :)  
нужно перенести найденные по условию значения на другой лист в соответствующие колонки.  
сделал циклом, но опять таки - очень долго на большом кол-ве строк :(  
пример прилагаю.  
заранее спасибо!
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
Можно изначально загнать содержимое этого друго листа в массив. И в ходе сравнения менять содержимое этого массива. Потом все оптом (весь полученный массив) выгрузить на лист.  
 
Пример коад выгрузки массива:  
With Sheets("ToAdm.")  
.Range("K1").Resize(UBound(main, 1), UBound(main, 2)) = main  
End With
 
\делал на скорую руку, мог чего-то не учесть)  
 
Sub compDict()  
   Dim Dictionary As Object, arr(), key As String, j As Long, i As Long  
     
   Set Dictionary = CreateObject("Scripting.Dictionary")  
   arr = Sheets(1).Range("A1").CurrentRegion.Value  
     
   For i = 1 To UBound(arr, 1)  
       key = arr(i, 1) & arr(i, 2)  
       Dictionary.Item(key) = Dictionary.Item(key) + arr(i, 3)  
   Next  
     
   With Sheets(2).Range("A1").CurrentRegion  
       arr = .Value  
       For j = 2 To UBound(arr, 1)  
           For i = 2 To UBound(arr, 2)  
               key = arr(j, 1) & arr(1, i)  
               arr(j, i) = Dictionary.Item(key)  
           Next  
       Next  
       .Value = arr  
   End With  
End Sub
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Спасибо, Саш. Но это не совсем то, что надо.  
Посмотри, пожалуйста, на результат цикла и на свой.  
у тебя суммирует, а мне нужно просто первое значение  
-50050-
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
замени эту строчку  
Dictionary.Item(key) = Dictionary.Item(key) + arr(i, 3)  
на эту  
If Not Dictionary.Exists(key) Then Dictionary.Add key, arr(i, 3)
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Немного другой код (см файл), интересно узнать какой быстрее на больших объемах ?  
Если не трудно, сравните.  
 
-= 62226 =- БИНГО !
Редко но метко ...
 
Спасибо, всё супер ;)
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
{quote}{login=LightZ}{date=28.03.2012 08:43}{thema=}{post}мне нужно просто первое значение  
-50050-{/post}{/quote}  
Так и не понял, какое отношение это имеет к полученному результату в твоем случае и случае Антона.  
 
Чтобы мой код заработал также, замени  
Dictionary.Item(key) = Dictionary.Item(key) + arr(i, 3)  
на  
If Dictionary.Exists(key) Then Dictionary.Remove (key)  
Dictionary.Add key, arr(i, 3)
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Саш, я воспользовался твоим кодом :), только чуток подкорректировал под свои нужды  
GIG_ant, Вам тоже спасибо!  
 
Set Dictionary = CreateObject("Scripting.Dictionary")  
   arr = Sheets(1).Range("A1:C" & lLastrow1).Value  
 
   For i = 1 To UBound(arr, 1)  
       key = arr(i, 1) & arr(i, 2)  
       If Not Dictionary.Exists(key) Then Dictionary.Add key, arr(i, 3)  
   Next  
   With Sheets(2).Range("A1:C" & lLastrow2)  
       arr = .Value  
       For j = 2 To UBound(arr, 1)  
           For i = 2 To UBound(arr, 2)  
               key = arr(j, 1) & arr(1, i)  
               arr(j, i) = Dictionary.Item(key)  
           Next  
       Next  
       .Value = arr  
   End With
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
Ещё вопрос - какой максимальный объём обрабатываемых данных с помощью словаря?  
при расчете на более 5к строк - выдает ошибку, но после добавления on error resume next - вроде всё считает правильно, где подвох? :)
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
Богдан, полный код давай. Мож ты там че наколбасил)
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук


https://github.com/nervgh
 
Sub GoYa()  
On Error Resume Next  
Application.ScreenUpdating = False  
   Dim lLastrow1 As Long  
   Dim lLastrow2 As Long  
   Dim Dictionary As Object, arr(), key As String, j As Long, i As Long  
   Dim MyArr()  
   Dim li As Long  
     
   Sheets(2).Cells.ClearContents  
   MyArr = Array("Данные", "google", "yandex", "Данные", "google", "yandex")  
   Sheets(2).[a1:f1] = MyArr
     
 
   Sheets(1).Range("A2:A" & Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).Copy  
   Sheets(2).[a2].PasteSpecial xlPasteValues
   Sheets(1).Range("E2:E" & Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).Copy  
   Sheets(2).Range("A" & Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row + 1).PasteSpecial xlPasteValues  
   Application.CutCopyMode = False  
   Sheets(2).Range("A1:A" & Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row).RemoveDuplicates Columns:=1, Header:=xlNo  
       For li = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1  
           If Sheets(2).Range("A" & li).Value = "" Then: Sheets(2).Range("A" & li).Delete (3)  
       Next  
   Sheets(2).Range("A2:A" & Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row).Copy Sheets(2).[d2]
 
   lLastrow1 = Sheets(1).Cells(Rows.Count, 1).End(xlUp).Row  
   lLastrow2 = Sheets(2).Cells(Rows.Count, 1).End(xlUp).Row  
 
 
   Set Dictionary = CreateObject("Scripting.Dictionary")  
   arr = Sheets(1).Range("A1:C" & lLastrow1).Value  
 
   For i = 1 To UBound(arr, 1)  
       key = arr(i, 1) & arr(i, 2)  
       If Not Dictionary.Exists(key) Then Dictionary.Add key, arr(i, 3)  
   Next  
 
   With Sheets(2).Range("A1:C" & lLastrow2)  
       arr = .Value  
       For j = 2 To UBound(arr, 1)  
           For i = 2 To UBound(arr, 2)  
               key = arr(j, 1) & arr(1, i)  
               arr(j, i) = Dictionary.Item(key)  
           Next  
       Next  
       .Value = arr  
   End With  
 
   Set Dictionary = CreateObject("Scripting.Dictionary")  
   arr = Sheets(1).Range("E1:G" & lLastrow1).Value  
 
   For i = 1 To UBound(arr, 1)  
       key = arr(i, 1) & arr(i, 2)  
       If Not Dictionary.Exists(key) Then Dictionary.Add key, arr(i, 3)  
   Next  
 
   With Sheets(2).Range("D1:F" & lLastrow2)  
       arr = .Value  
       For j = 2 To UBound(arr, 1)  
           For i = 2 To UBound(arr, 2)  
               key = arr(j, 1) & arr(1, i)  
               arr(j, i) = Dictionary.Item(key)  
           Next  
       Next  
       .Value = arr  
   End With  
Sheets(2).Select  
[a1].Select
Application.ScreenUpdating = True  
End Sub
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
 
Всё, сорри, Саш отбой, подправил чуть - вроде бы всё уже норм.  
За не совсем корректный код - не ругай, писал на быструю руку :)  
Спасибо :)
Киса, я хочу Вас спросить, как художник — художника: Вы рисовать умеете?
Страницы: 1
Наверх