Errors when calling certain Excel VBA macros from C#

血红的双手。 提交于 2020-01-23 08:13:46

问题


I have been struggling and searching on this problem to no avail... I have a few test macros that work perfectly when run from Excel, but either fail or don't work when called from C#, using the interop...

I am using MS Visual Studio 2012 (on 64 bit Windows 7) to create a console application that will call the VBA macro TestMacro() written in Excel 2007.

Here is the C# code to call the macro: (I basically copied what was done here Run Office Macros by Using Automation from Visual C# .NET)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Reflection;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;

namespace C#_Macro_Wrapper
{
    class Program
    {
        static void Main(string[] args)
        {
            RunVBATest();
        }


        public static void RunVBATest()
        {
            System.Globalization.CultureInfo oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            object oMissing = System.Reflection.Missing.Value;
            Excel.Application oExcel = new Excel.Application();
            oExcel.Visible = true;
            Excel.Workbooks oBooks = oExcel.Workbooks;
            Excel._Workbook oBook = null;
            oBook = oBooks.Open("C:\\Users\\ssampath\\Documents\\RMS Projects\\Beta 3 Testing\\TestMacroForVSTO.xlsm", oMissing, oMissing,
                oMissing, oMissing, oMissing, oMissing, oMissing, oMissing,
                oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);

            // Run the macro.
            RunMacro(oExcel, new Object[] { "TestMacro()" });


            // Quit Excel and clean up.
            oBook.Close(true, oMissing, oMissing);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
            oBook = null;
            System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
            oBooks = null;
            oExcel.Quit();
            System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
            oExcel = null;
            System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
        }


        private static void RunMacro(object oApp, object[] oRunArgs)
        {
            oApp.GetType().InvokeMember("Run",
                System.Reflection.BindingFlags.Default |
                System.Reflection.BindingFlags.InvokeMethod,
                null, oApp, oRunArgs);
        }
    }
}

The Macros are...

Sub TestMacro()  
Worksheets("Sheet1").ClearContents
End Sub

This macro fails with ComException to Visual Studio -> "Exception from HRESULT: 0x800A03EC"

Sub TestMacro()
Range("TestRange").ClearContents
End Sub

Does not return exception, but does not clear contents of TestRange

Sub TestMacro()
x = Range("TestRange").Count()
Cells(5, 5).Value = x
End Sub

But this works, thus the range name can be recognized, and the count operation can be done...

Sub TestMacro()
Worksheets("Sheet1").Select
x = Range("TestRange").Count()
Worksheets("Sheet2").Select
Cells(5, 5).Value = x
End Sub

This works like last case, but fails to switch to sheet 2, and instead writes result to sheet 1...

As said earlier all these macros work perfectly when run from excel, but fail when called from C#. None of the works sheets are protected, and I have set "enable all macros", "trust access to VBA project model" in Macro Security. I feel there is some access/permissions issue, but I have no idea how to fix it....any help would appreciated..

Thanks in advance!!


回答1:


There could be several things your missing. First here is the code I used to get it working, using the .Net reference Microsoft.Office.Interop.Excel v14 (for Office 2010):

using System;
using Microsoft.Office.Interop.Excel;

namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
    RunVBATest();
}

public static void RunVBATest()
{
    //System.Globalization.CultureInfo oldCI = System.Threading.Thread.CurrentThread.CurrentCulture;
    //System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
    //object oMissing = System.Reflection.Missing.Value;
    Application oExcel = new Application();
    oExcel.Visible = true;
    Workbooks oBooks = oExcel.Workbooks;
    _Workbook oBook = null;
    oBook = oBooks.Open("C:\\temp\\Book1.xlsm");

    // Run the macro.
    RunMacro(oExcel, new Object[] { "TestMsg" });

    // Quit Excel and clean up.
    oBook.Saved = true;
    oBook.Close(false);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oBook);
    oBook = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oBooks);
    oBooks = null;
    oExcel.Quit();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel);
    oExcel = null;
    //System.Threading.Thread.CurrentThread.CurrentCulture = oldCI;
}

private static void RunMacro(object oApp, object[] oRunArgs)
{
    oApp.GetType().InvokeMember("Run",
        System.Reflection.BindingFlags.Default |
        System.Reflection.BindingFlags.InvokeMethod,
        null, oApp, oRunArgs);
}
}
}

Second make sure you put the Macro code in a Module (a Global BAS file)..

Public Sub TestMsg()

MsgBox ("Hello Stackoverflow")

End Sub

Third make sure you enable Macro Security and Trust access to the VBA Project object model:

Also does anyone know if for this case there is a way to debug Excel VBA from Visual Studio 2012, the Com Exceptions are pretty unhelpful... – Sunny Sampath

When you overcome the Com exception, stepping through the code will cross processes from VS into Excel's VBE and then back to VS.

Edit:

Here is the VBA code to clear contents:

Dim activeSheet As Worksheet
Set activeSheet = Excel.activeSheet
activeSheet.UsedRange.Clear

Or if you want to delete a NameRange called TestRange:

Dim range As range
Set range = activeSheet.range("TestRange")
range.Clear

The other TestMacro's are too specific to your work for me to understand. Good luck!




回答2:


Well apparently there was a very easy solution. Instead of using RunMacro function...using the application method "Run" works for all macros. I used the line

oExcel.Run("TestMacro"); 

instead of calling

private static void RunMacro(object oApp, object[] oRunArgs)
{
    oApp.GetType().InvokeMember("Run",
        System.Reflection.BindingFlags.Default |
        System.Reflection.BindingFlags.InvokeMethod,
        null, oApp, oRunArgs);
}

with

RunMacro(oExcel, new Object[] { "TestMsg" });

Arghh..this issue stole 2 days of my life!



来源:https://stackoverflow.com/questions/17373967/errors-when-calling-certain-excel-vba-macros-from-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!