PC Review


Reply
Thread Tools Rate Thread

How do I Create 'ragged' arrays in Excel VBA?

 
 
David Empey
Guest
Posts: n/a
 
      11th Mar 2007
The following code seems to work, but is it safe?

Sub RaggedArray

Dim A() as Variant, B() as Long, i as Long, j as Long

ReDim A(1 to 10)
For i = 1 to 10
ReDim B(1 to I)
A(i) = B
For j = 1 to i
A(i)(j) = 10 * i + j
Next j
Next i

End Sub

This seems to create an array A whose elements are arrays
of varying lengths, which is what I want, but can I be
sure the elements of A won't be overwritten by some other
piece of code that needs to use memory? Does Visual
Basic know the elements of A exist?

Am I even asking a sensible question?

--
Dave Empey

Remember, if you're doing any major experiments in stellar
dynamics, always mount a scratch star first! --Richard Todd
 
Reply With Quote
 
 
 
 
John Coleman
Guest
Posts: n/a
 
      11th Mar 2007
Interesting example. I think that what happens is the following: VBA's
garbage collection is based on reference counting. When you run the
statement A(i) = B you are establishing a reference to the current
array B - a reference which won't be removed until *A(i)* is
reassigned (or destroyed). When ReDim B(1 to i) is run a brand new
array is allocated for B. This usually results in the old array being
garbage collected - but here you still have a reference keeping it
alive. Your code seems to work but it is not clear to me that you are
guaranteed that a ReDim B always allocates a separate memory block for
the new array and never overwrites the old B (unless it is ripe for
garbage collection) . In other words - I'm not sure if you have found
a subtle use of a documented behavior or a convienent use of an
undocumented. I suspect the former, but am not 100% sure. Maybe
someone with more knowledge of VBA's memory management will chip in.

-John Coleman


On Mar 11, 1:56 am, David Empey <dem...@cruzio.com> wrote:
> The following code seems to work, but is it safe?
>
> Sub RaggedArray
>
> Dim A() as Variant, B() as Long, i as Long, j as Long
>
> ReDim A(1 to 10)
> For i = 1 to 10
> ReDim B(1 to I)
> A(i) = B
> For j = 1 to i
> A(i)(j) = 10 * i + j
> Next j
> Next i
>
> End Sub
>
> This seems to create an array A whose elements are arrays
> of varying lengths, which is what I want, but can I be
> sure the elements of A won't be overwritten by some other
> piece of code that needs to use memory? Does Visual
> Basic know the elements of A exist?
>
> Am I even asking a sensible question?
>
> --
> Dave Empey
>
> Remember, if you're doing any major experiments in stellar
> dynamics, always mount a scratch star first! --Richard Todd



 
Reply With Quote
 
John Coleman
Guest
Posts: n/a
 
      11th Mar 2007
One further thought - it is possible to both make your intentions
clearer and lay to rest some lingering concerns by doing something
like:

Sub RaggedArray()


Dim A() As Variant, i As Long, j As Long


ReDim A(1 To 10)
For i = 1 To 10
A(i) = MakeArray(1, i)
For j = 1 To i
A(i)(j) = 10 * i + j
Next j
Next i

End Sub

Function MakeArray(lower As Long, upper As Long) As Variant
Dim A As Variant
ReDim A(lower To upper)
MakeArray = A
End Function

The cost would be a little less memory efficiency since MakeArray
returns a variant array. If it matters, you could do something like:

Sub RaggedArray()


Dim A() As Variant, i As Long, j As Long


ReDim A(1 To 10)
For i = 1 To 10
A(i) = MakeLongArray(1, i)
For j = 1 To i
A(i)(j) = 10 * i + j
Next j
Next i

End Sub

Function MakeLongArray(lower As Long, upper As Long) As Variant
Dim A() As Long
ReDim A(lower To upper)
MakeLongArray = A
End Function

Which seems to be functionally equivalent to your original code.

Hth

-John Coleman

On Mar 11, 10:21 am, "John Coleman" <jcole...@franciscan.edu> wrote:
> Interesting example. I think that what happens is the following: VBA's
> garbage collection is based on reference counting. When you run the
> statement A(i) = B you are establishing a reference to the current
> array B - a reference which won't be removed until *A(i)* is
> reassigned (or destroyed). When ReDim B(1 to i) is run a brand new
> array is allocated for B. This usually results in the old array being
> garbage collected - but here you still have a reference keeping it
> alive. Your code seems to work but it is not clear to me that you are
> guaranteed that a ReDim B always allocates a separate memory block for
> the new array and never overwrites the old B (unless it is ripe for
> garbage collection) . In other words - I'm not sure if you have found
> a subtle use of a documented behavior or a convienent use of an
> undocumented. I suspect the former, but am not 100% sure. Maybe
> someone with more knowledge of VBA's memory management will chip in.
>
> -John Coleman
>
> On Mar 11, 1:56 am, David Empey <dem...@cruzio.com> wrote:
>
>
>
> > The following code seems to work, but is it safe?

>
> > Sub RaggedArray

>
> > Dim A() as Variant, B() as Long, i as Long, j as Long

>
> > ReDim A(1 to 10)
> > For i = 1 to 10
> > ReDim B(1 to I)
> > A(i) = B
> > For j = 1 to i
> > A(i)(j) = 10 * i + j
> > Next j
> > Next i

>
> > End Sub

>
> > This seems to create an array A whose elements are arrays
> > of varying lengths, which is what I want, but can I be
> > sure the elements of A won't be overwritten by some other
> > piece of code that needs to use memory? Does Visual
> > Basic know the elements of A exist?

>
> > Am I even asking a sensible question?

>
> > --
> > Dave Empey

>
> > Remember, if you're doing any major experiments in stellar
> > dynamics, always mount a scratch star first! --Richard Todd- Hide quoted text -

>
> - Show quoted text -



 
Reply With Quote
 
RB Smissaert
Guest
Posts: n/a
 
      11th Mar 2007
I don't think there is anything wrong with this code and as far as I know
this is just
completely standard and will behave fine. No need to worry about memory
management.
If it compiles and behaves as expected in a few tests then that is it.

If you want you could make a collection of arrays, which may have some
advantage.

RBS

"David Empey" <(E-Mail Removed)> wrote in message
news:Xns98EFDF25967FDdempeycruziocom@64.209.0.87...
> The following code seems to work, but is it safe?
>
> Sub RaggedArray
>
> Dim A() as Variant, B() as Long, i as Long, j as Long
>
> ReDim A(1 to 10)
> For i = 1 to 10
> ReDim B(1 to I)
> A(i) = B
> For j = 1 to i
> A(i)(j) = 10 * i + j
> Next j
> Next i
>
> End Sub
>
> This seems to create an array A whose elements are arrays
> of varying lengths, which is what I want, but can I be
> sure the elements of A won't be overwritten by some other
> piece of code that needs to use memory? Does Visual
> Basic know the elements of A exist?
>
> Am I even asking a sensible question?
>
> --
> Dave Empey
>
> Remember, if you're doing any major experiments in stellar
> dynamics, always mount a scratch star first! --Richard Todd


 
Reply With Quote
 
David Empey
Guest
Posts: n/a
 
      11th Mar 2007
"John Coleman" <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

> In other words - I'm not sure if you have found
> a subtle use of a documented behavior or a convienent use of an
> undocumented. I suspect the former, but am not 100% sure. Maybe
> someone with more knowledge of VBA's memory management will chip in.
>


That's exactly my question. So far I haven't run into any trouble
(that I know of) doing it this way, but I'd like to be sure.
Thanks for your suggestions.

--
Dave Empey

Remember, if you're doing any major experiments in stellar
dynamics, always mount a scratch star first! --Richard Todd
 
Reply With Quote
 
Tom Ogilvy
Guest
Posts: n/a
 
      11th Mar 2007
I disagree with John's description of references in this instance.
>When you run the

statement A(i) = B you are establishing a reference to the current
array B - a reference which won't be removed until *A(i)* is
reassigned (or destroyed).

I don't believe this is correct. This should convince you that A(i) is
different from B. In otherwords, the array B is copied to A(i), not
referenced: (since B has not been reassigned, if it were only referenced,
A(i)(j) = B(j). But it doesn't. )

Sub RaggedArray()

Dim A() As Variant, B() As Long, i As Long, j As Long
Dim l As Long
ReDim A(1 To 10)
For i = 1 To 10
ReDim B(1 To i)
For j = 1 To i
B(j) = Int(Rnd() * 100 + 1)
Next
A(i) = B
For j = 1 To i
A(i)(j) = 10 * i + j
Next j
If i = 5 Then
For j = 1 To i
Debug.Print i, j, A(i)(j), B(j)
Next
End If

Next i

End Sub

So you should have no concerns using this approach.

--
Regards,
Tom Ogilvy


"David Empey" <(E-Mail Removed)> wrote in message
news:Xns98EFDF25967FDdempeycruziocom@64.209.0.87...
> The following code seems to work, but is it safe?
>
> Sub RaggedArray
>
> Dim A() as Variant, B() as Long, i as Long, j as Long
>
> ReDim A(1 to 10)
> For i = 1 to 10
> ReDim B(1 to I)
> A(i) = B
> For j = 1 to i
> A(i)(j) = 10 * i + j
> Next j
> Next i
>
> End Sub
>
> This seems to create an array A whose elements are arrays
> of varying lengths, which is what I want, but can I be
> sure the elements of A won't be overwritten by some other
> piece of code that needs to use memory? Does Visual
> Basic know the elements of A exist?
>
> Am I even asking a sensible question?
>
> --
> Dave Empey
>
> Remember, if you're doing any major experiments in stellar
> dynamics, always mount a scratch star first! --Richard Todd



 
Reply With Quote
 
Peter T
Guest
Posts: n/a
 
      11th Mar 2007
As others have said that's quite normal, known as an 'Array of Arrays'. Very
useful when needed, not particularly efficient if not. The array holder must
be a Variant as in your example.

Try this with your example -

'code
Next i
Dim C as variant
C = A
A(1) = C
Stop ' Alt-v,s look at A(1) in locals
End Sub

Regards,
Peter T

"David Empey" <(E-Mail Removed)> wrote in message
news:Xns98EFDF25967FDdempeycruziocom@64.209.0.87...
> The following code seems to work, but is it safe?
>
> Sub RaggedArray
>
> Dim A() as Variant, B() as Long, i as Long, j as Long
>
> ReDim A(1 to 10)
> For i = 1 to 10
> ReDim B(1 to I)
> A(i) = B
> For j = 1 to i
> A(i)(j) = 10 * i + j
> Next j
> Next i
>
> End Sub
>
> This seems to create an array A whose elements are arrays
> of varying lengths, which is what I want, but can I be
> sure the elements of A won't be overwritten by some other
> piece of code that needs to use memory? Does Visual
> Basic know the elements of A exist?
>
> Am I even asking a sensible question?
>
> --
> Dave Empey
>
> Remember, if you're doing any major experiments in stellar
> dynamics, always mount a scratch star first! --Richard Todd



 
Reply With Quote
 
John Coleman
Guest
Posts: n/a
 
      11th Mar 2007
You are correct. An even simpler example to show that Array
assignments don't create an alias would be something like

Dim A(), B() as long
Redim A(1 to 10)
Redim B(1 to 10)
A(1) = B
B(1) = 5
msgbox A(1)(1) 'won't return 5

my speculation was based on trying to figure out why VBA seems to
require B here (perhaps hidden in a function call as in my second
post) instead of a simple

Dim A(1 to 10) as variant
For i = 1 to 10
ReDim A(i)(1 to i) 'ReDim (A(i))(1 to i) isn't any better
Next i

(which is a syntax error).

If A(i) is a Variant and ReDim is a valid statement for Variants, then
why not for A(i)? My first guess was that B was playing some essential
role as the target of a reference, but it looks more like it is just
plugging a gap in VBA's syntax (although if you want the sub-arrays to
be of type other than variant something like B or a function call
would be required).
Thanks for the correction

-John Coleman





On Mar 11, 5:07 pm, "Tom Ogilvy" <twogi...@msn.com> wrote:
> I disagree with John's description of references in this instance.>When you run the
>
> statement A(i) = B you are establishing a reference to the current
> array B - a reference which won't be removed until *A(i)* is
> reassigned (or destroyed).
>
> I don't believe this is correct. This should convince you that A(i) is
> different from B. In otherwords, the array B is copied to A(i), not
> referenced: (since B has not been reassigned, if it were only referenced,
> A(i)(j) = B(j). But it doesn't. )
>
> Sub RaggedArray()
>
> Dim A() As Variant, B() As Long, i As Long, j As Long
> Dim l As Long
> ReDim A(1 To 10)
> For i = 1 To 10
> ReDim B(1 To i)
> For j = 1 To i
> B(j) = Int(Rnd() * 100 + 1)
> Next
> A(i) = B
> For j = 1 To i
> A(i)(j) = 10 * i + j
> Next j
> If i = 5 Then
> For j = 1 To i
> Debug.Print i, j, A(i)(j), B(j)
> Next
> End If
>
> Next i
>
> End Sub
>
> So you should have no concerns using this approach.
>
> --
> Regards,
> Tom Ogilvy
>
> "David Empey" <dem...@cruzio.com> wrote in message
>
> news:Xns98EFDF25967FDdempeycruziocom@64.209.0.87...
>
>
>
> > The following code seems to work, but is it safe?

>
> > Sub RaggedArray

>
> > Dim A() as Variant, B() as Long, i as Long, j as Long

>
> > ReDim A(1 to 10)
> > For i = 1 to 10
> > ReDim B(1 to I)
> > A(i) = B
> > For j = 1 to i
> > A(i)(j) = 10 * i + j
> > Next j
> > Next i

>
> > End Sub

>
> > This seems to create an array A whose elements are arrays
> > of varying lengths, which is what I want, but can I be
> > sure the elements of A won't be overwritten by some other
> > piece of code that needs to use memory? Does Visual
> > Basic know the elements of A exist?

>
> > Am I even asking a sensible question?

>
> > --
> > Dave Empey

>
> > Remember, if you're doing any major experiments in stellar
> > dynamics, always mount a scratch star first! --Richard Todd- Hide quoted text -

>
> - Show quoted text -



 
Reply With Quote
 
David Empey
Guest
Posts: n/a
 
      12th Mar 2007
"Tom Ogilvy" <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

>
> So you should have no concerns using this approach.
>


Tom, John, RB, Peter: thanks very much for your
responses. I'm glad to know the approach should
be safe.

--
Dave Empey

Remember, if you're doing any major experiments in stellar
dynamics, always mount a scratch star first! --Richard Todd
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Ragged Hierarchy banker123 Microsoft Excel Discussion 5 20th Dec 2007 07:53 PM
what is a ragged right margin? =?Utf-8?B?ZHB1Z2g2MA==?= Microsoft Word New Users 4 13th Jul 2006 07:06 AM
create arrays =?Utf-8?B?am9ubWFyY3I=?= Microsoft Excel Worksheet Functions 1 24th Sep 2004 07:36 PM
display ragged =?Utf-8?B?TGVxdWl0YSBDLiBMb2dhbg==?= Windows XP New Users 1 24th Dec 2003 03:44 AM
Ragged lines =?Utf-8?B?Q2hyaXM=?= Microsoft Powerpoint 1 12th Dec 2003 09:32 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 05:50 AM.