What I do is putting a dictionary into an array within a Sub Routine
That is the definition
Dim Arr() As Variant
ReDim Arr(0 To Dict.Count - 1)
For c= 0 To Dict.Count - 1
Arr(c) = Dict.Keys(c) ' <~~~~~~ Error here
Next c
The compiler says
Runtime Error 451: Property let procedure not defined and property get Procedure did not return an object.
It works great with
Public Sub SubRoutine(Dict As Scripting.Dictionary)
but not with
Public Sub SubRoutine(Dict As Object) –
Please refer to Declare a dictionary without Microsoft Scripting Runtime
<Solution>You do this
Dim Arr() As Variant
ReDim Arr(0 To Dict.Count - 1)
For c = 0 To Dict.Count - 1
Arr(c) = Dict.Keys(c)
Next c
But looping like this is quite unnecessary. That's what Arr = Dict.Keys does. So instead of the above, just do
Dim Arr As Variant
Arr = Dict.Keys
The added bonus is that this makes the error go away.
</Solution>But why did the error occur in the late bound version of the code but not the early bound?
<Educated guess>With early binding, the compiler knows that the .Keys method takes no parameters — it just returns an array. So it interprets Dict.Keys(c) as {returned array}(c) and returns the cth element of that returned array.
With late binding, I guess the Object container doesn't know that the .Keys method doesn't take parameters (a.k.a. arguments), so it sends c to it as a parameter. But there is no such getter (or setter) defined, hence the error. To remedy, you can apparently force it to send no parameters to the Keys method by saying Dict.Keys()(c), which brings back the {returned array}(c) behaviour.
</Educated guess>This is the first time I bump into a case like this where the late bound code behaves differently than the early bound.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With