excel - 组合框仅在宏结束后显示值
问题描述
我有一个包含一些图表和许多组合框(activex 控件)的应用程序。当用户更改任何组合框的值时,图表都会更新。这里没问题。
所以,我编写了一个代码来将应用程序的整个屏幕导出为图像。这用于模拟几个场景。
但是,这里是问题开始的地方。
此代码中有一些“for...next”循环来更改这些组合框的值。导出图像时,图表会按预期更新,但组合框不会更改其值。它们在每种情况下都显示相同的值,即使图表正在更新。
所以,问题是:有没有办法在代码结束之前刷新组合框的值?
Sub example()
For Each elem In myArray
Sheets("App").ComboBox1.Value = elem
Sheets("Temp").Shapes.AddChart
Set cht = Sheets("Temp").ChartObjects(1)
Sheets("App").Range("A1:AM103").CopyPicture Appearance:=xlScreen, Format:=xlBitmap
With cht.Chart
.Paste
.export Filename:="test.jpg", FilterName:="jpg"
.Parent.Delete
End With
Next
End Sub
解决方案
解释
首先,恭喜:您在这里发现了一个非常烦人的错误。我试图重现你的问题,我可以很容易地做到这一点。
- 如果在更新组合框后设置断点(即线程暂停)=> ActiveX 组件被刷新
- 如果您设置一个
Application.Wait (TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 5))
(即您在视觉上停止执行 5 秒,但从技术上讲线程仍在运行)=> 您可以清楚地看到 ActiveX 组件没有更新,这就是您的图像生成错误的原因。
我已经尝试了所有明显的技巧(Application.ScreenUpdating = True
, DoEvents
,等) Application.EnableEvents = True
,Application.Calculate
但无论如何都没有成功。
似乎只有在 VBA 线程结束时,Microsoft Excel 才会刷新 ActiveX 组件。哇。
我能想到的解决这个错误的唯一方法
我能想到的在更新 ActiveX 组件后从技术上停止执行并稍后恢复它的唯一方法是使用Application.OnTime
Excel 的方法:
Application.OnTime
安排一个程序在未来的特定时间运行(在一天中的特定时间或经过特定时间量之后)。
对于从技术角度来看它看起来有多丑,您可以更新您的组合框,然后安排其余代码在您完成后一秒钟发生。从技术角度来看:
- VBA 线程 1:更新您的 ComboBox 并结束 => ActiveX 组件被刷新
- 没有 VBA 线程的 1 秒暂停。
- VBA 线程 2:使用更新的 ActiveX 组件创建图表并导出图像。
实际上,您的代码看起来像这样:
Dim myArray(2) 'declare your array as global so that it can be accessed by all the macros - in my example I assume it contains 3 elements
Dim currentElem As Integer 'declare this index as global so it remains in memory even after the code ended execution
Sub example()
'call this macro.
'you first initialize your values:
myArray(0) = "test 1"
myArray(1) = "test 2"
myArray(2) = "test 3"
currentElem = 0
'and then call the first update of your activeX component
first_step_set_activeX
End Sub
Sub first_step_set_activeX()
If currentElem < UBound(myArray) Then
'for each element not treated yet
'(that's why the If currentElem < UBound(myArray)
elem = myArray(currentElem) 'get current element from array
Sheets("App").ComboBox1.Value = elem 'update your ActiveX component
currentElem = currentElem + 1 'increase the currentElem index
Application.OnTime TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 1), "second_step_make_chart_and_print" 'schedule the call of the printing part
End If
End Sub
Sub second_step_make_chart_and_print()
'here do the job of the printing part
Sheets("Temp").Shapes.AddChart
Set cht = Sheets("Temp").ChartObjects(1)
Sheets("App").Range("A1:AM103").CopyPicture Appearance:=xlScreen, Format:=xlBitmap
With cht.Chart
.Paste
.Export Filename:="test.jpg", FilterName:="jpg"
.Parent.Delete
End With
'and reschedule the call for the next activeX component
Application.OnTime TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 1), "first_step_set_activeX"
End Sub
推荐阅读
- python - 如何在 VS Code 中更改 Python 版本
- angular - 反应式表单是围绕可观察的流构建的
- windows - 我们可以使用 NMAKE.EXE 作为 GNU Make 的替代品吗?
- c# - 使用 COM 互操作从 VSTO C# 列出现有 Access 实例的 MS Access 表
- android - 如何在 opentok Cordova 中的发布者视频顶部显示 HTML 按钮
- javascript - 如何使用复选框禁用使用 Javascript 的表单“月”输入?
- python - 轮询命令 discord.py
- javascript - 如何在单击时使用 Javascript 折叠部分?
- c - 如何将文本文件中的两行存储为两个字符串
- c# - C# 无法从我的导航中获取当前选择记录值