# Option Base 0 or Option Base 1?



## Lokai

I prefer Option Base 1.
It makes transfer  from array-to-sheet and vice-versa less complicated. Option Base 0 is the default but I don't see the practical advantage.
?


----------



## dk

For me the answer is consistency and not getting confused over what has been set as base 1 and what hasn't.  Lots of controls with multiple items (e.g. listboxes, comboboxes) start at zero.  Any library you refer to will probably have collections and these are likely to always start at zero.  If I know that I should always start at zero then I'm less likely to make a mistake when writing code.

Anyway, I don't think there's a right or a wrong way, it's one of those things which is down to personal preference


----------



## Juan Pablo González

FWIW, VB .Net is "pushing" for 0 based arrays...


----------



## just_jon

Yeah, 0-based seems to be "in". Wonder why though. The theory of a zero-th unit perhaps? Really don't know. Personally, I prefer base=1 so First=1. Just seems easier to explain to people... 'course, then you've still got to explain why the variable "i" has a value of 11 after --

For i=1 to 10
Next i


----------



## dk

Don't think 0 is "in", it's always been like that.  I think it boils down to binary (yawn).  With 4 bits for example you can represent a number up to 15 (1+2+4+8).  If we count from 1 then that gives us 15 usable numbers but if we count from zero it gives us an extra number free!  That's 16 different memory addresses the computer can look at, or 16 bytes of information that can be written to a disk at a time, blah blah.  A poor analogy would be giving a postman who's strong enough to carry 16 parcels a bag only big enough to fit 15 in.  If he has 16 parcels to deliver then he's going to have to make a trip back to the depot to get his last parcel and he won't be a happy postman.

I promise I won't make another analogy on this board.


----------



## NateO

My answer is neither, I simply use the default, whether it's 1 or 0 on an array, never having touched the Option Base declaration. If I don't know where the default is, I tend to test the lower and upper boundaries while I'm developing. One trick, say with Resize() could be to add:

(lbound(myArr)-1)*-1

For a consistent 1-base effect.


----------



## NateO

JPG said:
			
		

> FWIW, VB .Net is "pushing" for 0 based arrays...


Indeed, maybe understating the matter eh. 

If portability to .Net has an impact on your thinking regarding the subject see the following: Use Zero Bound Arrays


----------



## just_jon

Well, that's a change worth noting.


----------



## Ivan F Moala

Use the default and amend when required.


----------



## XL-Dennis

Always explicit declaring Option Base 0 or 1 is good coding   

If You have 0 apples in real life it means You have no apples but this is not real life and it´s not about how many at all  :wink:  

If we have 4 apples we can name them in some kind of order like first, second... 0 or 1 based is used to index arrays. The use of 0-based indexing refers to assembly language and all the hardware starts with 0-based addresses.

So when JPG mention that VB.NET push for 0-based it means that MS accept the way things are in the computer-world   

There shouldn´t be a need to check the LBound for arrays if we know the basic about arrays in XL. Reading data into arrays from sheets will always return a 1-based array even if we explict states Option Base 0 as the below case shows.

Option Explicit
Option Base 0

Sub Read_Data()
Dim rnData As Range
Dim vaData As Variant
Dim i As Long

Set rnData = Range("A1:A4")

vaData = rnData.Value

'Wrong way
For i = 0 To 3
'This will erase runtime error 9 - subscription out of range
'as the index 0 does not exist
    Debug.Print vaData(i, 1)
Next i

'Right way
For i = 1 To 4
    Debug.Print vaData(i, 1)
Next i

End Sub

Personally I use 0-based and 1-based where they are the most suitable. As the case shown above it is sometime difficult to use 0-based.

So where is the third option based on index start at 1 and second option based on indext start at 0.



> I promise I won't make another analogy on this board.


You do   

Take care,
Dennis


----------



## al_b_cnu

I tend to use option base 0, but, where appropriate, just not use element (0)


----------



## NateO

And sometimes it's difficult to use 1-based:

<font face=Courier New><SPAN style="color:darkblue">Option</SPAN> <SPAN style="color:darkblue">Base</SPAN> 1

<SPAN style="color:darkblue">Sub</SPAN> TestArr()
<SPAN style="color:darkblue">Dim</SPAN> myArr1 <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>, myArr2 <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>
<SPAN style="color:darkblue">Dim</SPAN> MyArr3 <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>, myArr4 <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>
<SPAN style="color:darkblue">Dim</SPAN> myArr5() <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Byte</SPAN>, myArr6 <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>
<SPAN style="color:darkblue">Let</SPAN> myArr1 = Array(1, 2, 3)
<SPAN style="color:darkblue">Let</SPAN> myArr2 = [{1,2,3}]
<SPAN style="color:darkblue">Let</SPAN> MyArr3 = [transpose(transpose(a1:c1))]
<SPAN style="color:darkblue">Let</SPAN> myArr4 = [transpose(a1:a3)]
<SPAN style="color:darkblue">Let</SPAN> myArr5 = StrConv("1,2,3", vbFromUnicode)
<SPAN style="color:darkblue">Let</SPAN> myArr6 = Split("1|2|3", "|")
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(myArr1)
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(myArr2)
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(MyArr3)
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(myArr4)
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(myArr5)
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(myArr6)
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN></FONT>

One reason to not even bother mucking with the declaration, simply use LBound.



			
				XLD said:
			
		

> There shouldn´t be a need to check the LBound for arrays if we know the basic about arrays in XL.


There are so many ways to stack an array with VBA, and the results vary to such an extent that LBound & UBound are tremendous tools! 

I can certainly see a need to check the boundaries and it's hard to see why there would be any shame in using them, besides, like Colt 45, they work every time (including the previous example)!


----------



## parry

Like Dennis I prefer to explicitly declare LBound & UBound so anyone else reading the code is clear what the bounds are for the array.
Dim MyArray(1 to 5)

My understanding is when you assign a range directly to an array the range LBound is based upon whats in Option Base so the default is zero unless Option Base is declared otherwise. However, you can Redim to get around this, settle for Base 0 or use LBound if its a dynamic array.

Sub ThisWorks()
Dim Arr()
ReDim Arr(1 To 3)
Arr = Range("a1:c1")
[a2:c2] = Arr
End Sub

Sub ThisDoesnt()
Dim Arr(1 To 3)
Arr = Range("a1:c1")
[a2:c2] = Arr
End Sub

Some people use Option Base 1 alot but I dont like to rely on this at all if I can help it. Your procedure should preferably be self contained in my opinion unless its unavoidable as many people (including me) often miss seeing that Option Base 1 is set so wonder why the code fails. Especially people who dont understand the code and just paste it into their module.


----------



## NateO

Parry said:
			
		

> My understanding is when you assign a range directly to an array the range LBound is based upon whats in Option Base so the default is zero unless Option Base is declared otherwise.


Nope, this is the opposite of what Dennis has said, which is correct with respect to population via Range Object coercion (i.e., it's 1), e.g.,

<font face=Courier New><SPAN style="color:darkblue">Option</SPAN> <SPAN style="color:darkblue">Base</SPAN> 0

<SPAN style="color:darkblue">Sub</SPAN> ThisWorks()
<SPAN style="color:darkblue">Dim</SPAN> Arr() <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>
Arr = Range("a1:c1")
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(Arr)
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
</FONT>


----------



## parry

NateO said:
			
		

> Parry said:
> 
> 
> 
> 
> My understanding is when you assign a range directly to an array the range LBound is based upon whats in Option Base so the default is zero unless Option Base is declared otherwise.
> 
> 
> 
> Nope, this is the opposite of what Dennis has said, which is correct with respect to population via Range Object coercion (i.e., it's 1), e.g.,
> 
> <font face=Courier New><SPAN style="color:darkblue">Option</SPAN> <SPAN style="color:darkblue">Base</SPAN> 0
> 
> <SPAN style="color:darkblue">Sub</SPAN> ThisWorks()
> <SPAN style="color:darkblue">Dim</SPAN> Arr() <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>
> Arr = Range("a1:c1")
> <SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(Arr)
> <SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
> </FONT>
Click to expand...


I think you have just misunderstood me Nate & I dont believe this is the opposite at all. You certainly have more experience in this so I will bow to your knowledge. In your example LBound was 0 - just as I said because Option Base is 0 whether declared as 0 explicitly or omitted. I am saying if Option Base is 1 then the range is LBound 1, if its Option Base 0 the range is LBound 0 unless I redim the array to amend the bounds. If you are disagreeing then you are saying Option Base 1 will have no effect and the array will be LBound 0?   

Option Base 1

Sub AreYouSureNate()
Dim Arr() As Variant
Arr = Range("a1:c1")
Debug.Print LBound(Arr)
End Sub


----------



## XL-Dennis

Just to show that we don´t always need to use the LBound (or Ubound) below is a sample where we use pointers to read the memory to get the number of dimensions an array has.



		Code:
__


Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As _
    Any, source As Any, ByVal bytes As Long)

Function Count_Array_Dimensions(arr As Variant) As Long
Dim ptr As Long
Dim VType As Integer
    
Const VT_BYREF = &H4000&
    
CopyMemory VType, arr, 2
    
If (VType And vbArray) = 0 Then Exit Function
    
CopyMemory ptr, ByVal VarPtr(arr) + 8, 4
    
If (VType And VT_BYREF) Then
    CopyMemory ptr, ByVal ptr, 4
End If

If ptr Then
    CopyMemory Count_Array_Dimensions, ByVal ptr, 2
End If
End Function

Sub Check_Dimensions()
Dim stArray(1 To 4, 1 To 4, 1 To 4, 1 To 4)
Dim rnData As Range
Dim vaArray As Variant

Dim lnNumberofDim As Long

lnNumberofDim = Count_Array_Dimensions(stArray)

Debug.Print lnNumberofDim

With ActiveSheet
    Set rnData = .UsedRange
End With

vaArray = rnData.Value

lnNumberofDim = Count_Array_Dimensions(vaArray)

Debug.Print lnNumberofDim

End Sub


The point is that we don't need to mess around with the LBound. As for the Ubound I believe it is more useful then the LBound-function. But not by reduce it / add 1 to it.

And again, don't try to apply it in real life as this is not the case.

Comments are welcome but don´t expect me to get back to this thread again.


parry - go back to the first message I posted and take another look into it.

Kind regards,
Dennis


----------



## NateO

Hello Parry,

Well, I thought I knew what you were saying, but I'm far less confident about that at this point. Here's what Dennis was saying that I concur with:

When you coerce a Range Object to an array the lower boundary is 1. It doesn't matter if you use:

1) Option Base 0
2) Option Base 1
3) Option Base Fruity Pebbles
4) ReDim(Whatever you want to make up)

E.g.,

<font face=Courier New><SPAN style="color:darkblue">Option</SPAN> <SPAN style="color:darkblue">Base</SPAN> 0
<SPAN style="color:green">'Non-Factor</SPAN>

<SPAN style="color:darkblue">Sub</SPAN> NateIsFairlyCertain()
<SPAN style="color:darkblue">Dim</SPAN> Arr() <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Variant</SPAN>

<SPAN style="color:green">'Not even the folling matters:</SPAN>
<SPAN style="color:darkblue">ReDim</SPAN> Arr(5461 <SPAN style="color:darkblue">To</SPAN> 32768, 0 <SPAN style="color:darkblue">To</SPAN> 7)

Arr = Range("a1:c1")
<SPAN style="color:green">'Just a fox in the hen house has chicken for supper _
    every time, your immediate window will show 1 _
    on the lower boundary with this type of array _
    stack every time.</SPAN>
<SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(Arr, 1); <SPAN style="color:darkblue">UBound</SPAN>(Arr, 1); _
    <SPAN style="color:darkblue">LBound</SPAN>(Arr, 2); <SPAN style="color:darkblue">UBound</SPAN>(Arr, 2)
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
</FONT>

If this is consistent with what you're saying, then I agree, if not, then I don't. 

Edit: Tab spacing got bolloxed up!


----------



## NateO

XLD said:
			
		

> Just to show that we don´t always need to use the LBound (or Ubound) below is a sample where we use pointers to read the memory to get the number of dimensions an array has.


The number of dimensions does not correlate with the boundaries of any dimension. These are two different, independent aspects of an array.

You can memorize that Split() returns a 0-based array and a Range Object coerces to a 1-based array, yadda, yadda, yadda, but for me, life's too short. I'll use LBound().

Go back to my post with the 6 arrays and flip the base setting, you'll see it only impacts 1/6, and they're not consistent with each other!

It'll be easier to compare if you substitute all of the debug prints with the following single call:

<font face=Courier New><SPAN style="color:darkblue">Debug</SPAN>.<SPAN style="color:darkblue">Print</SPAN> <SPAN style="color:darkblue">LBound</SPAN>(myArr1); <SPAN style="color:darkblue">LBound</SPAN>(myArr2); <SPAN style="color:darkblue">LBound</SPAN>(MyArr3); <SPAN style="color:darkblue">LBound</SPAN>(myArr4); _
    <SPAN style="color:darkblue">LBound</SPAN>(myArr5); <SPAN style="color:darkblue">LBound</SPAN>(myArr6)</FONT>


----------



## parry

I like to challenge ideas to ensure better understanding but Im not sure Im 100% clear on this but I wont monopolize this thread anymore. Im surprised of the result in your code Nate and I will have to think about yours Dennis to understand it.

I guess you are very sure then Nate.   
I acquiesce to you guys superior knowledge.   

Sub DamnImWrong()
Dim Answer As MrExcelPost

If Answer = Dennis or Answer = Nate Then
 
End If
End Sub


----------

