Dihlofos881 Пользователь Сообщений: 101 |
#1 18.02.2021 05:54:14 Доброго времени суток, Друзья! Подскажите, пожалуйста, никак не могу найти ответ на данный вопрос в интернете..
|
||
evgeniygeo Пользователь Сообщений: 2272 |
#2 18.02.2021 06:01:07 Dihlofos881,
|
||
evgeniygeo, https://disk.yandex.ru/d/EFtU66b_Ywwp8g Не получилось сжать до 700 кб, файлы как смог уменьшил |
|
Dihlofos881, Сделайте пример попроще Вообще, я предполагаю, что проблема в формате даты на листе «Vol Pack», измените ее на стандартную и должно быть ок. Изменено: evgeniygeo — 18.02.2021 08:13:44 |
|
Согласен с предыдущем комментарием эксель прекрасно ищет даты я писал макрос для заполнения табеля учета рабочего времени там не было никаких проблем с датами. Просто нужно понимать что даты в эксель храняться не так как мы видим на экране 15.02.2021, на самом деле в этой ячейке записано число 44242. и эксель ищет это число возможно с форматом дат. И проверьте действительно ли в ячейках где ведете поиск записаны даты. А VBA воспринимает даты в таком формате 01/01/2021. Так что он дейсвительно ищет дату. Только в VBA запись 01/02/2021 означает дату 02.01.2021. Число и месяц меняются местами. |
|
evgeniygeo, состряпал примерчик. |
|
sokol92 Пользователь Сообщений: 4445 |
#7 18.02.2021 13:42:27 Метод Range.Find с параметром LookIn:=xlValues имеет ряд непростых для понимания особенностей. Для начала можно ознакомиться с замечательными разъяснениями Владимира ( ZVI ). Для того, чтобы пример из #6 заработал, необходимо: 1. Изменить формат ячеек первой строки листа Production c Д.М;@ на Д.М;@
Изменено: sokol92 — 18.02.2021 14:13:16 Владимир |
||
sokol92, Макрос теперь вроде находит, но не переносит значение…. |
|
sokol92 Пользователь Сообщений: 4445 |
Переносит. Если Вы в примере из #6 заполните ячейку B29 на листе Production, то макрос перенесет ее значение в ячейку B2 листа Vol Pack. Изменено: sokol92 — 18.02.2021 16:16:36 |
Dihlofos881 Пользователь Сообщений: 101 |
#10 19.02.2021 10:09:48 sokol92, это работает в примере, но…. почему-то не собирается работать в нужном мне файле.
Изменено: Dihlofos881 — 19.02.2021 10:10:18 |
||
Вроде работает проверяйте |
|
Евгений Смирнов, в файле примера работает это да, а вот в фалах из сообщения #3 не хочет. |
|
Проблема действительно в формате отображения данных в которых идет поиск. |
|
sokol92 Пользователь Сообщений: 4445 |
#14 23.02.2021 14:29:32
Послесловие. Ключ к разгадке — в этой теме . Владимир |
||
Поиск какого-либо значения в ячейках 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
JulyMar 3 / 3 / 0 Регистрация: 01.08.2013 Сообщений: 37 |
||||
1 |
||||
03.12.2013, 10:45. Показов 6453. Ответов 3 Метки нет (Все метки)
Добрый день, уважаемые форумчане!
0 |
Kubuntovod 2670 / 786 / 176 Регистрация: 14.01.2013 Сообщений: 3,672 |
||||
03.12.2013, 14:16 |
2 |
|||
Сообщение было отмечено как решение РешениеЕсли в ячейке только дата, то всё просто:
1 |
3 / 3 / 0 Регистрация: 01.08.2013 Сообщений: 37 |
|
03.12.2013, 14:28 [ТС] |
3 |
Спасибо огромное за быстрый ответ! Очень выручили!
0 |
Kubuntovod 2670 / 786 / 176 Регистрация: 14.01.2013 Сообщений: 3,672 |
||||
03.12.2013, 15:05 |
4 |
|||
Внимательнее перечитал задание и понял, что надо смотреть на дату окончания срока годности и сравнивать её с последним днём текущего месяца.
0 |
Поиск даты методом Find |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
||||||||
Ответить |
data on my Excel sheetI would like to finde a date in column A. This is the date formát: «yyyy/mm/dd hh:mm:ss». It always find nothing, but the date what I am searching for is in the column A.
This is a snippet of my code:
Dim LastDay As Date
Dim strdate As String
Dim rCell As Range
strdate = Format(LastDay, "yyyy/mm/dd hh:mm:ss")
Set rCell = Cells.Find(What:=CDate(strdate), After:=Range("A1"), LookIn:=xlValues _
, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
If rCell Is Nothing Then
MsgBox ("nothing")
Else
EDIT: New code per comments.
Sub Copy()
Dim LastDayRow As Long
Dim FirstDayRow As Long
Dim LastDay As Date
Dim FirstDay As Date
Dim rcell As Range
LastDayRow = Range("E" & Rows.Count).End(xlUp).Row
Range("E" & LastDayRow).Copy Range("G1")
FirstDayRow = Range("A" & Rows.Count).End(xlUp).Row
Range("A" & FirstDayRow).Copy Range("G2")
LastDay = Cells(LastDayRow, "E").Value
FirstDay = Cells(FirstDayRow, "A").Value
Set rcell = Cells.Find(What:=LastDay, After:=Range("A1"), LookIn:=xlFormulas _
, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If rcell Is Nothing Then
MsgBox ("nothing")
End If
End Sub