图表不会自动更新数据更改

希望这是一个容易的。 我在MS Excel中有一系列图表指向同一工作表上的数据。 工作表上的数据是使用VBA函数计算的。 当数据由VBA函数更新时,新数字不会反映在指向它们的图表中。 我试着调用Application.Calculate,但是这并没有办法。 有什么想法吗?


UDPATE:

我能够在更小的范围内复制这个问题。 就是这样:

  • 创build一个新的工作簿
  • 将Sheet 1重命名为“Summary”
  • 将Sheet 2重命名为“Data”
  • 在VBA编辑器中打开汇总表并粘贴以下代码:

    Private Sub Worksheet_Change(ByVal Target As Range) If Target.Parent.Range("worksheetDate") = Target Then Application.CalculateFull End If End Sub 
  • 创build一个新的VBA模块

  • 将下面的代码粘贴到新的VBA模块中(我道歉 – 我无法获得Stack Overflow来正确地为我的生活格式化 – 这是我能做到的最好的):

      Function getWeekValue (weekNumber As Integer, valuesRange As Range) As Integer Dim aCell As Range Dim currentDate As Date Dim arrayIndex As Integer Dim weekValues(1 To 6) As Integer currentDate = ThisWorkbook.Names("worksheetDate").RefersToRange.Value arrayIndex = 1 For Each aCell In valuesRange If month(currentDate) = month(ThisWorkbook.Sheets("Data").Cells( _ aCell.Row - 1, aCell.Column)) Then weekValues(arrayIndex) = aCell.Value arrayIndex = arrayIndex + 1 End If Next getWeekValue = weekValues(weekNumber) End Function 

  • 修改数据工作表以匹配以下图像:

替代文字

  • select单元格B1并命名范围“worksheetDate”
  • 在下图中复制第1到第3行:

替代文字

  • 在第4行的“第X周”标题下,input以下公式

  = getWeekValue(1, Data!$A$2:$M$2) 

每周将getWeekValue函数的第一个参数递增1(例如,第一周通过1,第二周,第三周,第三周等。

  • 使用单元格A3到E4作为数据创build一个条形图
  • 将单元格B2中的date更改为2010年10月1日到2010年12月31日之间的date,select除当前单元格中的月份以外的月份。 例如,如果date是12/11/2010,请将其更改为11/11/2010或10/11/2010之类的内容。 请注意数据和图表正确更新。
  • 修改单元格B2增益中的date。 请注意,数据更新,但图表不。

奇怪的是,经过一段时间(几分钟)后,图表最终更新。 我不知道是否这是因为我一直在执行触发更新的其他活动,或者因为Excel在几分钟后触发更新。

刚刚想出了解决这个问题的方法,就像我受到同样的困扰。

在打印或导出之前,我刚刚添加了“DoEvents()”,图表得到刷新。

 Sub a() Dim w As Worksheet Dim a Set w = Worksheets(1) For Each a In w.Range("a1:a5") a.Value = a.Value + 1 Next DoEvents End Sub 

例如:

 Sub a() Dim w As Worksheet Dim a Set w = Worksheets(1) For Each a In w.Range("a1:a5") a.Value = a.Value + 1 Next w.ChartObjects(1).Chart.Refresh End Sub 

替代文字

这个解决scheme为我工作。 对于有问题的工作表,请添加:

 Private Sub Worksheet_Activate() Dim rngSelection As Range Dim objChartObject As ChartObject Dim objChart As Chart Dim objSeriesCollection As SeriesCollection Dim objSeries As Series Dim strFormula As String Set rngSelection = Selection For Each objChartObject In Me.ChartObjects Set objChart = objChartObject.Chart Set objSeriesCollection = objChart.SeriesCollection For Each objSeries In objSeriesCollection strFormula = objSeries.Formula objSeries.Delete Set objSeries = objSeriesCollection.NewSeries objSeries.Formula = strFormula Next objSeries Next objChartObject rngSelection.Select End Sub 

在更改结束时,我closures了工作簿并重新打开。 这似乎是最简单和最可靠的方式来更新我的一切。

问题可能是getWeekValue的参数列表,它只包含星期编号和数据stream。

如果添加第三个参数worksheetDate,那么Excel的重新计算引擎将会在头部的一侧点击,而getWeekValue使用worksheetDate中保存的值。 在你当前的实现中,这个事实只能在VBA代码中进行,在这个代码中,重新计算引擎可能不可见。

我是这么写的,因为我不知道重新计算引擎的内部运作。 (也许有人知道这一点比我可以评论我的猜测更好)但是我做了一个testing,其中getWeekValue确实有第三个参数,并且图表正确地重新计算。 这个方法的好处是:你可以删除所有其他的VBA事件pipe理。 -HTH

我发现调用这个子工程…

 Sub DoAllEvents() DoEvents DoEvents End Sub 

微软警告说,在第一个DoEvents完成之前执行的下一个DoEvents会被捕获,这可能发生,这取决于调用之间没有延迟的频率。 因此,DoEvents似乎是一种非屏蔽中断,嵌套非屏蔽中断可能会导致机器出于多种原因而冻结,除了重启之外,没有任何恢复。

(注意:如果不经常调用上面的例程,嵌套可能不成问题。)

使用下面的Sub,我修改了他们的build议,防止这种情况发生。

 Sub DoAllEvents() On Error GoTo ErrorCheck Dim i For i = 1 To 4000 ' Start loop. Can be higher, MS sample shows 150000 'I've found twice is enough, but only increased it to four or 4000. If i Mod 1000 = 0 Then ' If loop has repeated 1000 times. DoEvents ' Yield to operating system. End If Next i Exit Sub ErrorCheck: Debug.Print "Error: "; Error, Err Resume Next End Sub 

我看来,所需的DoEvents数量是基于您的机器上运行的后台任务的数量,更新graphics似乎是应用程序的后台任务。 我只需要两个DoEvents,因为我经常调用这个例程。 不过,如果需要的话,我可能会稍后提高。 我也把Mod保持在1000,所以不要像微软那样改变每个DoEvents之间的延迟,防止嵌套。 如果您的系统不更新图表,可能需要将数字从2000增加到更高的数字。 增加此数字允许机器处理DoEvents可能遇到的大量后台事件,因为它们可能位于堆栈上,并且DoEvents事件只允许运行特定数量的周期,然后将其位置标记在堆栈中允许未处理的事件并返回,使它们在下一次调用中处理。 因此需要多次调用。 把它改成150000的例子似乎并不会让机器变得太慢,为了安全起见,你可能想把它变成150000。

注意:具有两个DoEvents的第一个示例Sub可能是安全的,具体取决于您调用Sub的频率,但是如果频繁调用,您的机器可能会冻结。 你的来电。 😉

PS:DoEvents将成为你最好的调用之一,如果你创build了大量的嵌套循环,并且程序没有像预期的那样工作。 幸运的是,这在所有使用VBA的应用程序中都可用!

只是一个想法:在您的Worksheet_Change Sub插入作为第一行:

 Application.EnableEvents = False 

为了避免自燃事件….
当然,在Sub的结尾处将其设置为True。