Excel VBA:工作簿范围,工作表相关的命名公式/命名范围(结果更改取决于活动工作表)

时间:2014-04-07 18:18:45

标签: excel vba excel-vba named-ranges

编辑:为清晰起见改变了标题。

快速摘要:我想知道工作簿作用域,依赖于工作表的命名公式(我将在下面介绍)的行为是否是Excel中的文档功能。如果是这样,请指出我某处某些文件的方向 - 我似乎无法在网上找到任何关于此的信息(也许我使用了不好的搜索条件......?)并且不想使用实际上是一个bug的东西,可能会在以后的版本中消失!

严格来说,这不是关于VBA的问题;然而,命名的公式是我和其他人use in VBA code all the time,所以它仍然适用于我认为的主题。

编辑:请注意,下面的VBA代码可能不完全正确 - 我还没有对其进行测试。

常规方法

对于工程/科学计算,我经常需要在同一工作簿中多次使用相同的命名公式/范围,但是在不同的工作表上。作为一个简化的例子,我可以为圆形区域实现类似的东西:

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公路设计规范中的公式,几乎每个版本都会改​​变!),我必须编辑每一个每个名称公式的单个实例。即使我写了一个VBA程序来为我做这件事,这也很乏味。

替代方法

前几天我在Excel 2013中发现了以下事故,并且无法在网上任何地方找到任何相关信息。这让我对开始使用它犹豫不决。

让我说我运行以下单行代码:

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

这导致以下SINGLE命名范围/公式(作用于工作簿):

=PI()*!Radius^2&lt; ---公式的范围是工作簿;请注意!Radius,而不是Radius

请注意,这与以下内容不同(没有感叹号):

=PI()*Radius^2&lt; ---请注意,此处Radius的范围限定为工作簿。

现在,AreaCircle将产生与上面第一种方法完全相同的行为:它将根据本地工作表定义的Radius值生成结果。因此,如果有两个名为Radius的命名范围(一个用于Sheet1,另一个用于Sheet2),则AreaCircle将根据Radius的值进行计算使用它的纸张。而且每次添加新工作表时,我都不再需要添加新版本(以及其他所有!)公式的额外好处(这是巨大的!)。

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

  1. 在工作簿中,创建两个或多个工作表并输入&#34; 1&#34;在A1的单元格Sheet1中,&#34; 2&#34;在Sheet2的单元格A1中,&#34; 3&#34;在Sheet3的单元格A1等等。
  2. 创建名为CellA1的命名范围(带有工作簿范围),并为公式输入以下内容:=!$A$1
  3. 在任何单元格中输入=CellA1将导致&#34; 1&#34;在Sheet1上,结果为&#34; 2&#34;在Sheet2等等
  4. 文档?

    嘿,你做到了 - 谢谢你在这里坚持下去!

    所以,正如我上面所说的那样,有人可以指出我这个&#34;功能的文档&#34;?我希望在一些更复杂的项目中开始实现这一点;如果不出意外,它只会使名称管理器更容易导航20次(没有所有重复的名称)。

2 个答案:

答案 0 :(得分:5)

关于文档,请参阅Evaluating Names and Other Worksheet Formula Expressions

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

Worksheet References

一起使用
  • 当前指的是Excel重新计算的内容......
  • 有效是指用户正在查看的内容......

这就是查尔斯威廉姆斯所展示的。至于你的用例,我推荐用户定义的函数,比如在VBA中。

答案 1 :(得分:3)

你需要小心使用!姓名参考:
带引号的名称以=开头!从VBA调用计算时可能会给出不正确的结果。计算它们就好像它们总是引用活动工作表而不是它们用于它们的工作表:

将1放入Sheet1的单元格A1中 a)将=CellA1放入Sheet1的A2中,其中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()可以避免这个问题 我们的名称管理器插件检测并警告使用这种语法。