Поиск какого-либо значения в ячейках Excel довольно часто встречающаяся задача при программировании какого-либо макроса. Решить ее можно разными способами. Однако, в разных ситуациях использование того или иного способа может быть не оправданным. В данной статье я рассмотрю 2 наиболее распространенных способа.
Поиск перебором значений
Довольно простой в реализации способ. Например, найти в колонке «A» ячейку, содержащую «123» можно примерно так:
Sheets("Данные").Select For y = 1 To Cells.SpecialCells(xlLastCell).Row If Cells(y, 1) = "123" Then Exit For End If Next y MsgBox "Нашел в строке: " + CStr(y)
Минусами этого так сказать «классического» способа являются: медленная работа и громоздкость. А плюсом является его гибкость, т.к. таким способом можно реализовать сколь угодно сложные варианты поиска с различными вычислениями и т.п.
Поиск функцией Find
Гораздо быстрее обычного перебора и при этом довольно гибкий. В простейшем случае, чтобы найти в колонке A ячейку, содержащую «123» достаточно такого кода:
Sheets("Данные").Select Set fcell = Columns("A:A").Find("123") If Not fcell Is Nothing Then MsgBox "Нашел в строке: " + CStr(fcell.Row) End If
Вкратце опишу что делают строчки данного кода:
1-я строка: Выбираем в книге лист «Данные»;
2-я строка: Осуществляем поиск значения «123» в колонке «A», результат поиска будет в fcell;
3-я строка: Если удалось найти значение, то fcell будет содержать Range-объект, в противном случае — будет пустой, т.е. Nothing.
Полностью синтаксис оператора поиска выглядит так:
Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
What — Строка с текстом, который ищем или любой другой тип данных Excel
After — Ячейка, после которой начать поиск. Обратите внимание, что это должна быть именно единичная ячейка, а не диапазон. Поиск начинается после этой ячейки, а не с нее. Поиск в этой ячейке произойдет только когда весь диапазон будет просмотрен и поиск начнется с начала диапазона и до этой ячейки включительно.
LookIn — Тип искомых данных. Может принимать одно из значений: xlFormulas (формулы), xlValues (значения), или xlNotes (примечания).
LookAt — Одно из значений: xlWhole (полное совпадение) или xlPart (частичное совпадение).
SearchOrder — Одно из значений: xlByRows (просматривать по строкам) или xlByColumns (просматривать по столбцам)
SearchDirection — Одно из значений: xlNext (поиск вперед) или xlPrevious (поиск назад)
MatchCase — Одно из значений: True (поиск чувствительный к регистру) или False (поиск без учета регистра)
MatchByte — Применяется при использовании мультибайтных кодировок: True (найденный мультибайтный символ должен соответствовать только мультибайтному символу) или False (найденный мультибайтный символ может соответствовать однобайтному символу)
SearchFormat — Используется вместе с FindFormat. Сначала задается значение FindFormat (например, для поиска ячеек с курсивным шрифтом так: Application.FindFormat.Font.Italic = True), а потом при использовании метода Find указываем параметр SearchFormat = True. Если при поиске не нужно учитывать формат ячеек, то нужно указать SearchFormat = False.
Чтобы продолжить поиск, можно использовать FindNext (искать «далее») или FindPrevious (искать «назад»).
Примеры поиска функцией Find
Пример 1: Найти в диапазоне «A1:A50» все ячейки с текстом «asd» и поменять их все на «qwe»
With Worksheets(1).Range("A1:A50") Set c = .Find("asd", LookIn:=xlValues) Do While Not c Is Nothing c.Value = "qwe" Set c = .FindNext(c) Loop End With
Обратите внимание: Когда поиск достигнет конца диапазона, функция продолжит искать с начала диапазона. Таким образом, если значение найденной ячейки не менять, то приведенный выше пример зациклится в бесконечном цикле. Поэтому, чтобы этого избежать (зацикливания), можно сделать следующим образом:
Пример 2: Правильный поиск значения с использованием FindNext, не приводящий к зацикливанию.
With Worksheets(1).Range("A1:A50") Set c = .Find("asd", lookin:=xlValues) If Not c Is Nothing Then firstResult = c.Address Do c.Font.Bold = True Set c = .FindNext(c) If c Is Nothing Then Exit Do Loop While c.Address <> firstResult End If End With
В ниже следующем примере используется другой вариант продолжения поиска — с помощью той же функции Find с параметром After. Когда найдена очередная ячейка, следующий поиск будет осуществляться уже после нее. Однако, как и с FindNext, когда будет достигнут конец диапазона, Find продолжит поиск с его начала, поэтому, чтобы не произошло зацикливания, необходимо проверять совпадение с первым результатом поиска.
Пример 3: Продолжение поиска с использованием Find с параметром After.
With Worksheets(1).Range("A1:A50") Set c = .Find("asd", lookin:=xlValues) If Not c Is Nothing Then firstResult = c.Address Do c.Font.Bold = True Set c = .Find("asd", After:=c, lookin:=xlValues) If c Is Nothing Then Exit Do Loop While c.Address <> firstResult End If End With
Следующий пример демонстрирует применение SearchFormat для поиска по формату ячейки. Для указания формата необходимо задать свойство FindFormat.
Пример 4: Найти все ячейки с шрифтом «курсив» и поменять их формат на обычный (не «курсив»)
lLastRow = Cells.SpecialCells(xlLastCell).Row lLastCol = Cells.SpecialCells(xlLastCell).Column Application.FindFormat.Font.Italic = True With Worksheets(1).Range(Cells(1, 1), Cells(lLastRow, lLastCol)) Set c = .Find("", SearchFormat:=True) Do While Not c Is Nothing c.Font.Italic = False Set c = .Find("", After:=c, SearchFormat:=True) Loop End With
Примечание: В данном примере намеренно не используется FindNext для поиска следующей ячейки, т.к. он не учитывает формат (статья об этом: https://support.microsoft.com/ru-ru/kb/282151)
Коротко опишу алгоритм поиска Примера 4. Первые две строки определяют последнюю строку (lLastRow) на листе и последний столбец (lLastCol). 3-я строка задает формат поиска, в данном случае, будем искать ячейки с шрифтом Italic. 4-я строка определяет область ячеек с которой будет работать программа (с ячейки A1 и до последней строки и последнего столбца). 5-я строка осуществляет поиск с использованием SearchFormat. 6-я строка — цикл пока результат поиска не будет пустым. 7-я строка — меняем шрифт на обычный (не курсив), 8-я строка продолжаем поиск после найденной ячейки.
Хочу обратить внимание на то, что в этом примере я не стал использовать «защиту от зацикливания», как в Примерах 2 и 3, т.к. шрифт меняется и после «прохождения» по всем ячейкам, больше не останется ни одной ячейки с курсивом.
Свойство FindFormat можно задавать разными способами, например, так:
With Application.FindFormat.Font .Name = "Arial" .FontStyle = "Regular" .Size = 10 End With
Поиск последней заполненной ячейки с помощью Find
Следующий пример — применение функции Find для поиска последней ячейки с заполненными данными. Использованные в Примере 4 SpecialCells находит последнюю ячейку даже если она не содержит ничего, но отформатирована или в ней раньше были данные, но были удалены.
Пример 5: Найти последнюю колонку и столбец, заполненные данными
Set c = Worksheets(1).UsedRange.Find("*", SearchDirection:=xlPrevious) If Not c Is Nothing Then lLastRow = c.Row: lLastCol = c.Column Else lLastRow = 1: lLastCol = 1 End If MsgBox "lLastRow=" & lLastRow & " lLastCol=" & lLastCol
В этом примере используется UsedRange, который так же как и SpecialCells возвращает все используемые ячейки, в т.ч. и те, что были использованы ранее, а сейчас пустые. Функция Find ищет ячейку с любым значением с конца диапазона.
Поиск по шаблону (маске)
При поиске можно так же использовать шаблоны, чтобы найти текст по маске, следующий пример это демонстрирует.
Пример 6: Выделить красным шрифтом ячейки, в которых текст начинается со слова из 4-х букв, первая и последняя буквы «т», при этом после этого слова может следовать любой текст.
With Worksheets(1).Cells Set c = .Find("т??т*", LookIn:=xlValues, LookAt:=xlWhole) If Not c Is Nothing Then firstResult = c.Address Do c.Font.Color = RGB(255, 0, 0) Set c = .FindNext(c) If c Is Nothing Then Exit Do Loop While c.Address <> firstResult End If End With
Для поиска функцией Find по маске (шаблону) можно применять символы:
* — для обозначения любого количества любых символов;
? — для обозначения одного любого символа;
~ — для обозначения символов *, ? и ~. (т.е. чтобы искать в тексте вопросительный знак, нужно написать ~?, чтобы искать именно звездочку (*), нужно написать ~* и наконец, чтобы найти в тексте тильду, необходимо написать ~~)
Поиск в скрытых строках и столбцах
Для поиска в скрытых ячейках нужно учитывать лишь один нюанс: поиск нужно осуществлять в формулах, а не в значениях, т.е. нужно использовать LookIn:=xlFormulas
Поиск даты с помощью Find
Если необходимо найти текущую дату или какую-то другую дату на листе Excel или в диапазоне с помощью Find, необходимо учитывать несколько нюансов:
- Тип данных Date в VBA представляется в виде #[месяц]/[день]/[год]#, соответственно, если необходимо найти фиксированную дату, например, 01 марта 2018 года, необходимо искать #3/1/2018#, а не «01.03.2018»
- В зависимости от формата ячеек, дата может выглядеть по-разному, поэтому, чтобы искать дату независимо от формата, поиск нужно делать не в значениях, а в формулах, т.е. использовать LookIn:=xlFormulas
Приведу несколько примеров поиска даты.
Пример 7: Найти текущую дату на листе независимо от формата отображения даты.
d = Date Set c = Cells.Find(d, LookIn:=xlFormulas, LookAt:=xlWhole) If Not c Is Nothing Then MsgBox "Нашел" Else MsgBox "Не нашел" End If
Пример 8: Найти 1 марта 2018 г.
d = #3/1/2018# Set c = Cells.Find(d, LookIn:=xlFormulas, LookAt:=xlWhole) If Not c Is Nothing Then MsgBox "Нашел" Else MsgBox "Не нашел" End If
Искать часть даты — сложнее. Например, чтобы найти все ячейки, где месяц «март», недостаточно искать «03» или «3». Не работает с датами так же и поиск по шаблону. Единственный вариант, который я нашел — это выбрать формат в котором месяц прописью для ячеек с датами и искать слово «март» в xlValues.
Тем не менее, можно найти, например, 1 марта независимо от года.
Пример 9: Найти 1 марта любого года.
d = #3/1/1900# Set c = Cells.Find(Format(d, "m/d/"), LookIn:=xlFormulas, LookAt:=xlPart) If Not c Is Nothing Then MsgBox "Нашел" Else MsgBox "Не нашел" End If
- Download script — 922 B
Introduction
This macro script is used to search for specific cells in Excel documents and copy the cells into a separate sheet.
Background
This is my first project on CodeProject, and my first VBA script, so I am open to suggestions on how to improve my code! I wrote this script along with the help of my co-workers to search through our documents quickly and retrieve data.
Using the Code
The code is meant to be imported into an Excel document. The file is linked with the .bas extension.
Error Catch
On Error GoTo ErrorCatch
Variables
Dim WorkSheet_Count As Integer Dim index As Integer Dim columnCount As Integer Dim inputRange As Range Dim cellContent As String
Initial Headers to Define Columns
Sheets("SearchResults").Range("A1:E1").Value = _ Array("Customer Name", "Example Column", "Example Column", "Example Column", "Example Column")
Main Body
DW1962</a>) to prevent flickering of the screen while processing data Application.ScreenUpdating = False WorkSheet_Count = ActiveWorkbook.Worksheets.Count For index = 2 To WorkSheet_Count Set inputRange = ActiveWorkbook.Worksheets(index).Cells.Find("Customer Name:") If Not inputRange Is Nothing Then cellContent = ActiveSheet.Cells(inputRange.Row, _ (inputRange.Column + 1)).Address(False, False) Sheets(ActiveWorkbook.Worksheets(index).Name).Range(cellContent).Copy Worksheets_ ("SearchResults").Range("A" & index) Else Sheets("SearchResults").Range_ ("A" & index).Value = "No Information" End If Set inputRange = Nothing Next index DW1962</a>) to "fix the columns' width" For columnCount = 1 To ActiveSheet.UsedRange.Columns.Count Columns(columnCount).EntireColumn.AutoFit Next columnCount Exit Sub ErrorCatch: MsgBox "There was an error while searching for the cell" End Sub
To find the cell, you need to replace the string
in inputRange
to whatever you want to search for:
Set inputRange = ActiveWorkbook.Worksheets(index).Cells.Find_ ("Whatever you want to search for here")
Also, you need to choose whatever you want your sheet that collects the search information to be:
Sheets(ActiveWorkbook.Worksheets(index).Name).Range(cellContent).Copy Worksheets_ ("Whatever sheet name you want").Range("A" & index)
Points of Interest
I learned much about how to program macros from making this project, and I hope it will help some of you as well!
Also, I got the worksheet looper from this Microsoft article.
How to Import the Macro
- Open Excel and then click Developer > Visual Basic.
- To import the macro, click File > Import File, go to the folder where you exported your macro, select the file, and then click Open.
- Save the module.
- Create a new sheet named «SearchResults» (whatever sheet name you specified in this line):
Sheets(ActiveWorkbook.Worksheets(index).Name).Range(cellContent).Copy Worksheets(«Whatever sheet name you want»).Range(«A» & index)
- Run the macro and gather results.
History
- V1.0 Released 12/13/2016
- V1.1 Released 12/15/2016
- Changed code, implementing suggestions
- Updated script in zip file
I am currently a high school senior, preparing to study in Computer Engineering at IUPUI.
I have programmed for about 6 years, mostly in C++.
My current job is pushing me to become more adept in various programming languages, including C# and VBA.
Метод 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:
|
LookAt | Поиск частичного или полного совпадения. Список констант xlLookAt:
|
SearchOrder | Определяет способ поиска. Список констант xlSearchOrder:
|
SearchDirection | Определяет направление поиска. Список констант xlSearchDirection:
|
MatchCase | Определяет учет регистра:
|
MatchByte | Условия поиска при использовании двухбайтовых кодировок:
|
SearchFormat | Формат поиска – используется вместе со свойством Application.FindFormat. |
* Примечания имеют две константы с одним значением. Проверяется очень просто: MsgBox xlComments
и MsgBox xlNotes
.
В справке Microsoft тип данных всех параметров, кроме SearchDirection, указан как Variant.
Знаки подстановки для поисковой фразы
Условные знаки в шаблоне поисковой фразы:
- ? – знак вопроса обозначает любой отдельный символ;
- * – звездочка обозначает любое количество любых символов, в том числе ноль символов;
- ~ – тильда ставится перед ?, * и ~, чтобы они обозначали сами себя (например, чтобы тильда в шаблоне обозначала сама себя, записать ее нужно дважды: ~~).
Простые примеры
При использовании метода Range.Find в VBA Excel необходимо учитывать следующие нюансы:
- Так как этот метод возвращает объект Range (в виде одной ячейки), присвоить его можно только объектной переменной, объявленной как Variant, Object или Range, при помощи оператора Set.
- Если поисковая фраза в заданном диапазоне найдена не будет, метод 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 |
Несмотря на то, что в ячейке дата отображается в виде текста, ее значение хранится в ячейке в виде числа. Поэтому текстовый формат необходимо перед поиском преобразовать в формат даты.
- Надстройки Excel
- Поиск в Excel
- Панель инструментов
- Книги Excel
- текстовые строки
- Форма ввода
Наверняка, вы сталкивались с ситуацией, когда необходимо производить поиск некоторого значения по всей книге Excel (искать частичное совпадение на всех листах активной книги)
Штатными средствами Excel вывести поле для поиска на панель инструментов не удаётся, а вызывать каждый раз диалоговое окно нажатием комбинации клавиш Ctrl + F не всегда удобно.
На помощь придёт эта надстройка — она формирует в строке меню Excel 2003 поле для поиска по всем листам:
Достаточно ввести искомый текст, и нажать клавишу Enter, — и перед вами полный список всех подходящих ячеек со всех листов книги.
Для перехода к найденной ячейке достаточно щелкнуть мышью на нужном результате — автоматически будет активирован нужный лист, и выделена искомая ячейка.
Поместите эту надстройку в папку автозагрузки Excel — и это поле будет появляться при каждом запуске программы.
Конечно, функциональность этой надстройки присутствует и в Excel, — если в настройках поиска выбрать опцию «Искать в книге»:
Моя же надстройка чуть упрощает работу — не надо нажимать лишние кнопки для типа Ctrl + F, и не надо выбирать область поиска.
К тому же, при использовании надстройки, вы можете провести мышом (при нажатой левой кнопке) по результатам поиска, — и Excel пролистает (выделит) все найденные ячейки по очереди (во встроенном поиске Excel надо щелкать на каждом результате отдельно)
(добавлено 29.07.2011) Немного подправил код надстройки:
- теперь форма с результатами закрывается по нажатию Esc
- при отсутствии открытой книги не выводится пустая форма
- панель инструментов не сбрасывается к настройкам «по-умолчанию» перед добавлением поля
- 200847 просмотров
Не получается применить макрос? Не удаётся изменить код под свои нужды?
Оформите заказ у нас на сайте, не забыв прикрепить примеры файлов, и описать, что и как должно работать.
Содержание
- Определение метода Range.Replace
- Синтаксис
- Параметры
- Макрос поиска ячейки с выпадающим списком
- Поиск функцией Find
- Примеры поиска функцией Find
- Поиск даты с помощью Find
- Предназначение и синтаксис метода Range.Find
- Синтаксис метода Range.Find
- Параметры метода Range.Find
- «Найти и заменить» в Excel
- Горячие клавиши
- Процедура «Найти и заменить» не работает
- Подстановочные знаки, или как найти «звездочку»
- Знаки подстановки для поисковой фразы
Определение метода Range.Replace
Range.Replace – это метод, который находит по шаблону подстроку в содержимом ячеек указанного диапазона, заменяет ее на другую подстроку и возвращает значение типа Boolean.
Метод имеет некоторые особенности, которые заключаются в следующем:
- при присвоении булева значения, возвращаемого методом Range.Replace, переменной, необходимо список параметров (аргументов) метода заключать в круглые скобки;
- если метод используется без присвоения возвращаемого значения переменной, параметры должны быть указаны без заключения их в круглые скобки.
Синтаксис
Синтаксис при замене подстроки и присвоении переменной возвращаемого значения типа Boolean:
variable = expression.Replace(What, Replacement, [LookAt], [SearchOrder], [MatchCase], [MatchByte], [SearchFormat], [ReplaceFormat])
Синтаксис при замене подстроки без присвоения переменной возвращаемого значения:
expression.Replace What, Replacement, [LookAt], [SearchOrder], [MatchCase], [MatchByte], [SearchFormat], [ReplaceFormat]
- variable – переменная (тип данных – Boolean);
- expression – выражение, возвращающее объект Range.
Параметры
Параметр | Описание |
---|---|
What | Искомая подстрока или шаблон*, по которому ищется подстрока в диапазоне ячеек. Обязательный параметр. |
Replacement | Подстрока, заменяющая искомую подстроку. Обязательный параметр. |
LookAt | Указывает правило поиска по полному или частичному вхождению искомой подстроки в текст ячейки: 1 (xlWhole) – поиск полного вхождения искомого текста; 2 (xlPart) – поиск частичного вхождения искомого текста. Необязательный параметр. |
SearchOrder | Задает построчный или постолбцовый поиск: 1 (xlByRows) – построчный поиск; 2 (xlByColumns) – постолбцовый поиск. Необязательный параметр. |
MatchCase | Поиск с учетом или без учета регистра: 0 (False) – поиск без учета регистра; 1 (True) – поиск с учетом регистра. Необязательный параметр. |
MatchByte | Способы сравнения двухбайтовых символов: 0 (False) – двухбайтовые символы сопоставляются с однобайтовыми эквивалентами; 1 (True) – двухбайтовые символы сопоставляются только с двухбайтовым символами. Необязательный параметр. |
SearchFormat | Формат поиска. Необязательный параметр. |
ReplaceFormat | Формат замены. Необязательный параметр. |
* Смотрите знаки подстановки для шаблонов, которые можно использовать в параметре What.
Макрос поиска ячейки с выпадающим списком
Допустим у нас имеется таблица Excel сформированная в результате экспорта журнала фактур из истории взаиморасчетов с клиентами фирмы, как показано ниже на рисунке:
Нам необходимо найти все выпадающие списки или определить каким ячейкам присвоена проверка вводимых данных, создана инструментом: «ДАННЫЕ»-«Работа с данными»-«Проверка данных».
В программе Excel по умолчанию есть встроенный инструмент для поиска ячеек с проверкой правил вводимых значений. Чтобы его использовать следует выбрать: ГЛАВНАЯ»-«Редактирование»-«Найти и выделить»-«Выделить группу ячеек». В появившемся диалоговом окне следует отметить опцию «проверка данных» и нажать на кнопку ОК. Но как всегда более гибким решением является написание своего специального макроса. Ведь в такие случаи всегда можно усовершенствовать инструмент и дописать много других полезных функций. А этот код макроса послужит прекрасным началом программы.
Откройте редактор макросов Visual Basic (ALT+F11) и создайте новый модуль выбрав в редакторе инструмент: «Insert»-«Module». В созданный модуль введите VBA код макроса:
SubProvDan()
DimiAs Long
Dimdiapaz1AsRange
Dimdiapaz2AsRange
Setdiapaz1 = Application.Range(ActiveSheet.Range("A1"), _
ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell))
On Error Resume Next
Fori = 1Todiapaz1.Count
IfIsError(diapaz1(i).Validation.Type)Then
Else
Ifdiapaz2Is Nothing Then
Setdiapaz2 = diapaz1(i)
Else
Setdiapaz2 = Application.Union(diapaz2, diapaz1(i))
End If
End If
Next
On Error GoTo0
Ifdiapaz2Is Nothing Then
MsgBox"Ненайдено ниодной ячейки!"
Else
diapaz2.Select
MsgBox"Найдено: "& diapaz2.Count &" ячеек!"
End If
End Sub
Если нужно выделить все ячейки в таблице, которые содержат проверку вводимых значений включенной инструментом «Проверка данных», тогда выберите инструмент: «РАЗРАБОТЧИК»-«Код»-«Макросы»-«ProvDan»-«Выполнить».
В результате выделились 14 ячеек в столбце G, для которых включена проверка данных в стиле выпадающего списка:
В данном коде мы сначала выделяем все ячейки на текущем листе с помощью инструкции:
Cells.Select
После, определяем диапазон ячеек на листе, который использует исходная таблица и с которыми будет работать наш макрос. Чтобы определить диапазон таблицы на рабочем листе Excel, мы могли бы использовать свойство UsedRange при создании экземпляра объекта Range в переменной diapaz1. Данное свойство охватывает только непустые ячейки, а это может быть даже несмежный диапазон. Но таблица может содержать пустые ячейки для, которых присвоена проверка ввода значений. Чтобы наш макрос не игнорировал пустые ячейки внутри таблицы мы определяем смежный (неразрывный) диапазон, который начинается с ячейки A1 и заканчивается последней используемой ячейкой на рабочем листе Excel.
Set diapaz1 = Application.Range(ActiveSheet.Range(“A1”), ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell))
Последняя ячейка находиться наиболее отдаленно от ячейки A1 (в данном примере – это G15) и была использована на листе (это обязательное условие). При чем использована в прямом смысле, она может даже не содержать значения, но иметь измененный числовой формат, другой цвет фона, другие границы, объединение и т.п. Чтобы найти последнюю используемую ячейку на листе стандартными средствами Excel, выберите инструмент: «ГЛАВНАЯ»-«Редактирование»-«Найти и выделить»-«Выделить группу ячеек».
В появившемся окне следует выбрать опцию «последнюю ячейку». А после просто нажать ОК. Курсор клавиатуры сразу переместиться на последнюю используемую ячейку на рабочем листе Excel.
Можно даже при создании экземпляра объекта Range в переменной diapaz1 использовать диапазон целого листа. Для этого просто замените выше описанную инструкцию на:
Set diapaz1 = Selection
Так на первый взгляд даже проще, но тогда макрос будет проверять все ячейки на листе и потребует больше ресурсов. Особенно если мы при изменении этой инструкции не удалим инструкцию выделения всех ячеек на листе Excel. Таким кодом макроса, можно существенно снизить производительность работы программы Excel при его выполнении. Поэтому так делать не рекомендуется. Проверяйте ячейки только те, которые были использованы на листе. Так вы получите в десятки раз меньший диапазон и выше производительность макроса.
Далее в коде макроса перед циклом прописана инструкция для выключения обработки ошибок, выполняемых в коде.
On Error Resume Next
Но после конца цикла обработка ошибок снова включается.
On Error GoTo 0
Внутри цикла проверяться по отдельности все ячейки на наличие включенной проверки вводимых значений инструментом «Проверка данных». Если ячейка содержит проверку вводимых значений?
If IsError(diapaz1(i).Validation.Type) Then
Тогда она присоединяется к диапазону ячеек, находящихся в переменной diapaz2.
Set diapaz2 = Application.Union(diapaz2, diapaz1(i))
В конце кода выделяется несмежный диапазон переменной diapaz2, который включает в себя все выпадающие списки на текущем рабочем листе Excel. И сразу же выводиться сообщение о количестве найденных и выделенных ячеек в этом же диапазоне.
MsgBox “Найдено: ” & diapaz2.Count & ” ячеек!”
Поиск функцией Find
Гораздо быстрее обычного перебора и при этом довольно гибкий. В простейшем случае, чтобы найти в колонке A ячейку, содержащую “123” достаточно такого кода:
Sheets("Данные").Select Set fcell = Columns("A:A").Find("123") If Not fcell Is Nothing Then MsgBox "Нашел в строке: " + CStr(fcell.Row) End If
Вкратце опишу что делают строчки данного кода:
1-я строка: Выбираем в книге лист “Данные”;
2-я строка: Осуществляем поиск значения “123” в колонке “A”, результат поиска будет в fcell;
3-я строка: Если удалось найти значение, то fcell будет содержать Range-объект, в противном случае – будет пустой, т.е. Nothing.
Полностью синтаксис оператора поиска выглядит так:
Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
What – Строка с текстом, который ищем или любой другой тип данных Excel
After – Ячейка, после которой начать поиск. Обратите внимание, что это должна быть именно единичная ячейка, а не диапазон. Поиск начинается после этой ячейки, а не с нее. Поиск в этой ячейке произойдет только когда весь диапазон будет просмотрен и поиск начнется с начала диапазона и до этой ячейки включительно.
LookIn – Тип искомых данных. Может принимать одно из значений: xlFormulas (формулы), xlValues (значения), или xlNotes (примечания).
LookAt – Одно из значений: xlWhole (полное совпадение) или xlPart (частичное совпадение).
SearchOrder – Одно из значений: xlByRows (просматривать по строкам) или xlByColumns (просматривать по столбцам)
SearchDirection – Одно из значений: xlNext (поиск вперед) или xlPrevious (поиск назад)
MatchCase – Одно из значений: True (поиск чувствительный к регистру) или False (поиск без учета регистра)
MatchByte – Применяется при использовании мультибайтных кодировок: True (найденный мультибайтный символ должен соответствовать только мультибайтному символу) или False (найденный мультибайтный символ может соответствовать однобайтному символу)
SearchFormat – Используется вместе с FindFormat. Сначала задается значение FindFormat (например, для поиска ячеек с курсивным шрифтом так: Application.FindFormat.Font.Italic = True), а потом при использовании метода Find указываем параметр SearchFormat = True. Если при поиске не нужно учитывать формат ячеек, то нужно указать SearchFormat = False.
Чтобы продолжить поиск, можно использовать FindNext (искать “далее”) или FindPrevious (искать “назад”).
Примеры поиска функцией Find
Пример 1: Найти в диапазоне “A1:A50” все ячейки с текстом “asd” и поменять их все на “qwe”
With Worksheets(1).Range("A1:A50") Set c = .Find("asd", LookIn:=xlValues) Do While Not c Is Nothing c.Value = "qwe" Set c = .FindNext(c) Loop End With
Обратите внимание: Когда поиск достигнет конца диапазона, функция продолжит искать с начала диапазона. Таким образом, если значение найденной ячейки не менять, то приведенный выше пример зациклится в бесконечном цикле. Поэтому, чтобы этого избежать (зацикливания), можно сделать следующим образом:
Пример 2: Правильный поиск значения с использованием FindNext, не приводящий к зацикливанию.
With Worksheets(1).Range("A1:A50") Set c = .Find("asd", lookin:=xlValues) If Not c Is Nothing Then firstResult = c.Address Do c.Font.Bold = True Set c = .FindNext(c) If c Is Nothing Then Exit Do Loop While c.Address <> firstResult End If End With
В ниже следующем примере используется другой вариант продолжения поиска – с помощью той же функции Find с параметром After. Когда найдена очередная ячейка, следующий поиск будет осуществляться уже после нее. Однако, как и с FindNext, когда будет достигнут конец диапазона, Find продолжит поиск с его начала, поэтому, чтобы не произошло зацикливания, необходимо проверять совпадение с первым результатом поиска.
Пример 3: Продолжение поиска с использованием Find с параметром After.
With Worksheets(1).Range("A1:A50") Set c = .Find("asd", lookin:=xlValues) If Not c Is Nothing Then firstResult = c.Address Do c.Font.Bold = True Set c = .Find("asd", After:=c, lookin:=xlValues) If c Is Nothing Then Exit Do Loop While c.Address <> firstResult End If End With
Следующий пример демонстрирует применение SearchFormat для поиска по формату ячейки. Для указания формата необходимо задать свойство FindFormat.
Пример 4: Найти все ячейки с шрифтом “курсив” и поменять их формат на обычный (не “курсив”)
lLastRow = Cells.SpecialCells(xlLastCell).Row lLastCol = Cells.SpecialCells(xlLastCell).Column Application.FindFormat.Font.Italic = True With Worksheets(1).Range(Cells(1, 1), Cells(lLastRow, lLastCol)) Set c = .Find("", SearchFormat:=True) Do While Not c Is Nothing c.Font.Italic = False Set c = .Find("", After:=c, SearchFormat:=True) Loop End With
Примечание: В данном примере намеренно не используется FindNext для поиска следующей ячейки, т.к. он не учитывает формат (статья об этом: https://support.microsoft.com/ru-ru/kb/282151)
Коротко опишу алгоритм поиска Примера 4. Первые две строки определяют последнюю строку (lLastRow) на листе и последний столбец (lLastCol). 3-я строка задает формат поиска, в данном случае, будем искать ячейки с шрифтом Italic. 4-я строка определяет область ячеек с которой будет работать программа (с ячейки A1 и до последней строки и последнего столбца). 5-я строка осуществляет поиск с использованием SearchFormat. 6-я строка – цикл пока результат поиска не будет пустым. 7-я строка – меняем шрифт на обычный (не курсив), 8-я строка продолжаем поиск после найденной ячейки.
Хочу обратить внимание на то, что в этом примере я не стал использовать “защиту от зацикливания”, как в Примерах 2 и 3, т.к. шрифт меняется и после “прохождения” по всем ячейкам, больше не останется ни одной ячейки с курсивом.
Свойство FindFormat можно задавать разными способами, например, так:
With Application.FindFormat.Font .Name = "Arial" .FontStyle = "Regular" .Size = 10 End With
Следующий пример – применение функции Find для поиска последней ячейки с заполненными данными. Использованные в Примере 4 SpecialCells находит последнюю ячейку даже если она не содержит ничего, но отформатирована или в ней раньше были данные, но были удалены.
Пример 5: Найти последнюю колонку и столбец, заполненные данными
Set c = Worksheets(1).UsedRange.Find("*", SearchDirection:=xlPrevious) If Not c Is Nothing Then lLastRow = c.Row: lLastCol = c.Column Else lLastRow = 1: lLastCol = 1 End If MsgBox "lLastRow=" & lLastRow & " lLastCol=" & lLastCol
В этом примере используется UsedRange, который так же как и SpecialCells возвращает все используемые ячейки, в т.ч. и те, что были использованы ранее, а сейчас пустые. Функция Find ищет ячейку с любым значением с конца диапазона.
При поиске можно так же использовать шаблоны, чтобы найти текст по маске, следующий пример это демонстрирует.
Пример 6: Выделить красным шрифтом ячейки, в которых текст начинается со слова из 4-х букв, первая и последняя буквы “т”, при этом после этого слова может следовать любой текст.
With Worksheets(1).Cells Set c = .Find("т??т*", LookIn:=xlValues, LookAt:=xlWhole) If Not c Is Nothing Then firstResult = c.Address Do c.Font.Color = RGB(255, 0, 0) Set c = .FindNext(c) If c Is Nothing Then Exit Do Loop While c.Address <> firstResult End If End With
Для поиска функцией Find по маске (шаблону) можно применять символы:
* – для обозначения любого количества любых символов;
? – для обозначения одного любого символа;
~ – для обозначения символов *, ? и ~. (т.е. чтобы искать в тексте вопросительный знак, нужно написать ~?, чтобы искать именно звездочку (*), нужно написать ~* и наконец, чтобы найти в тексте тильду, необходимо написать ~~)
Поиск даты с помощью Find
Если необходимо найти текущую дату или какую-то другую дату на листе Excel или в диапазоне с помощью Find, необходимо учитывать несколько нюансов:
- Тип данных Date в VBA представляется в виде #[месяц]/[день]/[год]#, соответственно, если необходимо найти фиксированную дату, например, 01 марта 2018 года, необходимо искать #3/1/2018#, а не “01.03.2018”
- В зависимости от формата ячеек, дата может выглядеть по-разному, поэтому, чтобы искать дату независимо от формата, поиск нужно делать не в значениях, а в формулах, т.е. использовать LookIn:=xlFormulas
Приведу несколько примеров поиска даты.
Пример 7: Найти текущую дату на листе независимо от формата отображения даты.
d = Date Set c = Cells.Find(d, LookIn:=xlFormulas, LookAt:=xlWhole) If Not c Is Nothing Then MsgBox "Нашел" Else MsgBox "Не нашел" End If
Пример 8: Найти 1 марта 2018 г.
d = #3/1/2018# Set c = Cells.Find(d, LookIn:=xlFormulas, LookAt:=xlWhole) If Not c Is Nothing Then MsgBox "Нашел" Else MsgBox "Не нашел" End If
Искать часть даты – сложнее. Например, чтобы найти все ячейки, где месяц “март”, недостаточно искать “03” или “3”. Не работает с датами так же и поиск по шаблону. Единственный вариант, который я нашел – это выбрать формат в котором месяц прописью для ячеек с датами и искать слово “март” в xlValues.
Тем не менее, можно найти, например, 1 марта независимо от года.
Пример 9: Найти 1 марта любого года.
d = #3/1/1900# Set c = Cells.Find(Format(d, "m/d/"), LookIn:=xlFormulas, LookAt:=xlPart) If Not c Is Nothing Then MsgBox "Нашел" Else MsgBox "Не нашел" End If
Предназначение и синтаксис метода Range.Find
Метод Find объекта Range предназначен для поиска ячейки и сведений о ней в заданном диапазоне по ее значению, формуле и примечанию. Чаще всего этот метод используется для поиска в таблице ячейки по слову, части слова или фразе, входящей в ее значение.
Синтаксис метода Range.Find
Expression.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat) |
Expression – это переменная или выражение, возвращающее объект Range, в котором будет осуществляться поиск.
В скобках перечислены параметры метода, среди них только What является обязательным.
Метод Range.Find возвращает объект Range, представляющий из себя первую ячейку, в которой найдена поисковая фраза (параметр What). Если совпадение не найдено, возвращается значение Nothing.
Параметры метода Range.Find
Наименование | Описание |
Обязательный параметр | |
What | Данные для поиска, которые могут быть представлены строкой или другим типом данных Excel. Тип данных параметра – Variant. |
Необязательные параметры | |
After | Ячейка, после которой следует начать поиск. |
LookIn | Уточняет область поиска. Список констант xlFindLookIn:
|
LookAt | Поиск частичного или полного совпадения. Список констант xlLookAt:
|
SearchOrder | Определяет способ поиска. Список констант xlSearchOrder:
|
SearchDirection | Определяет направление поиска. Список констант xlSearchDirection:
|
MatchCase | Определяет учет регистра:
|
MatchByte | Условия поиска при использовании двухбайтовых кодировок:
|
SearchFormat | Формат поиска – используется вместе со свойством Application.FindFormat. |
* Примечания имеют две константы с одним значением. Проверяется очень просто: MsgBox xlComments
и MsgBox xlNotes
.
** Тесты показали неработоспособность метода Range.Find с константой xlFormulas в моей версии VBA Excel.
В справке Microsoft тип данных всех параметров, кроме SearchDirection, указан как Variant.
Процедура поиска и замены данных — одна из самых востребованных в Excel. Базовая процедура позволяет заменить за один заход только одно значение, но зато множеством способов. Рассмотрим, как эффективно работать с ней.
Горячие клавиши
Сочетания клавиш ниже заметно ускорят работу с инструментом:
- Для запуска диалогового окна поиска — CTRL+F
- Для запуска окна поиска и замены — Ctrl+H
- Для выделения всех найденных ячеек (после нажатия кнопки «найти все» — CTRL+A
- Для очистки всех найденных ячеек — CTRL+Delete
- Для ввода одних и тех же данных во все найденные ячейки — Ввод текста, CTRL+Enter
Смотрите gif-примеры: здесь мы производим поиск ячеек с дальнейшим их редактированием. В отличие от замены, редактирование найденных ячеек позволяет быстро менять их содержимое целиком.
Процедура «Найти и заменить» не работает
Я сам когда-то неоднократно впадал в ступор в подобных ситуациях. Уверен и видишь своими глазами, что искомый паттерн в данных есть, но Excel при выполнении процедуры поиска сообщает:
или при замене:
Так вот, совет нажать кнопку «Параметры» в обоих этих сообщениях действительно полезен. Там наверняка активен чекбокс «Учитывать регистр» или «Ячейка целиком», которые мешают Excel найти искомое. Excel сохраняет конфигурацию последнего поиска.
Подстановочные знаки, или как найти «звездочку»
Сухая официальная справка по Excel сообщает, что можно использовать подстановочные символы «*» и «?». Что они означают несколько символов, включая их отсутствие, и один любой символ. И что их можно использовать для соответствующих процедур поиска.
Чего не говорит справка — это того, что в комбинации с опцией «ячейка целиком» эти символы позволяют, не прибегая к помощи расширенного фильтра и процедуры поиска группы ячеек:
- Находить ячейки, заканчивающиеся на определенный символ, слово или текст
- Аналогично, находить ячейки, начинающиеся с определенного символа, слова или текста
- Находить непустые ячейки
На примере ниже мы находим все двузначные числа, затем числа, заканчивающиеся и начинающиеся на 7, и, наконец, все непустые ячейки. Напомню, выделить все результаты поиска помогает горячее сочетание клавиш Ctrl+A
Так а как найти звездочку?
Действительно, забыл. Чтобы найти «звездочку», нужно в окошке поиска ставить перед ней знак «~» (тильда), находится обычно под клавишей Esc. Это позволяет экранировать «звездочку», как и вопросительный знак, и не воспринимать их как служебные символы.
Знаки подстановки для поисковой фразы
Условные знаки в шаблоне поисковой фразы:
- ? – знак вопроса обозначает любой отдельный символ;
- * – звездочка обозначает любое количество любых символов, в том числе ноль символов;
- ~ – тильда ставится перед ?, * и ~, чтобы они обозначали сами себя (например, чтобы тильда в шаблоне обозначала сама себя, записать ее нужно дважды: ~~).
Источники
- https://vremya-ne-zhdet.ru/vba-excel/metod-range-replace/
- https://exceltable.com/vba-macros/makros-poiska-yacheyki
- https://codernotes.ru/articles/vba/poisk-na-liste-excel.html
- https://vremya-ne-zhdet.ru/vba-excel/metod-range-find/
- https://SEMTools.guru/ru/change-replace-tools/bulk-replace/