Страницы: 1 2 След.
RSS
Метод Find с частичным совпадением даты
 
Уважаемые гуру форума, подскажите как решить мой небольшой вопрос. Для поиска в диапазоне дат первой ячейки с указанным месяцем я пытался использовать следующий код (значение "03.2017" в реальном коде вычисляется):
Код
Private Sub CommandButton1_Click()
    i = Range("A1:A5").Find("03.2017", LookIn:=xlValues, LookAt:=xlPart).Row
End Sub
Но пока ничего не выходит (ошибка 91 Object variable or With block variable not set). Пытался задать выражение для поиска как "??.03.2017", результат тот же. Подозреваю, что все дело в несовпадении форматов диапазона для поиска и выражения, но как это исправить (если это так) я не знаю.
Для пробы в соседнем столбце пытаюсь искать текстовое значение (также с частичным совпадением), все работает как надо.
Заранее спасибо всем откликнувшимся
 
А испробуйте SET i=
в ячейке десятичное число, вы ищите текст, поиск просто не находит ничего. даже "02.03.2017" не поможет, а вот Cdate("02.03.2017") даст результат. Всеж форма CTRL+F нечто большее чем просто вызов этого метода.
Изменено: БМВ - 11.03.2017 20:05:08
По вопросам из тем форума, личку не читаю.
 
Пробовал, не помогает :(
 
А что нужно в итоге?
Всё сложное - не нужно. Всё нужное - просто /М. Т. Калашников/
 
БМВ, спасибо за помощь, Ваш вариант находит нужную строку, но он не позволяет искать только указанный месяц (а мне надо именно так), т.е. ни вариант CDate("03.2017"), ни CDate("??.03.2017") работать не хотят. Можно ли устранить это?
 
Цитата
Михаил Лебедев написал:
А что нужно в итоге?
Михаил, мне нужно найти первую ячейку в которой имеется дата, принадлежащая к указанному месяцу (в данном случае к марту), т.е. в примере ячейку А4. Причем точной даты я указать не могу, поиск должен осуществляться только по месяцу_году
 
Цитата
OlegO написал:
CDate("??.03.2017")
ну это точно не поможет. Что то мне подсказывает, что загрузить облать в масив и перебрав сравнить что вам требуется - будет проще. Всего то определить попадает ли вмежду первым и последним числом месяца.
Изменено: БМВ - 11.03.2017 20:33:00
По вопросам из тем форума, личку не читаю.
 
Что-то сложнее и сложнее выходит, мне фактически нужна первая дата указанного месяца. А если через массив осуществлять поиск, то как это будет выглядеть в коде?
 
будет выглядить  нарушением правил форума.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
будет выглядить  нарушением правил форума
Вы имеете ввиду разбор 2-х вопросов в 1 теме? Создать новую?
 
Цитата
OlegO написал:
Создать новую?
Вы разрешение спрашиваете? ))
 
Юрий, просто сначала хотел узнать одно и то же ли мы с БМВ имеем ввиду, перед тем как уходить из этой темы и создавать новую
 
А перебором?
Код
For i = 1 To 5
        If Cells(i, 1) Like "*03.2017" Then Cells(i, 1).Select
Next
 
QwertyBoss, наверное стоить пояснить предысторию. Сейчас в коде рабочий цикл начинается с первой строки и заканчивается последней заполненной. Я предположил, что при большом кол-ве строк неразумно просматривать весь диапазон, а можно начать это делать с первой даты (любой, именно с первой найденной) указанного месяца. Скажем имеется 100000 строк, заполнены 930, нужные для кода данные начинаются с 850 строки, так и укажем для цикла, что он начинается с 850, а заканчивается 930 строкой. Вот для этого определения 850 строки я и поднял вопрос. А в Вашем предложении код перебирает в цикле весь диапазон :(, поэтому не подходит
Изменено: OlegO - 11.03.2017 21:50:41
 
OlegO,  а вы думаете Find не занимается перебором?
QwertyBoss,  а #7 чем отличается? только подходом и скоростью, а так перебор как перебор, да еще и тектовый Like притормозит дополнительно.
По вопросам из тем форума, личку не читаю.
 
БМВ, насчет принципа работы .find теперь ясно, как я уже писал выше Ваш код работает, но можно ли что-то сделать, чтобы поиск осуществлялся только по месяцу указанного года? Так как я просто не знаю какую дату мне искать (она может быть абсолютно любая), причем более поздняя дата может находиться выше более ранней (для текущего кода это неважно)
 
Если Вы про Find, то мне кажется, что не получится. Если Вы про другие варианты - пожалуйста, новую тему. Вопрос решаемый )
 
Ясно, попробую завтра сформулировать (про совет насчет массива я помню)
 
Ответ по теме:
Код
Sub FuzzyFindDate()
'ZVI:2017-03-12 http://www.planetaexcel.ru/forum/index.php?PAGE_NAME=message&TID=89095#message738666
  
  ' Маска поиска
  Const MASK = "3/*/2017"  ' Март 2017 в формате "m/d/yyyy"
  
  ' Локальные переменные
  Dim Rng As Range, x As Range
  
  ' Задать диапазон поиска
  Set Rng = Range("A1:A5")
  
  ' Задать формат поиска даты
  With Application.FindFormat
    .Clear
    .NumberFormat = "m/d/yyyy"
  End With
  
  ' Искать с учетом формата
  Set x = Rng.Find(What:=MASK, After:=Rng(Rng.Count), LookIn:=xlValues, _
        LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
        MatchCase:=False, SearchFormat:=True)
  
  ' Сообщить результат
  If x Is Nothing Then
    Debug.Print "Nothing"
  Else
    Debug.Print x.Address(0, 0), x.Value
  End If
  
  ' Очистить формат поиска, иначе он сохранится для поиска по умолчанию
  Application.FindFormat.Clear
  
End Sub

Тему правильнее было бы назвать так: Метод Find с частичным совпадением даты
Изменено: ZVI - 12.03.2017 03:13:26
 
Владимир, MVP в подписи не зря . Я вчера специально прошелся  по MSDN, но был уверен, что формат не поможет и макрорекордер то сбил еще больше, он то подлец вот так Selection.Find(What:="*.03.2017", оставил, несмотря на то что формат корректно со слышами занес. Application.FindFormat.NumberFormat = "m/d/yyyy"

Один вопрос,  Rng(Rng.Count), - типа для надежности от последнего пляшем чтоб по кругу на первый попасть?

Спасибо. и нам наука и автору в помощь.
По вопросам из тем форума, личку не читаю.
 
Спасибо за помощь ZVI, но теперь появились новые вопросы по открытой теме: учитывая мою предысторию (пост №14) вообще имеет с точки зрения грамотного кода сначала вычислять (перебором) первую строку для цикла? или разница в сравнении с текущим указанием строки вручную будет ничтожна, даже на больших объемах? И еще, учитывая что в другой раз может быть  придется искать не в датах, а в скажем тексте, попытался сваять конструкцию, используя словарь:
Код
  With CreateObject("Scripting.Dictionary"): .CompareMode = 1
        x = ActiveSheet.Range("A1:A" & ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row).Value
            For i = 1 To UBound(x)
                temp = x(i, 1)
                If Mid(temp, 4) = "03.2017" Then
                    r = i
                End If
            Next i
    End With
Результат выдает правильный, но грамотно ли я применил словарь или это следует писать иначе?
 
Цитата
БМВ написал: Один вопрос,  Rng(Rng.Count), - типа для надежности от последнего пляшем чтоб по кругу на первый попасть?
Если задан диапазон поиска, то первая ячейка, в которую заглянет метод Find - это не первая ячейка диапазона Rng, а вторая, что соответствует параметру After:=Rng.Cells(1) , дословно - начать поиск после первой ячейки. И если в первой ячейке диапазона Rng и в любой другой будет то, что ищется, то Find найдет ту самую другую ячейку вместо первой. А Rng(Rng.Count) или, более строго, Rng(Rng.Cells.Count)  - это последняя ячейка диапазона Rng. Поиск после последней ячейки начнется с первой, что и требуется.
По поводу MSDN - не заглядывал, просто поэкпериментировал немного :)
Изменено: ZVI - 12.03.2017 10:09:05
 
Цитата
OlegO написал: грамотно ли я применил словарь или это следует писать иначе?
Олег, словарь Вы обозначили, но не применили, нет в коде ни .Item , ни If .Exists
Если поиск в датах без числа предполагается выполнять многократно, то, действительно, сначала нужно по значениям столбца составить словарь ключей дат без числа, а в качестве значения записать номер строки. Затем при поиске проверить, есть ли в словаре то What, что ищем, и если есть, то узнать строку - If .Exists(What)  Then i = .Item(What). А для однократного поиска проще использовать Find из моего примера. Да и просто пробежаться по массиву можно в таком случае.
Изменено: ZVI - 12.03.2017 09:55:53
 
Спасибо ZVI, а по поводу первой части моего вопроса, в описанной ситуации это вообще имеет смысл затевать с точки зрения грамотности программирования?
 
Цитата
OlegO написал: по поводу первой части моего вопроса
По поводу первой части Вашего вопроса дописал в предыдущем сообщении - всё годится, но насколько - определять Вам для конкретных данных. Протестируйте время выполнения пробежки по большому массиву, если искомое значение где-нибудь в конце, затем сравните с Find. Затраченное время можно контролировать так:
Код
Sub TimeTest()
  
  Dim t As Single
  
  t = Timer
  Call Macro1 ' Макрос с перебором
  Debug.Print Round(Timer - t, 3) & " сек."

  t = Timer
  Call Macro2 ' Макрос с Find
  Debug.Print Round(Timer - t, 3) & " сек."

End Sub
Изменено: ZVI - 12.03.2017 10:04:16
 
Спасибо за помощь буду тестирвать
 
OlegO,
Любое сравнение текста будет более длительным , чем сравнение числа, а сравнить дату  - это сравнить число.
уже ушли от темы первоначальной так что

Код
   strDate = "03.2017"
   FirstDayDT = CDate("1." & strDate)
   LastDateDT = DateAdd("m", 1, FirstDayDT) - 1
   x = ActiveSheet.Range("A1:A" & ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row).Value
   For i = 1 To UBound(x)
        If x(i, 1) >= FirstDayDT And x(i, 1) <= LastDateDT Then
        r=i 
   Exit For
        End If
    Next i
По вопросам из тем форума, личку не читаю.
 
Цитата
ZVI написал:
дословно - начать поиск после первой ячейки.
вот ведь, а ведь прям написано "If you do no specify this argument, the search starts after the cell in the upper-left corner of the range." просто никогда на первою ячейку не нарывался.
По вопросам из тем форума, личку не читаю.
 
и всеж Владимир прав, но немного переусердствовал
достаточно преобразования "03.2017",в "3/*/2017"
Код
    i = Range("A1:A5").Find("3/*/2017", LookIn:=xlValues, LookAt:=xlPart).Row
Разве что с поправкой на After:
Это
Код
  With Application.FindFormat
    .Clear
    .NumberFormat = "m/d/yyyy"
  End With
в данном случае лишние действия, не несущие ни вреда,. ни пользы.
Изменено: БМВ - 13.03.2017 07:54:56
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал: ... лишние действия, не несущие ни вреда,. ни пользы.
Указывать NumberFormat не обязательно было, конечно. Это чтобы понятнее было, какой реально NumberFormat в ячейках и почему выбран именно такой шаблон поиска. Вспомните эту неочевидность. Но, в принципе, это действительно лишнее.
По поводу необходимости очистки формата, попробуйте в Excel нажать Ctrl-F - Параметры - Формат - и выбрать, например, какую-нибудь заливку цветом - OK - Закрыть (или Найти далее). А после это запустите макрос с Find - он не найдет дату без Application.FindFormat.Clear . Однажды введенный вручную или кодом формат поиска запоминается в течение сессии и его нужно очищать, что и делает Application.FindFormat.Clear
Про необходимость учета After уже обсуждалось.
Изменено: ZVI - 14.03.2017 00:56:34
Страницы: 1 2 След.
Читают тему
Наверх