VBA - Array Help

TheNoocH

Well-known Member
Joined
Oct 6, 2004
Messages
3,482
I'm in the process of trying to teach myself arrays...
for the most part i've been using cells in a worksheet to handle what i want to do...but i want to try and avoid using the worksheet...i'm assuming arrays would be the best replacement...

here's essentially what i want to try and accomplish...

1) enter data into an input box on a form and store it based upon one of 4 buttons i press....essentially i had 4 columns on the sheet and found the last row and stored the data in 1 row offset....assume for each command button that right(commandbutton,1) = 1, 2, 3, 4 to identify which column to store the data...

2) how do i declare the multidimensioned array especially since it will be dynamic in row size...the column size will always be the same...

3) any other basic info that may help me...

thanks for any help in getting me up to speed in arrays...
 
hatman...thanks for your continued help...glad this stuff is easy for you...ha...

let me see if my understanding of what you are trying to do is correct...

Code:
    ReDim arr(1 To 2, 0 To 1)
    arr(1, 0) = 1
    arr(2, 0) = 1

declarring arr with the first dimension (see i didn't use row) from 1 to 2 (so essentially 2 sets of data)
and the second dimension from 0 to 1.....this is essentially because the next two lines are setting the first data point in each of the 1st dimension to 1....which in the next part will compare to the ubound of the 2nd dimension?
i assume this code would need to go where ever i need the array initialized?

Code:
    If arr(1, 0) > UBound(arr, 2) Then
        ReDim Preserve arr(1 To 2, 0 To arr(1, 0))
    End If
    arr(1, arr(1, 0)) = arr(1, arr(1, 0) - 1) + adder

little confused here...but let me try to explain what i think and correct me if i'm wrong...

wait i "think" the light bulb went off...then it started to go out again...let me try to see what's what...

Code:
arr(1, 0) = arr(1, 0) + 1
above in the module we set arr(1,0)=1 so we're adding 1 + 1=2
assume using this as a counter?

Code:
If arr(1, 0) > UBound(arr, 2) Then

at this point arr(1,0)=2 and ubound(arr,2) =2 (i assume 0 to 1 would make the ubound 2)

that would be false so it skips the redim preserve at this point...

Code:
    arr(1, arr(1, 0)) = arr(1, arr(1, 0) - 1) + adder

this is the line that i think is losing me (assuming i'm not lost already)

arr(1,0)=2 so arr(1,2)=arr(1,2-1)+adder

so we are storing into arr(1,2) the value of arr(1,1)+adder
i don't understand where we got arr(1,1)...
and didn't we store arr(1,0)=2 ... if so why didn't we overwrite that?...little confused...


ps...i read your next post and that is what i had in mind to combine...thanks...
 
Upvote 0

Excel Facts

Last used cell?
Press Ctrl+End to move to what Excel thinks is the last used cell.
hatman...thanks for your continued help...glad this stuff is easy for you...ha...
nothing more than repitition in programming languages before I found VBA burind in Excel for the first time

let me see if my understanding of what you are trying to do is correct...

Code:
    ReDim arr(1 To 2, 0 To 1)
    arr(1, 0) = 1
    arr(2, 0) = 1

declarring arr with the first dimension (see i didn't use row) from 1 to 2 (so essentially 2 sets of data)
and the second dimension from 0 to 1.....this is essentially because the next two lines are setting the first data point in each of the 1st dimension to 1....which in the next part will compare to the ubound of the 2nd dimension?
i assume this code would need to go where ever i need the array initialized?

yes to everyting to this point

wait i "think" the light bulb went off...then it started to go out again...let me try to see what's what...

Code:
arr(1, 0) = arr(1, 0) + 1
above in the module we set arr(1,0)=1 so we're adding 1 + 1=2
assume using this as a counter?

yes, I am using the arr(n,0) positions to keep track of the last user defined data point in each data set. It eliminates the need for the Forr..Next loops, which would impact performance in VERY large arrays... but that's a side effect of my attempt to eliminate the need to designate a flag in the data set.

Code:
If arr(1, 0) > UBound(arr, 2) Then

at this point arr(1,0)=2 and ubound(arr,2) =2 (i assume 0 to 1 would make the ubound 2)
[/code]

No, on the first pass Ubound() is equal to 1. Ubound is very different than the .Count property (Method? can't remember) of VBA collection objects. The Ubound() function always returns the numerical value of the ordinate in the specified dimension. In other words, Ubound(arr,1) where Arr(10 to 50) is 50.

that would be false so it skips the redim preserve at this point...

nope, it executes the Redim Preserve for reason stated above

Code:
    arr(1, arr(1, 0)) = arr(1, arr(1, 0) - 1) + adder

this is the line that i think is losing me (assuming i'm not lost already)

arr(1,0)=2 so arr(1,2)=arr(1,2-1)+adder

so we are storing into arr(1,2) the value of arr(1,1)+adder
i don't understand where we got arr(1,1)...also what happened to arr(1,0)?

In re-reading some of our dialogue, I see that I assumed that you are wanting to performan arithmetic addition, when you may be using the term Add to mean Populate. I will continue on my assumption until you set me straight.

Arr(1,1) is zero. When a numerical array is initialized, all values are 0 until you set them to be something else. When I put this code together, I had to maintain the zeros in th efirst position of the array (arr(n,1)) due to my assumption that you wanted to perform an arithmetic addition. I did this by assigning arr(n,0) = 1. And this may very well be my bad. if you want to populate he user input into the array, rather than adding it to the previous value, then you would leave arr(n,0) as their initial value of 0, and do
Code:
arr(1, arr(1, 0)) = adder
rather than
Code:
arr(1, arr(1, 0)) = arr(1, arr(1, 0) - 1) + adder

So what happened to arr(1,0) you ask? Nothing. It's a counter that indicates the last ordinate of the second dimension where user data is stored in arr(1,n). We leave it alone for now, and use it as a pointer the next time the routine is called to immediately move to the proper location in the array, without the need to parse for a flag.

ps...i read your next post and that is what i had in mind to combine...thanks...

I didn't want to throw it at you too soon, because it's yet another level of indirection.

I made this code lean an mean... feel free to pop in some Watches or A=ubound(arr,2) to see how things behave in break mode.
 
Upvote 0
No, on the first pass Ubound() is equal to 1. Ubound is very different than the .Count property (Method? can't remember) of VBA collection objects. The Ubound() function always returns the numerical value of the ordinate in the specified dimension. In other words, Ubound(arr,1) where Arr(10 to 50) is 50.

ok...got it...thanks for the clarification

but that's a side effect of my attempt to eliminate the need to designate a flag in the data set.
good...i was hoping we didn't have to go there...and that was my initial fear...

In re-reading some of our dialogue, I see that I assumed that you are wanting to performan arithmetic addition, when you may be using the term Add to mean Populate. I will continue on my assumption until you set me straight.
sorry for the confusion...at this point i just want to poplulate...
eg #1 - if nothing in the array i want the first data element to be the value of the inputbox....eg #2 -if there are 3 data elements then i want the value of the inputbox to be the new 4th element...hope that clears it up...note: somewhere along the way i'm going to want to sum all the values...but i assume i can handle that with the for loop you showed me yesterday...

think the last couple things confused me again...can you whip up your combined code again ...but for poplulating vs. arithmetic? if so then i'll take a look at that and we'll go another round...

thanks again for your help...i'm learning alot from you...even if it does take a couple passes...ha....
 
Upvote 0
Okay... how's this:

Code:
Sub arr_help()

    ReDim arr(1 To 2, 0 To 1)
    
    UserForm1.CommandButton1.Caption = "Press to add 1"
    UserForm1.CommandButton2.Caption = "Press to add 2"
    UserForm1.CommandButton3.Caption = "Press to see data"
    
    UserForm1.Show
    

End Sub

and
Code:
Private Sub CommandButton1_Click()

    Call add_to_arr(1)

End Sub

Private Sub CommandButton2_Click()

    Call add_to_arr(2)
    
End Sub

Private Sub CommandButton3_Click()

    For cnt1 = 1 To UBound(arr, 2)
    
        For cnt2 = LBound(arr, 1) To UBound(arr, 1)
        
            output = output & arr(cnt2, cnt1) & " "
            
        Next cnt2
        
        output = output & vbCrLf
        
    Next cnt1
    
    MsgBox output
    
End Sub

Private Sub add_to_arr(dmsn As Long)

    adder = InputBox("Enter value")
    
    If Not IsNumeric(adder) Then
    
        Exit Sub
        
    End If
    
    arr(dmsn, 0) = arr(dmsn, 0) + 1
    
    If arr(dmsn, 0) > UBound(arr, 2) Then
        
        ReDim Preserve arr(1 To 2, 0 To arr(dmsn, 0))
        
    End If
    
    arr(dmsn, arr(dmsn, 0)) = adder
    


End Sub
 
Upvote 0
One mor ething that may be worth mentioning... not sure if you executed the code far enough to notice that in my Output routine, I changed Lbound(arr,2) to instead be 1... this causes the output to effectively IGNORE the counters in the data.

This is a trick I picked up long ago... a habit really. I always start my data at ordinate 1, using ordinate 0 for summary info, if needed. By always following this practice, I can add summary data to an array at a later date with little or no change to the code (although I used lbound() in this code originally, it's really something I rarely do... not sure what possessed me to do so here).
 
Upvote 0
ok...let me try to explain what i think is going on again...
ps...just read your next post...and i think that helps me now understand...but i'll let you be the judge...ha...
Code:
    arr(dmsn, 0) = arr(dmsn, 0) + 1
dmsn is being passed depending on which button is clicked...let's assume dsmn=1
arr(1,0)=arr(1,0)+1
arr(1,0) starts out = 0 when array is initialized...
now you use arr(1,0) as a counter stored into the array that we will have to ignore when doing the sum of the data....got this from your last post...
so if arr(1,0) started as 0 ...then arr(1,0)+1 now puts 1 into arr(1,0)


Code:
    If arr(dmsn, 0) > UBound(arr, 2) Then
        ReDim Preserve arr(1 To 2, 0 To arr(dmsn, 0))
    End If
arr(1,0)=1
and ubound(arr,2) =1 (from ReDim arr(1 To 2, 0 To 1) )
should it be = instead of > (noticed that you got rid of the arr(1,0)=1 in the module from before

Code:
    arr(dmsn, arr(dmsn, 0)) = adder
arr(dmsn,0)=arr(1,0)=1
arr(1,1)=adder (which is data from inputbox)

so i think i'm following except the = vs > above....
thanks again...


ps..i think i may have confused things...i think i used input box when i meant text box...but i can change that easy enough....
 
Upvote 0
EXACTLY!

The operator should be > as stated. With the latest change to populate without arithmetic operations, a side effect is that on the first pass for each dataset, arr(n,1) will get replaced (it's zero anyway).

I see now that I simply dismissed this nuance because it does not change the outcome, though it makes the very first pass different than all of the others.

When I changed the method from an Arithmetic Add to a Simple Populate, I should have initialized the array with ONLY the counters:

Code:
ReDim arr(1 To 2, 0)

Make this change and step through... it should make more sense, because it will now behave more like all of the other passes.

Sorry for the confusion...
 
Upvote 0
ps..i think i may have confused things...i think i used input box when i meant text box...but i can change that easy enough....

I wondered about that... started out with a text box myself because it made more sense :cool: ... but oh no: he wants an inputbox, so I'll do it that way :LOL:
 
Upvote 0
EXACTLY!

The operator should be > as stated. With the latest change to populate without arithmetic operations, a side effect is that on the first pass for each dataset, arr(n,1) will get replaced (it's zero anyway).

I see now that I simply dismissed this nuance because it does not change the outcome, though it makes the very first pass different than all of the others.

When I changed the method from an Arithmetic Add to a Simple Populate, I should have initialized the array with ONLY the counters:

Code:
ReDim arr(1 To 2, 0)

Make this change and step through... it should make more sense, because it will now behave more like all of the other passes.

Sorry for the confusion...

ok...i'll make the change....that makes more sense to me...
glad i'm starting to get the rest of the stuff...i really appreciate your help and patience...

ok...some more questions...
1) i also have a button "UNDO" ...this in essence just removes the last data entered....would that be as easy as...

arr(dmsn,arr(dmsn,0))=0
and
arr(dmsn,0)=arr(dmsn,0)-1

or do i need to do a redim preserve also

2) does ReDim arr(1 To 2, 0) clear all the data in the array...i'm assuming yes and it should be where i initialize all my stuff on my form?

3) i also have a label where i list all the data in reverse order...
so if i entered 1, 2, 3, 4 it would show as 4, 3, 2, 1 in the label...
would this code do that...

Code:
for i = arr(dmsn,0) to 1 step -1
  output=output & arr(dmsn, i) 
next i
output = output & vbCrLf



ps...sorry about the inputbox/textbox confusion...but thanks for being so accomodating...
 
Upvote 0
ok...i'll make the change....that makes more sense to me...

Yeah, me too, once I looke dat it from your POV...

glad i'm starting to get the rest of the stuff...i really appreciate your help and patience...
You got lucky: stuff is slow enough right now that I can afford to have a little fun... that could change at any time, though

ok...some more questions...
1) i also have a button "UNDO" ...this in essence just removes the last data entered....would that be as easy as...

arr(dmsn,arr(dmsn,0))=0
and
arr(dmsn,0)=arr(dmsn,0)-1

More or less... you probably need to declare a module level variable and assign dmsn to it each time you add another value to the array, so you can undo the correct thing. Also, some code to restrict to a single undo.

Alternatively, you store another global array with each value of dmsn, then treat it as a LIFO stack, and simply parse backwards.

or do i need to do a redim preserve also

Entirely up to you. Depends, partially, on what you are doing with your data. I wouldn;t bother, if it were me. A couple of zeroes at the end of the array should not be a problem. If it is, you need logic to be sure you do not truncate data in the OTHER set when you depopulate the first set.

2) does ReDim arr(1 To 2, 0) clear all the data in the array...i'm assuming yes and it should be where i initialize all my stuff on my form?
Yup. In fact, using the Redim command at all without Preserve will clear all data... but even more so when the boundaries are made smaller.

3) i also have a label where i list all the data in reverse order...
so if i entered 1, 2, 3, 4 it would show as 4, 3, 2, 1 in the label...
would this code do that...

Code:
for i = arr(dmsn,0) to 1 step -1
  output=output & arr(dmsn, i) 
next i
output = output & vbCrLf

Looks like it... try it out!


ps...sorry about the inputbox/textbox confusion...but thanks for being so accomodating...[/quote]
 
Upvote 0

Forum statistics

Threads
1,215,824
Messages
6,127,077
Members
449,358
Latest member
Snowinx

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top