Author Topic: 2D Array Help  (Read 5403 times)

0 Members and 1 Guest are viewing this topic.

Guest

  • Guest
2D Array Help
« 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...

Code: [Select]
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?
« Last Edit: February 11, 2008, 10:29:53 PM by Matt W »

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: 2D Array Help
« Reply #1 on: February 11, 2008, 11:19:35 PM »
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.

Quote from: On-Line Help
...

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
« Last Edit: February 11, 2008, 11:59:59 PM by MP »
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Fatty

  • Guest
Re: 2D Array Help
« Reply #2 on: February 12, 2008, 05:20:53 AM »
I was wondered how many programmers use
the following (dirty method for this task)
Anyway, it works

Code: [Select]
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'~

Guest

  • Guest
Re: 2D Array Help
« Reply #3 on: February 12, 2008, 06:12:34 AM »
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.

Quote from: On-Line Help
...

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.

Guest

  • Guest
Re: 2D Array Help
« Reply #4 on: February 12, 2008, 06:14:19 AM »
I was wondered how many programmers use
the following (dirty method for this task)
Anyway, it works

Code: [Select]
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.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: 2D Array Help
« Reply #5 on: February 12, 2008, 06:44:49 AM »
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.
« Last Edit: February 12, 2008, 06:58:35 AM by MP »
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: 2D Array Help
« Reply #6 on: February 12, 2008, 07:20:43 AM »
You could also create a UDT that hosts a dynamic array, and then make a dynamic array of said UDT.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Guest

  • Guest
Re: 2D Array Help
« Reply #7 on: February 12, 2008, 08:03:11 AM »
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:

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: 2D Array Help
« Reply #8 on: February 12, 2008, 08:38:48 AM »
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.
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Guest

  • Guest
Re: 2D Array Help
« Reply #9 on: February 12, 2008, 08:46:56 AM »
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.

MP

  • Seagull
  • Posts: 17750
  • Have thousands of dwgs to process? Contact me.
Re: 2D Array Help
« Reply #10 on: February 12, 2008, 09:02:43 AM »
Oversimplified example, but I've hurtin' for time. Put this in a module --

Code: [Select]
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
Engineering Technologist • CAD Automation Practitioner
Automation ▸ Design ▸ Drafting ▸ Document Control ▸ Client
cadanalyst@gmail.comhttp://cadanalyst.slack.comhttp://linkedin.com/in/cadanalyst

Guest

  • Guest
Re: 2D Array Help
« Reply #11 on: February 12, 2008, 12:11:58 PM »
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...


Code: [Select]
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.