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