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

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

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

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 27.10.2010, 11:17   #1
sn00p
Пользователь
 
Регистрация: 27.09.2010
Сообщений: 40
По умолчанию vplookup или find ??

всем дня доброго!
задача тривиальная - есть 2 таблици, на 2х листах.
в обеих есть т.н. ключевое поле - артикул. необходимо в 1й таблице подставить значения цены и кол-ва из второй таблицы соответственно артикулу.
как решаю?
у меня 2 варианта
работаем через find или через vplookup

Код:
'для кол-ва
For i = 1 To UBound(sekkk, 1)
    With Worksheets("ñëè÷èòåëüíàÿ").Range("b1:b" & nLastrow2)
        .Find(What:=sekkk(i, 2)).Activate
    End With
    ActiveSheet.Range("f" & Selection.Row) = sekkk(i, 3)
Next

nLastrow = iHowStr("öåíûSAP")

sekkk2 = ActiveWorkbook.Worksheets("öåíûSAP").Range("b7:d" & nLastrow)
'для цен
For i = 1 To UBound(sekkk2, 1)
    With Worksheets("ñëè÷èòåëüíàÿ").Range("b1:b" & nLastrow2)
        .Find(What:=sekkk2(i, 1)).Activate
    End With
    ActiveSheet.Range("e" & Selection.Row) = sekkk2(i, 3)
Next
и
Код:
For i = 2 To UBound(sekkk2, 1)
    nRowNum = nRowNum + 1
    mmmmm = sekkk2(i, 2)
    sekkk2(i, 2) = Application.IfError(Application.VLookup(mmmmm, sekkk, 2, False), 0)
    'ActiveSheet.Range("f" & i) = Application.IfError(zzzzz, 0)
 DoEvents

Next

ActiveWorkbook.Worksheets("ñëè÷èòåëüíàÿ").Range("a1").Resize(nRowNum, UBound(sekkk2, 2)).Value = sekkk2
1я версия работает боле менее сносно, если учесть, что в одной таблице 17к строк в другой 12 - она ее крутит 2+1\2 минуты, но постоянно с функцией find лезут грабли, типа валится вот такая ошибка
Object variable or With block variable not set
но по коду нет ни того ни другого, да и ошибка какая то фантомная, причем возникает всегда во втором блоке, который делает замену по ценам, хотя они идентичны! научите юзать find!! пожалуйста!

2я версия, где vplookup в полный рост - вообзе никогда не заканчивается, вернее ждал 5 минут и бросал это дело!))
товарищи - научите уму разуму)
sn00p вне форума Ответить с цитированием
Старый 27.10.2010, 11:25   #2
IgorGO
Новичок
СтарожилДжуниор
 
Аватар для IgorGO
 
Регистрация: 05.02.2008
Сообщений: 9,487
По умолчанию

Вашу же процедуру еще и запускать надо время от времени, надо еще решить когда..., а просто формулу написать в две колонки? ВПР(...
и данные постоянно актуальны, и не исключаю, что будет быстрее работать.
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете
IgorGO вне форума Ответить с цитированием
Старый 27.10.2010, 11:34   #3
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

Если в данных нет формул (ибо они затрутся) я бы сделал на массивах:
(в детали не вник, поэтому мысль в общем)
1. берём оба диапазона в массивы
2. циклом перебираем оба, заменяем в одном или обоих значения
3. выгружаем данные назад

17*12к обработает за пару секунд.
А с Find надо предусмотреть, что делать, если не нашлось. И никаких Activate - это только тормозит.
В общем, я бы сделал на массивах, или переписал заново с Find, если в той области есть формулы.
webmoney: E265281470651 Z422237915069 R418926282008
Hugo121 вне форума Ответить с цитированием
Старый 27.10.2010, 11:40   #4
sn00p
Пользователь
 
Регистрация: 27.09.2010
Сообщений: 40
По умолчанию

Цитата:
Сообщение от IgorGO Посмотреть сообщение
Вашу же процедуру еще и запускать надо время от времени, надо еще решить когда..., а просто формулу написать в две колонки? ВПР(...
и данные постоянно актуальны, и не исключаю, что будет быстрее работать.
это самы простой вариант, а что будет при открытии файла? он будете пересчитываться)

с массивами дела, как то очень долгло.
а без Activate - вернет позицию найденного?строку.?
sn00p вне форума Ответить с цитированием
Старый 27.10.2010, 11:50   #5
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

VBA массивы - это очень быстро. Быстрее, чем ADO...
Пример по поиску:
Код:
Set Found = Cells.Find("вот_такой_текст", lookAt:=xlWhole) 
If Not TypeName(Found) = "Nothing" Then ' Можно заменить конструкцией If Not Found Is Nothing Then 
     ' Точка входа найдена, удаляем 
     Rows(Found.Row & ":" & Cells.SpecialCells(xlLastCell).Row).Delete 
End If
Можно использовать Found.Row, Found.Column, Found.Address
Вместо Found можно использовать любую переменную, тип Range.
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 27.10.2010 в 11:54.
Hugo121 вне форума Ответить с цитированием
Старый 27.10.2010, 12:15   #6
EugeneS
Форумчанин
 
Регистрация: 06.08.2009
Сообщений: 472
По умолчанию

Цитата:
Сообщение от sn00p Посмотреть сообщение
всем дня доброго!
задача тривиальная - есть 2 таблици, на 2х листах.
в обеих есть т.н. ключевое поле - артикул. необходимо в 1й таблице подставить значения цены и кол-ва из второй таблицы соответственно артикулу.
Подобная задача может быть решена с помощью библиотеки ADO, см. вложение. Скорость обработки практически не зависит от объема данных. Предварительно необходимо подключить данну библиотеку: Сервис - Редактор Visual Basic - Tools - References - установите птичку напротив Microsoft ActiveX Data Objects 2.0 Library - OK. Нажмите "Выполнить". Результат: Лист3
Вложения
Тип файла: zip Прайс.zip (10.7 Кб, 14 просмотров)

Последний раз редактировалось EugeneS; 27.10.2010 в 12:21.
EugeneS вне форума Ответить с цитированием
Старый 27.10.2010, 12:33   #7
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

И тот же результат на массивах:
Код:
Sub PriceArr()
Dim a(), b()
Dim i As Long, ii As Long

a = Sheets(1).Range("a2:c" & Sheets(1).Range("A" & Rows.Count).End(xlUp).Row).Value
b = Sheets(2).Range("a2:c" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value

For i = 1 To UBound(a)
For ii = 1 To UBound(b)
If b(ii, 1) = a(i, 1) Then b(ii, 2) = a(i, 2): b(ii, 3) = a(i, 3): Exit For
Next ii, i
Sheets(2).Range("a2:c" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value = b
End Sub
Если сделать данных тысяч на 20, то можно и скорость померить.

P.S.Померил -в 3 раза массивы медленнее на таком переборе оказались...
Даже на чуть более быстром коде:
Код:
Sub PriceArr()
Dim tm
tm = Timer
Dim a(), b(), c()
Dim i As Long, ii As Long

a = Sheets(1).Range("a2:c" & Sheets(1).Range("A" & Rows.Count).End(xlUp).Row).Value
b = Sheets(2).Range("a2:a" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value
ReDim c(1 To UBound(b), 1 To 2)
For i = 1 To UBound(a)
For ii = 1 To UBound(b)
If b(ii, 1) = a(i, 1) Then c(ii, 1) = a(i, 2): c(ii, 2) = a(i, 3): Exit For
Next ii, i
Sheets(2).Range("b2:c" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value = c
Debug.Print Timer - tm
End Sub
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 27.10.2010 в 12:47.
Hugo121 вне форума Ответить с цитированием
Старый 27.10.2010, 12:47   #8
sn00p
Пользователь
 
Регистрация: 27.09.2010
Сообщений: 40
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
И никаких Activate - это только тормозит.
Worksheets("ñëè÷èòåëüíàÿ").Range("b 1:b" & nLastrow2).Find(What:=sekkk(i, 2))

вызывает ошибку:
compile error :
excepted :=
sn00p вне форума Ответить с цитированием
Старый 27.10.2010, 12:48   #9
Hugo121
Старожил
 
Регистрация: 11.05.2010
Сообщений: 5,170
По умолчанию

set x = Worksheets("ñëè÷èòåëüíàÿ").Range("b 1:b" & nLastrow2).Find(What:=sekkk(i, 2))

попробуйте так.
Опробовал, работает:
Код:
Sub rr()
Dim sekkk(1 To 2, 1 To 2)
Dim i
i = 1
sekkk(i, 2) = "tt"
nLastrow2 = 10
Set x = Worksheets("Лист2").Range("b1:b" & nLastrow2).Find(What:=sekkk(i, 2))
If Not x Is Nothing Then MsgBox x.Row Else MsgBox "Not Find!"
End Sub
webmoney: E265281470651 Z422237915069 R418926282008

Последний раз редактировалось Hugo121; 27.10.2010 в 12:55.
Hugo121 вне форума Ответить с цитированием
Старый 27.10.2010, 12:57   #10
sn00p
Пользователь
 
Регистрация: 27.09.2010
Сообщений: 40
По умолчанию

Цитата:
Сообщение от Hugo121 Посмотреть сообщение
И тот же результат на массивах:
Код:
Sub PriceArr()
Dim a(), b()
Dim i As Long, ii As Long

a = Sheets(1).Range("a2:c" & Sheets(1).Range("A" & Rows.Count).End(xlUp).Row).Value
b = Sheets(2).Range("a2:c" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value

For i = 1 To UBound(a)
For ii = 1 To UBound(b)
If b(ii, 1) = a(i, 1) Then b(ii, 2) = a(i, 2): b(ii, 3) = a(i, 3): Exit For
Next ii, i
Sheets(2).Range("a2:c" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value = b
End Sub
Если сделать данных тысяч на 20, то можно и скорость померить.

P.S.Померил -в 3 раза массивы медленнее на таком переборе оказались...
Даже на чуть более быстром коде:
Код:
Sub PriceArr()
Dim tm
tm = Timer
Dim a(), b(), c()
Dim i As Long, ii As Long

a = Sheets(1).Range("a2:c" & Sheets(1).Range("A" & Rows.Count).End(xlUp).Row).Value
b = Sheets(2).Range("a2:a" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value
ReDim c(1 To UBound(b), 1 To 2)
For i = 1 To UBound(a)
For ii = 1 To UBound(b)
If b(ii, 1) = a(i, 1) Then c(ii, 1) = a(i, 2): c(ii, 2) = a(i, 3): Exit For
Next ii, i
Sheets(2).Range("b2:c" & Sheets(2).Range("A" & Rows.Count).End(xlUp).Row).Value = c
Debug.Print Timer - tm
End Sub
попробую вариант с перебором простым
sn00p вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Cant Find mistake dikabraz Паскаль, Turbo Pascal, PascalABC.NET 10 19.10.2010 20:17
метод find kate158 Общие вопросы Delphi 4 15.12.2009 16:09
Find WebBrowser Edward Работа с сетью в Delphi 2 04.09.2009 20:03
Макрос, расширяющий функцию Find neugadal Microsoft Office Word 5 29.09.2008 08:32