Excel VBA:工作簿范围,工作表相关的名称公式/命名范围(结果根据活动工作表而变化)

编辑:标题更改为清晰。

快速总结:我想知道工作簿范围,工作表相关的命名公式(我将在下面描述)的行为是Excel中logging的function。 如果是这样的话,请指向某个文档的方向 – 我似乎无法find关于这个在线的任何东西(也许我正在使用坏的search条件..?),而不想使用的东西是实际一个错误,并可能消失在一个更高的版本!

严格地说,这不是一个关于VBA的问题。 然而,命名公式是我和其他人一直在使用的VBA代码 ,所以它仍然适用于我认为的主题。

编辑:请注意,下面的VBA代码可能不完全正确 – 我还没有testing过。

常规方法

对于工程/科学计算,我经常需要在同一工作簿中多次使用相同的命名公式/范围,但在不同的工作表上。 作为一个简单的例子,我可能在圆圈的区域实现这样的事情:

Dim sht as Worksheet For Each sht In ThisWorkbook Call sht.Names.Add(Name:="AreaCircle",RefersTo:="=PI()*'" & _ sht.Name & "'!Radius^2") Next sht 

其结果是以下一组命名范围/公式(范围为每个工作表):

 =PI()*Sheet1!Radius^2 <--- scoped to Sheet1 =PI()*Sheet2!Radius^2 <--- scoped to Sheet2 etc. etc. 

这当然很好,但是它有很大的缺点,很难做出未来的改变。 例如,如果公式发生变化(圆的面积当然不会改变!但是,例如AASHTO LRFD公路devise规范中的公式,几乎每一个版本都会改​​变!),我必须编辑每一个实例每一个单一的名称公式。 这很乏味,即使我写一个VBA程序来为我做。

替代方法

我发现Excel 2013中偶然发现了以下内容,并且无法在网上find任何有关它的信息。 这让我犹豫开始使用它。

比方说,我运行下面的一行代码:

 Call ThisWorkbook.Names.Add(Name:="AreaCircle",RefersTo:="=PI()*!Radius^2") 

导致以下单一命名范围/公式(范围到工作簿):

=PI()*!Radius^2 <—公式的作用域为Workbook; 注意!Radius ,而不是Radius

请注意,这是不一样的(没有感叹号):

=PI()*Radius^2 <—请注意,此处的Radius被限定在Workbook中。

现在, AreaCircle将产生与上述第一种方法完全相同的行为:它将根据Radius的本地工作表定义的值生成结果。 因此,如果有两个称为Radius名称范围(一个用于Sheet1 ,另一个用于Sheet2 ), AreaCircle根据正在使用的表中的Radius值来计算AreaCircle 。 而且,每当我添加一个新的工作表(这是巨大的!),我不再需要添加这个(和其他所有!)公式的新版本的附加好处。

这是难以描述的行为; 如果您对我的描述感到困惑,则可以执行以下步骤重新创build此行为:

  1. 在工作簿中,创build两个或多个工作表,并在Sheet1单元格A1中input“1”,在Sheet2的单元格A1中input“2”,在Sheet3的单元格A1中input“3”等。
  2. 创build一个名为CellA1的命名范围(带有工作簿范围),并为公式input以下内容: =!$A$1
  3. 在任何单元格中input=CellA1将在Sheet1产生“1”,在Sheet2上产生“2”等。

文档?

嘿,你做到了 – 谢谢你在这里粘着我!

所以,正如我上面所说,有人可以指向我的文档这个“function”? 我很乐意在一些更复杂的项目中开始实施这个项目。 如果没有别的,它只会使名称pipe理器更容易导航20次(没有所有重复的名称)。

至于文档,请参阅评估名称和其他工作表公式expression式

  • =A1引用当前表单元格A1
  • =!A1是指活动工作表上的单元格A1

结合工作表参考

  • 当前是指什么Excel正在重新计算…
  • 主动是指用户正在查看的内容…

查尔斯·威廉姆斯就是这样展示 至于你的用例,我build议用户定义的函数,在VBA中说。

您需要小心使用!名称中的参考:
名称与指代开始=! 从VBA调用计算时可能会给出不正确的结果。 他们的计算方式就像他们总是引用活动工作表而不是他们正在使用的工作表:

将1放在Sheet1的单元格A1中
a)在Sheet1的A2中放置=CellA1 ,其中CellA1被定义为=!$A$1
b)切换到手动计算
c)激活Sheet2
d)运行这个VBA代码

 Sub Testing() Worksheets("Sheet1").Range("a1") = 8 Application.Calculate End Sub 

e)现在切换回Sheet1,您将看到Sheet1!A2包含Sheet2!A1中的任何内容

使用indirect()可以避免这个问题
我们的名字pipe理器插件检测并警告使用这种语法。