web-dev-qa-db-ja.com

データが変更されてもグラフは自動的に更新されません

うまくいけば、これは簡単なものです。同じワークシートのデータを指す一連のグラフがMSExcelにあります。ワークシートのデータは、VBA関数を使用して計算されます。データがVBA関数によって更新されると、新しい数値はそれらを指しているグラフに反映されません。 Application.Calculateを呼び出してみましたが、うまくいきませんでした。何かご意見は?


UDPATE:

私はこの問題をはるかに小さな規模で再現することができました。方法は次のとおりです。

  • 新しいブックを作成する
  • シート1の名前を「概要」に変更
  • シート2の名前を「データ」に変更
  • 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  
    

  • 次の画像に一致するようにデータワークシートを変更します。

alt text

  • セルB1を選択し、範囲に「worksheetDate」という名前を付けます
  • 次の画像の行1から3を複製します。

alt text

  • 行4の「第X週」ヘッダーの下に、次の数式を入力します

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

getWeekValue関数の最初の引数を週ごとに1つずつインクリメントします(たとえば、1週目に1を渡し、2週目に2を渡し、3週目に3を渡します。

  • セルA3からE4をデータとして使用して棒グラフを作成します
  • セルB2の日付を2010年10月1日から2010年12月31日までの日付に変更し、現在セルにある月以外の月を選択します。たとえば、日付が12/11/2010の場合は、11/11/2010または10/11/2010のように変更します。データとグラフの両方が正しく更新されることに注意してください。
  • セルB2ゲインの日付を変更します。データは更新されますが、グラフは更新されないことに注意してください。

奇妙なことに、一定期間(数分)が経過した後、チャートは最終的に更新されます。これは、更新をトリガーした他のアクティビティを実行しているためなのか、Excelが数分後に更新をトリガーしているためなのかわかりません。

11
Adam

変更が終了したら、ブックを閉じて再度開きます。それは私にとってすべてを更新するための最も簡単で信頼できる方法のようです。

1
TmTron

私は同じ問題に苦しんでいたので、ちょうどこの問題の解決策を見つけました。

印刷またはエクスポートする前に「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  
1
Ageel Al-Shayeb

このサブを呼び出すとうまくいくことがわかりました...

Sub DoAllEvents()
    DoEvents
    DoEvents
End Sub

[〜#〜] but [〜#〜] Microsoftは、最初のDoEventsが完了する前に、次のDoEventsの実行に巻き込まれることについて警告しています。したがって、DoEventsはマスク不可割り込みの一種として機能しているように見え、マスク不可割り込みをネストするとすると、他の回復なしに複数の理由でマシンがフリーズする可能性があります。再起動するより。

(注:上記のルーチンを頻繁かつ迅速に呼び出さない場合、ネストは問題にならない可能性があります。)

私が彼らの提案から修正した以下のサブを使用すると、これが起こるのを防ぎます。

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

必要なDoEventの数は、マシンで実行されているバックグラウンドタスクの数に基づいているようです。グラフの更新は、アプリケーションのバックグラウンドタスクのようです。ルーチンを頻繁に呼び出すため、必要なDoEventは2つだけです。ただし、必要に応じて後でそれを上げることになるかもしれません。また、Microsoftが提案するように、各DoEvent間のラグを変更しないように、Modを1000に維持して、ネストを防ぎます。数値を2000からより高い数値に増やしたい理由の1つは、システムがグラフを更新しない場合です。この数を増やすと、マシンは、DoEventsがおそらくスタック上にあるため、複数の呼び出しを通じて発生する可能性のある多数のバックグラウンドイベントを処理できます。また、DoEventsイベントは、スタック内の場所をマークする前に、特定のサイクル数のみ実行できます。未処理のイベントと戻りを許可し、次の呼び出しで処理されるようにします。したがって、複数の呼び出しが必要です。これを150000の例に変更しても、マシンの速度がそれほど遅くなることはないようです。安全にプレイするには、150000にすることをお勧めします。

注:2つのDoEventを持つ最初の例のSubは、Subを呼び出す頻度によってはおそらく安全ですが、頻繁に呼び出すと、マシンがフリーズする可能性があります。あなたの呼び出し。 ;-)

PS:ネストされたループをたくさん作成し、プログラムが期待どおりに動作しない場合、DoEventsは最良の呼び出しの1つになります。幸い、これはVBAを使用するすべてのアプリで利用できます。

0
Cyberchipz

この解決策は私のために働いた。問題のあるワークシートに次を追加します。

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
0
SLeepdepD

例えば:

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  

alt text

0
Dr. belisarius

問題は、週番号とデータストリームのみを含むgetWeekValueの引数リストである可能性があります。

3番目の引数worksheetDateを追加すると、getWeekValueがworksheetDateに保持されている値を使用するという事実により、Excelの再計算エンジンが頭の側面でヒットします。現在の実装では、この事実はVBAコードでのみ保持されており、再計算エンジンからはおそらく見えません。

私は再計算エンジンの内部動作に精通していないので、これを非常に慎重に書いています。 (おそらく、私の推測についてコメントするよりも、これについてよく知っている人がいます)しかし、getWeekValueに3番目の引数があり、グラフが適切に再計算されるテストを実行しました。このアプローチの優れた追加の利点:他のすべてのVBAイベント管理を削除できます。 -HTH

0
user3716832

Excel2019を実行しています。

マクロコードに以下を追加しました。

ActiveSheet.ChartObjects(1).Chart.Refresh    
DoEvents

マクロの実行中にチャートが更新されるようになりました

0
Drkhrse