如何使用 Excel VBA 2010 中的消息泵?

发布于 2024-09-30 14:19:26 字数 241 浏览 0 评论 0原文

我有一个需要很长时间的 Excel 宏。当我让 Excel 无人看管时,它似乎会崩溃(我在任务栏中收到一条“无响应”消息),但如果我设置一个每五秒或十秒命中的断点,那就没问题了。问题是,我需要从断点处执行大约 25 万次(我们正在考虑大约 200 小时来执行这个野兽)

我猜测消息泵活动的缺乏正在与内核对抗,那么我该如何刷新消息队列呢?或者我完全找错了树?

顺便说一句,我对此很陌生,因此非常欢迎文档参考。

干杯, 盖伊

I have an Excel macro that takes an exceedingly long time. It seems to crash Excel (I get a Not Responding message in the taskbar) when I leave it unattended, but if I put a breakpoint that gets hit every five or ten seconds, it's OK. Trouble is, I'll need to step on from the breakpoint about a quarter of a million times (we're looking at about 200 hours to execute this beast)

I'm guessing that the absence of message pump activity is antagonising the kernel, so how might I flush the message queue? Or am I barking up the wrong tree entirely?

I'm very new to this, by the way, so documentation references will be very welcome.

Cheers,
Guy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

醉态萌生 2024-10-07 14:19:26

Seconding the opinion that 200h is a bit worrying, however you can try the DoEvents statement which "surrenders execution of the macro so that the operating system can process other events". (Note that calling DoEvents has an additional time penalty)

木森分化 2024-10-07 14:19:26

我必须同意 0xA3,如果您有一个 excel 例程预计需要超过 200 小时才能运行,那么您要么以非常低效的方式设置它,要么使用了错误的方法这项工作的工具。

无论如何,您可以采取一些措施来优化日常工作。如果您不断向单个单元格写入值,这些将特别有用。

Sub MarathonCalc

    Application.EnableEvents = False
    Application.ScreenUpdating = False

    ' Code to decode human genome goes here

    Application.EnableEvents = True
    Application.ScreenUpdating = True

End Sub

同样,如果您发布一些代码,也许我们可以帮助找出为什么需要这么长时间。

I have to agree with 0xA3, if you have an excel routine that is expected to take over 200 hours to run then you're either setting it up in a very inefficient manner or you're using the wrong tool for this job.

In any case, there are a few things you can do to optimize the routine. These will be especially helpful if you are constantly writing values to individual cells.

Sub MarathonCalc

    Application.EnableEvents = False
    Application.ScreenUpdating = False

    ' Code to decode human genome goes here

    Application.EnableEvents = True
    Application.ScreenUpdating = True

End Sub

Again, if you post some of your code perhaps we can help track down why it's taking so long.

逆光下的微笑 2024-10-07 14:19:26

“没有响应”并不意味着 Excel 崩溃了,它只是意味着它实际上没有响应窗口消息。

除非这是一个问题,否则您无需担心。我很担心你的评论,你预计任务需要 200 小时(超过一周!)。在我看来,您没有使用正确的工具来完成这项工作。试着找出是什么花了这么长时间,并解释一下你实际上在做什么。然后我们就可以看看如何更好地解决这个任务。

"Not responding" doesn't mean that Excel is crashing, it simply means that it does not actually respond to window messages.

Unless that is a problem there is nothing you need to worry about. I'm rather worried about your comment that you expect the task to take 200h (which is more than a week!). It seems to me that you are not using the right tool for this job. Try to find out what is taking so long and explain what you are actually doing. Then we can see how to better solve this task.

握住我的手 2024-10-07 14:19:26

前面的答案已经为您提供了“DoEvents”,这是解决您的问题的第一线方法。

然而……仔细观察正在发生的事情会引发一些令人担忧的问题。首先,Excel 的线程模型相当原始:只有一个进程(根据文档),内部或外部生成的事件、回调和消息不会创建新线程。一个进程,并且只有一个进程,其他一切都必须等到当前的 VBA 宏或电子表格计算运行完成。

实际上,有些事情可能会中断此操作:{esc} 和 {ctrl-break}(尽管可以暂时禁用它们),因此 Excel 中至少有一个其他线程一直在运行,并且您会期望操作系统允许闯入一个进程...不是吗?

丑陋的现实是,当宏或计算运行时,Excel 应用程序不允许外部事件和消息运行到“事件接收器”,除非您调用“DoEvents”,并且某些 Windows 消息(注意大小写)仍然不会予以处理。

如果未记录的数量的消息和外部事件仍然存在,应用程序将会崩溃。根据我自己的测试,我认为这个数字是50;有关于注册表设置的文档,但我没有链接到我认为不可靠的材料 - 我已经尝试了相关设置,发现它无效。

那么你会怎样呢?

首先,再次查看您的代码。 Application.EnableEvents = False 和 Application.ScreenUpdating = False 是有用的设置:下一步是查找对工作表上各个单元格的所有读取或写入操作,然后仅获取单元格数组 - 使用以下命令获取数组要快得多myVBAarray=Range.Value,在 VBA 中进行计算,并将 VBA 数组变体写回 Range.Value。

其次...您还看到断点施加的“等待”状态允许某些事情自行解决。这听起来像是一个异步运行的外部进程(数据库查询?):导致 Excel 崩溃的消息或事件是否来自该进程?

The previous answers have given you 'DoEvents' and that's the first-line fix for your problem.

However... A closer look at what's happening raises some worrying questions. Firstly, Excel's threading model is rather primitive: there's one process (according to the documentation) and no new threads are created by internally- or externally-generated events, callbacks and messages. One process, and one process ONLY, and everything else has to wait until the current VBA macro or spreadsheet calculation runs to completion.

Actually, some things can interrupt this: {esc} and {ctrl-break} (although these can be temporarily disabled), so there's at least one other thread running in Excel all the time, and you'd EXPECT the operating system to be allowed to break into a process... Wouldn't you?

The ugly reality is that the Excel application does not allow external events and messages to run to an 'event sink' while a macro or calculation is running, unless you call 'DoEvents' and some Windows Messages (note the capitalisation) still won't be dealt with.

If an undocumented number of messages and external events are left hanging around, the application will crash. Based on my own tests, I think the number is 50; there's documentation about a registry setting out there, but I'm not linking to material that I consider unreliable - I've tried the setting in question and found it to be ineffective.

So where does that leave you?

Firstly, look at your code again. Application.EnableEvents = False and Application.ScreenUpdating = False are useful settings: your next step is to find all and every read- or write operation to individual cells on the sheet and just grab arrays of cells - it's much faster to grab an array using myVBAarray=Range.Value, do your calculations in VBA, and write the VBA array variant back to Range.Value.

Secondly... You've also seen that the 'wait' state imposed by a breakpoint allows some things to sort themselves out. That sounds like an external process (a database query?) running asynchronously: could it be that the message or event which is crashing Excel is coming from that very process?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文