1

I'm making a program in VB6, and I can't properly loop through a String dictionary.

I've tried both ways of accesssing a value in the collection. Collection(Key), and Collection.Item(Key).

Dim line As Variant
Dim thismsg As New Collection
Dim thissection As String
For Each line In Split(NetRcv, vbLf)
    If Left(line, 3) = "BLK" Then
        thissection = Right(line, Len(line) - 3)
        MsgBox thissection
        GoTo nctlrParseLoopNext
    End If
    If Left(line, 3) = "BND" Then
        Exit For
    End If
    Dim key, value As String
    key = Left(line, InStr(line, " "))
    value = Right(line, InStr(line, " "))
    thismsg.Add key, value
nctlrParseLoopNext:
Next line
Dim member As Variant
For Each member In thismsg
    MsgBox member
    MsgBox thismsg(member)
Next member

The string in NetRcv is the following:

BLK modeswitch
mode codeslave
BND

I expect to see this sequence of MsgBoxes ...

modeswitch
mode
codeslave

... with possibly trailing spaces somewhere. I see the first two, and then it errors with

Run-time error '5':
Invalid procedure call or argument

I don't understand why this error occurs.

member is the key, correct?

If it is, then there's no reason this error should pop up.

  • `Collection` *is not* a Dictionary. Use `Scripting.Dictionary` instead. `Collection` internally is a linked list. – Adam Ryczkowski Jul 17 '19 at 10:46
  • Do you want an example of Dictionary use? – Adam Ryczkowski Jul 17 '19 at 10:48
  • oh. sorry. I assume I was using `Collection` exactly like `Scripting.Dictionary`. so `Collection` is basically the same thing as .NET's `List<>`? – ScottBeebiWan Jul 17 '19 at 11:49
  • I am not sure about .NET, but I am sure the VB6/VBA `Collection` has indexing speed O(N) (stumbled on it many times in large projects), so I infer it must be internally implemented as a list. – Adam Ryczkowski Jul 17 '19 at 12:42
  • 1
    Personally I never ever use `Collection`. It's main advantage - ability to gather heterogenous objects is usually its another weakness, including your case. Stick with Arrays or Scripting.Dictionary. – Adam Ryczkowski Jul 17 '19 at 12:43
  • `For Each member In thismsg` will iterate through the collection values. So inside the loop, member will have the value stored in the collection, it's not the key. The exception could be that the call `thismsg(member)` is not valid. – MarkL Jul 17 '19 at 13:11
  • Also - I don't believe that this line `value = Right(line, InStr(line, " "))` is going to do what you want it to. `InStr` returns an offset into the string. `Right` expects the number of characters to pull from the right side of the string. – MarkL Jul 17 '19 at 13:13
  • 1
    I'm a dinosaur coder and I abhor "goto" First time in decades I've even seen anyone use it. – Bill Hileman Jul 17 '19 at 18:56
  • 1
    @AdamRyczkowski `Collection`'s `Item` is `O(N)` only for integral indexes. For string keys access it's `O(log N)` and `For Each` enumeration is `O(1)`. There is no equivalent container in .Net framework but we use it like `Dictionary` mostly and never access it by index so the performance (and memory usage) is far better than `Scripting.Dictionary` counterpart. – wqw Jul 18 '19 at 21:55
  • @wqw if you happen to know what is the underlying data model of the `Collection`, would you care to answer `https://stackoverflow.com/q/57111861/1261153`? – Adam Ryczkowski Jul 19 '19 at 11:46

1 Answers1

2

For one thing, you have inverted the value and key. This:

thismsg.Add key, value

should be this:

thismsg.Add value, key

See here for the docos on the Add method

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/add-method-visual-basic-for-applications

tcarvin
  • 10,715
  • 3
  • 31
  • 52