从C#调用某些Excel VBA宏时出错

我一直在努力和搜索这个问题无济于事…我有一些测试宏在从Excel运行时工作得很好但是从C#调用时失败或不工作,使用互操作…

我正在使用MS Visual Studio 2012(在64位Windows 7上)创建一个控制台应用程序,它将调用用Excel 2007编写的VBA宏TestMacro()。

下面是调用宏的C#代码:(我基本上复制了在这里完成的操作从Visual C#.NET使用自动化运行Office宏 )

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); } } } 

宏是……

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

此宏失败,ComException为Visual Studio – >“来自HRESULT的exception:0x800A03EC”

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

不返回exception,但不清除TestRange的内容

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

但这是有效的,因此可以识别范围名称,并且可以完成计数操作……

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

这与上一种情况一样,但无法切换到表2,而是将结果写入表1 …

如前所述,所有这些宏在从excel运行时都能正常工作,但在从C#调用时会失败。 没有任何工作表受到保护,我在宏安全性中设置了“启用所有宏”,“信任访问VBA项目模型”。 我觉得有一些访问/权限问题,但我不知道如何解决它….任何帮助将赞赏..

提前致谢!!

你可能会遗漏几件事。 首先,我使用.Net参考Microsoft.Office.Interop.Excel v14(对于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); } } } 

第二,确保将宏代码放入模块(全局BAS文件)中。

 Public Sub TestMsg() MsgBox ("Hello Stackoverflow") End Sub 

第三,确保启用对VBA Project对象模型的宏安全性和信任访问:

在此处输入图像描述

也有人知道,对于这种情况,有一种方法从Visual Studio 2012调试Excel VBA,Com Exceptions非常无益…… – Sunny Sampath

当你克服了Comexception时,单步执行代码会将VS中的进程跨越到Excel的VBE,然后再回到VS.

编辑:

以下是清除内容的VBA代码:

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

或者,如果要删除名为TestRange的NameRange:

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

其他TestMacro对您的工作来说过于具体,我无法理解。 祝好运!

显然,有一个非常简单的解决方案。 而不是使用RunMacro函数…使用应用程序方法“运行”适用于所有宏。 我用了这条线

 oExcel.Run("TestMacro"); 

而不是打电话

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

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

唉……这个问题偷走了我生命的两天!