从 C# 运行 Excel 宏:从 VBA 捕获运行时错误
Posted
技术标签:
【中文标题】从 C# 运行 Excel 宏:从 VBA 捕获运行时错误【英文标题】:Run Excel Macro from C#: Catch Runtime error from VBA 【发布时间】:2018-06-05 08:01:48 【问题描述】:我在 *** 上找到了从 C# 执行 Excel 宏的解决方案,例如 here,它可以工作。
有没有办法将任何异常从 VBA 转发到 C#?在我看来,如果 VBA 代码遇到运行时错误并停止,调用 C# 代码就会停止。
【问题讨论】:
【参考方案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;
我通过How can I capture a Microsoft Access VBA debug error from my C# code? 找到了InvokeMember
的想法,因为我查看了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 中的订阅者。查看此图片以了解差异:
【讨论】:
【参考方案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. 调用预定义函数而不是执行宏(其作用与宏执行相同) 2. 但是如何检索 VBA 会抛出的不同错误消息? 你所说的(1)是什么意思?函数是宏还是您的意思是过程(子)?一个子不能返回任何东西,因此你需要一个函数。 (2) 如果要返回文本消息而不是错误号,请在 VBA 函数中使用Err.Description
作为返回值。以上是关于从 C# 运行 Excel 宏:从 VBA 捕获运行时错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 VBA 从 Excel 打开和关闭 Access 数据库 - Access 宏错误