在UDF中使用命名范围

时间:2016-05-10 15:04:56

标签: excel excel-vba vba

我试图创建一个使用命名范围的UDF。我的命名范围(" best_Grade")是一个单元格,带有一个值。 (命名范围的范围限定为工作簿)。

在工作簿模块中,当我尝试使用命名范围创建变量时,我得到

  

运行时错误' 1004':方法'范围'对象' _Global'失败

两条线都不起作用:

Dim namedRng As Range
Dim locDataWS As Worksheet

Set locDataWS = Sheets("Approval matrix 16")
Set namedRng = Range("best_Grade") ' errors
Set namedRng = locDataWS.Range("best_Grade") ' When I take above line out, this line errors too

我尝试过:

Dim wb As Workbook
Set wb = ActiveWorkbook

Set namedRng = wb.Names("best_Grade").RefersToRange

怎么会出错呢? This page说应该有效,不是吗?我是否必须将此UDF放在实际的工作表对象上,而不是在工作簿模块中?

编辑:注意:命名范围不是设置为单元格,而是设置为SumIf公式(best_Grade = SumIf(A2:A10," x",...)`可能导致错误?

编辑2:是的,这就是我想的原因。我为随机单元格创建了一个命名范围,并且能够使用Range("a_grade").Value并返回了预期值。由于我的best_Grade范围是一个公式,我认为这就是它出错的原因。但是,我不知道为什么,因为我认为命名范围是命名范围,无论它由什么组成...

编辑n + 1:注意有两个"答案"对此。如果我想继续使用命名范围作为Range变量,请参阅下面的答案。然而,我真正想要做的是@MacroMarc发布的内容,所以我选择了它作为"答案"。

5 个答案:

答案 0 :(得分:3)

您需要改为使用Names集合:

Sub t5()
' named range "Test" is `=Sum($A$1:$A$4)`

Dim rng As Double
rng = Evaluate(Names("Test").Value) 
Debug.Print rng
End Sub

Name对象必须返回字符串表示的各种属性。

答案 1 :(得分:2)

Sub t5()
' named range "Test" is `=Sum($A$1:$A$4)`
Set wb = ActiveWorkbook
Dim rng As String

rng = wb.Names("Test").RefersTo
Debug.Print rng

rng = Application.Evaluate(wb.Names("Test").RefersTo)
Debug.Print rng

End Sub

经过一些测试后,我发现上面的工作......并且很有趣。我在Chip Pearson帖子中也得到了Macro Man的评论。

键是定义的名称返回一个字符串=“你的结果”所以你可以评估它以获得答案,或者你可以做一些字符串操作来拉出引号和等号。你真的很接近你的RefersToRange选择。

根据您自己发布的答案查看Vegard的评论。

答案 2 :(得分:1)

它无效的原因是因为我的命名范围best_Grades不是单元格引用,而是公式。因此,在使用Range("best_Grades").Value时,它出错了。 (best_Grades = SumIf(A2:A10,"x", B2:B10, ...)

不知道为什么,因为我认为命名范围是一个命名范围,无论是什么原因......但我想不是。

目前,我的解决方案是根据实际的单元格值创建另一个命名范围,然后使用它。 (theBest_Grades = A2)。然后,我可以毫无问题地简单地调用Range("theBest_Grades").Value

我会把这个开放几天,以防有人知道我如何保持我的公式命名范围,并在VBA中使用它。

编辑:这基本上是我最初的工作表/命名范围: enter image description here

命名范围为:

enter image description here

但是,正如我所说,你不能在VBA中使用那种类型的命名范围(至少不是我找到的)。

所以,为了解决它,我只是在单元格中使用了SumIf,并为该单元格指定了范围:

enter image description here

现在我可以毫无问题地使用Range("findWindow_Example").Value

编辑n + 1: 我尝试使用Double进行简单的测试,但同样的事情,它出错:

Sub t5()
' named range "Test" is `=Sum($A$1:$A$4)`

Dim rng As Double
rng = Range("Test") 'Run time error 1004
Debug.Print rng
End Sub

答案 3 :(得分:1)

我在这里没有提到的一件事是UDF的基本规则在这里打破了恕我直言:

UDF需要的所有信息都应通过其参数传递给UDF。

如果您遵守该规则,则使用任何范围名称变得简单,因为范围名称的值将自动转移到参数。

答案 4 :(得分:0)

多个回答者已经找到了解决问题的正确方法,但正如我在评论中所说的那样(其后,其他人可能会感兴趣),错误的原因尚未明确。

您定义的命名范围不返回范围对象。这意味着这段代码:

Dim namedRng As Range
Set namedRng = Range("best_Grade")

无法工作(主要是因为命名范围返回一个数值。如果它返回一个字符串地址表示,它可能有一些语法改进)。

要从编译器的角度说明这一点,请在此处查看即时窗口中的打印输出(特别是第一行):

enter image description here

如果我们假设初始代码是伪代码,那么编译器的要求就是在公式之外构造一个范围(而不是它的'结果!)。

因此,如果我们将Set namedRng = Range("best_Grade")换成Set namedRng = Range(Names("namedRange")),结果可能(但不一定 - 请参阅帖子的结尾!)看起来像:

Set rng = Range("=SUMIF('Ark1'!$B$1:$B$5, "x", 'Ark1'!$A$1:$A$5)")

当然,这不起作用。但是,正如其他答案所示,将namedRange投入Evaluate将是完全合法的!

有趣的是,如果我们? Evaluate(Names("namedRange"))(省略.Value),我们会得到一个错误2015,尽管能够询问编译器? Names("namedRange")并获得一个字符串作为回报!