Пропустить ошибку функции и перейти к следующей проверке (VLOOKUP) - PullRequest
1 голос
/ 30 мая 2019

Я использую базовый VLOOKUP для получения адреса электронной почты сотрудников.

Однако, когда значение поиска вводит имя сотрудника, которого нет в массиве, оно выдает ошибку.

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

Я хочу, чтобы переменная поиска ProjectManName не существовала в массиве, чтобы просто пропустить эту строку и продолжить поиск в обычном режиме.Затем я пойду и заполню пустые адреса электронной почты вручную.

Dim myLookupValue As Range
Dim strResult As String
Dim lngLastRow As Long
Dim lngLoop As Long
Dim ProjectManName As String

Set myLookupValue = Worksheets("Employees").Range("A1", Worksheets("Employees").Range("B1").End(xlDown))

With Worksheets("Project Summary")

    lngLastRow = .Cells(.Rows.Count, 1).End(xlUp).Row

    For lngLoop = 2 To lngLastRow
        On Error Resume Next
       ProjectManName = .Cells(lngLoop, 1).Value
       strResult = Application.WorksheetFunction.VLookup(ProjectManName, myLookupValue, 2, False)
       Range("K" & lngLoop).Value = strResult
       ActiveCell.Offset(1, 0).Select
    Next

End With

Кроме того, для myLookupValue мне нужен второй экземпляр Worksheets («Сотрудники»)?Когда я этого не делал, он также выдавал ошибку, потому что вторая ячейка в диапазоне смотрела на текущую рабочую таблицу вместо рабочей таблицы сотрудников.

Наконец, как я могу заменить «K» в Range("K" & lngLoop).Value набыть первым пустым столбцом?

Ответы [ 2 ]

3 голосов
/ 30 мая 2019

когда значение поиска вводит имя сотрудника, которого нет в массиве, оно выдает ошибку.

Это полностью задумано. Application.WorksheetFunction функции имеют раннюю привязку и вызывают ошибок вместо , возвращая их, что является совершенно идиоматическим поведением VB.

Похоже, вам нужно поведение "Рабочий лист Excel", при котором функция рабочего листа, которая выдает ошибку, возвращает Variant/Error значение, которое ячейка отображает как #N/A: значение Variant/Error составляет IsError return True, и может быть юридически сопоставлен только с другими значениями ошибок, например CVErr(xlErrNa).

Как и многие типы COM, интерфейс Excel.Application имеет расширение , что означает, что к нему можно добавлять элементы во время выполнения. Оказывается, он эффективно расширяется за счет членов интерфейса WorksheetFunction, поэтому Application.VLookup не только прекрасно компилируется (как и Application.AnythingWhatsoever), это реализация с поздней привязкой, которая ведет себя точно так же, как функция рабочего листа, когда вызывается ячейка рабочего листа: она возвращает Variant/Error значение, а не повышение стандартной идиоматической ошибки времени выполнения ... при условии, что все параметры правильно заданы (вызовы с поздней привязкой не t IntelliSense / автозаполнение), потому что, если вы сделаете опечатку (Option Explicit не сможет вас спасти) или неправильно укажете параметры, ожидайте, что будет выдана ошибка 438 или 1004.

Но вы не можете зафиксировать возвращаемое значение в String - это будет ошибка несоответствия типов , когда поиск даст значение Error (вы не можете принудительно привести этот тип в ничего, кроме Variant).

Dim lookupResult As Variant
lookupResult = Application.VLookup(ProjectManName, myLookupValue, 2, False)
If Not IsError(lookupResult) Then
    strResult = CStr(lookupResult)
    '...
''Else
''    'lookup failed
End If

При этом версия с ранним связыванием, как правило, предпочтительнее, будь то только для IntelliSense . On Error Resume Next используется правильно может быть полезным здесь - просто перетащите поиск в его собственную область:

For lngLoop = 2 To lngLastRow
    ProjectManName = .Cells(lngLoop, 1).Value
    [ActiveSheet.]Range("K" & lngLoop).Value = GetProjectManager(ProjectManName)
    'ActiveCell.Offset(1, 0).Select '<~ why?
Next
Private Function GetProjectManager(ByVal name As String) As String
     Dim source As Range
     With Worksheets("Employees")
         On Error Resume Next
         GetProjectManager = Application.WorksheetFunction.VLookup(name, .Range("A1", .Range("B1").End(xlDown)), 2, False)
         On Error GoTo 0
     End With
End Function

Что касается myLookupValue (плохое имя: должно быть myLookupRange или lookupSource или lookupTable - «значение поиска» обычно понимается / читается как значение, которое вы ищете) - вы нужна ссылка на лист Employees (неквалифицированные Range вызовы - очень хороший рецепт для ошибки 1004) - это не означает, что вам нужно разыменовать этот объект из Worksheets collection дважды - как показано выше ... обратите внимание, что, перемещая поиск в его собственную область, мы также избавляем вызывающего пользователя от необходимости даже заботиться о исходной таблице поиска.

1 голос
/ 30 мая 2019

Публикация комментария в качестве ответа для удобства чтения.Отвечает только на последний вопрос в сообщении с несколькими вопросами.


Вы захотите найти последний столбец, чтобы заменить «K» в своем диапазоне.Я бы порекомендовал использовать Cells (), а не Range (), поскольку вы можете использовать число как есть:

dim lc as long
lc = sheets("project summary").cells(1, sheets("project summary").columns.count).end(xltoleft).column

, где «1» в ячейках - это первая строка (обычно заголовки), а «lc» обозначаетдля последнего столбца.Ссылка на ячейки будет Cells(ingLoop, lc), учитывая ваш пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...