I have a windows form application created in Visual Studio.
I have referenced a COM API and I am trying to run this
L_RESULT = Visualfiles.SystemScript("HIST-TEL", sampleVisualBasicColl, "")
The second parameter needs to bee a collection, so I created this
Dim sampleVisualBasicColl As New Microsoft.VisualBasic.Collection()
Dim item1, item2, item3, item4 As String
item1 = "Items"
item2 = "In"
item3 = "A"
item4 = "Collection"
sampleVisualBasicColl.Add(item1, "firstkey")
sampleVisualBasicColl.Add(item2, "secondkey")
sampleVisualBasicColl.Add(item3, "thirdkey")
sampleVisualBasicColl.Add(item4, "fourthkey")
But the error that I get is this
Unable to cast object of type 'Microsoft.VisualBasic.Collection' to type 'VBA.Collection'.
I have found this article which I think will help - https://support.microsoft.com/en-gb/kb/323737
But how do I complete steps 1-4?
I have visual studio community 2015 and I am not sure how to create this dll?
Thanks for any advice!
The Collection coclass is a chronic trouble-maker, Microsoft created too many implementations of it. And, quite unwisely, gave those implementations the same CLSID. Not that clear how this went so badly wrong, probably one group of programmers not talking to another group. The lousy solution they came up with was to force everybody to apply the [noncreatable] attribute.
Which stops you from adding a reference to, say, vba7.dll so you can create your own Collection object. Which is why the KB article tells you to use VB6 to create an instance of the object. Well, ugh, 18 years is a lot of dog lives and who has VB6 installed anymore today. You need an MSDN license or good luck at an Ebay auction.
Time to get this fixed the correct way instead of that lousy KB way. All you have to do is to create a concrete instance of the Collection object's default interface. By COM rules, the implementation of the interface never matters.
Add a new class to your project and paste this code:
Imports System.Runtime.InteropServices
Namespace VBA
<ComVisible(True), Guid("A4C46780-499F-101B-BB78-00AA00383CBB")>
Public Interface _Collection
<DispId(0)> Function Item(<[In]> ByRef Index As Object) As Object
<DispId(1)> Sub Add(<[In]> ByRef Item As Object, ByRef Optional Key As Object = Nothing,
ByRef Optional Before As Object = Nothing,
ByRef Optional After As Object = Nothing)
<DispId(2)> Function Count() As Integer
<DispId(3)> Sub Remove(<[In]> ByRef Index As Object)
<DispId(-4)> Function _NewEnum() As IEnumerator
End Interface
'' <ComVisible(True)>
<ClassInterface(ClassInterfaceType.None), Guid("A4C4671C-499F-101B-BB78-00AA00383CBB")>
Public Class Collection
Implements _Collection
Private impl As New Microsoft.VisualBasic.Collection
Public Sub Add(ByRef Item As Object, ByRef Optional Key As Object = Nothing, ByRef Optional Before As Object = Nothing, ByRef Optional After As Object = Nothing) Implements _Collection.Add
impl.Add(Item, CStr(Key), Before, After)
End Sub
Public Sub Remove(ByRef Index As Object) Implements _Collection.Remove
If TypeOf Index Is String Then impl.Remove(CStr(Index)) Else impl.Remove(CInt(Index))
End Sub
Public Function Count() As Integer Implements _Collection.Count
Return impl.Count
End Function
Public Function _NewEnum() As IEnumerator Implements _Collection._NewEnum
Return impl.GetEnumerator()
End Function
Public Function Item(ByRef Index As Object) As Object Implements _Collection.Item
Return impl(Index)
End Function
End Class
End Namespace
So instead of creating a new Collection object, now create a new VBA.Collection object to keep the component happy. I don't have a good way to test it anymore, hope it works.
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