我正在重构具有约100个模块的VBA项目。其中一些模块是Option Base 1
,其他模块是Option Base 0
(默认)。我希望所有模块都为Option Base 0
,因为这可以简化模块之间的移动功能,以便更合理地定位它们。
如果满足以下条件,我认为可以安全地删除项目中的所有Option Base 1
条语句:
所有设置数组维数的Dim
和ReDim
语句都有明确的下限。
我密切注意Array()
函数的使用,因为这将返回一个数组,其下限由其所在模块的Option Base
确定。
还有什么我需要担心的吗?
答案 0 :(得分:0)
请注意,Option Base
不会影响行计数,因此也不会影响超出范围值(如
Dim MyArr() As Variant
MyArr = Range("A1:A10").Value
不管MyArr(1 To 10)
是Option Base
还是1
,总是会产生数组0
。
您可能还需要注意函数是否返回使用Array()
创建的数组或没有明确下限的数组。在这种情况下,您还需要检查父函数/过程数组的处理方式(可能并不那么明显)。
如果在不同的模块中使用了不同的Option Base
,这尤其棘手。
Option Base 1 'if you plan to change this to 0
Function MyArrayReturningFunction() As Variant
MyArrayReturningFunction = Array(1, 2, 3)
End Function
'in another module
Option Base 0 'this was already 0
'so you might assume no changes are needed in this module BUT WRONG!
Sub ParentProcedure()
Dim MyArr As Variant
MyArr = MyArrayReturningFunction
Dim iItem As Long
For iItem = 1 To 3 'You need to take care here even if this module was already Base 0
'because the array was recieved from a Base 1 function.
'Especially in combination with cells (see next paragraph)
Debug.Print MyArr(iItem)
Next iItem
End Sub
如果将循环用于与单元格和范围组合的数组循环 ,则需要特别注意计数器。
Option Base 1
Sub Test()
Dim MyArr() As Variant
MyArr = Array(1, 2, 3, 4, 5) 'MyArr(1 To 5)
Dim iRow As Long
For iRow = LBound(MyArr) To UBound(MyArr) 'It looks like safe to change because
'LBound/UBound is used BUT see below …
Cells(iRow, A) = MyArr(iRow)
Next iRow
End Sub
需要更改为
Option Base 0
Sub Test()
Dim MyArr() As Variant
MyArr = Array(1, 2, 3, 4, 5) 'MyArr(0 To 4)
Dim iRow As Long
For iRow = LBound(MyArr) To UBound(MyArr) 'even if LBound/UBound is already used,
Cells(iRow + 1, A) = MyArr(iRow) 'the counter for the cells needs to be changed,
'but NOT for the MyArr
Next iRow
End Sub
通常,我认为这种方法很安全,但是您需要对代码进行体面的研究。可能存在一些看不见的陷阱。
答案 1 :(得分:0)
PEH撰写的所有文章都是正确的,尤其是进行此类更改需要仔细分析。
这是我所知的当前状态:
对更改模块顶部的Option Base
语句敏感的代码:
Dim MyArr(3)
设置的Option Base
下限。ReDim MyArr(5)
由Option Base
设置的下限。Private MyArr(3)
设置的Option Base
下限。Public MyArr(3)
设置的Option Base
下限。MyArr = Array(1,2,3)
除非写为VBA.Array
,否则Array
函数将返回一个数组,该数组的下限由模块的Option Base
设置。代码对更改Option Base
不敏感:
Dim MyArr(1 To 3)
的下限是1。ReDim MyArr(0 To 5)
的下限是0。Private MyArr(0 To 5)
的下限是0。Public MyArr(0 To 5)
的下限是0。MyArr = VBA.Array(1,2,3)
的下限是0。MyArr = Split("1,2,3",",")
的下限是0。MyArr = VBA.Split("1,2,3",",")
的下限是0。因此,与Array
不同,Split
的行为是相同的,无论是否以VBA.
为前缀。它总是返回下界为零的数组。无论模块的Option Base
,以下语句都是正确的:
Range.Cells
集合中。.Value
(具有多个单元格)的.Value2
和Range
属性是一个二维Variant()
数组,其下界为1。我不认为还有其他“陷阱”,但我想知道是否存在。