Invoke VBA code from C# without using PIA's?

B

Brian

We are currently hosting Word 2003 inside a DSO Framer inside our Click-Once
WinForms app.
We have implemented certain functionality as VBA inside the Word doc... and
we invoke that via the PIA.

Now we are trying to support Word 2007 and Word XP and Word 2000 (in
addition to Word 2003).
(We can mandate they have Word; but mandating which version is problematic.)
To do that most easily, we are trying to get away from using the PIA's at
all.
Most things can be handled by the DSO Framer interface.
The rest can be moved into VBA macros inside Word.

But we need some way to invoke our VBA macros from our C# WinForms code,
without the PIA's.
Any suggestions?
 
C

Cindy M.

Hi Brian,

Generally, the only way to call anything in the object model without using PIAs
is to go over late-binding. With C# we're talking about "PInvoke" (= GetType()
InvokeMember()). So you'd need to work with variables typed as objects. Below
my signature line you'll find some test code I played with a while back to give
you an idea how it's done in Excel. Same principle goes for Word, just use the
objects from the Word object model.

Of course, you want to program and test against the oldest version to make sure
you don't use things not available in that version. For optional parameters
that have been added since the oldest version, just leave them out of the
[args] array (last thing passed in InvokeMethod). New opt-params are added at
the end of the method signature.
We are currently hosting Word 2003 inside a DSO Framer inside our Click-Once
WinForms app.
We have implemented certain functionality as VBA inside the Word doc... and
we invoke that via the PIA.

Now we are trying to support Word 2007 and Word XP and Word 2000 (in
addition to Word 2003).
(We can mandate they have Word; but mandating which version is problematic.)
To do that most easily, we are trying to get away from using the PIA's at
all.
Most things can be handled by the DSO Framer interface.
The rest can be moved into VBA macros inside Word.

But we need some way to invoke our VBA macros from our C# WinForms code,
without the PIA's.

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any follow question or reply
in the newsgroup and not by e-mail :)

object excelObject;
object Books;
object Book;
object Sheets;
object Sheet;
object rng;
oExcel = Type.GetTypeFromProgID("Excel.Application");
excelObject = Activator.CreateInstance(oExcel);
System.Globalization.CultureInfo ci =
System.Threading.Thread.CurrentThread.CurrentCulture;
try
{
object[] oArgs = new object[1];
oArgs[0] = -1;
excelObject.GetType().InvokeMember("Visible",
System.Reflection.BindingFlags.SetProperty, null, excelObject, oArgs);

System.Threading.Thread.CurrentThread.CurrentCulture = new
System.Globalization.CultureInfo("en-US");

//get Books reference
Books = excelObject.GetType().InvokeMember("Workbooks",
System.Reflection.BindingFlags.GetProperty, null, excelObject, null);
//Open existing spreadsheet
object[] oArgs2 = new object[1];
oArgs2[0] = @"C:\Test\Test.xlsx";
//Excel.Application appXL = (Excel.Application)
System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
//appXL.Workbooks.Open(oArgs2[0].ToString(), missing, missing,
missing, missing, missing, missing, missing, missing, missing, missing,
missing, missing, missing, missing);

Books.GetType().InvokeMember("Open",
System.Reflection.BindingFlags.InvokeMethod,
null, Books, oArgs2);

//object booksCount = Books.GetType().InvokeMember("Count",
System.Reflection.BindingFlags.GetProperty, null, Books, null);
//MessageBox.Show(booksCount.ToString());

oArgs[0] = 1;
Book = Books.GetType().InvokeMember("Item",
System.Reflection.BindingFlags.GetProperty, null, Books, oArgs);

//Get the worksheets collection.
Sheets = Book.GetType().InvokeMember("Worksheets",
System.Reflection.BindingFlags.GetProperty, null, Book, null);

// //Get the first worksheet.
oArgs2[0] = "Sheet1";
Sheet = Sheets.GetType().InvokeMember("Item",
System.Reflection.BindingFlags.GetProperty, null, Sheets, oArgs2);

////Move to Named Reference Cell
oArgs[0] = "Test";
rng = Sheet.GetType().InvokeMember("Range",
System.Reflection.BindingFlags.GetProperty, null, Sheet, oArgs);
rng.GetType().InvokeMember("Select",
System.Reflection.BindingFlags.InvokeMethod, null, rng, null);
//excelObject.GetType().InvokeMember("Goto",
System.Reflection.BindingFlags.InvokeMethod, null, Books, oArgs);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}

finally
{
//object[] oArgs = new object[2];
excelObject.GetType().InvokeMember("Quit",
System.Reflection.BindingFlags.InvokeMethod, null, excelObject, null);
Book = null;
Books = null;
excelObject = null;
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
GC.Collect();
}

}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top