我在StackOverflow上找到了从C#执行Excel宏的解决方案,如here。
有没有办法将任何异常从VBA转发到C#?在我看来,如果VBA代码遇到运行时错误并停止,调用C#代码就会停止。
答案 0 :(得分:2)
您可以在VBA中捕获异常(错误处理)并返回例如。错误号码或其他东西回C#。
Public Function MyVbaFunction (myParameterA)
On Error Goto ERR_RETURN
'your code that throws error here
Exit Function
ERR_RETURN:
MyVbaFunction = Err.Number 'return error number
End Function
然后在C#中使用该返回
var excel = new Application {Visible = true};
excel.Workbooks.Open(filename);
var returned = excel.Run("MyVbaFunction", myParameterA);
和returned
现在包含错误编号或VBA返回的内容。
答案 1 :(得分:1)
如果您可以控制Excel工作表并且可以将公共子方法放在Excel的ThisWorkbook中而不是模块下,则可以使用此帮助程序方法来调用方法并抛出.Net异常:
static object CallSub(Workbook workbook, string name)
{
var bindingFlags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding;
try
{
return workbook.GetType().InvokeMember(
name,
bindingFlags,
null,
workbook,
new object[] { }, // arguments
null,
CultureInfo.InvariantCulture,
null);
}
catch (TargetInvocationException tie)
{
throw tie.InnerException;
}
}
我通过InvokeMember
找到了How can I capture a Microsoft Access VBA debug error from my C# code?的想法,因为我查看了Interaction.CallByName
。虽然您可以添加对Microsoft.VisualBasic的引用来获取该帮助程序类,但我选择将其删除至最低限度,只适用于简单方法。
这就是你如何使用它:
var app = new Microsoft.Office.Interop.Excel.Application();
var workbook = app.Workbooks.Open(@"test.xlsm");
try
{
CallSub(workbook, "DivByZero");
}
catch(DivideByZeroException dbz)
{
Console.WriteLine(dbz.Message);
}
或者如果你喜欢dynamic
,你可以这样做:
var app = new Microsoft.Office.Interop.Excel.Application();
var workbook = app.Workbooks.Open(@"test.xlsm");
dynamic wb = workbook; // cast workbook to dynamic
wb.DivByZero(); // the runtime figures it out for you
请记住,这仅适用于ThisWorkbook中的潜艇。请参阅此图片以了解差异: