哪些 Excel 对象是从零开始的,哪些是从一开始的?

Nou*_*non 23 vba microsoft-excel-2007

使用 VBA 访问工作表中的第一个工作表是 Worksheets(1)。ListBox 中的第一项是 myListBox.List(0)。我听说 Collections 是基于 1 的,但我不知道它们是什么。VBA 数组是基于 0 的。像 MID 这样的 Excel 字符串函数是从 1 开始的。是否有关于基于 0 或 1 的一般原则,或者您能否提供每个的列表?

pau*_*ica 30

VBA 中有 3 种主要类型的分组结构,索引之间有区别

  • 集合 - 基于 1 的索引

    • 基于 0 的异常:用户窗体集合,如选项卡、页面、控件(列表框、文本框)
    • 集合是包含逻辑相关对象组(或列表)的本机 Excel 对象
    • 通常用于保存复杂对象,但也可以保存基本类型
    • Excel 集合:

      • 工作簿、工作表、范围、形状
      • Sheets(1) 是文件中的第一个,Cells(1, 1) 是第一行第一列中的单元格
    • 集合的主要优点是方便按名称访问元素

      • For-Each 循环非常高效(与数组的 For-Each 处理相比)
      • 虽然通过索引访问单个项目比通过名称访问它们更快

  • 数组 - 默认从 0 开始,但第一个索引可以更改为任何数字(如下图所示)

    • 数组是包含一组相关变量的变量
    • 通常用于基本数据类型,如 Boolean、Integer、Long、String、Double 等
    • 一旦定义,它将只包含一种类型的项目: Dim x() As Long

      • 要保存更复杂的对象,可以将数组定义为 Dim x() As Variant
      • 变体可以是任何类型的对象,包括工作簿、表格、范围、数组

        • Dim x As Variant: x = Array(1) '1 Variant variable containing 1 array
        • Dim y(2) As Variant '1 Variant array containing 3 arrays
        • y(0) = Array(1): y(1) = Array(2): y(2) = Array(3)
    • 数组的主要优点是按索引访问项目时的性能

      • For index=0 To 10循环比For-Each循环快

  • 字典 - 未编入索引,但可以使用 Keys 模拟索引

    • 原生于 VB 脚本,而非 VBA(必须使用外部库)
    • 可以保存任何类型的对象,包括数组、集合或其他字典

ListBox 是一个复杂的对象,可以通过基于 0 的 Controls 集合访问

ListBox 的 .List() 属性是一个从 0 开始的数组

其他注意事项

  • 基于 0 的索引是其他语言的标准

  • VBA 引入了基于 1 的概念,以使其对新用户更直观:

    • Sheet1 到 Sheet3,集合 Count 为 3 比
    • Sheet0 到 Sheet2,集合计数为 3

它们的索引之间差异的一些实际示例:

Public Sub vbaCollections()
    Dim c As New Collection     '1-based index

    c.Add Item:="a", Key:="1"   'index 1; Key must a String
    c.Add Item:="b", Key:="2"   'index 2
    c.Add Item:="c", Key:="3"   'index 3

    Debug.Print c.Count         '3;   Items in index sequence: a,b,c, Keys: "1","2","3"
    Debug.Print c.Item(1)       'a;   not available for Dictionaries
    'Debug.Print c.Key("1")     'invalid, so is: c.Key(1)

    c.Remove Index:=2
    Debug.Print c.Count         '2;   items in index sequence: a,c, Keys: "1","3"
    'c.Remove Item:="c"         'invalid, so is: c.Remove Key:="3"

    'c.Add Item:="c", Key:="3", Before:=1   'Key must be unique - Error
    c.Add Item:="c", Key:="5", Before:=1    'allows duplicate Item
    Debug.Print c.Count         '3;   items in index sequence: c,a,c, Keys: "5","1","3"
End Sub
Run Code Online (Sandbox Code Playgroud)
Public Sub vbaArrays()
    Dim a() As Long, b(3) As Long   'Arrays default to "Option Base {0 | 1}"
    Dim c(0 To 0)                   'if "Option Base" not defined, it defaults to 0
    Dim ar(1) As Worksheet: Set ar(0) = Worksheets(1)   'array with 1 Worksheets object

    ReDim a(3)          'creates an array of 4 elements; indexes 0,1,2,3
        Debug.Print "LB: " & LBound(a) & ", UB: " & UBound(a)   'LB: 0, UB: 3
        Debug.Print UBound(a) - LBound(a)                       '3, array b() is the same

    'even whith "Option Base 1", the following still default to 0
    Dim v As Variant:  v = Split("A B")         'array with 2 items: v(0) = "A", v(1) = "B"
    'UserForm1.ListBox1.List = Array("Test")    'array with 1 item: .List(0,0) = "Test"

    ReDim a(0 To 3)     'creates an array of 4 elements; indexes 0,1,2,3
    a(0) = 1:   a(1) = 2:   a(2) = 3    'a(3) defaults to 0

        Debug.Print "LB: " & LBound(a) & ", UB: " & UBound(a)   'LB: 0, UB: 3
        Debug.Print UBound(a) - LBound(a)                       '3; offset index by -1

    ReDim a(1 To 3)     'creates an array of 3 elements; indexes 1,2,3
    a(1) = 1:   a(2) = 2:   a(3) = 3

        Debug.Print "LB: " & LBound(a) & ", UB: " & UBound(a)   'LB: 1, UB: 3
        Debug.Print UBound(a) - LBound(a)                       '2; offset count by +1

    ReDim a(5 To 7)     'creates an array of 3 elements; indexes 5,6,7
    a(5) = 1:   a(6) = 2:   a(7) = 3

        Debug.Print "LB: " & LBound(a) & ", UB: " & UBound(a)   'LB: 5, UB: 7
        Debug.Print UBound(a) - LBound(a)                       '2; offset count by +1

    ReDim a(-3 To -1)   'creates an array of 3 elements; indexes -3,-2,-1
    a(-3) = 1:  a(-2) = 2:  a(-1) = 3

        Debug.Print "LB: " & LBound(a) & ", UB: " & UBound(a)   'LB: -3, UB: -1
        Debug.Print UBound(a) - LBound(a)                       '2; offset count by +1
End Sub
Run Code Online (Sandbox Code Playgroud)
Public Sub vbsDictionaries()
    Dim d As Object         'not indexed (similar to linked lists)
    Set d = CreateObject("Scripting.Dictionary")    'native to VB Script, not VBA

    d.Add Key:="a", Item:=1 'index is based on Key (a, b, c)
    d.Add Key:="b", Item:=2
    d.Add Key:="c", Item:=3
    Debug.Print d.Count     '3; Keys: a,b,c, Items: 1,2,3

    Debug.Print d(1)        'output is empty ("") - adds new element: Key:="1", Item:=""
    Debug.Print d.Count     '4; Keys: a,b,c,1, Items: 1,2,3,Empty
    Debug.Print d("a")      '1
    Debug.Print d(1)        'output is Empty ("") from element with Key:="1"

    'd.Add Key:="b", Item:=2        'attempt to add existing element: Key:="b" - Error

    'd.Keys  - 0-based array (not available for Collections)
    'd.Items - 0-based array (not available for Collections)

    d.Remove d.Keys()(1)            'remove element Item:=2 (Key:="b")
        Debug.Print d.Count         '3; Keys: a,c,1, Items: 1,3,""
    d.Remove d.Items()(0)           'remove Items element 0 (Key:="1", Item:="")
        Debug.Print d.Count         '2; Keys: a,c, Items: 1,3
    d.Remove "c"                    'remove element Key:="c" (Item:=3)
        Debug.Print d.Count         '1; Keys: a, Items: 1

    d.Add Key:="c", Item:=3
        Debug.Print d.Count         '2; Keys: a,c, Items: 1,3

    'd.Remove d.Items()(0)          'invalid
    Debug.Print d.Items()(d.Count - 1)  '3
    d.Remove d.Keys()(d.Count - 1)  'remove last element; access last Key by Key
        Debug.Print d.Count         '1; Keys: a, Items: 1

    Debug.Print d.Exists("a")       'True (not available for Collections)
    Debug.Print d.Exists(2)         'False
End Sub
Run Code Online (Sandbox Code Playgroud)

进一步阅读: