组合框仅在宏结束后显示值

时间:2019-04-13 22:04:22

标签: excel vba combobox

我有一个带有一些图表和许多组合框(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

1 个答案:

答案 0 :(得分:1)

说明

首先,恭喜:您在这里发现了一个非常烦人的错误。 我已经尝试过重现您的问题,并且我可以非常轻松地完成。

  • 如果您在更新组合框后设置了断点(即线程已暂停)=> ActiveX组件将刷新
  • 如果您设置Application.Wait (TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 5))(即,您在视觉上停止执行5秒钟,但从技术上讲该线程仍在运行)=>您可以清楚地看到ActiveX组件没有得到更新,这就是您的图像的原因是错误生成的。

我尝试了所有显而易见的技巧(Application.ScreenUpdating = TrueDoEventsApplication.EnableEvents = TrueApplication.Calculate等),但无论如何都没有成功。

实际上,似乎只有在VBA线程结束时,Microsoft Excel才会刷新ActiveX组件。哇。

我能想到的解决此错误的唯一方法

在更新ActiveX组件后,我想到的唯一的方法是 停止执行,并在以后恢复执行,那就是使用Excel的Application.OnTime方法:

  

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