在UDF中使用命名范围

我试图创build一个使用命名范围的UDF。 我命名的范围(“best_Grade”)是一个具有值的单个单元格。 (命名范围的范围是工作簿)。

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

运行时错误'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 

怎么会出错? 这页说它应该工作,不是? 我是否必须将这个UDF放在实际的工作簿对象上,而不是工作簿模块中?

编辑:注意:命名的范围没有设置为单元格,但SumIf公式(best_Grade = SumIf(A2:A10,“X”,…)`这可能会导致错误?

编辑2:是的,这就是为什么我想。 我创build了一个随机单元格的命名区域,并且能够使用Range("a_grade").Value并且它返回了期望的值。 由于我的best_Grade是一个公式,所以我认为这就是错误的原因。 然而,我不知道为什么,因为我认为一个命名的范围是一个命名范围,不pipe它是由什么组成的…

编辑n + 1:注意这里有两个“答案”。 如果我想继续使用命名范围作为Rangevariables,请参阅下面的答案。 不过,我真正想做的是@MacroMarc发布的内容,所以我select了“答案”。

您需要使用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对象必须返回不同的属性才能返回string表示。

 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 

经过一些testing,我发现上面的工作…有趣的一种。 我从Macro Man的评论以及Chip Pearson的post中获得了领先。

关键是定义的名字返回一个string=“你的结果”,所以你可以评估它得到答案,或者你可以做一些string操作来拉引号和等号。 你真的很接近你的RefersToRangeselect。

看到Vegard的评论下你自己发布的答案。

它不工作的原因是因为我命名的范围best_Grades不是一个单元格引用,而是一个公式。 因此,当使用Range("best_Grades").Value ,它是错误的。 ( best_Grades = SumIf(A2:A10,"x", B2:B10, ...)

不知道为什么,因为我认为一个命名的范围是一个命名的范围,不pipe是什么让这个…但我想不是。

现在,我的解决scheme是根据实际的单元格值创build另一个命名范围,然后使用它。 ( theBest_Grades = A2 )。 然后,我可以简单地调用Range("theBest_Grades").Value没有任何问题。

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

编辑:这基本上是我最初有工作表/命名的范围: 在这里输入图像说明

命名范围如下:

在这里输入图像描述

但是,正如我所说的,你不能在VBA中使用这种types的命名范围(至less不是我发现的)。

所以,为了解决这个问题,我只是在单元格中使用了SumIf,并给了这个单元格命名的范围:

在这里输入图像说明

现在我可以使用Range("findWindow_Example").Value没有问题。

编辑n + 1:我试着用Double做一个简单的testing,尽pipe如此,它却出错了:

 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 

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

UDF需要的所有信息都应该通过它的parameter passing给UDF。

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

解决这个问题的正确方法已经被一个以上的答复者发现了,但是正如我在评论中所说(后来,其他人可能会感兴趣的思想),错误的原因还没有被确定。

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

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

(主要是因为命名的范围返回一个数值,如果它返回了一个string地址表示,它可能会有一些语法改进)。

为了从编译器的angular度来说明这一点,请看这里的直接窗口中的打印输出(特别是第一行):

在这里输入图像说明

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

因此,如果我们为Set namedRng = Range(Names("namedRange"))交换Set namedRng = Range("best_Grade") ,结果可能(但不一定 – 见末尾!)看起来像:

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

当然,这是行不通的。 但是像其他答案所显示的那样,将namedRange放入一个Evaluate将会完全合法!


有趣的是,如果我们这样做? Evaluate(Names("namedRange")) ? Evaluate(Names("namedRange")) (省略.Value),我们得到一个错误2015,尽pipe能够问编译器? Names("namedRange") ? Names("namedRange")并获取一个string作为回报!