从 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 宏错误

从 Excel VBA 运行访问查询

VBA宏:捕获具有特定字符串的行并返回它

我在 excel VBA 中有一个函数,它使用文本框从用户那里获取输入

运行宏时在 Excel VBA 中指定路径

Excel VBA 宏后期绑定