Chart creep on Userforms

Linus_99

Board Regular
Joined
Aug 28, 2002
Messages
145
Hi,

I have been using a number of charts on Userforms by exporting the charts as GIF images and then displaying them on a Userform as an image. This all works fine.

However, some of the charts (especially pie charts) seem to change their size when they are refreshed with different data. The overall chart stays the same size, but the plot area generally seems to decrease every time the chart is refreshed.

Any ideas on how to avoid this ? Thanks.
 

Excel Facts

Create a chart in one keystroke
Select the data and press Alt+F1 to insert a default chart. You can change the default chart to any chart type

RogerC

Well-known Member
Joined
Mar 25, 2002
Messages
533
Hi Linus_99, I'm having the same problem with charts on a UserForm. Did you ever find a solution?
This message was edited by RogerC on 2002-12-09 12:01
 

mjbeam

Well-known Member
Joined
Apr 6, 2002
Messages
756
I can't reproduce the problem. I put a chart on a userform, then added a button. When the button is clicked it changes the source data for the chart, copies the updated chart to a GIF and reloads the GIF to the image control. I am not seeing the plot area change sizes.

-Mike
 

Linus_99

Board Regular
Joined
Aug 28, 2002
Messages
145
Still happening, & I haven't found a solution that works.

The only clue is that when I first generate the chart, the contents are at one size, & every other time I generate the chart from the same form, the contents are at the second size. Generally, the second size has a larger plot area than the first size.

However, I'm using some code to try & stop the problem. My application uses a number of chart types, & for each type, I call a sub to try to manage the size.

For example, the sub for a rectangular chart is:

------------------------------------------
Sub set_rectangle()

With currentchart.Legend
.Top = 24
.Left = 40
End With

With currentchart.PlotArea
.Width = 440
.Height = 260
.Top = 50
.Left = 50
End With

End Sub
---------------------------------------

The code is executed before every appearance of the chart, so I don't know why the first display is different to every other display.

Cheers (& still clueless on this one) . . .
 

mjbeam

Well-known Member
Joined
Apr 6, 2002
Messages
756

ADVERTISEMENT

Are you refreshing the charts with different data or are you creating new charts?

-Mike
 

Linus_99

Board Regular
Joined
Aug 28, 2002
Messages
145
Same data. Each chart does not change between viewings.

On the form I have a chart viewer, with a list box that lists all the available charts that can be viewed. [Each chart shows a different type of result from a simulator].

When the user wants to see a particular chart, they click on a list item. The selected chart is then exported to a file "temp.gif" & then that gif image is shown as a picture on the form.
 

brettvba

MrExcel MVP
Joined
Feb 18, 2002
Messages
1,030
Try the following to display a chart as an image on a userform

in a userform put

Private Sub UserForm_Initialize()
ActiveSheet.Shapes("Chart 1").CopyPicture ' needs to be modified for your needs
Me.Image1.Picture = PastePicture
End Sub

in a module put

Option Explicit
Option Compare Text

''' User-Defined Types for API Calls

'Declare a UDT to store a GUID for the IPicture OLE Interface
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type

'Declare a UDT to store the bitmap information
Private Type uPicDesc
Size As Long
Type As Long
hPic As Long
hPal As Long
End Type

'''Windows API Function Declarations

'Does the clipboard contain a bitmap/metafile?
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Integer) As Long

'Open the clipboard to read
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long

'Get a pointer to the bitmap/metafile
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Integer) As Long

'Close the clipboard
Private Declare Function CloseClipboard Lib "user32" () As Long

'Convert the handle into an OLE IPicture interface.
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As uPicDesc, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long

'Create our own copy of the metafile, so it doesn't get wiped out by subsequent clipboard updates.
Declare Function CopyEnhMetaFile Lib "gdi32" Alias "CopyEnhMetaFileA" (ByVal hemfSrc As Long, ByVal lpszFile As String) As Long

'Create our own copy of the bitmap, so it doesn't get wiped out by subsequent clipboard updates.
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

'The API format types we're interested in
Const CF_BITMAP = 2
Const CF_PALETTE = 9
Const CF_ENHMETAFILE = 14
Const IMAGE_BITMAP = 0
Const LR_COPYRETURNORG = &H4

Function PastePicture(Optional lXlPicType As Long = xlPicture) As IPicture

'Some pointers
Dim h As Long, hPicAvail As Long, hPtr As Long, hPal As Long, lPicType As Long, hCopy As Long

'Convert the type of picture requested from the xl constant to the API constant
lPicType = IIf(lXlPicType = xlBitmap, CF_BITMAP, CF_ENHMETAFILE)

'Check if the clipboard contains the required format
hPicAvail = IsClipboardFormatAvailable(lPicType)

If hPicAvail <> 0 Then
'Get access to the clipboard
h = OpenClipboard(0&)

If h > 0 Then
'Get a handle to the image data
hPtr = GetClipboardData(lPicType)

'Create our own copy of the image on the clipboard, in the appropriate format.
If lPicType = CF_BITMAP Then
hCopy = CopyImage(hPtr, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG)
Else
hCopy = CopyEnhMetaFile(hPtr, vbNullString)
End If

'Release the clipboard to other programs
h = CloseClipboard

'If we got a handle to the image, convert it into a Picture object and return it
If hPtr <> 0 Then Set PastePicture = CreatePicture(hCopy, 0, lPicType)
End If
End If

End Function


''' Requires a reference to the "OLE Automation" type library


Private Function CreatePicture(ByVal hPic As Long, ByVal hPal As Long, ByVal lPicType) As IPicture

' IPicture requires a reference to "OLE Automation"
Dim r As Long, uPicInfo As uPicDesc, IID_IDispatch As GUID, IPic As IPicture

'OLE Picture types
Const PICTYPE_BITMAP = 1
Const PICTYPE_ENHMETAFILE = 4

' Create the Interface GUID (for the IPicture interface)
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

' Fill uPicInfo with necessary parts.
With uPicInfo
.Size = Len(uPicInfo) ' Length of structure.
.Type = IIf(lPicType = CF_BITMAP, PICTYPE_BITMAP, PICTYPE_ENHMETAFILE) ' Type of Picture
.hPic = hPic ' Handle to image.
.hPal = IIf(lPicType = CF_BITMAP, hPal, 0) ' Handle to palette (if bitmap).
End With

' Create the Picture object.
r = OleCreatePictureIndirect(uPicInfo, IID_IDispatch, True, IPic)

' If an error occured, show the description
If r <> 0 Then Debug.Print "Create Picture: " & fnOLEError(r)

' Return the new Picture object.
Set CreatePicture = IPic

End Function

Brett
 

Linus_99

Board Regular
Joined
Aug 28, 2002
Messages
145
I've been using . . . .
---------------------------------------------
Set currentchart = Sheets("Shifts").ChartObjects(3).Chart
currentchart.Parent.Width = 360
currentchart.Parent.Height = 170
currentchart.PlotArea.Width = 330
currentchart.PlotArea.Height = 160

' Save chart as GIF
fname = ThisWorkbook.Path & Application.PathSeparator & "temp.gif"
currentchart.Export Filename:=fname, FilterName:="GIF"

' Show the chart
ClockForm.Image1.Picture = LoadPicture(fname)

----------------------------------------------

What extra things does Brett's listing do ??
 

Forum statistics

Threads
1,143,640
Messages
5,719,985
Members
422,256
Latest member
downeybm

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Top