Доброго вечера, Планетяне! Я часто пользуюсь ИНДЕКС+ПОИСКПОЗ со вложенными проверками, но вот вводить её очень запарно каждый раз. На хабре нашёл способ, как сочинять UDF на основании штатных формул листа (кстати, там очень крутые ссылки на всякие интересности есть)
А интересно следующее: 1. Есть функция (со вложенными или без), в которой некоторые ссылки на ячейки/диапазоны повторяются 2. Как быстро ввести такую функцию, имея её "тело" в макросе и ЕДИНОЖДЫ задав все переменные?
Макрос из файла-примера:
Код
Option Explicit
Sub FastEnter()
'Для данного примера:
'ActiveCell = "B2"
'откуда_берём = справочник[ПОДТЯНУТЬ отсюда]
'где_ищем , справочник[ГДЕ искать]
'что_ищем, = [@[ЧТО искать]]
Dim откуда_берём As Range, где_ищем As Range, что_ищем As Range
Set откуда_берём = Application.InputBox("Откуда ВСТАВЛЯЕМ?", "Выделите ДИАПАЗОН", , Type:=8)
Set где_ищем = Application.InputBox("Где ИЩЕМ?", "Выделите ДИАПАЗОН", , Type:=8)
Set что_ищем = Application.InputBox("Что ИЩЕМ?", "Выделите ЯЧЕЙКУ", , Type:=8)
'Ввести КОНКРЕТНУЮ формулу:
'ActiveCell.FormulaLocal = "=ЕСЛИОШИБКА(ЕСЛИ(ИЛИ([@[ЧТО искать]]=""""; _ — так я просто вставлю конкретную формулу
'ИНДЕКС(справочник[ПОДТЯНУТЬ отсюда];ПОИСКПОЗ([@[ЧТО искать]];справочник[ГДЕ искать];0))=0);""""; _
'ИНДЕКС(справочник[ПОДТЯНУТЬ отсюда];ПОИСКПОЗ([@[ЧТО искать]];справочник[ГДЕ искать];0)));"""")"
'Ввести формулу С ПЕРЕМЕННЫМИ (что-то вроде):
'ActiveCell.FormulaLocal = "=ЕСЛИОШИБКА(ЕСЛИ(ИЛИ(что_ищем=""""; _
'ИНДЕКС(откуда_берём;ПОИСКПОЗ(что_ищем;где_ищем;0))=0);""""; _
'ИНДЕКС(откуда_берём;ПОИСКПОЗ(что_ищем;где_ищем;0)));"""")"
End Sub
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Тут немного другое надо учесть, какой диапазон: статический, динамический. То же самое поисковый критерий. Плюс точный или нет поиск. Так то придумать несложно, но всё равно надо будет либо ручками дописывать и убирать доллары, или вводить в функцию новые переменные которые будут описывать эти состояния.
Мастерство программиста не в том, чтобы писать программы, работающие без ошибок. А в том, чтобы писать программы, работающие при любом количестве ошибок.
Alemox, а если используется ТОЛЬКО в "умных" таблицах, совпадение всегда точное и диапазоны будут указываться корректно (выделением поля целиком в умной таблице)? Иными словами, формула после ввода макросом визуально не должна отличаться от того, если бы руками как обычно вводил. AddressLocal тут не помощник, как я понял(( Кстати! У Николая Павлова в PLEX'е есть что-то подобное. Можно добавить в библиотеку свою формулу и заменить ссылки на ячейки переменными (выглядеть, конечно, будет не так, как руками, но тоже вариант). Может это как-то поможет найти решение? Код из PLEX'а видел, но там формы друг на друга ссылаются и я ничего не понял(((
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Доброго вечера! Сочинил UDF на основе штатных функций Excel (для сохранения производительности), но она не работает. Подскажите, как её исправить, чтобы она заработала и можно ли "ускорить" подобную функцию, с учётом всех проверок?
UDF
Код
Function ПодтянутьСПроверками(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
ПодтянутьСПроверками = Application.WorksheetFunction.IfError( _
Application.WorksheetFunction.IF(Application.WorksheetFunction.Or(что_ищем = "", _
Application.WorksheetFunction.Index(откуда_берём, Application.WorksheetFunction.Match(что_ищем, где_ищем, 0)) = 0), "", _
Application.WorksheetFunction.Index(откуда_берём, Application.WorksheetFunction.Match(что_ищем, где_ищем, 0))) _
, "")
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Function BPR3(What As Range, Where As Range) As Range
If WorksheetFunction.CountIf(Where.Columns(1), What) = 0 Then Exit Function
Set BPR3 = Where.Columns(1).Find(What, Where.Cells(1), xlValues, xlWhole).Offset(0, 1)
End Function
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
Ігор Гончаренко, Игорь, спасибо большое))) суть понял - допилю сам)) то есть подтягивать через поиск и смещение быстрее, чем прямой ИНДЕКС+ПОИСКПОЗ?
ps: всё-таки непонятно, почему на формулах листа не сработало…
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Доброго дня! Подскажите, что не так с этим кодом? Хочу сделать UDF целиком на функциях рабочего листа.
Код
Function ПодтянутьСПроверками(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
ПодтянутьСПроверками = WorksheetFunction.IfError(WorksheetFunction.IF(Application.WorksheetFunction.Or(что_ищем = "", _
WorksheetFunction.Index(откуда_берём, WorksheetFunction.Match(что_ищем, где_ищем, 0)) = 0), "", _
WorksheetFunction.Index(откуда_берём, WorksheetFunction.Match(что_ищем, где_ищем, 0))), "")
End Function
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
А где Вы в WorksheetFunction нашли функцию If ? Используйте IIf ,но это не функция листа
Код
Function ПодтянутьСПроверками(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
With Application.WorksheetFunction
ПодтянутьСПроверками = .IfError(IIf(.Or(что_ищем = "", _
.Index(откуда_берём, .Match(что_ищем, где_ищем, 0)) = 0), "", _
.Index(откуда_берём, .Match(что_ищем, где_ищем, 0))), "")
End With
End Function
Sanja, большое вам спасибо! Сейчас ещё одну проверку добавлю (ЕСЛИОШИБКА не срабатывает. При отсутствии "что_ищем" в "где ищем" выводит #ЗНАЧ) и выложу все варианты)) подскажите, пожалуйста, как сделать проверку быстродействия UDF'ок в макросе? Ну, чтобы не строить огромные таблицы, а счётчик, цикл и время.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Sanja, доброго времени, крутая искалка. Подскажите, а можно ли ее наворотить чтоб она подтягивала например если два и более значения ну типа массив индекс поискпоз мин. Спасибо
Вот все варианты. Мне больше всего подошёл вариант через Find и Offset, который Игорь предложил. Думаю, что и по скорости должен быть быстрее. Sanja, вам большое спасибо за помощь и объяснения! Alemox, благодарю за участие. Любые подсказки по улучшению быстродействия и прочего только приветствуются! В файле сравнительная таблица. Чётко обходить ошибки в 2х вариантах так и не смог (ни ПОИСКПОЗ не проверить, ни ЕСЛИОШИБКА)
UDF
Код
Option Explicit
'ПодтянутьСПроверками (аналог ИНДЕКС+ПОИСКПОЗ с проверками)
'Автор: askv
'Экспериментировал с чужим кодом: Jack Famous
'Статья на хабре: (https://habrahabr.ru/post/314302/)
'Тема на форуме: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=96146&TITLE_SEO=96146-bystryy-vvod-dlinnykh-shtatnykh-funktsiy-excel
'===================================================================================================================================================================================================
Function ПодтянутьСПроверками_ИНДЕКС(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
Dim x As Range
Dim n&
n = WorksheetFunction.Match(что_ищем, где_ищем, 0)
If Application.IsNA(n) = True Then ПодтянутьСПроверками_ИНДЕКС = ""
ПодтянутьСПроверками_ИНДЕКС = откуда_берём(n).Value
If ПодтянутьСПроверками_ИНДЕКС = 0 Or VarType(ПодтянутьСПроверками_ИНДЕКС) = xlErrValue Then ПодтянутьСПроверками_ИНДЕКС = ""
End Function
'ПодтянутьСПроверками (аналог ИНДЕКС+ПОИСКПОЗ с проверками)
'Автор: Ігор Гончаренко
'Экспериментировал с чужим кодом: Jack Famous
'Тема на форуме: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=96146&TITLE_SEO=96146-bystryy-vvod-dlinnykh-shtatnykh-funktsiy-excel
'===================================================================================================================================================================================================
Function ПодтянутьСПроверками_ПОИСК(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
Dim x As Range
Dim ofs&
Set x = где_ищем.Find(что_ищем, где_ищем.Cells(1), xlValues, xlWhole)
ofs = откуда_берём.Column - где_ищем.Column
If WorksheetFunction.CountIf(где_ищем, что_ищем) = 0 Then
ПодтянутьСПроверками_ПОИСК = ""
Exit Function
End If
ПодтянутьСПроверками_ПОИСК = x.Offset(0, ofs).Value
If ПодтянутьСПроверками_ПОИСК = 0 Then ПодтянутьСПроверками_ПОИСК = ""
End Function
'ПодтянутьСПроверками (аналог ИНДЕКС+ПОИСКПОЗ с проверками)
'Автор: Sanja
'Тема на форуме: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=96146&TITLE_SEO=96146-bystryy-vvod-dlinnykh-shtatnykh-funktsiy-excel
'===================================================================================================================================================================================================
Function ПодтянутьСПроверками_КЛАССИКА(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
With Application.WorksheetFunction
ПодтянутьСПроверками_КЛАССИКА = .IfError(IIf(.Or(что_ищем = "", _
.index(откуда_берём, .Match(что_ищем, где_ищем, 0)) = 0), "", _
.index(откуда_берём, .Match(что_ищем, где_ищем, 0))), "")
End With
End Function
P.S.: alex1210, создавайте отдельную тему. Ваш вопрос за рамками обсуждения
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Всё-таки добил)) итак, осталось 2 UDF'ки: на Match (по мотивам хабра) и на Find (по совету Ігоря Гончаренко). Различаются они в том, что Match по результату работы абсолютно подобна (во всяком случае, не нашёл различий) связке функций, как в условии темы, в то время как Find числа-как-текст в "что_ищем" воспринимает, как обычные числа. По-моему, обе эти функции могут быть полезны, в зависимости от задачи. В файле всё хорошо видно.
UDF'ки
Код
Option Explicit
'ПодтянутьСПроверками (аналог ИНДЕКС+ПОИСКПОЗ с проверками)
'Нюансы: числа-как-текст воспринимает "как есть" (как текст)
'Автор: askv
'Экспериментировал с чужим кодом: Jack Famous
'Статья на хабре: (https://habrahabr.ru/post/314302/)
'Тема на форуме: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=96146&TITLE_SEO=96146-bystryy-vvod-dlinnykh-shtatnykh-funktsiy-excel
'===================================================================================================================================================================================================
Function ПодтянутьСПроверками_ИНДЕКС(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
Dim n&
On Error GoTo ends
n = Application.WorksheetFunction.Match(что_ищем, где_ищем, 0)
On Error GoTo 0
ПодтянутьСПроверками_ИНДЕКС = откуда_берём(n).Value
If ПодтянутьСПроверками_ИНДЕКС = 0 Then
GoTo ends:
End If
GoTo fin:
ends:
ПодтянутьСПроверками_ИНДЕКС = ""
On Error GoTo 0
Exit Function
fin:
On Error GoTo 0
End Function
'ПодтянутьСПроверками (аналог ИНДЕКС+ПОИСКПОЗ с проверками)
'Нюансы: числа-как-текст считает числами
'Автор: Ігор Гончаренко
'Экспериментировал с чужим кодом: Jack Famous
'Тема на форуме: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=96146&TITLE_SEO=96146-bystryy-vvod-dlinnykh-shtatnykh-funktsiy-excel
'===================================================================================================================================================================================================
Function ПодтянутьСПроверками_ПОИСК(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_берём As Range) As Variant
Dim fr&, ofs&
On Error Resume Next
fr = где_ищем.Find(что_ищем, где_ищем.Cells(1), xlValues, xlWhole).Row - 1
ofs = откуда_берём.Column - где_ищем.Column
On Error GoTo 0
If Application.WorksheetFunction.CountIf(где_ищем, что_ищем) = 0 Then
ПодтянутьСПроверками_ПОИСК = ""
Exit Function
End If
ПодтянутьСПроверками_ПОИСК = откуда_берём(fr).Value
If ПодтянутьСПроверками_ПОИСК = 0 Then
ПодтянутьСПроверками_ПОИСК = ""
End If
End Function
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
'СуммЕслиСПроверками
'Нюансы: если при сумме получается 0, то вернёт пустую ячейку
'Автор: Jack Famous
'Тема на форуме: http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=read&FID=1&TID=96146&TITLE_SEO=96146-bystryy-vvod-dlinnykh-shtatnykh-funktsiy-excel
'===================================================================================================================================================================================================
Option Explicit
Function СуммЕслиСПроверками(что_ищем As Variant, ByRef где_ищем As Range, ByRef откуда_суммируем As Range) As Variant
On Error GoTo ends
' If что_ищем = "" Then
' GoTo ends:
' End If
СуммЕслиСПроверками = Application.WorksheetFunction.SumIf(где_ищем, что_ищем, откуда_суммируем)
If СуммЕслиСПроверками = 0 Then
GoTo ends:
End If
GoTo fin:
ends:
СуммЕслиСПроверками = ""
On Error GoTo 0
Exit Function
fin:
On Error GoTo 0
End Function
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄