如何安全地从VBA项目中删除所有Option Base 1语句

时间:2019-05-21 14:41:27

标签: excel vba

我正在重构具有约100个模块的VBA项目。其中一些模块是Option Base 1,其他模块是Option Base 0(默认)。我希望所有模块都为Option Base 0,因为这可以简化模块之间的移动功能,以便更合理地定位它们。

如果满足以下条件,我认为可以安全地删除项目中的所有Option Base 1条语句:

  1. 所有设置数组维数的DimReDim语句都有明确的下限。

  2. 我密切注意Array()函数的使用,因为这将返回一个数组,其下限由其所在模块的Option Base确定。

还有什么我需要担心的吗?

2 个答案:

答案 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,以下语句都是正确的:

  • 从1开始索引到Range.Cells集合中。
  • .Value(具有多个单元格)的.Value2Range属性是一个二维Variant()数组,其下界为1。

我不认为还有其他“陷阱”,但我想知道是否存在。