Które obiekty Excel są oparte na zerach, a które na jednym?

20

Korzystanie z VBA w celu uzyskania dostępu do pierwszego arkusza w arkuszu to Arkusze (1). Pierwszym elementem ListBox jest myListBox.List (0). Słyszałem, że Kolekcje są oparte na 1, ale nie wiem, co to są. Macierze VBA są oparte na 0. Funkcje ciągów Excel, takie jak MID, są oparte na 1. Czy istnieje ogólna zasada oparta na 0 lub 1, czy możesz podać ich listę?

Noumenon
źródło
komórka (1,1). znaki (indeks, długość) jest oparta na 1, ale dokonuje pewnego rodzaju obcinania granicy, dzięki czemu komórka (1,1). znaki (0, długość) = komórka (1,1). znaki (1, length) (Excel 2013)
seanv507

Odpowiedzi:

24

Istnieją 3 główne typy konstrukcji grupujących dostępne w VBA, z rozróżnieniem między indeksami

  • Kolekcje - indeks 1

    • Wyjątki oparte na 0: kolekcje UserForm, takie jak Tabs, Pages, Controls (ListBox, TextBox)
    • Kolekcje to rodzime obiekty Excel zawierające grupy (lub listy) obiektów logicznie powiązanych
    • Zwykle używany do przechowywania złożonych obiektów, ale może również przechowywać podstawowe typy
    • Kolekcje Excel:

      • Skoroszyty, arkusze, zakresy, kształty
      • Arkusze (1) są pierwszymi w pliku, Komórki (1, 1) to komórki w pierwszym rzędzie i pierwszej kolumnie
    • Główną zaletą kolekcji jest wygoda dostępu do elementów według nazwy

      • Pętla For-Each jest bardzo wydajna (w porównaniu do przetwarzania tablic For-Each)
      • Dostęp do poszczególnych elementów według indeksu jest jednak szybszy niż dostęp do nich według nazwy

  • Tablice - domyślnie oparte na 0, ale pierwszy indeks można zmienić na dowolną liczbę (zilustrowano poniżej)

    • Tablice to zmienne, które zawierają zestaw powiązanych zmiennych
    • Zwykle używany do prymitywnych typów danych, takich jak Boolean, Integer, Long, String, Double itp
    • Po zdefiniowaniu pomieści tylko jeden typ przedmiotów: Dim x() As Long

      • Aby pomieścić bardziej złożone obiekty, tablicę można zdefiniować jako Dim x() As Variant
      • Warianty mogą być dowolnymi obiektami, w tym skoroszytami, arkuszami, zakresami, tablicami

        • 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)
    • Główną zaletą tablic jest wydajność podczas uzyskiwania dostępu do elementów według indeksu

      • For index=0 To 10Pętle są szybsze niż For-Eachpętle

  • Słowniki - nie indeksowane, ale indeksy można symulować za pomocą kluczy

    • Natywny dla skryptu VB, a nie VBA (musi używać zewnętrznej biblioteki)
    • Może pomieścić wszelkiego rodzaju obiekty, w tym tablice, kolekcje lub inne słowniki

ListBox jest złożonym obiektem i można uzyskać do niego dostęp poprzez kolekcję formantów opartych na 0

Właściwość .List () ListBox jest tablicą 0

Inne notatki

  • Indeksy oparte na 0 są standardem dla innych języków

  • VBA wprowadziła koncepcję 1, aby była bardziej intuicyjna dla nowych użytkowników:

    • Arkusz od 1 do 3, z kolekcją Liczba 3 jest łatwiejsza w użyciu niż
    • Arkusz 0 do arkusza 2, z kolekcją Liczba 3

Kilka praktycznych przykładów różnicy między ich indeksami:

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

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

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

Dalsza lektura:

Paul Bica
źródło