Vba match is error

Hi, I'm using function Match in VBA (for a fuzzy text search) in the line: Application.WorksheetFunction.Match("*" & Trim(Terms(i)) & "*", ActiveSheet.Range("B1:B250"), 0) Terms(i) is just a string, the function works fine except that eventually it doesn't find any matches. How could I catch...

  • #2

Not the biggest fan of using excel workbook specific functions in VBA. Usually there is no reason to use them. So, in your example I would use Find, i.e.

Code:

If Not Range("B1:B250").Find("*" & Trim(Terms(i)) & "*") Is Nothing Then
    'match found
Else
    'no match found
End If

  • #3

I appreciate your answer.

The reason I use Match is that it returns a position in a list (not a text). Therefore you can run a search multiple times with different search terms and then find the most likely cell using function Mode.

No idea on how that would be done with Find, though.

But there must be a way to catch errors with worksheet functions….. ??

  • #4

If it were «feet to the fire» for WorksheetFunction:

Code:

Sub x()
    terms = Array("A", "B", "A", "d")
    For i = 0 To UBound(terms)
        On Local Error Resume Next
        m = Application.[B]WorksheetFunction[/B].Match("*" & Trim(terms(i)) & "*", _
                                    ActiveSheet.Range("B1:B250"), 0)
        If Err <> 0 Then
            Debug.Print "not found: " & terms(i)
            Err.Clear
        Else
            Debug.Print "found: " & terms(i)
        End If
    Next i
End Sub

  • #5

Try this.

Code:

Dim res As Variant
 
res = Application.Match("*" & Trim(Terms(i)) & "*", ActiveSheet.Range("B1:B250"), 0)
 
If IsError(res) Then
     MsgBox "No match found"
Else
     MgsBox "Match found in row " & res
End If

  • #6

Thanks all, I’ve tried several solutions but Norie’s seems to be the one.

Oddly enough, the ONLY difference between her code and mine is/was:
NORIE’s (working)
X = Application.Match(«*» & Trim(Terms(i)) & «*», ActiveSheet.Range(«B1:B250»))

MINE (not working)
X = Application.WorkSheetFunction.Match(«*» & Trim(Terms(i)) & «*», ActiveSheet.Range(«B1:B250»))

Am I missing something? Aren’t we supposed to include the WorkSheetFunction when using Match in VBA (or any other function)??

  • #7

Hi,

I’m using function Match in VBA (for a fuzzy text search) in the line:

Code:

Application.WorksheetFunction.Match("*" & Trim(Terms(i)) & "*", ActiveSheet.Range("B1:B250"), 0)

Terms(i) is just a string, the function works fine except that eventually it doesn’t find any matches. How could I catch this error using IF?

I’ve tried this:

Code:

If IsError(Application.WorksheetFunction.Match("*" & Trim(Terms(i)) & "*", ActiveSheet.Range("B1:B250"), 0)) Then
            'do something
End If

but again, it throws an execution Debug error. Same for IsNull. IsNA is not available in VBA. Any ideas?

Thanks, a.

I believe you can use:

Code:

If IsNumeric(Application.Match("*" & Trim(Terms(i)) & "*", ActiveSheet.Range("B1:B250"), 0)) Then
Debug.Print "Match found!"
End If

RoryA

RoryA

MrExcel MVP, Moderator


  • #8

For the differences between Application.function_name and application.worksheetfunction.function_name see the Error Handling section on Chip’s page here.

  • #9

a ud

You can use workhseet functions in VBA without using WorksheetFunction.

The obvious advantage is that not using WorksheetFunction stops the code error.

I can’t remember exactly why/how it works though.:)

  • #10

The reason I use Match is that it returns a position in a list (not a text). Therefore you can run a search multiple times with different search terms and then find the most likely cell using function Mode.

A find returns a range. From there you can get any property of that range, i.e. the row (as what match does).

i.e.

Code:

If Not Range("B1:B250").Find("*" & Trim(Terms(i)) & "*") Is Nothing Then
    'match found
    Set r = Range("B1:B250").Find("*" & Trim(Terms(i)) & "*")
    Debug.Print r.Row 'etc
Else
    'no match found
End If

Description

This error in matching occurs when the Match function is used, but a match was not found.

The Match function is used in order to determine the position in a 1-dimension list at which a text or number is matched.

This error is of type ‘Run-time 1004’. A run-time error is the type of error that occurs during the execution of the code. VBA does not know about it prior to actually running the code. It stops the execution of the code.

The particular error ‘1004’ is related to an application-defined or object-defined error.

In other words, this particular variation of Run-time error occurs when VBA cannot identify an object. The Match function is supposed to return a match object. When a match is not found, VBA detects that there’s an unidentified match object, and that’s why it throws this particular Run-time 1004 error.

Take a look at https://software-solutions-online.com/run-time-error-1004-in-vba/ for other examples of run time errors.

Example 1: Use Application.Match Instead

A notable issue with using WorksheetFunction.Match is that it throws an error when the match is not found, which complicates things slightly (we will see in the next example how to deal with that). But why not use Application.Match instead?

It is the same exact thing, but without the error throwing part. This means that it will work exactly like WorksheetFunction.Match when a match is found, but when a match is not found, it will not throw an error.

Furthermore, Application.Match will recognize that there is an error and will be able to point that out for you if you ask it to. Another way to look at this is to think of WorksheetFunction.Match as a function that attempts to create a match object, and if it does not find a match, it does not know what to do.

But Application.Match is a function that attempts to create a match object and if it does not find a match, it instead creates an Error Object (that is why there is no error thrown).

Error throwing is disruptive; it halts the progress of the code and you end up with no valid objects to work with. But when you have an Error Object, then you have a valid object that you can work with. In this example, we will attempt to match a value in column 1 that does not exist. We will keep column 1 empty initially.

Sub No_Match()
matchRow = Application.WorksheetFunction.Match("test", Columns(1), 0)
End Sub

Unable to get the Match property of the WorksheetFunction class

To avoid the error we will replace WorksheetFunction.Match with Application.Match:

Sub No_Match()
matchRow = Application.Match("test", Columns(1), 0)
End Sub

The code will run without any issues. This should be sufficient to ensure that you never get the dreaded error that stops your entire application. In the next example, we will see how we can handle the error in a more meaningful way that fits our purpose.

Example 2: Handling the error

In this example, we will handle the error such that the flow of our code changes based on whether we got an error while matching or not.

This is usually very much needed in any real-world coding of applications because if we did not find what we’re looking for, we need to handle those issues.

Usually, we try to match a word in order to determine which row/column it is located at and hence do something with that row/column.

Sub mismatchErrorHandling()
matchRow = Application.Match("test", Columns(1), 0)
If IsError(matchRow) Then
    MsgBox "No Match"
Else
    MsgBox "Match row is: " &amp;amp; matchRow
End If
End Sub

Note that because we’re using Application.Match, we now can check if the matchRow object is an error object. If it is, then the statement IsError(matchRow) will evaluate to true and a message box will display “No Match.”

No match

Summary

Utilizing Application.Match instead of WorksheetFunction.Match will ensure that the object that will be assigned the result of the matching is defined even if the match was not found.

If the match is found, then it will be assigned the integer value of the match. But if it’s not found, then the object will be assign an error value and will become an error object that contains the standard error descriptors, such as error name, description, number, etc. It will be easy to determine whether it is an error object or not through the use of IsError(checkObj).

Tagged with: Application-Defined or Object-Defined Error, application.match, Error, error handling, error object, IsError, MATCH, Properties, Run-Time error ‘1004’, runtime error, worksheetfunction.match

Поискав по рунету материал на тему обработки ошибок в VBA, не увидал на первых двух страницах результатов поиска чего-то, что мне понравилось. Может плохо смотрел, но решил написать на эту тему свою статью.

Простите, но — немного словоблудия :)

Ошибки в программе

Ошибки времени исполнения программы возникают, когда среда программирования не может выполнить то, что вы хотите. Таких ситуаций может быть много. Например:

  1. Вы обращаетесь к объекту по имени, а объекта с таким именем в коллекции нет

  2. Вы хотите выделить ячеку на одном листе, а этот лист в данный момент не является активным (типичнейшая ошибка новичков в Excel VBA)

  3. Вы хотите удалить отфильтрованные автофильтром строки, а фильтр вообще не вернул записей и удалять нечего

  4. Вы ссылаетесь на элемент массива, который находится за пределами его границ.

  5. Вы пытаетесь присвоить переменной значение, которое оно не может хранить. Например, переменной типа Long нельзя присвоить строковую константу или переменной типа Integer присвоить знанчение превышающее число 32767.

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

  • Continue (продолжить) — этот пункт во время возникновения ошибки всегда не активен. Он активен, когда по ходу выполнения программы вы использовали оператор Stop. Кстати это очень полезный оператор для отладки программы.

  • End (завершить) — завершение исполнения программы

  • Debug (отладка) — переход в режим отладки, в котором можно посмотреть, на каком операторе возникла ошибка, что содержат переменные, можно даже перетащить жёлтую полоску, подсвечивающую текущий оператор, назад, и модифицировать знанчение переменных через окно Immediate window (впрочем это экзотика). В общем случае кнопка Debug позволяет посмотреть, где случилась ошибка и попытаться понять почему так случилось.

Если вы — автор программы, в которой случилась ошибка, то вы, должно быть, в начале будете рады увидеть подобное окно, ибо только так вы сможете отловить основные ошибки, скрытые в вашем коде. Однако, если эту ошибку видит пользователь, то для него это, мягко говоря, безрадостное и малопонятное зрелище. Ещё хуже, если за эту программу вам заплатили деньги. Поэтому в среде худо-бедно профессиональных программистов принято предусматривать обработку ошибок в своих программах.

Почему вообще в коде возникают ошибки?

  1. Много ошибок во время написания кода возникает по невнимательности или не совсем адекватного понимания того, что делаешь. Таких ошибок, как правило, очень много, особенно у начинающих программистов, но эти ошибки довольно легко отловить и исправить, так как, пока вы их не исправите, ничего не работает. Ну, например, вы должны извлечь данные из 5-го столбца, а вы извлекаете из 6-го, а их там банально нет. Ясно, что вы это очень быстро заметите.

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

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

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

Задачи механизмов обработки ошибок

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

  2. Информирование. Мало обработать ошибку и предотвратить завершение программы. Надо ещё и адекватно проинформировать пользователя о причинах нестандартного поведения программы. Частно причиной ошибок в программе являются некорректные действия пользователя, поэтому важно сообщать ему о них.

  3. Защита данных от повреждения. Программа обязана защищать от непреднамеренных повреждений результаты своей или пользовательской работы. Деструктивные действия должны быть снабжены соответствующими предупредительными диалоговыми окнами. Часто ошибка, не обработанная должным образом может повредить нужные данные.

Файл примера

Скачать

Код без обработки ошибок

Вот простой пример с потолка. Если вызвать Example_00, то она прекрасно отработает без ошибок и вернёт это:

В функцию GetCalories передаётся строка с блюдом, а она должна вернуть его калорийность, сверившись с таблицей в A1:B7.

Давайте поищем слабые места в этом коде. Первое, что должно прийти в голову — если мы ищем, то, что произойдёт, если мы не найдём? А произойдёт, конечно же, ошибка. Её инициирует метод Match.


Ещё одно слабое место этой подпрограммы: функция возвращает вещественный тип Double, и даже, если поиск оказался удачным, то в Cells(intRow, 2) может случайно находиться текстовая строка, а потому, когда вы числовому типу попытаетесь присвоить строковый тип, также произойдёт ошибка. И, если вы второй ошибки сможете избежать за счёт дополнительного оператора if с проверкой через IsNumber(), то избежать первой ошибки таким способом нельзя. Что же делать? А вот тут на сцену выходят операторы обработки ошибок.

Есть 2 подхода к обработке ошибок: автономный подход и выносной. Эти термины я придумал только что, чтобы проще было их обсуждать.

Автономный подход

Смысл автономного подхода в том, чтобы не выносить сор из избы. Если в подпрограмме возникла ошибка, то мы должны предположить, на каком месте она возникнет и поджидать её там с дубиной. С ошибкой, в этом случае, разбираются обычно в операторе, идущем сразу после потенциально опасного места. Давайте смотреть, как это может выглядеть:

Итак, что тут сделано:

  1. Сразу после объявления функции GetCalories_v1 идёт оператор on error resume next, который в случае возникновения в каком-либо месте ошибки, предписывает VBA просто передавать управление на следующий оператор, идущий после ошибочного.

  2. Мы объявили переменные. Необъявленные переменные получают тип Variant и значение по умолчанию Empty. Объявленные переменные числовых типов инициируются нулём, строковые — пустой строкой, то есть я наперёд знаю, что они содержат, а это хорошо для обработки ошибок.

  3. На вызове метода WorksheetFunction.Match у нас возникает ошибка, так как искомого значения в таблице нет. А это, между прочим, был оператор присваивания ( = ). Прежде, чем левой части оператора присваивания (intRow) что-то будет присвоено, необходимо вычислить правую часть оператора присваивания (WorksheetFunction.Match…), а поскольку в процессе этого вычисления возникает ошибка, то переменная intRow остаётся такой, какой была! А, как я уже сказал, VBA автоматически её инициализирует нулём до начала исполнения подпрограммы. Получается, что, если в этом операторе возникнет ошибка, то в intRow будет ноль. Если ошибки во время поиска не возникнет, то ноля там не будет ни при каких раскладах, так как строки на листе нумеруются с единицы.

  4. И вот этот ноль мы и контролируем, добавляя оператор If. Если intRow больше нуля, то WorksheetFunction.Match отработала штатно, а если нет — то работу подпрограммы надо прерывать, но об этом чуть позже.

  5. Далее мы помним, что Cells(intRow, 2) может теоретически вернуть строковое значение, которое вызовет ошибку Type missmatch при присвоении переменной типа Double (GetCalories_v1), поэтому мы вставляем дополнительную проверку промежуточной переменной varTemp тому, что она числовая. И если это так, то присваиваем GetCalories_v1 значение из varTemp.

  6. В случае возникновения любой ошибки внутри GetCalories_v1 она просто вернёт ноль. Почему ноль? Потому что переменная GetCalories_v1 тоже инициализируется нулём и об этом не надо заботиться, а в случае ошибки она останется в неприкосновенности.

  7. Соответственно родительский код (в нашем случае его роль играет процедура Example_01) должен проверить, а не вернёт ли GetCalories_v1 ноль, и быть готовым к этой ситуации.

  8. А вот теперь тонкий момент, который не все понимают. Почему я использовал промежуточные переменные intRow и varTemp? Вроде бы есть очевидный ответ — чтобы не вычислять значение выражений с Match и Cells 2 раза. Отчасти это, конечно, так. Но это, в данном случае, не главная причина. Главная причина в том, что такой код

    вызовет неправильное поведение программы. Если у нас Match вызовет исключение, то VBA передаст управление на СЛЕДУЮЩИЙ оператор, а следующий оператор в данном случае это то, что идёт после Then — присваивание переменной varTemp значения. Таким образом наша проверка на наличие ошибки сработает с точностью до наоборот, передав управление в ту часть кода, которая должна быть защищена от ситуации, когда Match не нашла строку в таблице. Вот почему важно в операторе If не иметь ничего такого, что могло бы вызвать ошибку.

  9. Как видите, в этом подходе мне зачастую даже нет необходимости проверять объект Err, чтобы понять, что произошла ошибка, так как я ориентируюсь на то, что промежуточные переменные остаются неинициализированными, что является показателем наличия ошибки.

Выносной подход

Данный метод основан на том, что, когда возникает ошибка, то VBA передаёт управление на специальный участок кода — обработчик ошибок, который обычно размещают в конце подпрограммы. Это может выглядеть так:

Обратите внимание, что:

  1. Оператор on error теперь в случае ошибки предписывает передавать управление на метку ErrorHandler, которая объявлена в конце кода процедуры GetCalories_v2

  2. В коде мы никак не заботимся о каких-либо проверках. Возникла ошибка? Иди на метку — там разберутся.

  3. Если ошибки не случилось, то, чтобы программа не стала исполнять строчки, предназначенные для обработки ошибок, перед меткой ErrorHandler обычно ставят оператор Exit Sub или Exit Function (в зависимости от типа подпрограммы).

  4. Принципиальный момент — наличие оператора On Error Resume Next сразу после метки ErrorHandler. Дело в том, что после того, как вы перешли на метку ErrorHandler, очень опасно иметь действующим оператор On Error GoTo ErrorHandler, так как, если у вас в обработчике ошибки случится любая ошибка, то управление будет передано опять на метку и, как нетрудно понять, образуется бесконечный цикл. Поэтому сразу после метки мы возможность возникновения цикла ликвидируем оператором On Error Resume Next.

Что лучше?

Какой метод лучше применять зависит от ваших предпочтений и конкретных ситуаций. Грамотную обработку ошибок можно сделать и так и эдак. Вот несколько соображений по преимуществам и недостакам данных подходов:

Автономный подход

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

Выносной подход

Преимущества Недостатки
Ни одна ошибка не проскочит незамеченной. Не смотря на то, что вы перехватите все ошибки, отреагировать на них правильно затруднительно, так как вы, по большому счёту, не знаете, на каком операторе произошла ошибка и почему.
Удобнее организовывать централизованный сбор логов по ошибкам в приложении. Однозначно, фаворит для больших проектов.

Кратко пробежимся по операторам, функциям и объектам VBA, которые предназначены для обработки ошибок времени исполнения программы.

Операторы

On Error { GoTo label | Resume Next | GoTo 0 }

Оператор on error управляет тем, на какой участок вашего кода будет передано управление в случае возникновения ошибки. Данный оператор можно вставить в любое место вашей программы или подпрограммы. Есть 3 варианта:

  1. On error goto label — после того, как этот оператор выполнен, ошибка, возникшая на других операторах программы приведёт к переходу на метку label.

  2. On error resume next — после такого оператора, VBA будет игнорировать возникшую ошибку и передавать управление на следующий оператор, стоящий за тем, в котором возникла ошибка.

  3. On error goto 0 — это режим по-умолчанию. В случае возникновения ошибки данный режим приведёт к появлению на экране стандартного обработчик ошибок VBA с кнопками End и Debug.

Resume { label | Next | [0] }

Данный оператор возобновляет выполнение программы. Применяется в выносном методе обработки ошибок.

  1. resume label— возобновление с метки label

  2. resume next — возобновление со следующего оператора

  3. resume или resume 0 — возобновление с оператора, вызвавшего ошибку. Это имеет смысл, если вы устранили ошибку в своём обработчике. На мой взгляд, на практике такое применяется крайне редко.

Goto label

Переход на метку. Может пригодиться, однако, использование меток в коде для чего-то большего, чем обработка ошибок, считается страшным моветоном.

Exit { Do | For | Function | Sub }

Досрочный выход из циклов (Do или For) и досрочный выход из подпрограмм (функции или процедуры). Могут пригодиться при обработке ошибок, но вообще это операторы и без того чрезвычайно полезны.

Объект Err

  1. Err — глобальный объект (его не надо объявлять, а можно сразу пользоваться), который содержит информацию о последней ошибке, случившейся в вашей программе. Проверяя Err сразу после возникновения исключения или после ситуации, которая могла привести к исключению, вы можете понять, что имело место на самом деле.

  2. Свойство Err.Number — содержит числовой код ошибки, по которому их различают в программе. Поскольку Number — свойство по умолчанию, то вы можете его опускать, то есть Err и Err.Number — это эквиваленты. Значение ноль говорит о том, что ошибки не произошло.

  3. Err.Description — содержит англоязычное краткое описание ошибки

  4. Err.Source — возвращает имя модуля, в котором возникла ошибка

  5. Err.Clear — сбрасывает последнюю ошибку. Err сбрасывается также при выполнении оператором Resume, Exit (любого типа кроме Do и For) и On Error.

  6. Err.Raise — искусственно вызывает исключение указанного в переданном параметре типа. Можно использовать для тестирования вашей подсистемы обработки ошибок.

P.S.

Лично я привык в своих программах использовать автономный подход и, возможно, поэтому я не совсем осознаю все преимущества выносного подхода. Буду рад прочесть в комментариях ваше мнение на этот счёт. Тема обработки ошибок данной статьёй, конечно, быть исчерпана не может, но она послужит вам хорошей стартовой точкой в этом важном деле.

Читайте также:

  • Работа с объектом Range

  • Работа с объектом Range (часть 2)

  • Sheet happens

  • Поиск границ текущей области

  • Массивы в VBA

  • Структуры данных и их эффективность

  • Автоматическое скрытие/показ столбцов и строк

 

e_artem

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

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

#1

03.10.2016 14:30:25

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

Код
 WorksheetFunction.IfError(WorksheetFunction.Match("29.06.2016", Rows(2), 0), 0) 

Иногда (на некоторых листах) работает нормально, а на других выдается ошибка 1004

Код
"Unable to get the Match property of the WorksheetFunction class"

Подскажите пожалуйста как победить и/или иной лучший способ поиска номера нужного столбца на VBA?

 

Sanja

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

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

Метод .Find ?

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

 

МатросНаЗебре

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

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

#3

03.10.2016 14:54:16

Код
Вариант 1.
    On Error Resume Next
        Cells(1).Value = WorksheetFunction.IfError(WorksheetFunction.Match("29.06.2016", Rows(2), 0), 0)
    If Err.Number <> 0 Then Cells(1).Value = 0
    On Error GoTo 0
----------------------------------------------------
Вариант 2.
    If WorksheetFunction.CountIfs(Rows(2), "29.06.2016") Then
        Cells(1).Value = WorksheetFunction.IfError(WorksheetFunction.Match("29.06.2016", Rows(2), 0), 0)
    Else
        Cells(1).Value = 0
    End If
 

e_artem

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

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

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

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

  • Book.xlsx (8.27 КБ)

Изменено: e_artem03.10.2016 15:16:32

 

Sanja

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

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

#5

03.10.2016 16:13:40

Цитата
e_artem написал: Во вложении файл, в котором ни первый вариант ни второй не работают

В Вашем файле вообще нет никаких макросов. Что там должно  работать?

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

  • Book.xlsm (15.34 КБ)

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

 

А Вы нас не тролите?

Во-первых, утверждаете, что код VBA не работает, и прикладываете файл «*.xlsx». Тут с Вами сложно спорить, VBA в таких файлах работать не будет.
Во-вторых, утверждаете, что «…данная дата на листе есть». Дата «29.09.2016» на листе действительно есть, но ни один MATCH её не признает как  «29.06.2016».

Как бы то ни было, пример с решением во вложении.

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

  • Book.xlsm (14.07 КБ)

 

e_artem

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

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

#7

03.10.2016 16:48:57

Прошу прощения, что не написал…. У меня не получилось прикрепить в форум ни xlsm ни xlsb файл. Прикрепился только xlsx.
Да, действительно, MATCH не понимает эту дату как таковую, и я не смог разобраться почему.
В итоге, я сделал так (переместил все в массив и его перебрал циклом)

Код
Dim Dt As Variant
Dt = Rows("2:2")
For i=1 to ...

Хотя этот подход не отличается особой интелигентостью решения (по эффективности исполнения кода)
Не могли бы вы прямо в форум кунить код из прикрепленного файла, не могу скачать его (политика инф. без.)?
Спасибо

 

МатросНаЗебре

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

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

#8

03.10.2016 16:51:23

Код
Sub aaaa()
    Dim d As Integer
    On Error Resume Next
        d = WorksheetFunction.Match(CLng(DateValue("29.06.2016")), Rows(2), 0)
    If Err.Number <> 0 Then d = 0
    On Error GoTo 0
    
    MsgBox ("Столбец " & d)
End Sub

Изменено: МатросНаЗебре03.10.2016 16:52:15

 

e_artem

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

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

#9

03.10.2016 16:59:32

Теперь понятно, нужно было завернуть в фантик нормализующими функциями! Спасибо.
P.S.
Поковыряюсь еще, кто его знает как далеко может зайти пользовательская выдумка по заполнению диапазона из второй строки.

Alan,
it is Excel’s built formula function. If you type it in excel, you get this help.

MATCH function

This article describes the formula syntax and usage of the MATCHfunction in Microsoft Excel.

Description

The MATCH function searches for a specified item in a range of cells, and then returns the relative position of that item in the range. For example, if the range A1:A3 contains the values 5, 25, and 38, then the formula

=MATCH(25,A1:A3,0)

returns the number 2, because 25 is the second item in the range.

Use MATCH instead of one of the LOOKUP functions when you need the position of an item in a range instead of the item itself. For example, you might use the MATCH function to provide a value for the row_num argument of the INDEX function.

Syntax

MATCH(lookup_value, lookup_array, [match_type])

The MATCH function syntax has the following arguments:

## lookup_value Required. The value that you want to match in lookup_array. For example, when you look up someone’s number in a telephone book, you are using the person’s name as the lookup value, but the telephone number is the value you want.

The lookup_value argument can be a value (number, text, or logical value) or a cell reference to a number, text, or logical value.

## lookup_array Required. The range of cells being searched.

## match_type Optional. The number -1, 0, or 1. The match_type argument specifies how Excel matches lookup_value with values in lookup_array. The default value for this argument is 1.

The following table describes how the function finds values based on the setting of the match_type argument.

Match_type

Behavior

1 or omitted

MATCH finds the largest value that is less than or equal to lookup_value. The values in the lookup_array argument must be placed in ascending order, for example: …-2, -1, 0, 1, 2, …, A-Z, FALSE, TRUE.

0

MATCH finds the first value that is exactly equal to lookup_value. The values in the lookup_array argument can be in any order.

-1

MATCH finds the smallest value that is greater than or equal to lookup_value. The values in the lookup_array argument must be placed in descending order, for example: TRUE, FALSE, Z-A, …2, 1, 0, -1, -2, …, and so on.

Note

## MATCH returns the position of the matched value within lookup_array, not the value itself. For example, MATCH(«b»,{«a»,»b»,»c»},0) returns 2, which is the relative position of «b» within the array {«a»,»b»,»c»}.

## MATCH does not distinguish between uppercase and lowercase letters when matching text values.

##If MATCH is unsuccessful in finding a match, it returns the #N/A error value.

##If match_type is 0 and lookup_value is a text string, you can use the wildcard characters — the question mark (?) and asterisk (*) — in the lookup_value argument. A question mark matches any single character; an asterisk matches any sequence of characters. If you want to find an actual question mark or asterisk, type a tilde (~) before the character.

Example

Copy the example data in the following table, and paste it in cell A1 of a new Excel worksheet. For formulas to show results, select them, press F2, and then press Enter. If you need to, you can adjust the column widths to see all the data.

Product

Count

Bananas

25

Oranges

38

Apples

40

Pears

41

Formula

Description

Result

=MATCH(39,B2:B5,1)

Because there is not an exact match, the position of the next lowest value (38) in the range B2:B5 is returned.

2

=MATCH(41,B2:B5,0)

The position of the value 41 in the range B2:B5.

4

=MATCH(40,B2:B5,-1)

Returns an error because the values in the range B2:B5 are not in descending order.

Понравилась статья? Поделить с друзьями:
  • Vba excel обработка ошибок on error
  • Vba excel как отключить compile error
  • Vba excel как изменить цвет текста
  • Vba excel как изменить цвет кнопки
  • Vba excel как изменить формат ячейки