• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VBAでリアルタイムで計算結果をグラフに表示)

VBAでリアルタイムで計算結果をグラフに表示する方法

このQ&Aのポイント
  • Excel2010でVBAを使っています。30分くらいかかる計算があるのですが、計算が終了するまで待っていたのでは、計算結果がどのようなものになるのか分からないためリアルタイムで計算結果をグラフに表示してくれるプログラムを書きたいと考えています。
  • VBA上でユーザーフォーム上でグラフを表示させることはできないようです。しかし、シート上でのグラフを画像として表示させることは可能です。その方法は、計算結果が更新される度にシート上のグラフをキャプチャし、画像として表示するというものです。
  • 以下の方法でリアルタイムで計算結果を表示させることができます。1. VBAで計算処理を行う2. 計算結果が更新される度にシート上のグラフをキャプチャする3. キャプチャした画像を別のシートに貼り付ける4. 貼り付けた画像を表示する5. 一定の時間をおいて2~4の処理を繰り返す

質問者が選んだベストアンサー

  • ベストアンサー
  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.4

#3です。 下記の様なコードで普通にグラフは書き換わりますので、何が問題なのかわかりかねます。 ☆ワークシートモジュールに記載、コマンドボタンを2個もうけている。 Dim stopFlag As Boolean Private Sub CommandButton1_Click() Dim i As Long Dim j As Double stopFlag = False i = 1 Do While Not stopFlag j = i ^ 2 + 3 * i + 4   ’グラフのデータ範囲のセル一個だけ変更している Me.Range("B3").Value = j i = i + 1 DoEvents: DoEvents: DoEvents Loop End Sub Private Sub CommandButton2_Click() stopFlag = True End Sub

MOUIIKAO
質問者

お礼

ありがとうございます。 簡単なプログラムだとリアルタイムでグラフを更新されることに気がつきました。 いま少し複雑なプログラムを書いているのですが このプログラムだとなぜか更新されません。 Do eventsとなっているところを DoEvents: DoEvents: DoEvents にしたり、 Application.Wait [Now() + "0:00:00.1"] を書いてタイムラグを発生させたりすると リアルタイムで更新されるようになりました。 Do eventsと DoEvents: DoEvents: DoEvents って何が異なるのでしょうか?

すると、全ての回答が全文表示されます。

その他の回答 (4)

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.5

#4です 理由は存じませんが、(検索してみても、経験談くらいしか見つからないのですが) xl2010になってから(VBA7になってから?) 従来は一個で十分であったDoEventsが、3回以上続けないと思うように機能しない様です。

すると、全ての回答が全文表示されます。
  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.3

#2です。お役に立つかどうか分かりませんが、「シート上のグラフを画像として表示する」の応用編です。 ファイルを介さずメモリ上で処理します。xl2010でグラフをCopyすると、Picture Objectもクリップボード内にあるのですが、直接取り出す方法が大分探しましたが見つけられませんでした。BitmapもしくはEMFからPictureに変換しています。 Userformに、Imageコントロールと、CommandButton2個を置いています ☆UserForm1モジュール Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Dim stopFlag As Boolean Private Sub UserForm_Initialize() Me.Image1.PictureSizeMode = fmPictureSizeModeStretch End Sub Private Sub CommandButton1_Click() Dim i As Long stopFlag = False i = 1 Do While Not stopFlag '単に既存のグラフの範囲のセル一個の値を変更しているだけ(すなわち単純な状況でしか試験してないです)   'この代わりに計算結果をセルに入れれば良いと思いますが、毎回セルにアクセスすると遅くなると思いますので、   '1000回毎にとかにする方が良いと思います。 Sheets(1).Range("C7").Value = i i = i + 1 Sheets(1).ChartObjects(1).Copy Me.Image1.Picture = PastePicture   ’今回の課題ではCPU100%占有しても良さそうなので入れなくても可 Sleep 10 DoEvents: DoEvents: DoEvents Loop End Sub Private Sub CommandButton2_Click() stopFlag = True End Sub ☆標準モジュール Private Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(0 To 7) As Byte End Type Private Type uPicDesc Size As Long Type As Long hPic As Long hPal As Long End Type Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long Private Declare Function CloseClipboard Lib "user32" () As Long Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long Declare Function CopyImage Lib "user32" (ByVal handle As Long, ByVal un1 As Long, ByVal n1 As Long, ByVal n2 As Long, ByVal un2 As Long) As Long Const CF_BITMAP = 2 Const CF_PALETTE = 9 Const CF_ENHMETAFILE = 14 Const IMAGE_BITMAP = 0 Const LR_COPYRETURNORG = &H4 'メインルーチンはこれだけ Sub test() UserForm1.Show End Sub Function PastePicture(Optional lXlPicType As Long = xlPicture) As IPicture Dim h As Long, hPicAvail As Long, hPtr As Long, hPal As Long, lPicType As Long, hCopy As Long lPicType = IIf(lXlPicType = xlBitmap, CF_BITMAP, CF_ENHMETAFILE) hPicAvail = IsClipboardFormatAvailable(lPicType) If hPicAvail <> 0 Then h = OpenClipboard(0&) If h > 0 Then hPtr = GetClipboardData(lPicType) If lPicType = CF_BITMAP Then hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG) Else hCopy = CopyEnhMetaFile(hPtr, vbNullString) End If h = CloseClipboard If hPtr <> 0 Then Set PastePicture = CreatePicture(hCopy, 0, lPicType) End If End If End Function Private Function CreatePicture(ByVal hPic As Long, ByVal hPal As Long, ByVal lPicType) As IPicture Dim r As Long, uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPicture Const PICTYPE_BITMAP = 1 Const PICTYPE_ENHMETAFILE = 4 With IID_IDispatch .Data1 = &H7BF80980 .Data2 = &HBF32 .Data3 = &H101A .Data4(0) = &H8B .Data4(1) = &HBB .Data4(2) = &H0 .Data4(3) = &HAA .Data4(4) = &H0 .Data4(5) = &H30 .Data4(6) = &HC .Data4(7) = &HAB End With With uPicInfo .Size = Len(uPicInfo) .Type = IIf(lPicType = CF_BITMAP, PICTYPE_BITMAP, PICTYPE_ENHMETAFILE) .hPic = hPic .hPal = IIf(lPicType = CF_BITMAP, hPal, 0) End With r = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, IPic) If r <> 0 Then MsgBox "Create Picture Error" Set CreatePicture = IPic End Function

MOUIIKAO
質問者

お礼

丁寧なご回答ありがとうございます。 しかしながら、難しすぎて私には手に負えないと思います。 代替案なのですが、 シート上に存在するグラフをリアルタイムで更新することはできないのでしょうか? Doeventsを実行することで一瞬だけWindowsの制御をactiveにするわけですが グラフの更新も同時にactiveにすることってできないのでしょうか?

すると、全ての回答が全文表示されます。
  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.2

UserFormに自前で描画するご参考になるかもしれません。 http://okwave.jp/qa/q7331192.html 昔々C言語でWindowsの基本的な機能で描画していた頃と同じ事をVBAでやろうという事なので面倒臭いです。 http://www.kumei.ne.jp/c_lang/sdk/sdk_23.htm

すると、全ての回答が全文表示されます。
  • nda23
  • ベストアンサー率54% (777/1416)
回答No.1

>ユーザフォーム ということはExcelでしょうか? 安直なのはStatusBarを使う方法があります。 表示:Application.StatusBar = String(10, "□") 消去:Application.StatusBar = False 左から■を増やしていくとか・・・ これはDoEventsをやらないでも表示が変わる ので、安全な処理です。 その他、プログレスバーコントロールや、 グラフ系の処理は全てウィンドウの メッセージを処理するため、計算処理の スレッドが走っている間はメッセージが 処理されないので、画面は変化しません。 これを処理させるには描画毎にDoEventsを 実行します。 ただ、このステートメントは全てのイベントを 拾うので、画面を閉じる操作も受け付けます。 処理中にバッタリ画面が閉じても問題が無い というなら良いのですが、そうでない場合は 制御が面倒です。

MOUIIKAO
質問者

お礼

計算結果というのは、計算過程を表示したいという意味ではなく http://www.johoka.net/vbsin02.gif のような計算した結果を表示したいという意味です。

すると、全ての回答が全文表示されます。

関連するQ&A