相对引用、重新生成宏、VBA

问题描述

我正在使用相对引用在 VBA 中录制宏,我首先选择单元格 A1。生成代码是这样的:

 ActiveCell.FormulaR1C1 = "First Cell"
 ActiveCell.Offset(1,1).Range("A1").Select
 ActiveCell.FormulaR1C1 = "Second Cell"
 ActiveCell.Offset(1,0).Range("A1").Select

我想知道的是为什么我们在第二个和第四个单元格中得到 ".Range.("A1)"?相对引用不应该以这样的方式表现,我们只是从起始单元格开始,我们可以有从其他地方开始,所以“A1”不需要出现在代码中? 我尝试从第二行重新创建 ".Range("A1")",宏似乎做了同样的事情?

解决方法

当您选择一个启用了相对引用的范围时,宏记录器会做两件事:

  1. 它确定与将成为新选定范围左上角单元格的活动单元格的偏移量。如果您从 A1 转到 B1,它会构建 ActiveCell.Offset(0,1) 以向下移动零行和向右移动一列。
  2. 它确定新选择范围的宽度和高度,并以 A1 表示法构建高度和宽度的命令。如果您从 A1 转到 B1,它会计算出新范围为 1x1。在 A1 符号中,相对于活动单元格的 1x1 选择是“A1”,因此它继续将命令构建为 ActiveCell.Offset(0,1).Range("A1")

他们必须构建宏记录器以分两步完成此操作,因为您可以选择多个单元格。如果您从 A1 转到 B1:C7。你得到

ActiveCell.FormulaR1C1 = "First Cell"
ActiveCell.Offset(0,1).Range("A1:B7").Select

这转化为“从活动单元格右侧零行一列的单元格开始,然后就好像它是整个工作表的左上角单元格一样,选择一个两列宽、七个单元格高的范围.

关于它的令人困惑的部分是 A1 符号。人们只会想到像 A1 这样的单元格引用来引用整个工作表。所以像 C6 这样的引用永远是第三列第六行。

但在 VBA 中,您可以从任何单元格开始使用 A1 表示法。您可以选择单元格 K10,然后在立即窗口中输入:

?activecell.Range("b2").Range("b2").Range("b2").Address

你会得到 13 美元。这些 B2 引用中的每一个都意味着向右移动一列和向下移动一行。他们中的三个连续这样做了三遍。关键在于它以Range 对象开始,即ActiveCell。如果您从一张工作表开始,例如 Sheet1ActiveSheet,那么 A1 表示法将相对于工作表的左上角。

为什么没有它也能工作?

如果您选择单个单元格,它只能在没有 Range("A1") 的情况下工作。如果您选择了多个单元格,您仍然可以删除 Range 部分,但代码将不一样。

它在没有 Range 部分的情况下工作的另一个重要原因是因为 Offset 属性返回一个 Range 对象。有许多返回 Range 对象的属性,包括 RangeOffsetResizeCells。任何返回 Range 对象的属性后面都可以跟 .Select,因为 SelectRange 对象的属性。

为什么记录器将它包含在单个单元格中?

除了创建宏记录器的程序员之外,没有人知道。他们可以很容易地计算出新选择的范围是单个单元格并在 ActiveCell.Offset(0,1).Select 处停止,但无论新选择的高度和宽度如何,执行这两个步骤可能更容易。