简体   繁体   English

Excel VBA-在VBA函数中使用命名范围作为参数

[英]Excel VBA - Use Named Range as Parameter in a VBA Function

Trying to use Named Ranges as parameter in a function but facing issues when I execute the function in a worksheet different that where the Named Range is located. 尝试使用命名范围作为函数中的参数,但是当我在与命名范围所在位置不同的工作表中执行该函数时遇到问题。

Tried to search within the forum but couldn't find a solution as most posts have the Named Range or the Worksheet where same is located hard-coded in VBA. 试图在论坛中进行搜索,但找不到解决方案,因为大多数帖子的命名范围或工作表均在VBA中进行了硬编码。 Would like to avoid this limitation as the function is supposed to be working with different Named Ranged from different Worksheets... 希望避免此限制,因为该功能应该与来自不同工作表的不同命名范围一起使用...

The following code works fine when entered in the same worksheet as the selected Named Range. 在与所选命名范围相同的工作表中输入以下代码时,效果很好。 Unfortunately it falls apart when the selected Named Range is in another worksheet (even though all ranges that I'm using as parameters are "Workbook specific"). 不幸的是,当选定的“命名范围”在另一个工作表中时,它就崩溃了(即使我用作参数的所有范围都是“特定于工作簿的”)。

In this particular line: 在此特定行中:

Set FullRange = NamedRange

Have been experimenting for some time trying to create a reference that would work from any worksheet but unfortunately with no luck... 已经尝试了一段时间尝试创建可以在任何工作表上使用的引用,但不幸的是没有运气...

Any help will be much appreciated! 任何帮助都感激不尽!

The concept is to declare a Named Range as parameter. 概念是将命名范围声明为参数。 In turn, the function finds this Named Range and creates a new range from a part of it (see SpecificRange). 反过来,该函数会找到此命名范围,并从其中的一部分创建一个新范围(请参见SpecificRange)。 Finally it performs certain calculations with the data from this new range. 最后,它使用该新范围内的数据执行某些计算。 All of these work fine but only in the same worksheet... Here is the code: 所有这些都可以正常工作,但只能在同一工作表中...以下是代码:

Function myResult(NamedRange As Range, Vessel As String, FromDate As Date, ToDate As Date)

'declare variables in addition to the function parameters declared above
Dim SpecificRange As Range
Dim FullRange As Range
Dim Result As Double
Dim i As Byte

'find the row within the declared "NamedRange" range which contains information for the declared "Vessel"
Set FullRange = NamedRange
Set SpecificRange = Range(FullRange.Find(Vessel, , xlValues, xlWhole).Address, FullRange.Find(Vessel, , xlValues, xlWhole).Offset(0, FullRange.Columns.Count - 1).Address)

i = 1
Result = 0

For i = 1 To FullRange.Columns.Count - 2
    If FullRange(2, i) = "Date" Then
        With WorksheetFunction
            Result = Result + .Max(0, .Min(ToDate, SpecificRange(1, i + 2).Value) - .Max(FromDate, SpecificRange(1, i).Value)) * SpecificRange(1, i + 1).Value
        End With
    End If
Next

myResult = Result

End Function

Many thanks! 非常感谢!

+++++ +++++

To add some more details, please note that when entered in a worksheet different than where the NamedRange is located, the function returns zero (0.00) and not an error. 要添加更多详细信息,请注意,当在与NamedRange所在位置不同的工作表中输入时,该函数将返回零(0.00),而不是错误。

Also, when I have the exact same function (a) in the worksheet where the NamedRange is located (say "Sheet1") and (b) in another worksheet (say "Sheet2"), then, when I run the function in Sheet1, the function in Sheet2 is updated correctly! 另外,当我在工作表中具有NamedRange所在的函数(例如,“ Sheet1”)和(b)在另一个工作表(例如,“ Sheet2”)中具有完全相同的功能时,那么,当我在Sheet1中运行该功能时, Sheet2中的功能已正确更新! But when I run the function directly in Sheet2 it returns zero... 但是当我直接在Sheet2中运行该函数时,它返回零...

It seems like it cannot locate the NamedRange when the relevant worksheet is not active... 当相关工作表未激活时,似乎无法找到NamedRange ...

Here is a screeshot: https://i.stack.imgur.com/RpHf3.png 这是一个快照: https ://i.stack.imgur.com/RpHf3.png

The Named Range is entered as a parameter by the user in the function (see first parameter) The second parameter in the function (ie Vessel as String), refers to the first column shown in the screenshot. 用户在函数中将命名范围作为参数输入(请参阅第一个参数)函数中的第二个参数(即以字符串形式表示的容器)是指屏幕快照中显示的第一列。

So when the user enters the formula, the function finds the NamedRange and then creates another range (ie SpecificRange) which is essentially the row where the second parameter was found (Criteria 4 in the example screenshot). 因此,当用户输入公式时,该函数将找到NamedRange,然后创建另一个范围(即SpecificRange),该范围本质上是找到第二个参数的行(示例屏幕快照中的条件4)。

Then it is just a matter of calculations based on the remaining two parameters but this does not seem relevant to this issue. 然后,仅需根据其余两个参数进行计算,但这似乎与该问题无关。

You are collecting the named range successfully, your issue is that later in your code you are setting a range based on Address, but not specifying the sheet. 您正在成功收集命名范围,您的问题是,稍后在代码中您将基于“地址”设置范围,但未指定工作表。 In other words, your code is looking at ActiveSheet.Range(.ADDRESS) . 换句话说,您的代码正在查看ActiveSheet.Range(.ADDRESS)

You can actually collect the sheet from a range variable, here's an example: Set WS = ThisWorkbook.Sheets(NamedRange.Parent.Name) 您实际上可以从范围变量中收集工作表,这是一个示例: Set WS = ThisWorkbook.Sheets(NamedRange.Parent.Name)

UPDATED v3 with a few more comments (PGC:) 更新的v3,还有更多注释(PGC :)

Function myResult(NamedRange As Range, Vessel As String, FromDate As Date, ToDate As Date)

'declare variables in addition to the function parameters declared above
Dim SpecificRange As Range
Dim FullRange As Range 'PGC: not sure you need this
Dim Result As Double
Dim i As Long 'PGC: use long instead of byte https://stackoverflow.com/questions/26409117/why-use-integer-instead-of-long/51689021#51689021
Dim WS As Worksheet 'PGC: this will be used to narrow your approach.


'find the row within the declared "NamedRange" range which contains information for the declared "Vessel"
Set FullRange = NamedRange 'I don't think you need to change this variable. Using NamedRange should work if you use below.

'PGC: set the WS to be the parent of the range you're working with:
Set WS = ThisWorkbook.Sheets(NamedRange.Parent.Name)

'PGC: since you're using the address text to set the range (probably not ideal), you'll need to specify which WS this Range is on.
Set SpecificRange = WS.Range(FullRange.Find(Vessel, , xlValues, xlWhole).Address, FullRange.Find(Vessel, , xlValues, xlWhole).Offset(0, FullRange.Columns.Count - 1).Address)

'PGC: alternative untested approach that avoids using the address property that is probably best method:
'Set SpecificRange = Range(FullRange.Find(Vessel, , xlValues, xlWhole), FullRange.Find(Vessel, , xlValues, xlWhole).Offset(0, FullRange.Columns.Count - 1))


i = 1
Result = 0

For i = 1 To FullRange.Columns.Count - 2
    If FullRange(2, i) = "Date" Then
        With WorksheetFunction
            Result = Result + .Max(0, .Min(ToDate, SpecificRange(1, i + 2).Value) - .Max(FromDate, SpecificRange(1, i).Value)) * SpecificRange(1, i + 1).Value
        End With
    End If
Next

myResult = Result

End Function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM