VB6 and COM use a mixture of 0- and 1-based indexing (arrays are 0-based except when you change this with Option Base or declare them otherwise explicitly).
COM collections are usually 1-based in earlier COM object models, but sometimes 0-based...
Dim/Redim data(1 To N) is an array of N elements indexed from 1 to N
Dim/Redim data(0 to N-1) is an array of N elements indexed from 0 to N-1
Dim/Redim data(N) is an array of N+1 elements indexed from 0 to N (if Option Base is 0)
The last case is the one that sometimes confuses, data(N) usually means data(0 To N) which is an array of N+1 elements.
Personally I always declare arrays explicitly as (0 To N-1) and don't rely on Option Base, which is more familiar for developers who use more than one language.
There is one edge case: VBA does not support zero-length arrays, you must always have at least one element (for each dimension in multidimensional arrays). So the smallest array you can declare is data(0 To 0) or data(1 To 1) with one element.
In your case, I suspect you are creating an array with one element, then adding an element each time through the loop:
ReDim data(1 To 1)
While Cells(ndx, 1).Value <> vbNullString
ReDim Preserve data(1 To (UBound(data) + 1))
ndx = ndx + 1
Wend
Instead (and leaving aside for the moment considerations of the efficiency of calling ReDim Preserve in a loop), you should be using:
ReDim data(1 To 1)
nStartIndex = ndx
While Cells(ndx, 1).Value <> vbNullString
' On the first iteration this does nothing because
' the array already has one element
ReDim Preserve data(1 To ndx - nStartIndex + 1)
ndx = ndx + 1
Wend