TheSwamp
Code Red => VB(A) => Topic started by: Guest on February 11, 2008, 10:24:28 PM
-
I've been struggling to wrap my head around this 2D array stuff. I want to be able to store 1) the drawing name and 2) a layout tab name in an array. I guess it'd be a 2D array. The big problem I'm running into is the REDIM portion. The size of the array will vary and I'm not sure how to go about resizing it properly. I keep getting an error so _obviously_ I'm doing something wrong.
Here's what I've got so far...
Public Sub SheetCount()
Dim oSheet As AcSmSheet
Dim nSheetCount As Integer
Dim oEnumDB As IAcSmEnumDatabase
Dim oItem As IAcSmPersist
Dim oSheetSetMgr As AcSmSheetSetMgr
Set oSheetSetMgr = New AcSmSheetSetMgr
Set oEnumDB = oSheetSetMgr.GetDatabaseEnumerator
Set oItem = oEnumDB.Next
Dim oSheetDb As AcSmDatabase
Dim strFileInfo() As String
ReDim strFileInfo(nSheetCount, 2)
Do While Not oItem Is Nothing
Set oSheetDb = oItem
Dim oEnum As IAcSmEnumPersist
Dim oItemSh As IAcSmPersist
Set oEnum = oSheetDb.GetEnumerator
Set oItemSh = oEnum.Next
Do While Not oItemSh Is Nothing
If oItemSh.GetTypeName = "AcSmSheet" Then
Set oSheet = oItemSh
nSheetCount = nSheetCount + 1
strFileInfo(nSheetCount, 1) = oSheet.GetLayout.ResolveFileName
strFileInfo(nSheetCount, 2) = oSheet.GetNumber
ReDim Preserve strFileInfo(1, UBound(strFileInfo) + 1)
End If
Set oItemSh = oEnum.Next
Loop
MsgBox nSheetCount
Set oItem = oEnumDB.Next
Loop
End Sub
...or would a collection or dictionary be better to use?
-
If I pretend to understand what you're trying to do (or what you're code is doing), i.e. redim and preserve both dimensions of a 2D array (looks like you're trying to decrease the 1st dimension and increase the 2nd dimension) I'm afraid you can't. When using preserve you can only resize the last dimension; in your case the 2nd dimension.
...
If you use the Preserve keyword, you can resize only the last array dimension and you can't change the number of dimensions at all. For example, if your array has only one dimension, you can resize that dimension because it is the last and only dimension. However, if your array has two or more dimensions, you can change the size of only the last dimension and still preserve the contents of the array.
The following example shows how you can increase the size of the last dimension of a dynamic array without erasing any existing data contained in the array.
' Initial ReDim
ReDim X(10, 10, 10)
' Latter ReDim
ReDim Preserve X(10, 10, 15)
...
If you cannot solve your challenge within these lines you may have to roll your own (collection) class.
My ½¢ ... Michael
-
I was wondered how many programmers use
the following (dirty method for this task)
Anyway, it works
Sub test()
' define the first dimension of array approximately
Dim ar(9999, 1)
Dim i As Long, j As Long
' here you'll populate an array at runtime,
' as many as you need (of course you don't know how much)
' just for example
For i = 0 To 333
ar(i, 0) = i + 1: ar(i, 1) = i + 3
Next
' declare the new hard bounded array instead
ReDim newar(i - 1, 1)
While Not IsEmpty(ar(j, 0))
newar(j, 0) = ar(j, 0): newar(j, 1) = ar(j, 1)
j = j + 1
Wend
' return new array
End Sub
Btw, I like to use collection too
~'J'~
-
If I pretend to understand what you're trying to do (or what you're code is doing), i.e. redim and preserve both dimensions of a 2D array (looks like you're trying to decrease the 1st dimension and increase the 2nd dimension) I'm afraid you can't. When using preserve you can only resize the last dimension; in your case the 2nd dimension.
...
If you use the Preserve keyword, you can resize only the last array dimension and you can't change the number of dimensions at all. For example, if your array has only one dimension, you can resize that dimension because it is the last and only dimension. However, if your array has two or more dimensions, you can change the size of only the last dimension and still preserve the contents of the array.
The following example shows how you can increase the size of the last dimension of a dynamic array without erasing any existing data contained in the array.
' Initial ReDim
ReDim X(10, 10, 10)
' Latter ReDim
ReDim Preserve X(10, 10, 15)
...
If you cannot solve your challenge within these lines you may have to roll your own (collection) class.
My ½¢ ... Michael
It would be increasing - I think.
Thanks for the info. I found that later last night after I had posted this. I'll see what I can do.
-
I was wondered how many programmers use
the following (dirty method for this task)
Anyway, it works
Sub test()
' define the first dimension of array approximately
Dim ar(9999, 1)
Dim i As Long, j As Long
' here you'll populate an array at runtime,
' as many as you need (of course you don't know how much)
' just for example
For i = 0 To 333
ar(i, 0) = i + 1: ar(i, 1) = i + 3
Next
' declare the new hard bounded array instead
ReDim newar(i - 1, 1)
While Not IsEmpty(ar(j, 0))
newar(j, 0) = ar(j, 0): newar(j, 1) = ar(j, 1)
j = j + 1
Wend
' return new array
End Sub
Btw, I like to use collection too
~'J'~
I would prefer to use a collection but I'm not sure how I would store the name of the drawing and the layout tab name(s) and be able to "link" the two together. I'm drawing a blank on this one. Can you post a snippet?
Thanks.
-
Sounds like a jagged array ... is this the kind of info you need to host?
| Drawing1 | | Layout1 | | Layout2 | |
| Drawing2 | | Layout1 | | Layout2 | | Layout3 | |
| Drawing3 | | Layout1 | | Layout2 | |
| Drawing4 | | Layout1 | |
| Drawing5 | | Layout1 | | Layout2 | | Layout3 | | Layout4 | | Layout5 | |
If so there are a number of ways you can do this without rolling your own class, though rolling your own class will hide the messy details from client applications, exposing only what is needed to make it appear elegant. I did say appear didn't I?
One way is to use a collection as the primary container and dynamic arrays as the items. To be clear: Each item within the collection is a dynamic 2D array, with the first dimension always 1 (hosting the drawing name), 2nd dimension growing as needed to host the multiple (and varying) layout names. I like this way at face value because your data is still typed.
A variation of the above is to have each item in the collection as a dynamic single dimensioned string array. The first array element is the drawing name, subsequent elements the layout names. Simpler than the preceding and your data is still typed.
Another way is to use a collection of collections. Each child collection grows as required, the first item in each child collection is the Drawing name, subsequent items the layouts. Geometrically speaking think of the primary collection as vertical, each child collection as horizontal. Do-able but I'm not fussy about it.
Another is a dynamic array of collections; many ways to skin the cat. Not all of them good | efficient.
Of course all of this is messy, and why .net gives you jagged arrays (and yet a no brainer in lisp).
If none of this makes sense worry not, it's me, not you. Another crappy night of nominal sleep, up way too early, and without the benefit of coffee.
Ackkk.
-
You could also create a UDT that hosts a dynamic array, and then make a dynamic array of said UDT.
-
Sounds like a jagged array ... is this the kind of info you need to host?
Um.... jagged??!? :? Never heard of that one, but it sounds like what I want. Can you 'splain more... this time in english?? :wink:
-
Um.... jagged??!? :? Never heard of that one, but it sounds like what I want. Can you 'splain more... this time in english?? :wink:
A Jagged Array is simply an array of an arrays in which the length of each array can vary.
e.g. An array with 5 child arrays, each having lengths of 3, 4, 3, 2 and 6 respectively --
| item1 | | item2 | | item3 | |
| item1 | | item2 | | item3 | | item4 | |
| item1 | | item2 | | item3 | |
| item1 | | item2 | |
| item1 | | item2 | | item3 | | item4 | | item5 | | item6 | |
Supported in .NET (I've tried them in C#) but not in VBA without slight of hand as noted previously. The array of UDTs approach being the most efficient memory wise as well as being fully typed.
-
Um.... jagged??!? :? Never heard of that one, but it sounds like what I want. Can you 'splain more... this time in english?? :wink:
A Jagged Array is simply an array of an arrays in which the length of each array can vary.
e.g. An array with 5 child arrays, each having lengths of 3, 4, 3, 2 and 6 respectively --
| item1 | | item2 | | item3 | |
| item1 | | item2 | | item3 | | item4 | |
| item1 | | item2 | | item3 | |
| item1 | | item2 | |
| item1 | | item2 | | item3 | | item4 | | item5 | | item6 | |
Supported in .NET (I've tried them in C#) but not in VBA without slight of hand as noted previously. The array of UDTs approach being the most efficient memory wise as well as being fully typed.
Do you have any good links or snippets for jagged arrays and UDTs - two things which I have NO experience with! Thanks.
-
Oversimplified example, but I've hurtin' for time. Put this in a module --
Type TStrArray
Items() As String
End Type
Sub Test()
Dim jagged() As TStrArray
[color=green] '' add the first "record"[/color]
ReDim jagged(0)
[color=green] '' add a "field"[/color]
ReDim jagged(0).Items(0)
[color=green] '' populate it[/color]
jagged(0).Items(0) = "Drawing1"
[color=green] '' oh my, we just discovered we have a layout, we need another "field"[/color]
ReDim Preserve jagged(0).Items(1)
[color=green] '' ok, populate it[/color]
jagged(0).Items(1) = "Layout2"
[color=green] '' oh my, and yet another layout[/color]
ReDim Preserve jagged(0).Items(2)
[color=green] '' populate it[/color]
jagged(0).Items(2) = "Layout3"
[color=green] '' ok, let's add another "record"[/color]
ReDim Preserve jagged(1)
[color=green] '' add 4 "fields" to this record (remember that basic is
'' goofy, dim (3) = elements 0,1,2,3 so 4 elements total[/color]
ReDim Preserve jagged(1).Items(3)
jagged(1).Items(0) = "Drawing2"
jagged(1).Items(1) = "Layout1"
jagged(1).Items(2) = "Layout2"
jagged(1).Items(3) = "Layout3"
[color=green] '' yada. Add debug.print statments to suit to illuminate the contents
'' in practice one would try to know ahead of time the number
'' of array elements required, for the primary and nested arrays.
'' There's a significant performance hit every time you use redim
'' preserve; use it only when absolutely necessary.[/color]
End Sub
-
I was looking up UDTs and it sounds like it might be a good (easy) fit for what I'm trying to do. The only problem I have with them is trying to retrieve data from it. I can't figure that part out. Here's what I've got...
Option Explicit
Type SSMFileInfo
ID As Integer
SSMLayout As String
SSMFileName As String
Counter As Integer
End Type
Public Sub SheetCount()
Dim BBXFileInfo As SSMFileInfo
Dim strSheetFileName As String
Dim strSheetLayoutName As String
Dim oSheet As AcSmSheet
Dim nSheetCount As Integer
Dim oEnumDB As IAcSmEnumDatabase
Dim oItem As IAcSmPersist
Dim oSheetSetMgr As AcSmSheetSetMgr
Set oSheetSetMgr = New AcSmSheetSetMgr
Set oEnumDB = oSheetSetMgr.GetDatabaseEnumerator
Set oItem = oEnumDB.Next
Dim oSheetDb As AcSmDatabase
Do While Not oItem Is Nothing
Set oSheetDb = oItem
Dim oEnum As IAcSmEnumPersist
Dim oItemSh As IAcSmPersist
Set oEnum = oSheetDb.GetEnumerator
Set oItemSh = oEnum.Next
Do While Not oItemSh Is Nothing
If oItemSh.GetTypeName = "AcSmSheet" Then
Set oSheet = oItemSh
BBXFileInfo.ID = oSheet.GetNumber
BBXFileInfo.SSMLayout = oSheet.GetLayout.GetName
BBXFileInfo.SSMFileName = oSheet.GetLayout.ResolveFileName
nSheetCount = nSheetCount + 1
BBXFileInfo.Counter = nSheetCount
End If
Set oItemSh = oEnum.Next
Loop
Set oItem = oEnumDB.Next
Loop
' Iterate through UDT info....
End Sub
I added the counter portion but I'm still having a hard time extracting data from it.