如何避免VBA中的默认属性陷阱?

Nei*_*ass 10 excel vba excel-vba

我偶尔只使用VBA,每次回到它时我会被以下的一些变化所困扰:

我有一个Range对象,currentCell用于跟踪我在电子表格中使用的单元格.当我更新它以指向不同的单元格时,我写道:

currentCell = currentCell.Offset(ColumnOffset:=1)
Run Code Online (Sandbox Code Playgroud)

问题是我忘记了Set关键字,所以上面的行实际上是使用Range对象的默认属性:

currentCell.Value = currentCell.Offset(ColumnOffset:=1).Value
Run Code Online (Sandbox Code Playgroud)

所以当前单元格的内容会被新单元格中的内容覆盖,而我的currentCell变量并没有改变为指向一个新单元格,当我意识到我第一百次犯了同样的错误时,我感到愤怒. .

可能没有一个更好的答案,而不是把一个贴在我的显示器上说"你有没有记得今天使用Set?",但如果有人有任何建议来帮助我,我会很感激听到他们.特别是:

  • 当您隐式使用默认属性时,有没有办法打开警告?我从来没有故意这样使用它们,Range.Value如果这就是我的意思,我总是打电话.
  • 是否有任何将变量标记为"只应用于从电子表格中读取"的良好做法?在我编写的大多数代码中,几乎所有变量都用于收集数据,如果某些事情无意中编辑了这样的单元格,那么获取警告会很方便.

end*_*and 6

我花了一段时间来了解你是如何遇到问题的,因为我认为尽管多年来使用范围对象我还没有遇到过这个问题.在思考问题后,我意识到在使用单元格时我会100%执行以下操作 - 我不断使用offsetcells函数 - 我很少使用Set重新定义当前变量.

如果我有一个循环我正在迭代通过电子表格,我可能会做类似的事情

Dim startRng as Range
Set startRng = range("A1")

for i = 1 to 100
   startRng.offset(i,0).value = i
   startRng.offset(i,1).value = startRng.offset(i,0).value
next i
Run Code Online (Sandbox Code Playgroud)

要么

for i = 1 to 100
    cells(i,0).value = i
    cells(i,1).value = cells(i,0).value
next i
Run Code Online (Sandbox Code Playgroud)

这些符号中的任何一个意味着我几乎不需要使用Set范围对象 - 几乎总是发生一次(如果有的话)并且指示我将迭代或引用的范围中的第一个单元格.

它也很清楚offset- 因为你指定了row/column- 这使得代码中发生的事情变得非常简单,并且因为它引用单个单元格而更容易跟踪.您不必向下追踪并向后追溯到更新currentCell Range对象的最后3个位置.

采用这种风格的编码风格应该可以消除你所犯的几乎所有这些错误.当我说我记不起在我编写VBA的所有年份中都发生了类似的错误时,我非常认真 - 我在代码中连续使用offsetcells函数(这些示例中的循环,但我在代码中使用类似的方法和其他所有示例)而不是将范围设置为新范围.副作用是,当您在代码中设置范围时,它几乎总是紧跟在Dim语句之后并且更加明确.


Jea*_*ett 3

\n

当您隐式使用默认属性时,有什么方法可以打开警告吗?

\n
\n\n

不。

\n\n
\n

是否有将变量标记为“这只能用于从电子表格中读取”的良好做法?

\n
\n\n

好吧,您可以制定自己的变量命名约定, \xc3\xa0 la让错误的代码看起来错误,但您仍然需要直观地检查自己的代码,并且编译器不会帮助您这样做。所以我不会太依赖这个。

\n\n

currentCell更好的选择是完全避免重复重新定义的需要.Offset

\n\n

相反,读取 Variant 数组感兴趣的整个范围,在该数组上进行工作,然后在完成修改后将其放回到工作表上。

\n\n
Dim i As Long\nDim j As Long\nDim v As Variant\nDim r As Range\n\nSet r = Range("A1:D5") \'or whatever\n\nv = r.Value \'pull from sheet\n\nFor i = 1 To UBound(v, 1)\n    For j = 1 To UBound(v, 2)\n        \'code to modify or utilise element v(i,j) goes here\n    Next j\nNext i\n\nr.Value = v \'slap v back onto sheet (if you modified it)\n
Run Code Online (Sandbox Code Playgroud)\n\n

瞧\xc3\xa0。不使用默认属性或任何可能造成混淆的内容。作为奖励,这将加快您的代码执行速度。

\n

  • 如果您必须在最后编写“Range("A1:D5").Value = v`,这并不会使其变得更简洁......最好避免像这样在代码中间出现文字。 (2认同)