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 c
th 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