在VBA中,如何在不使用Application.Run()的情况下从未知模块调用特定方法?
我正在尝试在 VBA 中即兴创作一个类似 Drupal 的钩子机制(继续批评,我知道这听起来很愚蠢)。我努力的原因是我没有找到其他方法可以在团队中正确划分工作,因此我希望通过这种机制引入一些 Drupal 久经考验的钩子调用系统。我已经做到了,效果很好,但有一点缺点。
这就是我所做的:一个调度程序模块,它基本上循环我的项目中的所有模块,并测试它们是否以特定前缀开头(暗示它们是钩子模块),当它找到一个时,它就会这样做这:
Call Application.Run(Module.Name & ".hook_" & HookName)
我知道,这不是很原创,但是如果我循环所有模块并为所有 Workbook 事件调用钩子,它就开始有点像 AOP。这意味着我允许任意数量的模块对 Workbook_SheetChange
进行操作,而不会污染 ThisWorkbook 中的代码。更好的是,不同的人将在不同的钩子模块中处理不同的功能(大好处)。
正如我所说,这是可行的,但我还必须在这些调用之前调用 Application.EnableEvents = False
,并在调用之后调用 Application.EnableEvents = True
,所以我不最终陷入无限调用循环。这也可以。
我的问题:我想在所有钩子之上创建一个通用错误处理程序,这样如果一个钩子搞砸了某些事情,我可以在我的顶级调度程序中捕获错误并重新启用事件。听起来是个好主意,但因为我使用了 Application.Run()
,整个错误处理机制在中间被破坏,所以调度程序不会收到钩子内发生的任何错误就是这样调用的。这也会将应用程序事件设置为 False
,这很糟糕(请记住,我在调用挂钩之前将它们设置为 False
)。
我的问题:有没有一种方法可以在不使用 Application.Run 的情况下调用未知模块内的特定命名函数,这样我的错误就会冒泡到调度程序?我尝试了这个:
Call Module.hook_WorksheetChange()
但它没有编译(我并没有因为它的成功而屏住呼吸,但我希望......)。这里,Module
是一个保存 VBComponent 的 Object
,而 hook_WorksheetChange()
是在模块。
请问有什么想法吗?让每个钩子始终处理 Application.EnableEvents = True
清理并不是太优雅 - 它应该只关心它自己的、特定于功能的错误处理。
I'm trying to improvise a Drupal-like hook mechanism in VBA (go ahead and criticise, I know it sounds stupid). The reason of my endeavour is that I've found no other way of properly dividing the work across a team, so with this mechanism I hope to bring a little of Drupal's tried-and-true hook invocation system. I've done it, it works nicely, but I have a little shortcoming.
Here's what I've done: a dispatcher module, which basically loops over all the modules in my project, and tests whether they start with a specific prefix (a hint that they're hook modules), and when it finds one, it does this:
Call Application.Run(Module.Name & ".hook_" & HookName)
Not very original, I know, but if I loop over all the modules and invoke hooks for all Workbook events, it's beginning to smell a little like AOP. This means I allow any number of modules to act upon, say, Workbook_SheetChange
, without polluting the code in ThisWorkbook. Even better, different people will work on different features inside different hook modules (BIG BONUS).
As I said, this works, but I must also call Application.EnableEvents = False
before these invocations, and Application.EnableEvents = True
after the invocations, so I don't end up in infinite invocation loops. This is ok too.
My problem: I'd like to make a general error handler above all hooks, so that if one hook screws something up, I could catch the error inside my top dispatcher and re-enable events. Sounds like a good idea, but because I use Application.Run()
, the whole error-handling mechanism gets broken in the middle, so the dispatcher won't receive any error that happens inside a hook that is invoked like that. This will also leave the application events set to False
, which is bad (remember that I'm setting them to False
just before I invoke the hook).
My question: Is there a way to invoke a specifically named function inside an unkown module without Application.Run, so my errors bubble up to the dispatcher? I tried this:
Call Module.hook_WorksheetChange()
But it didn't compile (I wasn't holding my breath over its success, but I hoped...). Here, Module
is an Object
that holds the VBComponent, and hook_WorksheetChange()
is an actual Sub
defined in a module.
Ideas, please? It wouldn't be too elegant to let every hook always deal with the Application.EnableEvents = True
cleanup - it should only be concerned with it's own, feature-specific error handling.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您按照
基本上博维等人。让每个入口点例程成为一个 Sub,每个非入口点例程成为一个 Function。所有函数都返回一个指示错误状态的布尔值。所有错误都会冒泡到顶部。它运作得很好。
这里唯一的问题是 Application.Run 是否可以返回值。我刚刚查了一下,确实可以。
我强烈推荐这本书,但为了完整起见,我将他们推荐的模板放在下面。
希望有帮助。哦,如果您要在 Excel/VBA 中执行复杂的操作,请阅读 他们的书。
入口点例程
非入口点例程
中央错误处理例程
If you're doing your error handling in the way described in this book, then you should be fine.
Basically Bovey et al. give make every entry point routine a Sub and every non-entry point routine a Function. All functions return a boolean indicating the error status. All errors bubble up to the top. It works very well.
The only question here was whether or not Application.Run can return a value. I've just checked, and it can.
I strongly recommend the book, but for the sake of completeness, I've put the the templates they recommend below.
Hope that helps. Oh, and if you're going to be doing complex stuff in Excel/VBA, read their book.
Entry point routines
Non entry point routines
Central Error-Handling Routine