Поиск по нескольким условиям excel vba

 

VIZ_VIZ

Пользователь

Сообщений: 106
Регистрация: 20.07.2017

#1

28.10.2019 09:21:11

Коллеги, в VBA не силен, поэтому идея с Find может быть глупой… Find привлек значительно более высокими скоростями поиска по сравнению с другими методами (например, с поиском в цикле, используя If).
Задача: имеем таблицу, в которой первый и второй столбец содержат уникальный цифровой ключ клиента (ключ состоит из двух частей), необходимо выбрать определенного клиента. Необходимо иметь в виду, что «половинки» ключа не уникальны — могут быть одинаковыми у разных клиентов — то есть нужно искать клиента именно по полному ключу). Если такая возможность для Find существует, то прошу поделиться примером кода.
Для наглядности предлагаю считать, что две переменные (половинки) ключа нам известны:  Nm — код №1, а Nkl — код №2.
Если кому-то пригодиться, то вот оригинальный устаревший код, который искал информацию ориентируясь только на половинку кода — именно его я и адаптирую под текущую потребность.

Код
Set old_base_act = old_wb.sheets("База клиентов").Colomns(1).Find(what:=old_wsh.Cells(oCell.Row,2).value, Lookat:=xlWhole, Lookin:=xlFormulas)

Здесь old_wsh.Cells(oCell.Row,2).value — это переменная Nkl, Nm можно найти аналогично
Если Find не умеет искать по двум параметрам, то прошу подсказать другие быстрые методы (про СУММАМН для VBA знаю, именно ее и планирую использовать как запасной вариант, но, думаю, что Find будет быстрее).
Спасибо всем, кто откликнется.

 

БМВ

Модератор

Сообщений: 21385
Регистрация: 28.12.2016

Excel 2013, 2016

#2

28.10.2019 09:29:35

Цитата
VIZ_VIZ написал:
Find привлек значительно более высокими скоростями поиска по сравнению

— это не всегда так
вы не код приводите в примере а что за данные у вас и по какому признаку надо и что найти.
Если искать надо в двух столбцах, то сперва ищется в одном и проверяется выполнения условия во втором, если не выполнилось , повторяется с поиска в первом.

https://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&FID=1&TID=121840&TITLE_SEO=121840-pri-pomoshchi-find-osushchestvit-poisk-po-stseplennym-dvum-stolbtsam&MID=1008529#message1008529

По вопросам из тем форума, личку не читаю.

 

VIZ_VIZ

Пользователь

Сообщений: 106
Регистрация: 20.07.2017

#3

28.10.2019 10:12:08

Цитата
БМВ написал:
сперва ищется в одном и проверяется выполнения условия во втором, если не выполнилось , повторяется с поиска в первом.

Можно чуть подробнее? Как я понимаю, Find найдет несколько совпадений в столбце №1, выберет самую верхнюю строку (первое совпадение), я проверю данные в соседнем столбце, они могут не совпасть с искомыми. Как мне перейти к следующему совпадению?
И я не уверен, что Find умеет искать все совпадения, предполагаю, что данный метод выбирает самое первое совпадение и останавливается — это верно или я не прав?
За пример с циклами спасибо, но нам это не подходит — очень большие таблицы — циклы будут тормозить. Вместо циклов я планирую использовать ЕСЛИМН — думаю, что он будет быстрее, чем циклы. Либо я не разобрался в примере…

 

Пытливый

Пользователь

Сообщений: 4587
Регистрация: 22.12.2012

Метод у диапазона бывает не только Find, но и FindNext. В справке по F1 есть пример использования.

Кому решение нужно — тот пример и рисует.

 

Jack Famous

Пользователь

Сообщений: 10852
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#5

28.10.2019 10:24:07

Цитата
VIZ_VIZ: Find привлек значительно более высокими скоростями поиска по сравнению с другими методами (например, с поиском в цикле, используя If)

это вы ещё про массивы, видимо, не знаете. Обычно Find используется для поиска/замены с учётом формата.

По реализации:

без файла-примера разговор пустой…

Изменено: Jack Famous28.10.2019 10:24:20

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

VIZ_VIZ

Пользователь

Сообщений: 106
Регистрация: 20.07.2017

#6

28.10.2019 11:02:36

Цитата
Пытливый написал:
бывает не только Find, но и FindNext.

понравился пример по F1, но есть один вопрос, может быть подскажете, как с ними поступить?

Код
With Worksheets(1).Range("a1:a500")
     Set c = .Find(2, lookin:=xlValues)
     If Not c Is Nothing Then
        firstAddress = c.Address 'вместо этой строки поставлю проверку по второму столбцу
        Do 'в этот цикл добавлю свой код
            c.Value = 5
            Set c = .FindNext(c)
        If c is Nothing Then
            GoTo DoneFinding
        End If
        Loop While c.Address <> firstAddress
      End If
      DoneFinding:
End With

With Worksheets(1).Range(«a1:a500») — у нас нет конкретных границ таблицы (она постоянно растет), можно изменить код на такой? With Worksheets(1)
Будет макрос работать или нужен другой код?

 

Hellmaster

Пользователь

Сообщений: 208
Регистрация: 26.03.2019

#7

28.10.2019 11:14:13

VIZ_VIZ, задайте переменную последней заполненной строки таблицы и сделайте

Код
With Worksheets(1).Range("a1:a" & lastrow)
 

БМВ

Модератор

Сообщений: 21385
Регистрация: 28.12.2016

Excel 2013, 2016

#8

28.10.2019 11:37:10

Цитата
Hellmaster написал:
задайте переменную последней заполненной строки таблицы и сделайте

не имеет смысла

Код
With Worksheets(1).Range("a:a") 

будет достаточно так как Find сам справится с используемым диапазоном.

По вопросам из тем форума, личку не читаю.

 

VIZ_VIZ

Пользователь

Сообщений: 106
Регистрация: 20.07.2017

#9

28.10.2019 11:44:44

Цитата
Jack Famous написал:
это вы ещё про массивы, видимо, не знаете.

Я вас правильно понял, с массивами VBA работает еще быстрее, чем с Find? Это полезная информация — буду знать. Спасибо!

 

Jack Famous

Пользователь

Сообщений: 10852
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

VIZ_VIZ, а вы файл-пример сделайте — там и сравним. Я Find не использую…

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

Пытливый

Пользователь

Сообщений: 4587
Регистрация: 22.12.2012

#11

28.10.2019 12:04:55

Можно еще вычислить количество строк используемого диапазона. Если у вас таблица на листе начинается с первой строки, то можно вычислить количество используемых строк на листе через UsedRange:

Код
RowNum=Activesheet.UsedRange.Rows.Count

А потом найденное значение задать в диапазоне, в котором применяете Find

Код
Range("A1:A" & RowNum).Find(.....)

Кому решение нужно — тот пример и рисует.

 

VIZ_VIZ

Пользователь

Сообщений: 106
Регистрация: 20.07.2017

Коллеги, спасибо всем, кто откликнулся. Думаю, что смогу допилить макрос на основе ваших подсказок.
Пример файла выложить не могу — под местный ресурс его очень долго обрезать — много весит. Да и интересного там ничего нет — две таблицы на разных страницах. В каждой первый и второй столбец — это составные части уникального номера клиента. Соответственно из первой таблицы макрос узнает номер нужного клиента, а из второй таблицы находит доп. информацию для данного клиента.

 

БМВ

Модератор

Сообщений: 21385
Регистрация: 28.12.2016

Excel 2013, 2016

#13

28.10.2019 12:34:26

Цитата
Jack Famous написал:
Я Find не использую…
Цитата
Jack Famous написал:
Обычно Find используется для поиска/замены с учётом формата.

Алексей, не надо навязывать свои методы, любовь все загрузить в массив — тоже не всегда уместна. А давайте найдем последнюю заполненую ячейку на листе если и срока и столбец интересует.  А если это под миллион строк и несколько десятков столбцов — все в массив и перебор Так только загрузка в массив, займет время, а у некоторых и память может закончится :-).
Так что использовать надо то что нужно, и не использовать то что ненужно.

По вопросам из тем форума, личку не читаю.

 

Jack Famous

Пользователь

Сообщений: 10852
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#14

28.10.2019 12:49:30

Цитата
БМВ: не надо навязывать свои методы

где вы это увидели?

Цитата
БМВ: любовь все загрузить в массив — тоже не всегда уместна

а где я писал, что это всегда уместно?

Цитата
БМВ: давайте найдем последнюю заполненую ячейку на листе если и срока и столбец интересует

давайте

— в чём проблема, собственно и какое отношение имеет к задаче?

Цитата
БМВ: А если это под миллион строк и несколько десятков столбцов

а если нет? Я поэтому про пример и сказал…

Цитата
БМВ: использовать надо то что нужно, и не использовать то что ненужно

очевидная истина, только как определить, что и когда нужно  ;)

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

Юрий М

Модератор

Сообщений: 60586
Регистрация: 14.09.2012

Контакты см. в профиле

#15

28.10.2019 12:58:52

Цитата
Jack Famous написал:
Обычно Find используется для поиска/замены с учётом формата.

Джек,  откуда это? Я про «обычно» ))

 

Jack Famous

Пользователь

Сообщений: 10852
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#16

28.10.2019 13:17:20

Юрий М, хорошо — перефразирую: я считаю, что Find практически незаменим для эффективного поиска (и замены) с учётом формата, т.к. массивы работают только со значениями. Find можно использовать и просто для поиска значений, но при прочих равных, массивы при правильном использовании будут быстрее

Тут очень много может быть «если» и именно поэтому…

Цитата
Jack Famous: По реализации: без файла-примера разговор пустой…

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

Юрий М

Модератор

Сообщений: 60586
Регистрация: 14.09.2012

Контакты см. в профиле

Уже не так категорично, и это хорошо ))

 

Jack Famous

Пользователь

Сообщений: 10852
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

Юрий М, БМВ, прошу прощения, если это выглядело категорично — не вкладывал такой смысл… Разумеется, «методы всякие нужны, методы всякие важны»  :D

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

VIZ_VIZ

Пользователь

Сообщений: 106
Регистрация: 20.07.2017

Jack Famous, Заинтересовали ваши комментарии про массивы. Можете черкнуть пару строк кода под условия, которые я указал в предыдущем комментарии?

 

БМВ

Модератор

Сообщений: 21385
Регистрация: 28.12.2016

Excel 2013, 2016

#20

28.10.2019 13:48:43

Цитата
Jack Famous написал:
просто для поиска значений, но при прочих равных, массивы при правильном использовании будут быстрее

Алексей, не которое время назад занимались замерами и зависимость была такова, что на определенном размере массивы проигрывали и проигрыш был на времени загрузки Arr=Range.
Что касается конкретного вопроса, то простой SQL запрос с проверкой двух ключей, возможно , уделает и find и Arr. Вопрос, только в том, что нужно на выходе получить.

По вопросам из тем форума, личку не читаю.

 

Jack Famous

Пользователь

Сообщений: 10852
Регистрация: 07.11.2014

OS: Win 8.1 Корп. x64 | Excel 2016 x64: | Browser: Chrome

#21

28.10.2019 14:13:12

Цитата
БМВ: Вопрос, только в том, что нужно на выходе получить

ну и что на входе))) и опять всё упирается в необходимость примера…
Самый быстрый (по моим наблюдениям и тестам  :D ) вариант передачи диапазона в массив — это

Код
Dim arr
arr=Range.Value2

— то есть переменная должна быть вариативной и не массивной, и именно Value2 (проигрывает Value только на булевых, но совсем незаметно, зато в других случаях очень хорошо выигрывает), но это уже совершенно другая

тема

Цитата
VIZ_VIZ: Заинтересовали ваши комментарии про массивы

строго говоря, это и под тему не очень попадает, т.к. у вас вопрос конкретно про Find. Если правда интересно, то создайте новую тему с перекрёстными ссылками и сделайте в ней файл-пример — разберём  ;)

Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄

 

Дмитрий(The_Prist) Щербаков

Пользователь

Сообщений: 14182
Регистрация: 15.09.2012

Профессиональная разработка приложений для MS Office

#22

28.10.2019 14:32:21

Немного дегтя в сторону Find: у него проблема при поиске данных из VBA, если применен фильтр или строки/столбцы скрыты.
А в остальном: не всегда Find предпочтительнее, но и массивы далеко не всегда выигрывают. При поиске в больших текстовых массивах Find будет в подавляющем большинстве случаев быстрее. Но все как всегда зависит от многих факторов.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

@JMB17 

Unfortunately, I’m working on two computers. I cannot see the attached file because this computer does not have a full suite of Excel and the other is restricted for downloads.

Below is the VBA code I’m using and working perfectly. So instead of section CommandBox1 having only one search criteria, I want to have two and the ability to list up to ten orders (TextBox 2, 3, etc) that meet that criteria. Then when I add a date in TextBox14 and click the update button, those orders are updated.

Private Sub CommandButton1_Click()

Dim Current_Status As String

Currrent_Status=Trim(TextBox1.Text)

lastrow=Worksheets(«Overall»).Cells(Rows.Count, 1).End(x1Up).Row

For i =2 To lastrow

If Worksheets(«Overall»).Cells(i, 1).Value=Current_Status Then

TextBox2.Text=Worksheets(«Overall»).Cells(i, 3).Value

TextBox14.Text=Worksheets(«Overall»).Cells(i, 11).Value

End If

Next

End Sub

————————————————————

Private Sub CommandButton2_Click()

Dim Current_Status As String

Currrent_Status=Trim(TextBox1.Text)

lastrow=Worksheets(«Overall»).Cells(Rows.Count, 1).End(x1Up).Row

For i =2 To lastrow

If Worksheets(«Overall»).Cells(i, 1).Value=Current_Status Then

Worksheets(«Overall»).Cells(i, 3).Value=TextBox2.Text

Worksheets(«Overall»).Cells(i, 11).Value=TextBox14.Text

End If

Next

End Sub

Sorry for the long post but I hope it provides clarity to what I want to do.

Thank you,

Roy

Поиск в столбце по нескольким условиям

Гордей

Дата: Вторник, 19.02.2019, 22:21 |
Сообщение № 1

Группа: Пользователи

Ранг: Новичок

Сообщений: 32


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Приветствую!

Помогите пожалуйста доделать макросы, чтобы из двух сделать один. Суть такова — есть данные (диапазон C1:C3000), по которым макрос производит поиск (а-ля Ctrl-f) и находит каждое заданное в макросе совпадение после текущей ячейки и останавливается на найденной, выделяя её, затем при новом выполнении макроса следующую найденную ячейку. На данный момент это всё работает, но с помощью двух макросов, а надо бы вообще 3 слова для совпадения. Так как Find не позволяет делать OR, чтобы задать не одно, а несколько искомых слов, и поиск возможных готовых решений в Интернете приводит к очень сложным примерам, то прошу помочь в создании такого макроса вас, уважаемые Гуру VBA.

Цель — один макрос, который в заданном диапазоне построчно просматривает на наличие трёх вариантов, и останавливается на первом из найденных. При следующем запуске макроса он ищет дальше.
В прикреплённом файле упростил до 111,222 и тд

К сообщению приложен файл:

Macro.xlsb
(28.2 Kb)

 

Ответить

_Boroda_

Дата: Среда, 20.02.2019, 16:00 |
Сообщение № 2

Группа: Модераторы

Ранг: Местный житель

Сообщений: 16618


Репутация:

6465

±

Замечаний:
0% ±


2003; 2007; 2010; 2013 RUS

Такой вариант
[vba]

Код

Sub PoiskNesk()
n_ = 3
ReDim ar(1 To n_)
ar(1) = 222
ar(2) = 333
ar(3) = 444
z_ = 9999999
r1_ = z_
r2_ = z_
c0_ = «C»
r00_ = 12
rr_ = Cells(Rows.Count, c0_).End(3).Row
r0_ = ActiveCell.Row
If r0_ > rr_ Then
r0_ = rr_
End If
On Error Resume Next
For i = 1 To n_
r_ = Cells(r00_, c0_).Resize(rr_ — r00_ + 1).Find(What:=ar(i), After:=Cells(r0_, c0_), LookIn:=xlValues).Row
If r_ < r0_ Then
If r_ < r1_ Then
r1_ = r_
End If
Else
If r_ < r2_ Then
r2_ = r_
End If
End If
Next i
If r2_ <> z_ Then
r1_ = r2_
End If
Cells(r1_, c0_).Activate
End Sub

[/vba]
Можно пойти дальше и искомые значения писать не в коде макроса, а прямо на кнопке, потом макросом оттуда считывать и искать. А кнопок таких несколько штук сделать, для разных поисков. Но макрос на всех этих кнопках будет один
Не стал так делать потому, что не знаю, нужно или нет. А просто так неохота время тратить

К сообщению приложен файл:

Macro_1.xlsb
(23.9 Kb)


Скажи мне, кудесник, любимец ба’гов…
Платная помощь:
Boroda_Excel@mail.ru
Яндекс-деньги: 41001632713405 | Webmoney: R289877159277; Z102172301748; E177867141995

 

Ответить

InExSu

Дата: Среда, 20.02.2019, 19:53 |
Сообщение № 3

Группа: Друзья

Ранг: Ветеран

Сообщений: 646


Репутация:

96

±

Замечаний:
0% ±


Excel 2010

Привет!

Для любого количества искомых значений, любых диапазонов (надеюсь и не тестировал) во вложении.


Разработчик Битрикс24 php, Google Apps Script, VBA Excel

Сообщение отредактировал InExSuСреда, 20.02.2019, 19:58

 

Ответить

Гордей

Дата: Среда, 20.02.2019, 20:42 |
Сообщение № 4

Группа: Пользователи

Ранг: Новичок

Сообщений: 32


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Но макрос на всех этих кнопках будет один

Ох.. Спасибо огромное! В представленном Вами варианте работает! На кнопки вешать искомые слова не нужно, они будут всегда статичны и прописаны в самом макросе.

Но после редактирования макроса по свои нужды выяснилось следующее: при поиске по столбцу С, если есть пустые ячейки между данными (а их может быть много) — то макрос почему-то стопорится на одной из ячеек и дальше «не идёт»

В прикреплённом варианте макрос останавливается на 31-й строке, хотя дальше находятся много искомых слов. Посмотрите пожалуйста, уважаемый _Boroda_ :shy:

UPDATE:

Для любого количества искомых значений, любых диапазонов (надеюсь и не тестировал) во вложении.

Приветствую! Спасибо большое! Код Бороды выглядит для меня более понятным и простым) Благодарю Вас за помощь!

К сообщению приложен файл:

Macro2.xlsb
(34.2 Kb)

Сообщение отредактировал ГордейСреда, 20.02.2019, 20:49

 

Ответить

InExSu

Дата: Среда, 20.02.2019, 20:59 |
Сообщение № 5

Группа: Друзья

Ранг: Ветеран

Сообщений: 646


Репутация:

96

±

Замечаний:
0% ±


Excel 2010


С какой строки мой код менее понятен? А то я, ничтоже сумняшеся, свой код считаю более понятным :-)


Разработчик Битрикс24 php, Google Apps Script, VBA Excel

 

Ответить

Гордей

Дата: Среда, 20.02.2019, 21:10 |
Сообщение № 6

Группа: Пользователи

Ранг: Новичок

Сообщений: 32


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

С какой строки мой код менее понятен? А то я, ничтоже сумняшеся, свой код считаю более понятным :-)

Например: в коде Бороды быстро нашёл, где поменять значения искомых слов и задать их кол-во. В Вашем макросе данные для поиска берутся из ячеек, и как их «впихнуть» в макрос (а их 6-7 слов для поиска) — не представляю, потому что не владею VBA. И ещё в Вашем макросе идёт поиск только по данным, пока не встретится пустая ячейка(и). А данные могут быть как угодно по столбцу С распределены, но не более 3000 строк. Скачайте мой файл выше с кодом Бороды — я там его переделал для своих нужд, посмотрите.. Если поправите Ваш макрос, и он будет работать без сюрпризов — супер!

Сообщение отредактировал ГордейСреда, 20.02.2019, 21:11

 

Ответить

_Boroda_

Дата: Среда, 20.02.2019, 21:34 |
Сообщение № 7

Группа: Модераторы

Ранг: Местный житель

Сообщений: 16618


Репутация:

6465

±

Замечаний:
0% ±


2003; 2007; 2010; 2013 RUS

Да, не учел, что Миша может быть единственный
Добавьте знак «=» в строку 25
[vba][/vba]


Скажи мне, кудесник, любимец ба’гов…
Платная помощь:
Boroda_Excel@mail.ru
Яндекс-деньги: 41001632713405 | Webmoney: R289877159277; Z102172301748; E177867141995

 

Ответить

Гордей

Дата: Среда, 20.02.2019, 21:43 |
Сообщение № 8

Группа: Пользователи

Ранг: Новичок

Сообщений: 32


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Добавьте знак «=» в строку 25

Ай СПАСИБО Вам, дорогой и уважаемый Борода! ОГРОМНОЕ, такое, БОЛЬШОЕ СПАСИБО!!! Всех благ Вам!

InExSu, и Вам СПАСИБО за участие! Благодарю! Макрос Бороды работает теперь идеально.

 

Ответить

InExSu

Дата: Среда, 20.02.2019, 21:53 |
Сообщение № 9

Группа: Друзья

Ранг: Ветеран

Сообщений: 646


Репутация:

96

±

Замечаний:
0% ±


Excel 2010


маловероятно.
Во вложении.


Разработчик Битрикс24 php, Google Apps Script, VBA Excel

Сообщение отредактировал InExSuСреда, 20.02.2019, 21:53

 

Ответить

Гордей

Дата: Среда, 20.02.2019, 22:57 |
Сообщение № 10

Группа: Пользователи

Ранг: Новичок

Сообщений: 32


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Вроде без сюрпризов работает код. Только не пойму, как переделать код так, чтобы данные для поиска были жёстко прописаны в макросе, а не брались из ячеек столба 1

 

Ответить

InExSu

Дата: Среда, 20.02.2019, 23:27 |
Сообщение № 11

Группа: Друзья

Ранг: Ветеран

Сообщений: 646


Репутация:

96

±

Замечаний:
0% ±


Excel 2010


Разработчик Битрикс24 php, Google Apps Script, VBA Excel

 

Ответить

Гордей

Дата: Четверг, 21.02.2019, 01:09 |
Сообщение № 12

Группа: Пользователи

Ранг: Новичок

Сообщений: 32


Репутация:

0

±

Замечаний:
0% ±


Excel 2007

Спасибо! Всё замечательно. Буду юзать две кнопки) Одну с макросом от Бороды, когда нужно зацикливать поиск, и вторую с Вашим макросом, когда нужно будет доходить до последнего найденного и останавливаться.

Ещё раз огромное спасибо вам!!! Вы настоящие Профи!!!

 

Ответить

Метод Find объекта Range для поиска ячейки по ее данным в VBA Excel. Синтаксис и компоненты. Знаки подстановки для поисковой фразы. Простые примеры.

Метод Find объекта Range предназначен для поиска ячейки и сведений о ней в заданном диапазоне по ее значению, формуле и примечанию. Чаще всего этот метод используется для поиска в таблице ячейки по слову, части слова или фразе, входящей в ее значение.

Синтаксис метода Range.Find

Expression.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)

Expression – это переменная или выражение, возвращающее объект Range, в котором будет осуществляться поиск.

В скобках перечислены параметры метода, среди них только What является обязательным.

Метод Range.Find возвращает объект Range, представляющий из себя первую ячейку, в которой найдена поисковая фраза (параметр What). Если совпадение не найдено, возвращается значение Nothing.

Если необходимо найти следующие ячейки, содержащие поисковую фразу, используется метод Range.FindNext.

Параметры метода Range.Find

Наименование Описание
Обязательный параметр
What Данные для поиска, которые могут быть представлены строкой или другим типом данных Excel. Тип данных параметра — Variant.
Необязательные параметры
After Ячейка, после которой следует начать поиск.
LookIn Уточняет область поиска. Список констант xlFindLookIn:

  • xlValues (-4163) – значения;
  • xlComments (-4144) – примечания*;
  • xlNotes (-4144) – примечания*;
  • xlFormulas (-4123) – формулы.
LookAt Поиск частичного или полного совпадения. Список констант xlLookAt:

  • xlWhole (1) – полное совпадение;
  • xlPart (2) – частичное совпадение.
SearchOrder Определяет способ поиска. Список констант xlSearchOrder:

  • xlByRows (1) – поиск по строкам;
  • xlByColumns (2) – поиск по столбцам.
SearchDirection Определяет направление поиска. Список констант xlSearchDirection:

  • xlNext (1) – поиск вперед;
  • xlPrevious (2) – поиск назад.
MatchCase Определяет учет регистра:

  • False (0) – поиск без учета регистра (по умолчанию);
  • True (1) – поиск с учетом регистра.
MatchByte Условия поиска при использовании двухбайтовых кодировок:

  • False (0) – двухбайтовый символ может соответствовать однобайтовому символу;
  • True (1) – двухбайтовый символ должен соответствовать только двухбайтовому символу.
SearchFormat Формат поиска – используется вместе со свойством Application.FindFormat.

* Примечания имеют две константы с одним значением. Проверяется очень просто: MsgBox xlComments и MsgBox xlNotes.

В справке Microsoft тип данных всех параметров, кроме SearchDirection, указан как Variant.

Знаки подстановки для поисковой фразы

Условные знаки в шаблоне поисковой фразы:

  • ? – знак вопроса обозначает любой отдельный символ;
  • * – звездочка обозначает любое количество любых символов, в том числе ноль символов;
  • ~ – тильда ставится перед ?, * и ~, чтобы они обозначали сами себя (например, чтобы тильда в шаблоне обозначала сама себя, записать ее нужно дважды: ~~).

Простые примеры

При использовании метода Range.Find в VBA Excel необходимо учитывать следующие нюансы:

  1. Так как этот метод возвращает объект Range (в виде одной ячейки), присвоить его можно только объектной переменной, объявленной как Variant, Object или Range, при помощи оператора Set.
  2. Если поисковая фраза в заданном диапазоне найдена не будет, метод Range.Find возвратит значение Nothing. Обращение к свойствам несуществующей ячейки будет генерировать ошибки. Поэтому, перед использованием результатов поиска, необходимо проверить объектную переменную на содержание в ней значения Nothing.

В примерах используются переменные:

  • myPhrase – переменная для записи поисковой фразы;
  • myCell – переменная, которой присваивается первая найденная ячейка, содержащая поисковую фразу, или значение Nothing, если поисковая фраза не найдена.

Пример 1

Sub primer1()

Dim myPhrase As Variant, myCell As Range

myPhrase = «стакан»

Set myCell = Range(«A1:L30»).Find(myPhrase)

If Not myCell Is Nothing Then

MsgBox «Значение найденной ячейки: « & myCell

MsgBox «Строка найденной ячейки: « & myCell.Row

MsgBox «Столбец найденной ячейки: « & myCell.Column

MsgBox «Адрес найденной ячейки: « & myCell.Address

Else

MsgBox «Искомая фраза не найдена»

End If

End Sub

В этом примере мы присваиваем переменной myPhrase значение для поиска – "стакан". Затем проводим поиск этой фразы в диапазоне "A1:L30" с присвоением результата поиска переменной myCell. Далее проверяем переменную myCell, не содержит ли она значение Nothing, и выводим соответствующие сообщения.

Ознакомьтесь с работой кода VBA в случаях, когда в диапазоне "A1:L30" есть ячейка со строкой, содержащей подстроку "стакан", и когда такой ячейки нет.

Пример 2

Теперь посмотрим, как метод Range.Find отреагирует на поиск числа. В качестве диапазона поиска будем использовать первую строку активного листа Excel.

Sub primer2()

Dim myPhrase As Variant, myCell As Range

myPhrase = 526.15

Set myCell = Rows(1).Find(myPhrase)

If Not myCell Is Nothing Then

MsgBox «Значение найденной ячейки: « & myCell

Else: MsgBox «Искомая фраза не найдена»

End If

End Sub

Несмотря на то, что мы присвоили переменной числовое значение, метод Range.Find найдет ячейку со значением и 526,15, и 129526,15, и 526,15254. То есть, как и в предыдущем примере, поиск идет по подстроке.

Чтобы найти ячейку с точным соответствием значения поисковой фразе, используйте константу xlWhole параметра LookAt:

Set myCell = Rows(1).Find(myPhrase, , , xlWhole)

Аналогично используются и другие необязательные параметры. Количество «лишних» запятых перед необязательным параметром должно соответствовать количеству пропущенных компонентов, предусмотренных синтаксисом метода Range.Find, кроме случаев указания необязательного параметра по имени, например: LookIn:=xlValues. Тогда используется одна запятая, независимо от того, сколько компонентов пропущено.

Пример 3

Допустим, у нас есть многострочная база данных в Excel. В первой колонке находятся даты. Нам необходимо создать отчет за какой-то период. Найти номер начальной строки для обработки можно с помощью следующего кода:

Sub primer3()

Dim myPhrase As Variant, myCell As Range

myPhrase = «01.02.2019»

myPhrase = CDate(myPhrase)

Set myCell = Range(«A:A»).Find(myPhrase)

If Not myCell Is Nothing Then

MsgBox «Номер начальной строки: « & myCell.Row

Else: MsgBox «Даты « & myPhrase & » в таблице нет»

End If

End Sub

Несмотря на то, что в ячейке дата отображается в виде текста, ее значение хранится в ячейке в виде числа. Поэтому текстовый формат необходимо перед поиском преобразовать в формат даты.

9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

1

Поиск в таблице и подстановка в форму по нескольким критериям

13.11.2019, 07:55. Показов 4670. Ответов 26


Студворк — интернет-сервис помощи студентам

Добрый день.

Есть такой вопрос. Есть форма, которая вызывается листа Мастердата.

В форме юзер вводит артикул, после ввода должно идти обращение к листу Сток и подставиться значение из колонки «Место» в поле Скл место на форме. Но только поиск должен выбрать критерии:

— самый главный поиск — это конечно артикул из формы (1 столбец в таблице)
— выбрать только Зону 1 в таблице
— выбрать статусы 2 либо 32 в таблице
— после всего этого подставить в форму Скл место из колонки Место в таблице

Подскажите пожалуйста, как такое можно реализовать?

Если ни один из критериев не подойдет, выход msbox с инфо



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 09:07

2

Dimasterfrom4e, интересно, а есть ли у вас приятель, который, прочитав ваше описание темы, сказал бы без дополнительных пояснений: «Всё понятно!»?



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 09:26

 [ТС]

3

Цитата
Сообщение от Burk
Посмотреть сообщение

«Всё понятно!»?

Здравствуйте. Приятель все понял. Если что не понятно, могу объяснить. Я стараюсь все доступно объяснять))

Я знаю только поиск Find в VBA только по одному значению в таблице, а тут несколько критериев для поиска, потому и спрашиваю здесь))



0



208 / 183 / 43

Регистрация: 02.08.2019

Сообщений: 586

Записей в блоге: 23

13.11.2019, 09:51

4

Dimasterfrom4e, привет! не смотрел твой файл, но попробуй придумать что то с доп столбцом, который сцепляет твои столбцы в зависимости от условия и по нему ищи уже, как вариант



1



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 10:07

5

Dimasterfrom4e, значит я такой недопонимающий, а почему бы тогда вашему приятелю не поучаствовать в вашей теме, вопрос риторический, отвечать не надо.



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 13:05

 [ТС]

6

Цитата
Сообщение от Burk
Посмотреть сообщение

приятелю не поучаствовать

При чем здесь приятель? Вопрос мой он понял, но excel vba не знает.

Цитата
Сообщение от Burk
Посмотреть сообщение

вопрос риторический, отвечать не надо.

так уж получилось, что надо…

Добавлено через 1 минуту

Цитата
Сообщение от art1289
Посмотреть сообщение

доп столбцом, который сцепляет твои столбцы в зависимости от условия и по нему ищи уже, как вариант

Похоже так и придется, спасибо) Просто думал, что узнаю про новый метод поиска кроме Find



0



Burk

1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 14:05

7

Dimasterfrom4e, ну уж теперь как я понял, сделал через фильтры 1 столбец — артикул, второй — зона, третий — статус. Если после установки фильтров число видимых строк будет = 1, значит видны только заголовки (нет совпадений) иначе входим в цикл по видимым (отфильтрованным) строкам и делайте, что вам нужно с ними. Кстати, ваш файл не читается.

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Sub Filt()
Dim X As Range, J As Long
With ActiveSheet.ListObjects("tStock").Range
  .AutoFilter Field:=1, Criteria1:=Enter_data.txb_art
  .AutoFilter Field:=2, Criteria1:="1"
  .AutoFilter Field:=5, Criteria1:="2", Operator:=xlOr, Criteria2:="=32"
  J = .SpecialCells(xlCellTypeVisible).Rows.Count
  If J = 1 Then 'найден видимым только заголовок
    MsgBox "Нет строк с такими значенияями фильтров!"
  Else
    J = .Rows.Count
    For Each X In Range("A2:A" & J).SpecialCells(xlCellTypeVisible)
        '....... здесь обработка данных
'        MsgBox X.Address
    Next
  End If
  'включаем все строки
  .AutoFilter Field:=1
  .AutoFilter Field:=2
  .AutoFilter Field:=5
End With
End Sub



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 14:47

 [ТС]

8

Цитата
Сообщение от Burk
Посмотреть сообщение

ваш файл не читается.

прошу прощения. Формат файла .xlsb проверил, открывается))

Цитата
Сообщение от Burk
Посмотреть сообщение

сделал через фильтры

я так не пробовал еще. Спасибо Вам)) В конце фильтры убираются, как я понял?))

Добавлено через 13 минут

Цитата
Сообщение от Burk
Посмотреть сообщение

For Each X In Range(«A2:A» & J).SpecialCells(xlCellTypeVisible)
        ‘……. здесь обработка данных
‘        MsgBox X.Address
   Next

А если мне в форму нужно найденное первое по фильтрам место записать из колонки 3 ?



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 15:00

9

Цитата
Сообщение от Dimasterfrom4e
Посмотреть сообщение

проверил, открывается

я тоже проверил на двух компах, не открывается без ошибок, а вы открывали из своего послания или с компа? Было с одним человеком такое же, в итоге у него оказался некачественный архиватор.
Фильтры не удаляются, а включается ВЫДЕЛИТЬ ВСЕ, в программе есть пояснение

Добавлено через 7 минут

Цитата
Сообщение от Dimasterfrom4e
Посмотреть сообщение

первое по фильтрам место записать из колонки 3

Номер строки из цикла по Х запишется так Nom=X.Row ну а значение из 3 колонки ПолеВформе=Cells(Nom,3)
Только с учетом того, что у вас создана таблица, а здесь я написал ячейки напрямую, проверьте, то ли берётся



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 15:09

 [ТС]

10

Цитата
Сообщение от Burk
Посмотреть сообщение

Было с одним человеком такое же, в итоге у него оказался некачественный архиватор.

Возможно, заархивировалось с ошибкой… Но это архиватор на рабочем компе…



0



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 15:26

 [ТС]

11

Цитата
Сообщение от Burk
Посмотреть сообщение

Фильтры не удаляются, а включается ВЫДЕЛИТЬ ВСЕ, в программе есть пояснение

я попробовал сделать запись в форму, но даже при наличии записи на листе Сток выдает сообщение, что не найдено…

И в ячейку формы не пишет…



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 15:40

12

Dimasterfrom4e, ну та же ошибка, сделайте файл xls, там у него ограничение 100Кб, может хватит, если нет, то грохните большую часть ваших данных. Файлы xls можно посылать без архивации. Либо попробуйте xlsm с архивацией



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 15:44

 [ТС]

13

В xlsm



0



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 15:45

 [ТС]

14

Цитата
Сообщение от Burk
Посмотреть сообщение

ну та же ошибка,

изменил в xlsm



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 15:55

15

Dimasterfrom4e, ну что же вы делаете, почему Nom = X.Row вне цикла, конечно же внутри.

Добавлено через 10 минут
теперь прочиталось, посмотрю ещё. Только порядок ваших действий? Жмем кнопку на каком листе, вводим некий (какой) артикул, запускаем макрос или там всё включено?



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 16:03

 [ТС]

16

Цитата
Сообщение от Burk
Посмотреть сообщение

Только порядок ваших действий?

в форме ввожу артикул и нажимаю кнопку (тоже на форму добавил). по факту нажатия этой кнопки должен выполниться поиск с фильтрами:

— если найдено что то по критериям, вывести в форме в ячейке Скл место инф из 3-ей колонки таблицы (одно первое найденное значение)
— если не найдено ничего — месседжбокс

Добавлено через 1 минуту

Цитата
Сообщение от Burk
Посмотреть сообщение

вне цикла, конечно же внутри.

Я его двигал внутрь — то же самое. Выдает msb даже когда есть нужные значения в таблице



0



1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 16:12

17

Dimasterfrom4e, исправьте единицу на ноль в
If J = 1 Then ‘найден видимым только заголовок (If J = 0 Then ‘)

Добавлено через 4 минуты
Dimasterfrom4e, и я же писал про соответствие таблиц и ячеек. включите для отладки вывод на экран X.Address (строка 14) и посмотрите адрес (строку) выбираемой ячейки, сообщите мне



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 16:27

 [ТС]

18

Цитата
Сообщение от Burk
Посмотреть сообщение

вывод на экран X.Address

после изменения значения на ноль он все равно до X.Address не доходит, появляется дебаг ошибка



0



Burk

1813 / 1135 / 346

Регистрация: 11.07.2014

Сообщений: 4,002

13.11.2019, 19:07

19

Dimasterfrom4e, там неправильно определялось количество отфильтрованных строк, взял где-то на форуме, оказалось не работает.
Посмотрите теперь. И вы маленько начинайте понимать макрос, я вам написал цикл по фильтрованным строкам так как не знал что вы будете с ними делать. А вы так и оставили, хотя вам нужна только одна строка. Оставил закомментированный фильтр на всякий случай, но теперь будет работа с первой строкой

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Sub Filt()
Dim X As Range, J As Long
 
Set Sh_stock = ThisWorkbook.Worksheets("$Stock")
Set StockObj = Sh_stock.ListObjects("tStock")
With Sh_stock.ListObjects("tStock").Range
  .AutoFilter Field:=1, Criteria1:=Enter_data.txb_art
  .AutoFilter Field:=2, Criteria1:="1"
  .AutoFilter Field:=5, Criteria1:="2", Operator:=xlOr, Criteria2:="=32"
  J = .Columns(1).SpecialCells(xlCellTypeVisible).Count 
  If J = 1 Then 'найден видимым только заголовок
    MsgBox "Нет строк с такими значениями фильтров!"
  Else
    J = .Rows.Count
    Set X = Range("A2:A" & J).SpecialCells(xlCellTypeVisible)
'    For Each X In Range("A2:A" & J).SpecialCells(xlCellTypeVisible)
        Nom = X.Row
        Enter_data.txb_place = Cells(Nom, 3)
'    Next
  End If
  'включаем все строки
  .AutoFilter Field:=1
  .AutoFilter Field:=2
  .AutoFilter Field:=5
End With
End Sub



1



9 / 8 / 0

Регистрация: 27.09.2015

Сообщений: 837

13.11.2019, 19:14

 [ТС]

20

Цитата
Сообщение от Burk
Посмотреть сообщение

цикл по фильтрованным строкам

Спасибо вам большое!

Цитата
Сообщение от Burk
Посмотреть сообщение

А вы так и оставили, хотя вам нужна только одна строка.

Я таким образом еще не делал поиск, до этого только по одному значению через Find)) не требовалось больше критериев, пока от коллег просьба не поступила…



0



Like this post? Please share to your friends:
  • Поиск по другому листу excel
  • Поиск по нескольким документам excel
  • Поиск по документу сочетание клавиш word
  • Поиск по наименованию листа в excel
  • Поиск по документу сочетание клавиш excel