views:

616

answers:

1

I'm running into a problem with excel interop. Basically, what I'm trying to do is call a macro in an excel workbook from .NET with a complex argument type. However, in doing so I'm running into some differences between Application and ApplicationClass that are giving me some headaches.

Here is some code:

Dim complexType As New BigBadClass

Dim result As Boolean = importerClass.ExcelApplication.ComObject.GetType().InvokeMember("Run", _
            Reflection.BindingFlags.Default + Reflection.BindingFlags.InvokeMethod, Nothing, _
            importerClass.ExcelApplication.ComObject, _
            New Object() {"TheMacroName", AStringValue, ALongValue, complexType})

In the excel VBA macro, complexType gets mapped to an Object.

(Interesting side note, I tried this in C# first and kept getting Type Mismatch exceptions, the only difference between this and the C# code is that this passes in a complexType created in VB.NET, and the C# version passed in a complexType created in C#. For some reason that I haven't figured out yet (some kind of subtle differences in the Object type?), the C# one fails, whereas the VB.NET one works)

Anyways, with the above code snippet. It only works if the ExcelApplication.ComObject is an ApplicationClass, and not the Application interface. Application does not have a GetType() member. And since they are COM classes, you cannot cast them. I would prefer to use Application if possible as I have another piece that will load open workbooks automatically for the user by using GetObject(..) and this breaks when using ApplicationClass (as once again you cannot cast COM classes, so you can only cast GetObject(..) into an Application interface).

Has anyone come across this problem before?
Is there a way to use something like GetObject(..) with ApplicationClass?
Or a way to use GetType() with Application? Or possibly some way to cast COM objects? ie: casting Application to ApplicationClass

Hopefully my explanation is clear enough, and the code illustrates what I am doing.

A: 

This should be of interest to you:

Run macro using VB.Net

The second I saw reflection I knew this wasn't quite right.

Just for reference I've posted the code available on the source:

    Dim oExcel As Excel.ApplicationClass
    Dim oBook As Excel.WorkbookClass
    Dim oBooks As Excel.Workbooks

    'Start Excel and open the workbook.'
    oExcel = CreateObject("Excel.Application")
    oExcel.Visible = True
    oBooks = oExcel.Workbooks
    oBook = oBooks.Open("c:\book1.xls")

    'Run the macros.'
    oExcel.Run ("DoKbTest")
    oExcel.Run("DoKbTestWithParameter", "Hello from VB .NET Client")

    'Clean-up: Close the workbook and quit Excel.'
    oBook.Close (False)
    System.Runtime.InteropServices.Marshal.ReleaseComObject (oBook)
    oBook = Nothing
    System.Runtime.InteropServices.Marshal.ReleaseComObject (oBooks)
    oBooks = Nothing
    oExcel.Quit()
    System.Runtime.InteropServices.Marshal.ReleaseComObject (oExcel)
    oExcel = Nothing
Spence
Doh, I feel like such a dingbat. I had actually tried that method in C#, but it didn't work (due to the reasons in my question in parentheses likely... and I didn't really want to use Missing.Value 30 times :)), but I never even tried to use it in VB.NET. It all works now. Thank you.
David Dietrich
I hate interop. The new C# has a new way of calling office interop which has way better format for the function calls (nearly identical to VB) C# probably wasn't working because the casting in C# is explicit, you probably needed to shove a (object)myobject on the call to make it work, plus all 30 Ref.missing on the function call :).
Spence