2015-03-05 3 views
2

Я пишу несколько функций VBA для работы и столкнулся с проблемой, которую нужно легко решить, но каким-то образом я не могу это сделать, несмотря на мои лучшие попытки найти ответьте здесь и на Google. Я написал функцию, которая должна дать мне диапазон между двумя строками в колонке:Передача диапазона от одной функции VB к другой

Function FindRng(StartRng As String, EndRng As String) As Variant 
Dim TopOfRange As Single 
Dim BottomOfRange As Single 

TopOfRange = WorksheetFunction.Match(StartRng, Sheets("InfCom").Range("B:B"), 0) 
BottomOfRange = WorksheetFunction.Match(EndRng, Sheets("InfCom").Range("B:B"), 0) 

FindRng = Range(Sheets("InfCom").Cells(TopOfRange, 2), Sheets("InfCom").Cells(BottomOfRange, 2)) 
End Function 

Так что, если входы А и В на строках 100 и 105, он должен вернуться B100: B105. Когда я тестирую это, адаптируя код для чтения FindRng = Range (...). Адрес, я действительно получаю $ B $ 100: $ B $ 105.

Однако, когда я затем ввожу результат FindRng в настраиваемую функцию сопоставления индексов, я получаю сообщение об ошибке. Функция выглядит следующим образом:

Function subsetPBPC(rngReturn As Range, LookupValueH As Variant, TopOfRange As String, BottomOfRange As String, LookupValueV As Variant) As Variant 

subsetPBPC = sPBPC(rngReturn, LookupValueH, FindRng(TopOfRange, BottomOfRange), LookupValueV) 

End Function 

Проблема заключается в том, что он, кажется, читает вывод FindRng не как диапазон, но как содержание этого диапазона: когда я использую Evaluate инструмент Формулы на FindRng встроенный в другом Формула показывает результат FindRng как {A, B, C, D, E} вместо $ B $ 100: $ B $ 105, где от A до E - содержимое ячеек в диапазоне. У меня такое чувство, что решение действительно просто, но я этого не вижу. Функции, лежащие в основе настроенной функции Match Match, были протестированы, и все они работают как шарм.

+1

попытка объявить функцию как диапазон: Function FindRng (...) Как Range – Seb

ответ

2

Набор вместо let. Позволяет присваивать значение выражения переменной. Set присваивает ссылку объекта переменной. Вы хотите вернуть ссылку на объект диапазона, а не возвращать значение, заданное по умолчанию для свойства объекта диапазона.

В VBA написания

FindRng = Range(...) 

неявно написание

Let FindRng = Range(...) 

Однако вы хотите

Set FindRng = Range(...) 

Edit 1:
Очень важно понимать разницу между объектом ссылку и значение в VBA. Это аналогичная концепция для передачи аргументов по значению или по ссылке. Надеемся, что эти две ссылки помогают некоторые из них:
The Let statement on MSDN
The Set statement on MSDN

Edit 2:
О, и я предполагаю, что я должен коснуться свойств по умолчанию! Некоторые объекты, такие как диапазон, имеют свойства по умолчанию. Если вы рассматриваете диапазон как значение вместо объекта, он использует свойство по умолчанию вместо того, чтобы бросать ошибку, потому что это объект, а не значение. В случае диапазона свойство по умолчанию - Value. Поэтому, если вы скажете A = Range("A1"), то, что вы на самом деле говорите, это Let A = Range("A1").Value, если вы имеете в виду Set A = Range("A1"). Таким образом, вы получаете значение, содержащееся в ячейке A1, вместо объекта диапазона, представляющего эту ячейку.

+0

Спасибо AndASM! Это было полезное объяснение, которое разрешило проблему. –

+0

См. Также ответ Бреттдж. Используя наиболее специфический тип, который вы можете использовать, например, Range вместо Variant, если вы всегда возвращаетесь или проходите диапазон, это хорошая идея. Это помогает предотвратить и обнаружить ошибки, а также потенциально работать быстрее. – AndASM

1

Подобрав, что ваш текущий код должен как

  • использование Set согласно CommNet AndADM в
  • измерение SetRng как Range вместо Вариант

вы можете упростить функцию как показано ниже (что может сэкономить время, если вы вызываете его повторно)

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

Function SetRng(str1 As String, str2 As String) As Range 

With Sheets("infCom").Columns(2) 
    Set SetRng = Range(.Find(str1, , xlValues, xlWhole), .Find(str2, , xlValues, xlWhole)) 
End With 

End Function 
+0

Да, я собирался прокомментировать достоинства и преимущества использования наиболее конкретных типов, которые вы можете использовать, а не общий тип, например Variant. Но мой ответ уже был немного здоров. :) – AndASM

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