-
Aug 5th, 2019, 07:01 PM
#1
Thread Starter
Lively Member
[RESOLVED] Using UBound elements from existing array to create new array?
Hi all, been a while but I'm back at it but little fuzzy on this one. How do I take the UBound() elements from an existing array, and use it to populate a brand new array? For example, let's say the existing array has UBound(10000). A new string array, let's call it NewArrayLineCounter() is created. NewArrayLineCounter() would need to be created, and then I assume using a For...Next loop to populate each new array element with a line number reference. So example array contents might include NewArrayLineCounter(1) = "Line000001", NewArrayLineCounter(2) = "Line000002", etc. through 100000 in this case (note in advance I can't use a multidimensioned array or that would have been preferred). Thanks for any advice, I hope it's something simple I'm overlooking...
-
Aug 5th, 2019, 08:09 PM
#2
Re: Using UBound elements from existing array to create new array?
Why can't you use an MD array?
-
Aug 5th, 2019, 09:18 PM
#3
Re: Using UBound elements from existing array to create new array?
Originally Posted by swambast
How do I take the UBound() elements from an existing array, and use it to populate a brand new array?
I've read that sentence about five times, and can't figure out its intent. I read the example about three times, and it didn't help.
The best I can figure out is that you're trying to copy one array to another array. If that's the case, just use dynamic arrays and then you can do simple array assignment:
Code:
Option Explicit
Private Sub Form_Load()
Dim a1() As String
Dim a2() As String
ReDim a1(0 To 3)
a1(0) = "asdf"
a1(1) = "qwer"
a1(2) = "zxcv"
a1(3) = "poiu"
a2 = a1 ' Copies the entire array.
Debug.Print a2(0), a2(1), a2(2), a2(3) ' Output is: asdf qwer zxcv poiu
End Sub
Are you possibly trying to take some subset of elements out of array #1 and place them into array #2? If that's the case, the most obvious way is to use a loop. However, depending on the array type (non reference, i.e., non-string, non-object) then you could speed things up with some smart use of CopyMemory. However, you suggested an array of strings. If that's the case, and you're trying to create some subset in a new array, I'd recommend a loop. Using CopyMemory in that case, you'd have to take care of how you erased your new array, as you'd be aliasing strings which is always dangerous.
However, I still fear that I don't understand what you're trying to do.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Aug 5th, 2019, 09:25 PM
#4
Re: Using UBound elements from existing array to create new array?
It doesn't sound like he wants to copy an array to me.
It sounds like given some array of existing data, they want to create a parallel array of the same size and store some additional data related to each element of the first array. Also current constructs or code doesn't allow them to add a second dimension to the existing array to store this additional information or else he would have done that as the preferred method of adding addition "columns" of information to the existing data.
My preference would be to stick with the single array, but make it an array of a User Defined Type, and add additional "fields" to the type rather than create, perhaps, multiple parallel arrays to hold additional item related information. Since we don't know the existing code that deals with the array looks like, we can't really estimate the impact of alternate approaches to add additional data to your elements.
Last edited by passel; Aug 5th, 2019 at 09:32 PM.
-
Aug 5th, 2019, 09:48 PM
#5
Re: Using UBound elements from existing array to create new array?
Originally Posted by passel
It sounds like given some array of existing data, they want to create a parallel array of the same size and store some additional data related to each element of the first array.
Hmmm, ok, if that's the case, yes an array of some UDT structure is what comes to mind for me. Swambast, with a UDT, you could mix different data types in each array element, which is precisely what UDTs are for.
Code:
Option Explicit
'
Private Type MyUdtType
i As Long
s As String
End Type
Private Sub Form_Load()
Dim MyUdtArray() As MyUdtType
ReDim MyUdtArray(0 To 3)
MyUdtArray(0).i = 123: MyUdtArray(0).s = "asdf"
MyUdtArray(1).i = 456: MyUdtArray(1).s = "qwer"
MyUdtArray(2).i = 789: MyUdtArray(2).s = "zxcv"
MyUdtArray(3).i = 765: MyUdtArray(3).s = "ghjk"
' And so on.
End Sub
I suppose parallel arrays would also work, but then you'd have to make sure you keep the dimensions in-sync.
Good Luck,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Aug 6th, 2019, 07:02 AM
#6
Re: Using UBound elements from existing array to create new array?
Originally Posted by SamOscarBrown
Why can't you use an MD array?
Homework?
Originally Posted by swambast
Hi all, been a while but I'm back at it but little fuzzy on this one. How do I take the UBound() elements from an existing array, and use it to populate a brand new array? For example, let's say the existing array has UBound(10000). A new string array, let's call it NewArrayLineCounter() is created. NewArrayLineCounter() would need to be created, and then I assume using a For...Next loop to populate each new array element with a line number reference. So example array contents might include NewArrayLineCounter(1) = "Line000001", NewArrayLineCounter(2) = "Line000002", etc. through 100000 in this case (note in advance I can't use a multidimensioned array or that would have been preferred). Thanks for any advice, I hope it's something simple I'm overlooking...
I think this is what you're looking for...
It's not that difficult... you redim the new array with the size you want, loop for a count of the size and generate the string you need.
air code...
Code:
Dim aCount as Integer
Dim idxCounter as Integer
ReDim NewArrayLineCounter(aCount) ' Assuming it's been predefined as a string array somewhere else
aCount = UBound(someArr) 'You didn't mention what the original array was called
for idxCount = 1 to aCount
NewArrayCounter(idxCounter) = "Line" & Format$("000000", idxCounter)
Next
-tg
-
Aug 6th, 2019, 08:14 AM
#7
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
Man, I love this forum – thank you for all the replies. Yes, the intent is much like passel understood. I can’t use MD array because the source legacy component only accepts single dimension arrays as input, and no it’s not a homework project (LOL). I’m thinking my problem actually lies in the declaration of the UBound elements of the source array. For example, I thought the Ubound(AnyArray) can accept a string array or a constant value – so you can’t simply use a new variable declared as an integer. I took a swag at leveraging techgnome's base code and here's where I'm at. Right now though I'm getting
Code:
'============================================================
'Gives run time error 6 - OVERFLOW always at line: aCount = UBound(strSourceFileArray)
'Name of the new array that will be based off the original strSourceFileArray()
'and contain the same number (not contents) of array elements
'E.g., total array elements of source array and new array will have same UBound values
Dim NewArrayLineCounter() As String
'Name of the original source array - we need to get the total number of array elements from this array
'and pass it into the NewArrayLineCounter such that total array elements of source array and new array will have same UBound values
Dim strSourceFileArray() As String
Dim aCount As Integer
Dim idxCounter As Integer
aCount = UBound(strSourceFileArray) 'Assume it's been predefined as: Dim strSourceFileArray() As String
ReDim NewArrayLineCounter(aCount) 'Assume it's been predefined as: Dim NewArrayLineCounter() As String (although why would this line be needed)?
For idxCounter = 1 To aCount 'Count from 1 to the total number of array elements in the strSourceFileArray
NewArrayLineCounter(idxCounter) = "Line" & Format$("000000", idxCounter) 'Populate the NewArrayLineCounter elements
Debug.Print NewArrayLineCounter(idxCounter)
Next
What am I missing?
-
Aug 6th, 2019, 08:20 AM
#8
Re: Using UBound elements from existing array to create new array?
Try using a Long instead of Integer... Overflow means that hte value being assigned is larger than it can hold... simailar to pouring 6gal into a 5gal bucket... it overflows.
-tg
-
Aug 6th, 2019, 08:27 AM
#9
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
Thanks techgnome, dim aCount as Long gives same error/result unfortunately...
-
Aug 6th, 2019, 08:51 AM
#10
Re: Using UBound elements from existing array to create new array?
Code:
For idxCounter = 1 To aCount 'Count from 1 to the total number of array elements in the strSourceFileArray
NewArrayLineCounter(idxCounter) = "Line" & Format$("000000", idxCounter) 'Populate the NewArrayLineCounter elements
Debug.Print NewArrayLineCounter(idxCounter)
Next
Here's what's confusing to me. By building that array, it looks like all you're doing is chewing lots of memory. I don't understand why you couldn't just build the appropriate string for the line number anytime you needed it ... thereby saving tons of memory. You're always going to have idxCounter, or how else could you address your new array. Therefore, forget this array and just build these strings "on the fly". Unless, as suggested above, this is some kind of homework assignment.
EDIT1: Here's a function for you, and it doesn't take an array:
Code:
Public Function MyLineNumber(idxCounter As Long) As String
MyLineNumber = "Line" & Format$("000000", idxCounter)
End Function
Last edited by Elroy; Aug 6th, 2019 at 08:57 AM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Aug 6th, 2019, 09:05 AM
#11
Re: Using UBound elements from existing array to create new array?
Your code doesn't make any sense, so you get an error. You can't use Ubound on an array that doesn't have any elements in it.
Code:
Dim strSourceFileArray() As String
Dim aCount As Integer
Dim idxCounter As Integer
aCount = UBound(strSourceFileArray) '
You declared an empty array, and then asked for the UBound of it.
technome left notes in his code that you have to fill in, assuming you would use your real array that has elements in it.
-
Aug 6th, 2019, 09:09 AM
#12
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
Hi Elroy, thanks for your suggestion. Yes, I could alternatively use a string (and split back into an array) which was the Plan B but the problem identified still remains. That is, how do you pass the UBound count of the original source array into the function (if it won't accept a Long variable) or an otherwise appropriate variable type such as an integer. I'm guess at this point what I'm really trying to figure out is what is UBOUND(X) - thought it was LONG, and how can it be successfully converted into something like an integer value. I must be missing something right under my nose!!!
-
Aug 6th, 2019, 09:12 AM
#13
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
@techgnome - yes, it makes sense as the original sourcearray will always have array elements. Those are populated earlier but I can clearly see why you would be confused as my example doesn't show that, sorry about that!
-
Aug 6th, 2019, 09:18 AM
#14
Re: Using UBound elements from existing array to create new array?
So, you have a failure in some code that you don't want to show, but we are suppose to see the problem?
Why not post a working example of the problem if you don't want to post the code itself, so we have code to look at that demonstrates the problem, otherwise we'll just have to assume it is your fault and nothing can be done about it.
-
Aug 6th, 2019, 09:34 AM
#15
Re: Using UBound elements from existing array to create new array?
Originally Posted by swambast
Hi Elroy, thanks for your suggestion. Yes, I could alternatively use a string (and split back into an array) which was the Plan B but the problem identified still remains. That is, how do you pass the UBound count of the original source array into the function (if it won't accept a Long variable) or an otherwise appropriate variable type such as an integer. I'm guess at this point what I'm really trying to figure out is what is UBOUND(X) - thought it was LONG, and how can it be successfully converted into something like an integer value. I must be missing something right under my nose!!!
Normally, if you double click on UBound to select and hit the F1 key you should get help on it. It shows that it does return a Long.
I don't understand where you need to pass that to a function. You didn't indicate that was a need. You only wanted to create a parallel array for some reason.
I went ahead and wrote a quick test case, requires a button on a form, and is a mix of your and techgnome's inputs.
It works fine for redimensioning a parallel array for an initial array of 100 thousand (and 1) items in an array.
It only populates 100000 elements in the parallel array (it skips item 0).
Code:
Option Explicit
Private strSourceFileArray() As String
Private NewArrayLineCounter() As String
Private Sub Form_Load()
ReDim strSourceFileArray(100000)
Dim i As Long
For i = 0 To 100000
strSourceFileArray(i) = "This is a line of code: " & CStr(i)
Next
End Sub
Private Sub Command1_Click()
Dim aCount As Long
Dim idxCounter As Long
aCount = UBound(strSourceFileArray) 'You didn't mention what the original array was called
ReDim NewArrayLineCounter(aCount) ' Assuming it's been predefined as a string array somewhere else
For idxCounter = 1 To aCount
NewArrayLineCounter(idxCounter) = "Line" & Format$("000000", idxCounter)
Next
Debug.Print UBound(NewArrayLineCounter); " "; NewArrayLineCounter(aCount)
End Sub
The output (from the debug.print) in the Immediate window shows:
indicating that the parallel array does have a ubound of 100 thousand, and that it has been populated with the string as techgnome's code was designed to do.
Last edited by passel; Aug 6th, 2019 at 09:40 AM.
-
Aug 6th, 2019, 10:58 AM
#16
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
Passel, I was trying to upload an image from my computer here but can't get it to work. Anyway, please know I appreciate you and everyone else's efforts and help. I'll be darned though as I surprised myself - think I've figured out the root cause and just about have a working code set now...will post back soon but suffice to say it absolutely has to do with inherent limitations unless I'm overlooking something.
-
Aug 6th, 2019, 12:12 PM
#17
Re: Using UBound elements from existing array to create new array?
Originally Posted by swambast
Hi Elroy, thanks for your suggestion. Yes, I could alternatively use a string (and split back into an array) which was the Plan B but the problem identified still remains. That is, how do you pass the UBound count of the original source array into the function (if it won't accept a Long variable) or an otherwise appropriate variable type such as an integer. I'm guess at this point what I'm really trying to figure out is what is UBOUND(X) - thought it was LONG, and how can it be successfully converted into something like an integer value. I must be missing something right under my nose!!!
Yes, UBound is absolutely a Long. Here's the SafeArray structure for a 1D array:
Code:
Public Type SAFEARRAY1D
cDims As Integer ' Number of dimensions.
fFeatures As Integer ' See SaFlagsEnum.
cbElements As Long ' The size of an array element.
cLocks As Long
pvData As Long ' Pointer to data.
cElements As Long ' Count of elements.
lLbound As Long ' Lower bound. Count is used to determine upper bound.
End Type
UBound isn't in there, but it's basically: cElements + lLbound - 1&. And we see that both cElements and lLbound are Long. Also, yes, MSDN says it's a Long.
However, and this is a BIG however, an undimensioned array has no UBound, and you'll get an error if you try and get it. The base structure of a SafeArray is:
Code:
Public Type SAFEARRAY
cDims As Integer ' Number of dimensions.
fFeatures As Integer ' See SaFlagsEnum.
cbElements As Long ' The size of an array element.
cLocks As Long
pvData As Long ' Pointer to data.
End Type
First, notice no cElements nor lLbound items, and subsequently no UBound value. An undimensioned array will have ZERO for that cDims value, and no LBound nor UBound. You can't pass it ... you can't even get it, as it doesn't exist.
Maybe that will help.
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Aug 6th, 2019, 12:49 PM
#18
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
THANK YOU all for the continued support - see revised code below. My initial options, although I'm sure there are others, might be breaking the source array into chunks or finding another approach that can handle a greater max range...any other suggestions welcomed and encouraged. Like I said, it's been a while and I had no clue that the range limitations would be the culprit. I tested by using array elements below that threshold and it worked perfectly.
Code:
Dim strlinecount_workaround As String
Dim lcounter As Integer
Dim arraymax As Long
'assume strsourcefilearraycount has elements in it, for example in this case 92978 elements,
'and has been declared as Dim strSourceFileArray() As String
'Here is the kicker! The arraymax integer is only 16-bit, and therefore has max range of up to 32,767!
'Therefore, if your source array exceeds this, you will error out with Run-Time error 6 Overflow
arraymax = UBound(strSourceFileArray)
For lcounter = 1 To arraymax
strlinecount_workaround = strlinecount_workaround & Format$(lcounter + 1, "00000") & vbCrLf
Next
Debug.Print strlinecount_workaround
-
Aug 6th, 2019, 12:51 PM
#19
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
Sorry, somehow posted twice - feel free to delete this "blank" post if possible...but again let me state what a great community this is!
Last edited by swambast; Aug 6th, 2019 at 12:54 PM.
Reason: double posted
-
Aug 6th, 2019, 02:10 PM
#20
Re: Using UBound elements from existing array to create new array?
Dim arraymax As Long
...
...
'Here is the kicker! The arraymax integer is only 16-bit, and therefore has max range of up to 32,767!
Yeah, I think I'm going to throw the BS flag on this one here... I'm reasonably sure that isn't true. arraymax is a long... which should be a 32-bit integer... NOT a 16-bit integer. If arraymax is topping out at 16 bits, even when declared as a long, then you may have other issues. Unless you're not really running VB6 here... in which case, all bets are off.
-tg
-
Aug 6th, 2019, 02:53 PM
#21
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
@techgnome - Throw whatever flag you want; it's easy enough to test. I believe I've found the root cause, and perhaps there might be a better explanation for it. If you need help testing it, simply set arraymax to 32767 or greater and tell me if you can get it to work...my bet is you can't
-
Aug 6th, 2019, 03:21 PM
#22
Re: Using UBound elements from existing array to create new array?
well, seeing as how I'm on a Mac and don't have access to VB6... I can't... but I do have access to the internet and many years of experience... 32676 is a memorable number... it's the max size of a 16-bit integer... longs are 32-bit... I may be old(er) and my memory isn't what it used to be, but I do know that the range of a Long far exceeds 32676... that's why a couple of lifetimes ago, when I did do VB6 programming, we used Longs for our IDs... because we knew we would easily exceed that 32676 boundary.... when you deal with tens of thousands of financial transactions a day, those IDs add up. And exceeding the limits of an integer would only last us a couple hours at best, so we used Longs.
Personally I think there;s somehting else wrong here... whether you see it or not, or even believe it or not...
-tg
-
Aug 6th, 2019, 03:29 PM
#23
Re: Using UBound elements from existing array to create new array?
Code:
Dim strlinecount_workaround As String
Dim lcounter As Integer
Dim arraymax As Long
'assume strsourcefilearraycount has elements in it, for example in this case 92978 elements,
'and has been declared as Dim strSourceFileArray() As String
'Here is the kicker! The arraymax integer is only 16-bit, and therefore has max range of up to 32,767!
'Therefore, if your source array exceeds this, you will error out with Run-Time error 6 Overflow
arraymax = UBound(strSourceFileArray)
For lcounter = 1 To arraymax
strlinecount_workaround = strlinecount_workaround & Format$(lcounter + 1, "00000") & vbCrLf
Next
Your problem isn't arraymax, it is lcounter.
-
Aug 6th, 2019, 03:42 PM
#24
Thread Starter
Lively Member
Re: Using UBound elements from existing array to create new array?
Your problem isn't arraymax, it is lcounter.
@OptionBase1 - you rock! I didn't think of it as possibly being a limitation "the other way around", way to go and thanks for your insight! With that change we now have a fully functioning resolution. I'm grateful for all that spent their time on this, I'm going to go ahead and consider this one resolved momentarily!
-
Aug 6th, 2019, 04:08 PM
#25
Re: [RESOLVED] Using UBound elements from existing array to create new array?
It's called tunnel vision,... and apparently we all suffer from it... focussed on the wrong counter... whoops... sometimes it's good to have another pair of eyes on things. Glad it's resolved and working now.
-tg
-
Aug 6th, 2019, 07:20 PM
#26
Re: [RESOLVED] Using UBound elements from existing array to create new array?
Yeah, you shouldn't have jumped to the conclusion that the value was limited to 16-bits because the example code in post #15 demonstrated running the code with an array of 100 thousand strings. When your code didn't work you should have wondered why the example in post 15 did.
-
Aug 6th, 2019, 07:23 PM
#27
Thread Starter
Lively Member
Re: [RESOLVED] Using UBound elements from existing array to create new array?
Yeah, but post 15 hard coded the array values and that's not what was requested since that value would always be dynamic but noteworthy for sure.
-
Aug 6th, 2019, 07:50 PM
#28
Re: [RESOLVED] Using UBound elements from existing array to create new array?
Well, yes it was an example but the hardcoding of the number of items that was in the source array shouldn't have detracted from the fact that the second array was created based on the number of elements in the source array. You could have changed that number if you wanted to test a few "dynamic" cases. I originally set the array to 10 thousand items and ran it and it worked fine. I then changed it to 100 thousand to verify it worked for an array of more items than could be indexed by an Integer.
I suppose it could have been more dynamic any number of ways, i.e. in the form load doing a ReDim (100000 + Int(100000 * Rnd)) so the dimension would not be predetermined, but that wouldn't be a more valid test of the code being able to create a parallel array based on the size of the source array.
The redimensioning of the parallel array wasn't hardcoded, it depended on the size of the source array.
-
Aug 6th, 2019, 10:23 PM
#29
Re: [RESOLVED] Using UBound elements from existing array to create new array?
I'm not sure I understand what y'all are talking about, but the lower bound and upper bound of arrays are longer than 2 bytes.
I don't want to push memory, and it wouldn't surprise me if the sign-bit of a Long was prohibited, but here's an example that illustrates that they're more than an Integer.
Code:
Option Explicit
Private Sub Form_Load()
Dim a() As Long
Dim b(1 To 40000) As Long
ReDim a(1 To 40000)
a(1) = 1
b(1) = 1
a(40000) = 40000
b(40000) = 40000
Debug.Print a(1), a(40000), b(1), b(40000)
End Sub
That Debug.Print statement outputs exactly what you'd expect it to: 1 40000 1 40000
Now, when arrays get big enough, we do have to remember our 2GB memory limit. But that's an entirely different issue from the lower and upper bounds of an array.
EDIT1: For grins, I also tried it all at 70000, and it still worked fine. So, that further proves that these bounds are not some kind of unsigned Integer. They're truly a 4-byte Long.
Last edited by Elroy; Aug 6th, 2019 at 10:26 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Aug 6th, 2019, 10:43 PM
#30
Thread Starter
Lively Member
Re: [RESOLVED] Using UBound elements from existing array to create new array?
Elroy, thanks for the additional commentary as it's interesting. We figured it out though with OptionBase1's insight, it was the counter declared as an integer that actually caused the limitation of the array to 32676 elements! This was deceiving because it limited the array elements no matter if the array was appropriately declared as long.
-
Aug 7th, 2019, 09:08 AM
#31
Re: [RESOLVED] Using UBound elements from existing array to create new array?
It didn't limit the array elements, it limited your index into the array of elements. I didn't see any deception there.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|