[英]Charts Do Not Automatically Update When Data Changes
希望這是一個容易的。 我在 MS Excel 中有一系列圖表,它們指向同一工作表上的數據。 工作表上的數據是使用 VBA 函數計算的。 當 VBA 函數更新數據時,新數字不會反映在指向它們的圖表中。 我嘗試調用 Application.Calculate,但這並沒有奏效。 有什么想法嗎?
UDPATE:
我能夠以更小的規模復制這個問題。 方法如下:
在 VBA 編輯器中打開摘要表並粘貼以下代碼:
Private Sub Worksheet_Change(ByVal Target As Range) If Target.Parent.Range("worksheetDate") = Target Then Application.CalculateFull End If End Sub
創建一個新的 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
.
修改數據工作表以匹配下圖:
.
= getWeekValue(1, Data!$A$2:$M$2)
每周將 getWeekValue 函數的第一個參數遞增 1(例如,第 1 周傳遞 1,第 2、3 周傳遞 2,第 3 周傳遞,等等。
奇怪的是,經過一段時間(幾分鍾)后,圖表終於更新了。 我不確定這是因為我一直在執行觸發更新的其他活動,還是因為 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
在更改結束時,我關閉工作簿並重新打開它。 這對我來說似乎是更新所有內容的最簡單和最可靠的方法。
這個解決方案對我有用。 對於違規工作表添加:
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
問題可能出在 getWeekValue 的參數列表上,它只包含周數和數據流。
如果您添加第三個參數 worksheetDate,則 Excel 的重新計算引擎將在頭部一側受到影響,因為 getWeekValue 使用了 worksheetDate 中保存的值。 在您當前的實現中,此事實僅存在於 VBA 代碼中,在該代碼中,重新計算引擎可能看不到它。
我寫這篇文章是因為我不了解重新計算引擎的內部工作原理。 (也許有人比我對我的猜測更了解這一點)但我確實做了一個測試,其中 getWeekValue 確實有第三個參數,並且圖表確實重新計算正確。 這種方法的額外好處是:您可以刪除所有其他 VBA 事件管理。 -HTH
例如:
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
我發現調用這個 Sub 有效......
Sub DoAllEvents()
DoEvents
DoEvents
End Sub
但是微軟警告不要在第一個 DoEvents 完成之前被下一個 DoEvents 捕獲,這可能會發生,這取決於它在調用之間沒有延遲的情況下被調用的頻率。 因此,DoEvents 似乎充當了一種不可屏蔽的中斷,嵌套不可屏蔽的中斷會導致機器由於多種原因而凍結,除了重新啟動之外沒有任何恢復。
(注意:如果沒有經常快速地調用上面的例程,嵌套可能不是問題。)
使用下面的 Sub ,我根據他們的建議進行了修改,可以防止這種情況發生。
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 數量取決於您的機器上運行的后台任務的數量,更新圖表似乎是應用程序的后台任務。 我只需要兩個 DoEvents,因為我經常調用例程; 但是,如果需要,我可能會在稍后結束它。 我還將 Mod 保持在 1000,這樣就不會像 Microsoft 建議的那樣更改每個 DoEvents 之間的延遲,從而防止嵌套。 您可能希望將數字從 2000 增加到更高的一個可能原因是您的系統沒有更新圖表。 增加這個數字允許機器處理 DoEvents 可能通過多次調用遇到的大量后台事件,因為它們可能在一個堆棧上,並且 DoEvents 事件在標記它在堆棧中的位置之前只允許運行特定數量的周期允許未處理的事件並返回,讓它們在下一次調用時處理。 因此需要多次調用。 將其更改為 150000 的示例似乎不會使機器變慢太多,為了安全起見,您可能希望將其設為 150000。
注意:第一個帶有兩個 DoEvent 的示例 Sub 可能是安全的,具體取決於您調用 Sub 的頻率,但是,如果調用太頻繁,您的機器可能會死機。 您的來電。 ;-)
PS:如果你創建了很多嵌套循環並且程序沒有按預期運行,DoEvents 將成為你最好的調用之一。 幸運的是,這適用於所有使用 VBA 的應用程序!
運行 Excel 2019。
在宏代碼中添加了以下內容:
ActiveSheet.ChartObjects(1).Chart.Refresh
DoEvents
圖表現在在宏執行期間更新
UDF getWeekValue必須標記為 volatile。
Function getWeekValue (weekNumber As Integer, valuesRange As Range) As Integer
Application.Volatile '!!
Dim aCell As Range
Dim currentDate As Date
'...
只是一個想法:在您的 Worksheet_Change Sub 中,作為第一行插入:
Application.EnableEvents = False
為了避免自發事件......
當然,在 Sub 結束時將其設置回 True。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.