Results 1 to 7 of 7

Thread: Cannot change array element in collection

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jul 2016
    Posts
    230

    Cannot change array element in collection

    Hey

    I found today that apparently one cannot change an array element's value if that array is stored in a collection. The only way to change it is to remove the array from the collection and replace it with a different one.
    Is this true, or have I lost it?

    Code:
    Dim c As Collection
    Dim a(0 To 1) As String
    Dim b(0 To 1) As String
    
    Set c = New Collection
    
    a(0) = "foo"
    a(1) = "123"
    c.Add a, "key1"
    
    Debug.Print "0: " & c("key1")(0)
    Debug.Print "1: " & c("key1")(1)
    
    c("key1")(0) = "bar"
    c("key1")(1) = "789"
    
    Debug.Print "0: " & c("key1")(0)
    Debug.Print "1: " & c("key1")(1)
    
    b(0) = "bar"
    b(1) = "789"
    
    c.Add "", "REPLACE", "key1"
    c.Remove "key1"
    c.Add b, "key1", , "REPLACE"
    c.Remove "REPLACE"
    
    Debug.Print "0: " & c("key1")(0)
    Debug.Print "1: " & c("key1")(1)
    And the output:
    Code:
    0: foo
    1: 123
    0: foo
    1: 123
    0: bar
    1: 789

  2. #2
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: Cannot change array element in collection

    Quote Originally Posted by OldClock View Post
    I found today that apparently one cannot change an array element's value if that array is stored in a collection.
    That's problem #1 - but it can be solved by changing to Collection-Replacements, which allow changing Elements directly
    (without a Remove->Re-Add sequence).

    Quote Originally Posted by OldClock View Post
    The only way to change it is to remove the array from the collection and replace it with a different one.
    Is this true, or have I lost it?
    That's a (slightly different) problem #2...

    An Array in VB is implemented as a SafeArray - being a "Pointer-Type" (like a String).

    So, assuming you have already switched to a Collection which supports changing Elements directly,
    you still cannot do something like:
    Code:
    Col(i)(k) = New_ArrayValue_For_Index_k
    Instead you will have to retrieve the whole Array, change stuff in it - and set it back into the Index-Position i in the Col.:
    Code:
    Col(i) = Replace_ArrayValue_Inside( Col(i) )
    
    Function Replace_ArrayValue_Inside( Arr() As SomeType ) As SomeType()
      Arr(k) = NewValue
      Replace_ArrayValue_Inside = Arr 'return the changed result from the helper-function
    End Function
    Same thing with Strings (in case you assume for a moment, that "String" is just another name for "Array of Chars")
    Code:
    Col(i) = Replace_StringValue_Inside( Col(i) )
    
    Function Replace_StringValue_Inside( S As String ) As String
      Replace_StringValue_Inside = Replace(S, "OldChars", "NewChars")
    End Function
    To achieve what you want, you will have to switch to Object-Encapsulations of Arrays or Strings.
    E.g. the following works with
    - the RC5-cCollection (a VB-compatible Collection-replacement, which allows direct Item-Changes)
    - the RC5-cArrayList (a wrapper around differently typeable, single-dimension-arrays)

    Code:
    Private Sub Form_Load()
      Dim Col As cCollection
      Set Col = New_c.Collection
      
      'add a ByteArray to the Collection (with 3 Byte-Value-Members)
      Col.Add New_c.ArrayList(vbByte, 1, 2, 3)
      
      'Print the current Array-content at the (OneBased) Collection-Index 1
      Debug.Print Col(1).Join(",") '... will print out: 1,2,3
      
      'since the ByteArray is wrapped behind an Object, you can now directly change the first Array-Member (at Idx 0)
      Col(1)(0) = 111
      
      'Print the current Array-content again
      Debug.Print Col(1).Join(",")  '... will print out: 111,2,3
    End Sub
    HTH

    Olaf
    Last edited by Schmidt; Dec 21st, 2017 at 02:25 PM.

  3. #3
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Cannot change array element in collection

    Another option could be to use a class that holds your array, similar to what Olaf was describing as "Object-Encapsulations"

    Class. We'll name this clsArray
    Code:
    Private myArray() As String ' variant, long, integer, etc
    Public Sub SizeArray(lowerBound As Long, upperBound As Long, Optional bPreserve as Boolean = False)
        If bPreserve Then
            ReDim Preserve myArray(lowerBound to upperBound)
        Else
            ReDim myArray(lowerBound to upperBound)
        End If
    End Sub
    
    Public Property Get Item(Index As Long) As String ' variant, long, integer, etc
        Item = myArray(Index)
    End Property
    Public  Property Let Item(Index As Long, Value As String)
        myArray(Index) = Value
    End Property
    
    Public Property Get LowerBound() As Long
        LowerBound = LBound(myArray)
    End Property
    Public Property Get UpperBound() As Long
        UpperBound = UBound(myArray)
    End Property
    now using your example:
    Code:
    Dim c As Collection, a As ClsArray
    
    Set a = New ClsArray
    a.SizeArray 0, 1
    
    Set c = New Collection
    a.Item(0) = "foo"
    a.Item(1) = "123"
    c.Add a, "key1"
    
    Debug.Print "0: " & c("key1").Item(0)
    Debug.Print "1: " & c("key1").Item(1)
    
    c("key1").Item(0) = "bar"
    c("key1").Item(1) = "789"
    
    Debug.Print "0: " & c("key1").Item(0)
    Debug.Print "1: " & c("key1").Item(1)
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  4. #4

    Thread Starter
    Addicted Member
    Join Date
    Jul 2016
    Posts
    230

    Re: Cannot change array element in collection

    Thank you for the replies!

    Schmidt by "Collection-Replacements" and RC5 do you mean this?
    http://vbrichclient.com/
    What you wrote here in the forum has me interested, but:
    - there is no page clearly explaining what vbRichClient is (in simple terms, i.e. it doesn't sell itself), what it can do for me, which Windows versions it runs on and which it has issues with, whether it runs in Wine as VB6 classic can,
    - it does not state what licence the code is under, or whether it is in the public domain,
    - the "about" text on that site states that the framework will be completed in "another 1.5-2 years or so" and that was written in 2013,
    - many pages have "no content yet...",
    - there is no documentation,
    Those point are quite discouraging from investing time in digging into it - would be great if you could clarify.

    LaVolpe interesting solution!

  5. #5
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,412

    Re: Cannot change array element in collection

    Hi OldClock, I've been a happy user of the vbRichClient5 library (and it's earlier dhRichClient incarnations) for over a decade. The web-site doesn't do it justice!

    RC5 (as I'll shorten vbRichClient5) is an framework/library intended to modernize your VB6 applications. It is completely free to use and distribute, but is not open source.

    Some of the features it includes:

    • Graphical enhancements (PNG, alpha/transparency support, etc...) by way of a wrapper for the open source Cairo library.
    • A fast, powerful, self-contained database support via a wrapper for the public domain SQLite.
    • The ability to perform remote procedure calls (RPC) over a network (client-server apps).
    • All manner of helpful, powerful, and high-performance classes for things like the cCollection class he introduced you to in this thread. Others include an ArrayList class, FSO replacement, encryption & hash functions, etc...


    There's a lot more too. Here's some projects & demos that use the library that might interest you:



    There are a lot more demos to be found here: Click Here for Search Results.

    Anyway, I recommend giving it a try - it certainly won't hurt!

  6. #6
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Cannot change array element in collection

    @OldClock, just fyi...

    If you use the class method, you can set the default property of the class to the Item property. Doing so allows you to exclude the Item term in the sample code to be more like your original example. So...

    Instead of: c("key1").Item(0) = "bar"
    changed to: c("key1")(0) = "bar"
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Cannot change array element in collection

    LaVolpe I change your idea to something else:

    item must be the default property
    Code:
    Private myArray() ' variant, long, integer, etc
    Public Sub SizeArray(LowerBound As Long, UpperBound As Long, Optional bPreserve As Boolean = False)
        If bPreserve Then
            ReDim Preserve myArray(LowerBound To UpperBound)
        Else
            ReDim myArray(LowerBound To UpperBound)
        End If
    End Sub
    
    Public Property Get Item(Optional Index As Variant) As Variant ' variant, long, integer, etc
        Dim m As ClsArray
        If IsMissing(Index) Then
            Item = myArray()
        ElseIf IsNumeric(Index) Then
            Item = myArray(Index)
        Else  '  not used here........If TypeName(Index) = "Variant()" Then
            Set m = New ClsArray
            m() = Index
            Item = m()
    
        End If
    End Property
    Public Property Let Item(Optional Index As Variant, Value As Variant)
        If IsMissing(Index) Then
          myArray() = Value
        Else
            myArray(Index) = Value
        End If
    End Property
    
    Public Property Get LowerBound() As Long
        LowerBound = LBound(myArray)
    End Property
    Public Property Get UpperBound() As Long
        UpperBound = UBound(myArray)
    End Property

    So now we have this code working


    Code:
    Sub test()
    Dim c As Collection, a As ClsArray
    
    Set a = New ClsArray
    
    Set c = New Collection
    a() = Array("foo", "123")
    c.Add a, "key1"
    
    Debug.Print "0: " & c("key1")(0)
    Debug.Print "1: " & c("key1")(1)
    
    c("key1") = a(Array("bar", "789"))
    
    Debug.Print "0: " & c("key1")(0)
    Debug.Print "1: " & c("key1")(1)
    
    
    c("key1") = a(Array("alfa", "beta"))
    Debug.Print "0: " & c("key1")(0)
    Debug.Print "1: " & c("key1")(1)
    Debug.Print c("key1").UpperBound
    
    c("key1") = a(Array(a(Array("foo", "123")), a(Array("alfa", "beta"))))
    Debug.Print "0: " & c("key1")(0)(0)
    Debug.Print "1: " & c("key1")(1)(1)
    
    
    
    End Sub
    Last edited by georgekar; Dec 22nd, 2017 at 06:00 PM.

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
  •  



Click Here to Expand Forum to Full Width