Excel vba ближайшее значение

В данном примере предоставлен код VBA-макроса с пояснениями для поиска ближайшего значения указанному на всех листах книги в Excel.

Как найти ближайшее значение заданному на листах книги макросом VBA

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

различные денные.

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

Для открытия редактора используйте Alt+F11. В открывшемся окне нажмите правой кнопкой мыши на «Modules», выберите пункт «Insert» и в раскрывшемся списке – пункт «Module»:

Insert.

Введите код макроса в открывшемся окне для ввода кода:

Module.

Sub Module1()
   Dim strFindData As String
   Dim tempArr() As Integer
   Dim rgFound As Range
   Dim i As Integer
   Dim indexTempArr As Integer
   strFindData = InputBox("Введите данные для поиска")
   'проверка введенных данных
   If IsNumeric(strFindData) = False Then
      MsgBox ("Вы ввели не число")
      Exit Sub
   Else:
        strFindData = strFindData * 1
   End If
    For i = 1 To Worksheets.Count
        With Worksheets(i).UsedRange.Cells
            Set rgFound = .Find(strFindData, LookIn:=xlValues, LookAt:=xlWhole)
            If Not rgFound Is Nothing Then
                MsgBox ("Найдено точное совпадение - " & rgFound & " на " & Worksheets(i).Name)
                Exit Sub
            'поиск ячеек с числовыми значениями и запись этих значений в массив
            Else:
                For Each cl In Worksheets(i).UsedRange.Cells
                    If cl <> "" And IsNumeric(cl) Then
                        ReDim Preserve tempArr(indexTempArr)
                        tempArr(indexTempArr) = cl.Value * 1
                        indexTempArr = indexTempArr + 1
                    End If
                Next
            End If
      End With
   Next
'сортировка массива по возрастанию
Dim k As Integer
Dim sortedArr As Variant
   sortedArr = SortingArr(tempArr)
   Worksheets.Add.Name = "Result"
   For l = LBound(sortedArr) To UBound(sortedArr)
      Worksheets("Result").Range("B" & l + 1) = sortedArr(l)
   Next l
   Worksheets("Result").Range("C1").FormulaLocal = _
   "=ЕСЛИ(B1<" & strFindData & ";СУММПРОИЗВ(МАКС((B1:B" & UBound(sortedArr) + 1 & _
   "<" & strFindData & ")*(B1:B" & UBound(sortedArr) + 1 & ")));B1)"
   Dim resultValue As Integer
   resultValue = Worksheets("Result").Range("C1").Value
   Sheets("Result").Application.DisplayAlerts = False
   Worksheets("Result").Delete
   MsgBox ("Найдено приближенное значение - " & resultValue)
   'MsgBox ("Поиск не дал результатов")
End Sub
Function SortingArr(myTempArr, Optional First As Long = -1, Optional Last As Long = -1) As Variant
 Dim i As Long, j As Long, MidEl As Variant, t As Variant
    On Error Resume Next
    First = IIf(First = -1, LBound(myTempArr), First)
    Last = IIf(Last = -1, UBound(myTempArr), Last)
    i = First
    j = Last
    MidEl = myTempArr((First + Last) 2)
    Do While i <= j
        If myTempArr(i) < MidEl Then
            i = i + 1
        Else
            If myTempArr(j) > MidEl Then
                j = j - 1
            Else
                t = myTempArr(i)
                myTempArr(i) = myTempArr(j)
                myTempArr(j) = t
                i = i + 1
                j = j - 1
            End If
        End If
    Loop
    If First < j Then Call SortingArr(myTempArr, First, j)
    If i < Last Then Call SortingArr(myTempArr, i, Last)
    SortingArr = myTempArr
End Function

Теперь для поиска ближайшего значения заданному на всех листах можно воспользоваться макросом, для вызова которого необходимо выбрать вкладку «Вид», нажать на кнопку «Макросы» (ALT+F8), в открывшемся окне выбрать название требуемого модуля и нажать «Выполнить»:

Макросы.

В окне нашего пользовательского VBA-макроса введите значение 78 для поиска на всех листах книги. И нажмите ОК:

VBA-макрос.

В результате макрос нас информирует о том, что найдено значение 78 на Лист2:

найдено значение.

Теперь введите значение 35 которого нет на листах. Но наш VBA макрос не растерялся. В место традиционного «Значения не найдено :(» он выполнил поиск и нашел нам максимально приблизительное значение к исходному (35):

приблизительное значение.

Теперь чтобы узнать на каком листе находится найденное максимально приближенное значение нам всего лишь нужно еще раз в форму поиска ввести его (29) для повторного поиска.



Логика работы макроса для поиска ближайшего значения заданному на всех листах

В первую очередь организуем ввод данных через InputBox и проверку типа данных, полученных на вход (IsNumeric). Если введено не число, макрос прекратит свою работу с соответствующим сообщением.

Последующий код макроса можно условно разделить на две части: поиск точного совпадения числа и нахождение ближайшего ему значения.

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

Примечание: поскольку поиск ведется по всем листам книги, используем выражение «For i = 1 To Worksheets.Count» для перебора листов в цикле. Поскольку ячеек на листе может быть огромное множество, с помощью свойства UsedRange организовываем поиск только в используемой области ячеек.

Если точное совпадение не найдено, выполняется участок кода, который выбирает все числовые значения из ячеек всех листов и заполняет ими массив данных tempArr с последующей сортировкой с использованием функции Function QuickSort (реализована отдельно для удобства).

Для упрощения кода, данные из отсортированного массива передаются в ячейки нового листа (Worksheets.Add.Name = «Result») с названием «Result». Затем в соседней ячейке используется формула Excel для поиска ближайшего числа в диапазоне:

Поскольку новый лист необходим только для промежуточных расчетов, полученное максимально приближенное значение передаем в переменную resultValue, а лист «Result» удаляем. Для вывода искомого значения используем метод MsgBox («Найдено приближенное — » & resultValue).

Полезный совет! Чтобы выполнить макросом поиск по всех листах книги Excel не только числовые значение, а и текстовые измените параметры функции .Find(), которая находится на 29-ой строке кода. Так же не забудьте отключить проверку типа данных IsNumeric(strFindData) закомментировав строки 16-18.

Скачать макрос поиска ближайшего значения на всех листах

Примечание: при выполнении данного макроса могут возникать некоторые ошибки, так как во избежание нагромождения кода в нем были упущены проверки типов данных и некоторые другие условия. Также можно добавить новую функцию, выполняющую поиск ближайшего значения путем перебора элементов массива вместо использования временного листа «Result».

 

Добрый день.

Есть таблица со списком чего-то (назовем n). У каждого n есть координаты долготы и широты и по 2 критерия. Нужно найти для каждого n ближайшие к его координатам координаты других n (1 больше и 1 меньше), учитывая 2 критерия (чтобы критерии n начального совпадали с критериями n искомого) и подставить в столбцы «Координаты1, Координаты2….» Данные из столбца «Наименование» от n, которые мы нашли по ближайшим координатам. Третий день сижу и не могу придумать как это сделать макросом. Подскажите советом или куском кода. Файл во вложении.

Прикрепленные файлы

  • пример.xlsx (10.62 КБ)

 

msi2102

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

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

Hellmaster, А сортировка Вам не поможет

 

msi2102, сортировку надо будет делать по каждому n, которых у меня больше 1000. Может есть какое-то решение вроде поискпоз(макс…) или с вба вроде приблизительного поиска, типа find или like?

Изменено: Hellmaster01.08.2019 12:38:29

 

msi2102

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

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

Я из Вашего описания не понял, что именно надо и как это должно выглядеть, Вы в примере покажите как должно быть, а не просто данные которые есть.

 

Попытался объяснить в файле во вложении. Красить ячейки не надо. Я для наглядности, что откуда брать.

Прикрепленные файлы

  • пример.xlsx (11.17 КБ)

Изменено: Hellmaster01.08.2019 12:51:22

 

msi2102

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

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

Поиск осуществляется на основании критериев 1 и 2, то есть на основании критериев у нас образуются группы и в них мы ищем данные? Или какой-то другой принцип.

 

msi2102, все верно. есть группа по критерию 1 и группа по критерию 2. нужно проверить, правильно ли привязаны к наименованию n способом, который я описал выше

 

см. вложение в колонках координаты указан № строки, содержащей данные с координатами ближайшими к текущим данным

Прикрепленные файлы

  • Книга2.xlsx (12.02 КБ)

Изменено: Ігор Гончаренко01.08.2019 13:55:18

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

msi2102

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

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

Hellmaster, посмотрите файл. Это должно быть так?

 

msi2102, Все так, кроме ячейки I18. Там координаты должны сопоставиться с ячейкой E20 и подтянуть ячейку С20 в ячейку I18

 

Ігор Гончаренко, Ваш вариант подтягивает не те значения.  

 

у меня в файле написано:
строка 2 ближайшая точка с такими же критериями в 26 строке
строка 3 ближайшая в 18, след в 11 и самая дальняя в 27 строке
….
строка 30 ближайшая в строке 15, след в 19, 16, 7

Изменено: Ігор Гончаренко01.08.2019 14:45:40

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

Возможно, я не так объяснил, что должно произойти в файле. Нужно пройти по каждой n и сопоставить координаты с координатами остальных n. То есть, есть n1, n2, n3 с координатами долготы 56,57,58 соответственно (с учетом, что все эти n находятся в одной группе по совпадению двух критериев). Нужно подтянуть к n1 значение из столбца «Название». Координаты n1 = 56. Верхнее значение для поиска для n1 будет 57, т.к. это следующее после 56. Соответственно, в столбец «Координаты1» подтягивается значение столбца «Название» от n2. Нижнего значения для поиска не будет, т.к. в этой группе у n1 наименьшее число по координатам. Перейти к n2 и сделать то же самое. К n2 подтянется значение столбца «Название» n3 как верхнее и n1 как нижнее.

 

msi2102

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

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

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

 

msi2102, к строке не привязывается. Нужно найти ближайшее значение по координатам в одной группе. Группы разбиты правильно. Расставить в тех ячейках, у которых будет что-то подтягиваться. Исправил в названии столбцов, чтобы не путаться.

 

msi2102

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

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

#16

01.08.2019 15:00:02

Цитата
Hellmaster написал:
Расставить в тех ячейках, у которых будет что-то подтягиваться.

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

Изменено: msi210201.08.2019 15:08:39

 

msi2102, в идеале, должно все подтянуться, найдя верхнее и нижнее каждого n. Подтягивать нужно в последние 4 столбца, в соответствии с строкой искомого n. Сортировка да. Столбцов с критерием будет 2, но в каждом до 100 разных критериев. Критерии определенные. Насчет пустых хороший вопрос… Я упустил этот момент. Видимо, если при поиске координат попадет на строку с пустой ячейкой по столбцу С, то продолжить поиск до следующих координат.

Изменено: Hellmaster01.08.2019 15:12:45

 

Андрей VG

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

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

Excel 2016, 365

Доброе время суток.
Вариант на Power Query для поиска ближайшей точки к данной в пределах равных критериев с допущением, что широты где-то рядом :)

 

БМВ

Модератор

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

Excel 2013, 2016

#19

01.08.2019 15:31:33

Цитата
Hellmaster написал:
больше и меньше VBA

Я вот не понимаю что может быть больше и меньше VBA  :qstn:  :D  

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

 

так?

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

Ігор Гончаренко, да. Все верно. Как вы это сделали?

 

Андрей VG, можно подробнее? Я не работал с Query.

 

однако, в начале я искал ближайшие по расстоянию
собственно, искал не я, а макрос, который я написал

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

Андрей VG

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

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

Excel 2016, 365

#24

01.08.2019 15:51:59

Цитата
Hellmaster написал:
Я не работал с Query.

А зачем, если

Цитата
Hellmaster написал:
Ігор Гончаренко , да. Все верно

Вы же хотели макрос?
Но, на всякий случай на правах рекламы

Книга «Скульптор данных в Excel с Power Query»

 

Андрей VG, конечно, идеально было бы макрос. Желательно скелет макроса, который я бы смог дописать, доделать. Но Power Query тоже полезный навык и было бы полезно и его изучить)

 

Ігор Гончаренко, а можете показать макрос?

 

Ігор Гончаренко

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

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

#27

01.08.2019 16:32:36

Код
Sub FindNearestKoord()
  Dim a, r&(1 To 2), n(1 To 4), i&
  a = Cells(2, 1).Resize(Cells(Rows.Count, 1).End(xlUp).Row - 1, 9)
  For r(1) = 1 To UBound(a)
    For i = 1 To 4:  n(i) = Empty:  Next
    r(2) = 1:  Application.StatusBar = r(1) & " " & UBound(a)
    Do While r(2) <= UBound(a)
      If a(r(1), 1) = a(r(2), 1) And a(r(1), 2) = a(r(2), 2) And r(1) <> r(2) Then
        If a(r(2), 4) > a(r(1), 4) Then
          If IsEmpty(n(1)) Then n(1) = r(2) Else If a(r(2), 4) < a(n(1), 4) Then n(1) = r(2)
        Else
          If IsEmpty(n(2)) Then n(2) = r(2) Else If a(r(2), 4) > a(n(2), 4) Then n(2) = r(2)
        End If
        If a(r(2), 5) > a(r(1), 5) Then
          If IsEmpty(n(3)) Then n(3) = r(2) Else If a(r(2), 5) < a(n(3), 5) Then n(3) = r(2)
        Else
          If IsEmpty(n(4)) Then n(4) = r(2) Else If a(r(2), 5) > a(n(4), 5) Then n(4) = r(2)
        End If
      End If
      r(2) = r(2) + 1
    Loop
    For i = 1 To 4
      If Not IsEmpty(n(i)) Then a(r(1), i + 5) = a(n(i), IIf(i < 3, 4, 5))
    Next
  Next
  Cells(2, 1).Resize(UBound(a), UBound(a, 2)) = a: Application.StatusBar = False
End Sub

это решение в лоб. понятно на 30 строках все моментально

Программисты — это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!

 

Ігор Гончаренко, спасибо большое

 

Андрей VG

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

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

Excel 2016, 365

Добавил расчёт расстояния по сфере в км. Коректнее будет определяться в случае большой разбежки широт.

 

sokol92

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

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

#30

01.08.2019 17:42:56

Цитата
Андрей VG написал:
на правах рекламы

Здравствуйте, Андрей! Вы отличный агент — книгу купил. :)  

Владимир

Подбор ближайшего значения (текста)

ZamoK

Дата: Четверг, 11.05.2017, 12:53 |
Сообщение № 1

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

Добрый день!

Нужна помощь специалиста VBA.

Настоящая таблица очень большая порядка 8 — 10 тыс. строк на листе «Данные» тоже самое, потому файл обрезан до минимума.

Суть: нужно привести столбец «наименование» к ближайшему подходящему значению с листа «Данные», т.е. заменить значение. Ключом является цифровая часть наименования. Прочитал много тем по замене текста, перепробовал все! Но к сожалению либо печаль, либо куча несоответствий. Потому решил попытать счастья тут. Пробовал обработку найти и заменить, но она не даёт 100% результата. Предположительно думаю должен быть макрос, с использованием библиотек т.к. объём оч внушительный.

Любая помощь, совет, направление :D приветствуется.

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

_2.xlsm
(72.8 Kb)


Я не Гуру, но стремлюсь!

Сообщение отредактировал ZamoKПятница, 12.05.2017, 09:32

 

Ответить

wild_pig

Дата: Четверг, 11.05.2017, 16:20 |
Сообщение № 2

Группа: Проверенные

Ранг: Обитатель

Сообщений: 516


Репутация:

97

±

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


2003, 2013

Хоть бы показали эти самые «соответствия» в файле.

 

Ответить

ZamoK

Дата: Пятница, 12.05.2017, 09:37 |
Сообщение № 3

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

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


Я не Гуру, но стремлюсь!

 

Ответить

sboy

Дата: Пятница, 12.05.2017, 11:00 |
Сообщение № 4

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

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

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


Excel 2010

Добрый день.
Вариант формулой (массива)

Код

=ИНДЕКС(Данные!$A$2:$A$261;МАКС(ЕЧИСЛО(ПОИСК(ПОДСТАВИТЬ(ПОДСТАВИТЬ(Данные!$A$2:$A$261;».»;»»);» «;»»);ПОДСТАВИТЬ(ПОДСТАВИТЬ(B2;».»;»»);» «;»»)))*СТРОКА($A$1:$A$260)))

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

_2-1-.xlsm
(75.2 Kb)


Яндекс: 410016850021169

 

Ответить

ZamoK

Дата: Пятница, 12.05.2017, 14:17 |
Сообщение № 5

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

sboy, Диапазоны: Данные!$A$2:$A$261 и $A$1:$A$260 не постоянны, поэтому оч сложно

Настоящая таблица очень большая порядка 8 — 10 тыс. строк на листе «Данные» тоже самое, потому файл обрезан до минимума.

Меняются ежедневно.


Я не Гуру, но стремлюсь!

 

Ответить

sboy

Дата: Пятница, 12.05.2017, 14:51 |
Сообщение № 6

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

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

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


Excel 2010

Диапазоныне постоянны, поэтому оч сложно

в диспетчер имен «Данные»

Код

=Данные!$A$1:ИНДЕКС(Данные!$A:$A;СЧЁТЗ(Данные!$A:$A))

формула

Код

=ИНДЕКС(Данные;МАКС(ЕЧИСЛО(ПОИСК(ПОДСТАВИТЬ(ПОДСТАВИТЬ(Данные;».»;»»);» «;»»);ПОДСТАВИТЬ(ПОДСТАВИТЬ(B2;».»;»»);» «;»»)))*СТРОКА(Данные)))

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

5045966.xlsm
(75.1 Kb)


Яндекс: 410016850021169

 

Ответить

ZamoK

Дата: Пятница, 12.05.2017, 16:16 |
Сообщение № 7

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

sboy, Вроде все хорошо, только есть номера с двумя точками на конце (я этот момент упустил) формула подхватывает именно его, а нужен без точек.
Файл обновил

И ещё у меня макрос протягивает формулу до конца списка
[vba]

Код

Range(«G2:G» & Cells(Rows.Count, 1).End(xlUp).Row).Formula = [G2].FormulaR1C1 ‘протягиваем формулу

[/vba]
Он её превращает в простую формулу из формулы массива, может как-то по другому протягивать?

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

5363382.xlsm
(74.6 Kb)


Я не Гуру, но стремлюсь!

Сообщение отредактировал ZamoKПятница, 12.05.2017, 16:18

 

Ответить

sboy

Дата: Пятница, 12.05.2017, 16:19 |
Сообщение № 8

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

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

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


Excel 2010

Для формулы массива нужно в коде писать
[vba][/vba]
По поводу двух точек не совсем понял, покажите в файле


Яндекс: 410016850021169

 

Ответить

ZamoK

Дата: Пятница, 12.05.2017, 16:31 |
Сообщение № 9

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

Все ровно результата нет, хоть .FormulaArray хоть .Formula — все ровно убивает массив.


Я не Гуру, но стремлюсь!

 

Ответить

sboy

Дата: Пятница, 12.05.2017, 16:57 |
Сообщение № 10

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

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

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


Excel 2010

[vba]

Код

Sub formula()
    fa = «=INDEX(Данные,MAX(ISNUMBER(SEARCH(SUBSTITUTE(SUBSTITUTE(Данные,»».»»,»»»»),»» «»,»»»»),SUBSTITUTE(SUBSTITUTE(RC[-5],»».»»,»»»»),»» «»,»»»»)))*ROW(Данные)))»
    For Each cl In Range(«G2:G» & Cells(Rows.Count, 1).End(xlUp).Row).Cells
       cl.FormulaArray = fa
    Next cl
End Sub

[/vba]
так работает


Яндекс: 410016850021169

 

Ответить

ZamoK

Дата: Понедельник, 15.05.2017, 08:25 |
Сообщение № 11

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

Не не хочет, или я что не так сделал?

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

6290146.xlsm
(81.1 Kb)


Я не Гуру, но стремлюсь!

Сообщение отредактировал ZamoKПонедельник, 15.05.2017, 08:34

 

Ответить

sboy

Дата: Понедельник, 15.05.2017, 09:27 |
Сообщение № 12

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

Ранг: Участник клуба

Сообщений: 2566


Репутация:

724

±

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


Excel 2010

ZamoK, ваш файл работает нормально, макросом формула нормально вставляется… Что Вы от него ждете?
Если Вы хотите, чтобы заменялись данные в столбце В, то макрос нужно дописывать


Яндекс: 410016850021169

 

Ответить

ZamoK

Дата: Понедельник, 15.05.2017, 09:58 |
Сообщение № 13

Группа: Проверенные

Ранг: Обитатель

Сообщений: 268


Репутация:

4

±

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


Excel 2003-2016

sboy, Вроде все хорошо, только есть номера с двумя точками на конце (я этот момент упустил) формула подхватывает именно его, а нужен без точек.

Вот я про что! , но если это никак наверно автозамену надо будет дописать или как-то по другому можно решить?


Я не Гуру, но стремлюсь!

 

Ответить

Поиск какого-либо значения в ячейках Excel довольно часто встречающаяся задача при программировании какого-либо макроса. Решить ее можно разными способами. Однако, в разных ситуациях использование того или иного способа может быть не оправданным. В данной статье я рассмотрю 2 наиболее распространенных способа.

Довольно простой в реализации способ. Например, найти в колонке «A» ячейку, содержащую «123» можно примерно так:

Минусами этого так сказать «классического» способа являются: медленная работа и громоздкость. А плюсом является его гибкость, т.к. таким способом можно реализовать сколь угодно сложные варианты поиска с различными вычислениями и т.п.

Гораздо быстрее обычного перебора и при этом довольно гибкий. В простейшем случае, чтобы найти в колонке A ячейку, содержащую «123» достаточно такого кода:

Вкратце опишу что делают строчки данного кода:
1-я строка: Выбираем в книге лист «Данные»;
2-я строка: Осуществляем поиск значения «123» в колонке «A», результат поиска будет в fcell;
3-я строка: Если удалось найти значение, то fcell будет содержать Range-объект, в противном случае — будет пустой, т.е. Nothing.

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

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 (искать «назад»).

Пример 1: Найти в диапазоне «A1:A50» все ячейки с текстом «asd» и поменять их все на «qwe»

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

Пример 2: Правильный поиск значения с использованием FindNext, не приводящий к зацикливанию.

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

Пример 3: Продолжение поиска с использованием Find с параметром After.

Следующий пример демонстрирует применение SearchFormat для поиска по формату ячейки. Для указания формата необходимо задать свойство FindFormat.

Пример 4: Найти все ячейки с шрифтом «курсив» и поменять их формат на обычный (не «курсив»)

Примечание: В данном примере намеренно не используется FindNext для поиска следующей ячейки, т.к. он не учитывает формат (статья об этом: https://support.microsoft.com/ru-ru/kb/282151)

Коротко опишу алгоритм поиска Примера 4. Первые две строки определяют последнюю строку (lLastRow) на листе и последний столбец (lLastCol). 3-я строка задает формат поиска, в данном случае, будем искать ячейки с шрифтом Italic. 4-я строка определяет область ячеек с которой будет работать программа (с ячейки A1 и до последней строки и последнего столбца). 5-я строка осуществляет поиск с использованием SearchFormat. 6-я строка — цикл пока результат поиска не будет пустым. 7-я строка — меняем шрифт на обычный (не курсив), 8-я строка продолжаем поиск после найденной ячейки.

Хочу обратить внимание на то, что в этом примере я не стал использовать «защиту от зацикливания», как в Примерах 2 и 3, т.к. шрифт меняется и после «прохождения» по всем ячейкам, больше не останется ни одной ячейки с курсивом.

Следующий пример — применение функции Find для поиска последней ячейки с заполненными данными. Использованные в Примере 4 SpecialCells находит последнюю ячейку даже если она не содержит ничего, но отформатирована или в ней раньше были данные, но были удалены.

В этом примере используется UsedRange, который так же как и SpecialCells возвращает все используемые ячейки, в т.ч. и те, что были использованы ранее, а сейчас пустые. Функция Find ищет ячейку с любым значением с конца диапазона.

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

Пример 6: Выделить красным шрифтом ячейки, в которых текст начинается со слова из 4-х букв, первая и последняя буквы «т», при этом после этого слова может следовать любой текст.

Для поиска функцией Find по маске (шаблону) можно применять символы:
* — для обозначения любого количества любых символов;
? — для обозначения одного любого символа;

. (т.е. чтобы искать в тексте вопросительный знак, нужно написать

Если необходимо найти текущую дату или какую-то другую дату на листе Excel или в диапазоне с помощью Find, необходимо учитывать несколько нюансов:

Приведу несколько примеров поиска даты.

Пример 7: Найти текущую дату на листе независимо от формата отображения даты.

Пример 8: Найти 1 марта 2018 г.

Искать часть даты — сложнее. Например, чтобы найти все ячейки, где месяц «март», недостаточно искать «03» или «3». Не работает с датами так же и поиск по шаблону. Единственный вариант, который я нашел — это выбрать формат в котором месяц прописью для ячеек с датами и искать слово «март» в xlValues.

Тем не менее, можно найти, например, 1 марта независимо от года.

Пример 9: Найти 1 марта любого года.

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

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

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

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

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

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

* Примечания имеют две константы с одним значением. Проверяется очень просто: MsgBox xlComments и MsgBox xlNotes .
** Тесты показали неработоспособность метода Range.Find с константой xlFormulas в моей версии VBA Excel.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Методы объекта Range, использующие команды Excel

В данном разделе рассматриваются методы, использующие встроенные в Excel команды. Эти методы позволяют эффективно работать с диапазоном: заполнять его элементами по образцу, сортировать, фильтровать и консолидировать данные, строить итоговую таблицу и создавать сценарии, решать нелинейное уравнение с одной неизвестной.

Метод DataSeries (прогрессия) создает профессии. Вручную метод DataSeries выполняется с помощью команды Правка, Заполнить, Прогрессия (Edit, Fill, Series).

Объект.DataSeries(rowcol, type, date, step, stop, trend)

Диапазон с начальными данными прогрессии. Метод DataSeries позволяет одновременно строить несколько однотипных профессий с одинаковым шагом, но различными начальными элементами

Задает, вводятся профессии по строкам или столбцам. Допустимые значения:

Определяет тип прогрессии. Допустимые значения:

Определяет тип последовательности дат, если параметр type принимает значение xlChronological. Допустимые значения:

Шаг изменения прогрессии. По умолчанию 1

Предельное значение прогрессии. По умолчанию строится прогрессия во всем выделенном диапазоне

Допустимые значения: True (создается арифметическая или геометрическая прогрессия) или False (создается список)

Приведем соответствие между аргументами метода DataSeries и построением последовательности на рабочем листе командой Правка, Заполнить, Прогрессия (Edit, Fill, Series) на примере построения геометрической профессии.

О В ячейку AI вводим первый член прогрессии, например 1. В методе DataSeries за начальное значение прогрессии отвечает объект, к которому применяется метод. В данном случае метод DataSeries надо применить к диапазону Range («A1») . О Выберите команду Правка, Заполнить, Прогрессия (Edit, Fill, Series), которая приведет к появлению диалогового окна Прогрессия (Series) (рис. 3.1).

В диалоговом окне Прогрессия (Series) в группе Расположение (Series in) выберите, например, переключатель по строкам (Rows), т. к. будем строить геометрическую профессию в первой строке. В группе Тип (Туре) выберите переключатель геометрическая (Growth) В поле Шаг введите например, 1.2, а в поле Предельное значение (Stop value) — 3, т. е. геометрическая прогрессия будет строиться с шагом 1.2 до тех пор, пока ее члены не достигнут значения 3. Нажатие кнопки ОК приводит к построению требуемой профессии (рис. 3.2). В методе DataSeries за расположение профессии отвечает аргумент rowcoi. В данном случае ему надо присвоить значение xiRows. За тип прогрессии отвечает аргумент type, которому присвоим значение xiGrowth. За шаг и предельное значение отвечают аргументы step и stop, которым присвоим 1.2 и з соответственно. Таким образом, имеем:

Range ( «А1» ). DataSeries Rowcol : =xlRows , Type : =xlGrowth, Step:=1.2, Stop:=3

Рис. З.2. Результат построения геометрической прогрессии

Метод AutoFill (автозаполнение) автоматически заполняет ячейки диапазона элементами последовательности. Метод AutoFill отличается от метода DataSeries тем, что явно указывается диапазон, в котором будет располагаться прогрессия. Вручную этот метод эквивалентен расположению указателя мыши на маркере заполнения выделенного диапазона (в который введены значения, порождающие создаваемую последовательность) и протаскивании маркера заполнения вдоль диапазона, в котором будет располагаться создаваемая последовательность.

Диапазон, с которого начинается заполнение

Диапазон, который заполняется

Допустимые значения: xiFiilDefauit, xlFillSeries, xlFillCopy, xlFillFormats, xlFillValues, xlFillDays, xlFillWeekdays, xlFillMonths, xlFillYears, xlLinearTrend, xlGrowthTrend. По умолчанию xlFillDefault

Приведем соответствие между аргументами метода AutoFill и построением последовательности на рабочем листе вручную на примере построения арифметической прогрессии по двум ее первым членам.

В ячейку AI введите первый член профессии, например 5. В ячейку А2 введите второй член профессии, например 7. Выделите диапазон А1:А2, содержащий два первых члена арифметической профессии. Расположите указатель мыши над маркером заполнения выделенного диапазона так, чтобы он превратился в черный крест (рис. 3.3).

Рис. 3.3. Выделение двух первых членов прогрессии

При нажатой левой кнопке мыши, протащите маркер заполнения вниз по столбцу так, чтобы создать требуемую последовательность. В данном случае протащим маркер заполнения так, чтобы создать последовательность в диапазоне А1:А5 (рис. 3.4). Тот же результат получается, если аргументу Destination метода AutoFill присваивается Range («Ai:A5»), аргументу туре присваивается xiFiiiDefauit, а метод применяется к диапазону Range («A1:A2») . Таким образом, имеем:

Range ( «Al :A2») .AutoFill

Destination: =Range ( «Al : A5» ),_

Type : =xlFillDef ault

Метод AutoFilter (автофильтр) представляет собой простой способ запроса и фильтрации данных на рабочем листе. Если AutoFilter активизирован, то каждый заголовок поля выделенного диапазона данных превращается в поле с раскрывающимся списком. Выбирая запрос на вывод данных в поле с раскрывающимся списком, вы осуществляете вывод только тех записей, которые удовлетворяют указанным условиям. Поле с раскрывающимся списком содержит следующие типы условий: Все (АИ), Первые десять (Тор 10), Условие (Custom), конкретный элемент данных, Пустые (Blanks) и Непустые (NohBlanks). Вручную метод запускается посредством выбора команды Данные, Фильтр, Автофильтр (Data, Filter, AutoFilter).

При применении метода AutoFilter допустимы два синтаксиса.

В этом случае метод AutoFilter выбирает или отменяет команду Данные, Фильтр, Автофильтр (Data, Filter, AutoFilter), примененную к диапазону, заданному в аргументе объект.

Объект.AutoFilter(field, criterial, operator, criteria2)

В этом случае метод AutoFilter выполняет команду Данные, Фильтр, Автофильтр (Data, Filter, AutoFilter) по критериям, указанным в аргументе.

Целое, указывающее поле, в котором производится фильтрация данных

criterial И criteria2

Задают два возможных условия фильтрации поля. Допускается использование строковой постоянной, например 101, и знаков отношений >, =,

Допустимые значения: П xiAnd (логическое объединение первого и второго критериев) П xior (логическое сложение первого и второго критериев) П xiTopioitems (для показа первых десяти элементов поля)

При работе с фильтрами полезны метод ShowAllData и свойства FilterMode и AutoFilterMode.

Показывает все отфильтрованные и неотфильтрованные строки рабочего листа

Допустимые значения: True (если на рабочем листе имеются отфильтрованные данные со скрытыми строками), False (в противном случае)

Допустимые значения: True (если на рабочем листе выведены раскрывающиеся списки метода AutoFilter), False (в противном случае)

Приведем соответствие между аргументами метода AutoFilter и выполнением команды Данные, Фильтр, Автофильтр (Data, Filter, AutoFilter) при фильтрации базы данных регистрации туристов.

Выделяем диапазон A1 = E1, содержащий заголовки полей базы данных. Выберем команду Данные, Фильтр, Автофильтр (Data, Filter, AutoFilter). В результате в заголовках полей появятся раскрывающиеся списки (рис. 3.5). В этих раскрывающихся списках предлагаются варианты допустимой фильтрации. В методе AutoFilter за диапазон с названиями полей отвечает объект, к которому применяется метод. В данном случае метод

AutoFilter надо Применить к диапазону Range («A1: E1») .

Рис. 3.5. Раскрывающиеся списки метода AutoFilter

Отфильтруем в базе данных, например, только данные о клиентах, направляющихся в афины (рис. 3.6). С этой целью в раскрывающемся списке поля Направление тура выберем Афины. В результате на рабочем листе будут выведены только записи, соответствующие турам в Афины. В методе AutoFilter за выбор поля, в котором производится фильтрация, отвечает аргумент

Field. В данном Случае для выбора поля Направление тура

аргументу Field надо присвоить значение 4. За критерии, покоторым производится фильтрация, отвечают аргументы criteria1 и criteria2. В данном случае фильтрация производилась по одному критерию — АФИНЫ, поэтому только аргументу criterial надо присвоить значение АФИНЫ. Таким образом, имеем:

Range ( «Al : El » ) . Select Selection. AutoFilte r Selection. AutoFilter Field:=4, Criteria1 : =»Афины»

Рис. 3.6. Фильтрация списка по критерию Афины

Рис. 3.7. Диалоговое окно Пользовательский автофильтр

При фильтрации по условию появляется диалоговое окно Пользовательский автофильтр (Custom AutoFilter), позволяющее отфильтровать записи по двум критериям в одном поле (рис. 3.7). Например, отфильтруем все туры в Афины и Берлин. В методе AutoFilter это соответствует присвоению аргументам Сriterial и criteria2 значений Афины и Берлин соответственно, а аргументу operator — значения хlor, т. к. будут отображаться либо туры в Афины, либо в Берлин .

Таким образом, имеем:

Range («A1:E1») .Select Select ion. AutoFilter Selection. AutoFilter Field:=4,

Criterial : =»=Афины» , Operator : =xlOr ,

Метод AdvancedFilter (расширенный фильтр) является более мощным и универсальным средством фильтрации, чем метод AutoFilter. Он позволяет использовать фильтрацию по большему числу критериев, причем допустимо применение критериев, включающих формулы. Кроме того, метод AdvancedFilter позволяет фильтровать список с выводом результата фильтрации как непосредственно на том месте, где он расположен, так и в новое специфицированное место. Вручную метод запускается посредством выбора команды Данные, Фильтр, Расширенный фильтр (Data, Filter, Advanced Filter).

Объект.AdvancedFilter(Action, CriteriaRange, CopyToRange, Unique)

Допустимые значения:: xiFilterinPiace (фильтровать список на месте) и xiFiiterCopy (скопировать результат на новое место)

Ссылка на диапазон с критериями

Если параметр Action принимает значение xiFiiter-сору, то он указывает диапазон, куда будет копироваться результат фильтрации

Допустимые значения True (отбирается только один вариант записи из многократно встречающихся в списке) и False (отбираются все встречающиеся записи)

Приведем соответствие между аргументами метода Advanced Filter и выполнением команды Данные, Фильтр, Расширенный фильтр (Data, Filter, Advanced Filter) при фильтрации базы данных регистрации туристов.

Выделяем диапазон AI : G13, содержащий фильтруемую базу данных. (рис. 3.8). Прежде чем выбирать команду Данные, Фильтр, Расширенный фильтр (Data, Filter, Advanced Filter), необходимовыполнить предварительные построения по созданию диапазона критериев. Верхняя строка диапазона критериев должна содержать заголовки полей фильтруемых данных. При этом нет необходимости включать все заголовки и сохранять их порядок. В диапазон критериев также должны входить строки с условиями фильтрации. Все условия в диапазоне критериев, записанные под заголовком поля, относятся к этому полю. При применении расширенного фильтра допустима запись нескольких условий в строке диапазона критериев. Условия, расположенные в одной строке, рассматриваются как условия, объединенные логической операцией и (And) , а расположенные в нескольких — логической операцией или (Or) В данном случае под диапазон критериев отведем диапазон A16:G17. В базе данных выберем записи обо всех мужчинах, которые едут в Лондон. С этой целью в ячейку С17 диапазона критериев введем значение муж, а в ячейку D17— Лондон.

Выберем команду Данные, Фильтр, Расширенный фильтр (Data, Filter, Advanced Filter). Появится диалоговое окно Расширенный фильтр (Advanced Filter) (рис. 3.9).

Range ( «A1 : G13» ) .AdvancedFiiter

CriteriaRange : =Range («A16:G17» ) ,

CopyToRange : =Range ( » Al 9 : Gl 9 » ) , Unique : =False

Макрос для поиска ближайшего значения заданному на всех листах книги Excel

В данном примере предоставлен код VBA-макроса с пояснениями для поиска ближайшего значения указанному на всех листах книги в Excel.

Как найти ближайшее значение заданному на листах книги макросом VBA

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

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

Для открытия редактора используйте Alt+F11. В открывшемся окне нажмите правой кнопкой мыши на «Modules», выберите пункт «Insert» и в раскрывшемся списке – пункт «Module»:

Введите код макроса в открывшемся окне для ввода кода:

Sub Module1()
Dim strFindData As String
Dim tempArr() As Integer
Dim rgFound As Range
Dim i As Integer
Dim indexTempArr As Integer
strFindData = InputBox( «Введите данные для поиска» )
‘проверка введенных данных
If IsNumeric(strFindData) = False Then
MsgBox ( «Вы ввели не число» )
Exit Sub
Else :
strFindData = strFindData * 1
End If
For i = 1 To Worksheets.Count
With Worksheets(i).UsedRange.Cells
Set rgFound = .Find(strFindData, LookIn:=xlValues, LookAt:=xlWhole)
If Not rgFound Is Nothing Then
MsgBox ( «Найдено точное совпадение — » & rgFound & » на » & Worksheets(i).Name)
Exit Sub
‘поиск ячеек с числовыми значениями и запись этих значений в массив
Else :
For Each cl In Worksheets(i).UsedRange.Cells
If cl <> «» And IsNumeric(cl) Then
ReDim Preserve tempArr(indexTempArr)
tempArr(indexTempArr) = cl.Value * 1
indexTempArr = indexTempArr + 1
End If
Next
End If
End With
Next
‘сортировка массива по возрастанию
Dim k As Integer
Dim sortedArr As Variant
sortedArr = SortingArr(tempArr)
Worksheets.Add.Name = «Result»
For l = LBound(sortedArr) To UBound(sortedArr)
Worksheets( «Result» ).Range( «B» & l + 1) = sortedArr(l)
Next l
Worksheets( «Result» ).Range( «C1» ).FormulaLocal = _
«=ЕСЛИ(B1 MidEl Then
j = j — 1
Else
t = myTempArr(i)
myTempArr(i) = myTempArr(j)
myTempArr(j) = t
i = i + 1
j = j — 1
End If
End If
Loop
If First

Теперь для поиска ближайшего значения заданному на всех листах можно воспользоваться макросом, для вызова которого необходимо выбрать вкладку «Вид», нажать на кнопку «Макросы» (ALT+F8), в открывшемся окне выбрать название требуемого модуля и нажать «Выполнить»:

В окне нашего пользовательского VBA-макроса введите значение 78 для поиска на всех листах книги. И нажмите ОК:

В результате макрос нас информирует о том, что найдено значение 78 на Лист2:

Теперь введите значение 35 которого нет на листах. Но наш VBA макрос не растерялся. В место традиционного «Значения не найдено :(» он выполнил поиск и нашел нам максимально приблизительное значение к исходному (35):

Теперь чтобы узнать на каком листе находится найденное максимально приближенное значение нам всего лишь нужно еще раз в форму поиска ввести его (29) для повторного поиска.

Логика работы макроса для поиска ближайшего значения заданному на всех листах

В первую очередь организуем ввод данных через InputBox и проверку типа данных, полученных на вход (IsNumeric). Если введено не число, макрос прекратит свою работу с соответствующим сообщением.

Последующий код макроса можно условно разделить на две части: поиск точного совпадения числа и нахождение ближайшего ему значения.

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

Примечание: поскольку поиск ведется по всем листам книги, используем выражение «For i = 1 To Worksheets.Count» для перебора листов в цикле. Поскольку ячеек на листе может быть огромное множество, с помощью свойства UsedRange организовываем поиск только в используемой области ячеек.

Если точное совпадение не найдено, выполняется участок кода, который выбирает все числовые значения из ячеек всех листов и заполняет ими массив данных tempArr с последующей сортировкой с использованием функции Function QuickSort (реализована отдельно для удобства).

Для упрощения кода, данные из отсортированного массива передаются в ячейки нового листа (Worksheets.Add.Name = «Result») с названием «Result». Затем в соседней ячейке используется формула Excel для поиска ближайшего числа в диапазоне:

Поскольку новый лист необходим только для промежуточных расчетов, полученное максимально приближенное значение передаем в переменную resultValue, а лист «Result» удаляем. Для вывода искомого значения используем метод MsgBox («Найдено приближенное — » & resultValue).

Полезный совет! Чтобы выполнить макросом поиск по всех листах книги Excel не только числовые значение, а и текстовые измените параметры функции .Find(), которая находится на 29-ой строке кода. Так же не забудьте отключить проверку типа данных IsNumeric(strFindData) закомментировав строки 16-18.

Примечание: при выполнении данного макроса могут возникать некоторые ошибки, так как во избежание нагромождения кода в нем были упущены проверки типов данных и некоторые другие условия. Также можно добавить новую функцию, выполняющую поиск ближайшего значения путем перебора элементов массива вместо использования временного листа «Result».

VBA Find Range in Excel

VBA Find Range in Excel will help you while automating a task to find a cell with specific string or value in a range. You can specify the different options while looking for a string. It can be exact match, search direction, search after, etc.

ON SALE 80% OFF

50+ Project Management Templates Pack
Excel PowerPoint Word

Advanced Project Plan & Portfolio Template
Excel Template

Ultimate Project Management Template
Excel Template

20+ Excel Project Management Pack
Excel Templates

20+ PowerPoint Project Management Pack
PowerPoint Templates

10+ MS Word Project Management Pack
Word Templates

VBA to Find Value in a Range – Syntax

Here is the syntax to find a string or value in a range. Find method will return the range of the matched cell.

What: String or a value to be searched.
After – (Optional): You can mention the search start cell, By defaults it will be the first cell in the given range.
LookIn – (Optional):The information which you want look in the given range. It can be xlValues, xlFormulas and xlComments.
SearchOrder – (Optional): We can tell how to search weather it is by rows or by columns by using xlByRows and xlByColumns.
SearchDirection – (Optional): You can mention the search direction – next or preivious by using xlNext and xlPrevious.
MatchCase – (Optional): You can specify if your search is case sensitive: True = Case Sensitive.
SearchFormat – (Optional): You can specify the Search format.

VBA to Find Value in a Range – Example

Below is the Excel VBA Macro to find a string in specific range and return the matched range address.

This macro will search for the string “ab” from the first cell of the given range and returns matched range address.

VBA to Find Value in a Range – After

Below is the Excel VBA Macro to find a string in specific range and return the matched range address. The start cell must be in the specified range.

This macro will search for the string “ab” from “B3” and returns matched range address.

VBA to Find Value in a Range – MatchCase

Below is the Excel VBA Macro to find a string in specific range and return the matched range address. The start cell must be in the specified range. When we write MatchCase:=True that means find string is case sensitive.

This macro will search for the string “ab” from “B3” and returns matched range address. As we mentioned MatchCase:=True, it will look for exact match only.

VBA to Find Value in a Range – Instructions

Please follow the below step by step instructions to execute the above mentioned VBA macros or codes:

  1. Open an Excel Workbook from your start menu or type Excel in your run command
  2. Enter some data in any cells in range “B2:D10″ to test this macro.
  3. Press Alt+F11 to Open VBA Editor or you can go to Developer Tab from Excel Ribbon and click on the Visual Basic Command to launch the VBA Editor
  4. Insert a Module from Insert Menu of VBA
  5. Copy the above code (for copying a range using VBA) and Paste in the code window(VBA Editor)
  6. Save the file as Macro Enabled Workbook (i.e; .xlsm file format)
  7. Press ‘F5′ to run it or Keep Pressing ‘F8′ to debug the code line by line.

Now, it will the search for the exact match string “ab” from “B3” and returns matched range address.

Вам не нужно использовать VBA для вашей проблемы, Excel сделает это отлично!

Попробуй это

=vlookup(E2;A:A;2;true)

и для того, что вы пытаетесь сделать, вам нужно отсортировать столбец A по возрастанию, иначе вы получите ошибку!

И если вам это нужно в VBA,

простая для + если структура с таким тестом

    Function pr24(ByVal Value_To_Match As Double) As Range


For i = 2 To ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
    If Cells(i, 1) > Value_To_Match Then
        If Abs(Cells(i - 1, 1) - Value_To_Match) >= Abs(Cells(i, 1) - Value_To_Match) Then
            pr24 = Range(Cells(i, 1))
        Else
            pr24 = Range(Cells(i - 1, 1))
        End If

        Exit For
    Else

    End If
Next i



End Function

или вы можете использовать функцию листа Vlookup

Application.WorksheetFunction.VLOOKUP()

Понравилась статья? Поделить с друзьями:
  • Excel vba ассоциативные массивы
  • Excel vba аргументы функции
  • Excel vba аналог впр
  • Excel vba анализ данных
  • Excel vba активный лист активной книги