2013-12-23 4 views
2

В Excel 2007 я перебираю значения столбца 4 в Листе 2. Еще в Листе 2 я хочу вывести результат моей формулы vlookup в столбец 5. Формула vlookup должна обратитесь к Листу 1, где указаны ссылочные столбцы. Для того, чтобы сделать это я следующая формулаVBA vlookup ссылка в другом листе

Range("E2") = Application.WorksheetFunction.VLookup(Range("D2"), _ 
      Worksheets("Sheet1").Range("A1:C65536"), 1, False) 

проблемы, он возвращает код ошибки 1004. Я читал, что это потому, что мне нужно выбрать лист 1 перед запуском формул, таких как:

ThisWorkbook.Worksheets("Sheet1").Select 

Но тогда искомое значение Диапазон («D2») не относится к Листу 1, и оно все еще возвращает код 1004 после того, как принесет лист 1 в поле зрения.

Каков правильный способ обращения к другому листу в этом случае?

+1

Почему вы используете VBA для возврата результата формулы, которая может быть введена непосредственно в 'Worksheets (« Sheet2 »). Range (« E2 »)'? –

+0

Я согласен с логикой Марка, поэтому я разместил альтернативу вашему коду, который будет делать то же самое. Но, если вы хотите придерживаться своей логики, попробуйте добавить '.Value' к аргументу массива. Как этот «Application.WorksheetFunction.Vlookup (Range (« D2 »),« Листы »(« Лист1 »). Диапазон (« A1: C65536 »). Значение, 1, False)'. Кроме того, возвращаете ли вы значения в колонке A? Вы используете '1' в третьем аргументе' Vlookup', который является 'col_index_num'. – L42

+1

@Mark: этот код содержится в цикле, итерации для нескольких столбцов, выводя результат в строковые переменные, которые я буду конкатенатировать в конце обработки каждой строки в последний столбец. Я только упростил свой код, чтобы избежать вставки всего моего макроса здесь. – CloseISQ

ответ

2

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

Function fsVlookup(ByVal pSearch As Range, ByVal pMatrix As Range, ByVal pMatColNum As Integer) As String 
    Dim s As String 
    On Error Resume Next 
    s = Application.WorksheetFunction.VLookup(pSearch, pMatrix, pMatColNum, False) 
    If IsError(s) Then 
     fsVlookup = "" 
    Else 
     fsVlookup = s 
    End If 
End Function 

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

+0

Это всегда возвращает в случае ошибки значение предыдущего поиска успеха. По крайней мере для меня.. – Iso

5

попробовать это:

Dim ws as Worksheet 

Set ws = Thisworkbook.Sheets("Sheet2") 

With ws 
    .Range("E2").Formula = "=VLOOKUP(D2,Sheet1!$A:$C,1,0)" 
End With 

End Sub 

Это только упрощенная версия того, что вы хотите.
Не нужно использовать Application, если вы просто выведете ответ в Range("E2").

Если вы хотите придерживаться своей логики, объявите переменные.
См. Ниже, например.

Sub Test() 

Dim rng As Range 
Dim ws1, ws2 As Worksheet 
Dim MyStringVar1 As String 

Set ws1 = ThisWorkbook.Sheets("Sheet1") 
Set ws2 = ThisWorkbook.Sheets("Sheet2") 
Set rng = ws2.Range("D2") 

With ws2 
    On Error Resume Next 'add this because if value is not found, vlookup fails, you get 1004 
    MyStringVar1 = Application.WorksheetFunction.VLookup(rng, ws1.Range("A1:C65536").Value, 1, False) 
    On Error GoTo 0 
    If MyStringVar1 = "" Then MsgBox "Item not found" Else MsgBox MyStringVar1 
End With 

End Sub 

Надеюсь, что вы все начали.

+0

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

+0

+1 для определения того, на каком рабочем листе принадлежит rng. Если вы объявляете свои переменные и определяете их правильно, вам не нужно выбирать листы. – PermaNoob

2

Ваш код работает нормально, при условии, что значение в Sheet2!D2 существует в Sheet1!A:A. Если это не так, то возникает ошибка 1004.

Чтобы справиться с этим делом, попробуйте

Sub Demo() 
    Dim MyStringVar1 As Variant 
    On Error Resume Next 
    MyStringVar1 = Application.WorksheetFunction.VLookup(Range("D2"), _ 
     Worksheets("Sheet1").Range("A:C"), 1, False) 
    On Error GoTo 0 
    If IsEmpty(MyStringVar1) Then 
     MsgBox "Value not found!" 
    End If 

    Range("E2") = MyStringVar1 

End Sub 
+0

+1 для использования 'IsEmpty' для проверки' MyStringVar1'. Я думаю, что это намного безопаснее. :) – L42

0

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

Ошибка, которую вы получаете, скорее всего, вызвана искомым значением Sheet2!D2 не найден в найденном диапазоне Sheet1!A1:A65536. Это может быть вызвано двумя случаями:

  1. Значение на самом деле отсутствует (указано chris nielsen).

  2. Вы ищете неправильный Range. Если ActiveSheet равен Sheet1, то с использованием Range("D2") без квалификации он будет искать Sheet1!D2, и он будет вызывать ту же ошибку, даже если искомое значение присутствует в правильном диапазоне. Код учета этого (и комплектность) следующим образом:

    Sub srch() 
        Dim ws1 As Worksheet, ws2 As Worksheet 
        Dim srchres As Variant 
    
        Set ws1 = Worksheets("Sheet1") 
        Set ws2 = Worksheets("Sheet2") 
    
        On Error Resume Next 
        srchres = Application.WorksheetFunction.VLookup(ws2.Range("D2"), ws1.Range("A1:C65536"), 1, False) 
        On Error GoTo 0 
        If (IsEmpty(srchres)) Then 
         ws2.Range("E2").Formula = CVErr(xlErrNA) ' Use whatever you want 
        Else 
         ws2.Range("E2").Value = srchres 
        End If 
    End Sub 
    

укажу несколько дополнительных примечательных моментов:

  1. Поймать ошибку, как это сделано с помощью Крис Нильсен является хорошим практика, вероятно, обязательная, если используется Application.WorksheetFunction.VLookup (хотя она не подходит для случая 2).

  2. Эта уловка фактически выполняется функцией VLOOKUP, введенной в ячейку (и, если искомое значение не найдено, результат ошибки представляется в виде #N/A). Вот почему первый солонтон L42 не требует дополнительной обработки ошибок (позаботится об =VLOOKUP...).

  3. Использование =VLOOKUP... принципиально отличается от Application.WorksheetFunction.VLookup: первая оставляет формулу, результат которой может измениться, если ячейки, на которые делается ссылка, изменяются; второй записывает фиксированное значение.

  4. Оба решения по L42 соответствуют диапазонам соответственно.

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

Смежные вопросы