我有一个带有一些图表和许多组合框(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
答案 0 :(得分:1)
首先,恭喜:您在这里发现了一个非常烦人的错误。 我已经尝试过重现您的问题,并且我可以非常轻松地完成。
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组件后,我想到的唯一的方法是 停止执行,并在以后恢复执行,那就是使用Excel的Application.OnTime
方法:
Application.OnTime
安排一个程序在将来的指定时间(在一天中的特定时间或经过特定时间后)运行。
从技术角度看,它看上去有多丑,您可以更新组合框,然后计划其余代码在执行后再进行一秒钟。从技术角度来看:
实际上,您的代码如下所示:
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