I am trying to create some buttons dynamically, and assign code to them.
The following code works
Dim MyR As Range, MyB As OLEObject
Dim MyR_T As Long, MyR_L As Long
Set MyR = Cells(i + 1, 11) 'just an example - you get that from your own script
MyR_T = MyR.Top 'capture positions
MyR_L = MyR.Left '...
'create button
Set MyB = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False, DisplayAsIcon:=False)
'set main button properties
With MyB
.Name = "MyPrecodedButton" 'important - code must exist ... see below
.Object.Caption = "MyCaption"
.Top = MyR_T
.Left = MyR_L
.Width = 50
.Height = 18
.Placement = xlMoveAndSize
.PrintObject = True 'or false as per your taste
End With
It creates the buttons within my loop. However, I want to assign something to the on click, so I use the following code
Dim MyR As Range, MyB As OLEObject
Dim MyR_T As Long, MyR_L As Long
Set MyR = Cells(i + 1, 11) 'just an example - you get that from your own script
MyR_T = MyR.Top 'capture positions
MyR_L = MyR.Left '...
'create button
Set MyB = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Link:=False, DisplayAsIcon:=False)
'set main button properties
With MyB
.OnAction = "interpHere"
.Name = "MyPrecodedButton" 'important - code must exist ... see below
.Object.Caption = "MyCaption"
.Top = MyR_T
.Left = MyR_L
.Width = 50
.Height = 18
.Placement = xlMoveAndSize
.PrintObject = True 'or false as per your taste
End With
Sub interpHere()
MsgBox "hi"
End Sub
I have basically added .OnAction = "interpHere" but when I run it, I get an error, unable to set the onaction property.
Where am I going wrong?
try this code
Sub CreateButtons()
Dim btn As Button
ActiveSheet.Buttons.Delete
Dim t As Range
For i = 2 To 6 Step 2
Set t = ActiveSheet.Cells(i, 3)
Set btn = ActiveSheet.Buttons.Add(t.Left, t.Top, t.Width, t.Height)
With btn
.OnAction = "interpHere"
.Caption = "Btn " & i
.Name = "Btn" & i
End With
Next i
End Sub
Sub interpHere()
MsgBox "hi"
End Sub
Related
I have the following code to insert multiple images in selected range:
Private Sub CommandButton1_Click()
Dim sPicture, PhotoCell() As Variant, pic As shape
Dim PictCell As Range
Dim fname As String
Dim I, x As Integer
ActiveSheet.Unprotect Password:="123"
On Error Resume Next
PhotoCell() = Array("K6:P17", "A19:D29", "L19:P29", "A30:D40", "L30:P40", "A41:D51", "L41:P51")
sPicture = Application.GetOpenFilename _
("Pictures (*.jpeg; *.gif; *.jpg; *.bmp; *.tif; *.png), *.jpeg; *.gif; *.jpg; *.bmp; *.tif", 0, "Select Photo", "OK", True)
x = 0
If IsArray(sPicture) Then
For I = LBound(sPicture) To UBound(sPicture)
fname = sPicture(I)
If I Mod 2 = 1 Then
Set PictCell = ActiveSheet.Range(PhotoCell(x))
x = x + 1
Else
Set PictCell = ActiveSheet.Range(PhotoCell(x))
x = x + 1
End If
Set pic = ActiveSheet.Shapes.AddPicture(fname, msoFalse, msoCTrue, 0, 0, 100, 100)
pic.Delete
With pic
.LockAspectRatio = msoFalse
.Height = PictCell.Height
.Width = PictCell.Width
.Top = PictCell.Top
.Left = PictCell.Left
.Placement = xlMoveAndSize
End With
Set pic = Nothing
Next I
ActiveSheet.Protect Password:="123"
Else
MsgBox "No Picture Selected"
End If
End Sub
however, I have lost all image objects when inserting this command
pic.Delete
so actually I want to replace the old image in the selected range with the new image and make sure that the old image is completely deleted.
Try something like this:
Private Sub CommandButton1_Click()
Const PW As String = "123"
Dim sPictures, sPic, PhotoCell() As Variant, pic As Shape
Dim PictCell As Range
Dim fname As String
Dim x As Long, ws As Worksheet
Set ws = ActiveSheet
PhotoCell() = Array("K6:P17", "A19:D29", "L19:P29", "A30:D40", "L30:P40", "A41:D51", "L41:P51")
sPictures = Application.GetOpenFilename( _
"Pictures (*.jpeg; *.gif; *.jpg; *.bmp; *.tif; *.png), *.jpeg; *.gif; *.jpg; *.bmp; *.tif", 0, _
"Select Photo", "OK", MultiSelect:=True)
x = 0
If IsArray(sPictures) Then
ws.Unprotect PW
For Each sPic In sPictures
Set PictCell = ActiveSheet.Range(PhotoCell(x))
x = x + 1
RemovePicsInRange PictCell 'delete any existing shape in this range
With ws.Shapes.AddPicture(sPic, msoFalse, msoCTrue, 0, 0, 100, 100)
.LockAspectRatio = msoFalse
.Height = PictCell.Height
.Width = PictCell.Width
.Top = PictCell.Top
.Left = PictCell.Left
.Placement = xlMoveAndSize
End With
Next sPic
ActiveSheet.Protect Password:=PW
Else
MsgBox "No Picture Selected"
End If
End Sub
'Delete any shapes whose TopLeftCell intersects with range `rng`
Sub RemovePicsInRange(rng As Range)
Dim i As Long, allPics
Set allPics = rng.Parent.Shapes
For i = allPics.Count To 1 Step -1
If Not Application.Intersect(allPics(i).TopLeftCell, rng) Is Nothing Then
Debug.Print "Deleting shape at " & allPics(i).TopLeftCell.Address
allPics(i).Delete
End If
Next i
End Sub
I'm trying to insert pictures into Excel files from entering the serial number in a cell.
I get a syntax error where it is trying to insert the pictures. Specifically where it says .Shapes.AddPicture.
Sub picture_insert()
Dim picBild As Picture
Dim blnAvailable As Boolean
Dim link As String
Dim Pattern As String
Dim Serial As String
Dim t As String
Dim P1 As String
Dim P2 As String
link = "\\chimera\home\hillerbr\My Documents\Index project\"
Pattern = Range("A14")
Serial = Range("B14")
t = ".jpg"
P1 = Range("C14")
P2 = Range("D14")
With Worksheets("Data Breakdown")
For Each picBild In .Pictures
If picBild.Name = "280.1" Then
'The picture already exists
blnVorhanden = True
Exit For
End If
Next picBild
'only execute if picture does not yet exist
If blnVorhanden = False Then
With .Shapes.AddPicture Filename := link & Pattern & Serial & P1 & t
.Name = Range("C14")
.ShapeRange.LockAspectRatio = msoFalse
.Width = 450
.Height = 500
.Left = Worksheets("Data Breakdown").Range("A10").Left
.Top = Worksheets("Data Breakdown").Range("G20").Top
End With
With .Shapes.AddPicture Filename := link & Pattern & Serial & P1 & t
.Name = Range("D14")
.ShapeRange.LockAspectRatio = msoFalse
.Width = 450
.Height = 500
.Left = Worksheets("Data Breakdown").Range("E10").Left
.Top = Worksheets("Data Breakdown").Range("G20").Top
End With
End If
End With
End Sub
Sub Image_Remove()
Dim picBild As Picture
With Worksheets("Data Breakdown")
For Each picBild In .Pictures
If picBild.Name = Range("C14") Then
picBild.Delete
Exit For
End If
Next picBild
For Each picBild In .Pictures
If picBild.Name = Range("D14") Then
picBild.Delete
Exit For
End If
Next picBild
End With
End Sub
Providing your variables point to a valid image I found the below code works.
Sub Test()
Dim sht As Worksheet
Set sht = Worksheets("Data Breakdown")
With sht
With .Shapes.AddPicture(Filename:=link & Pattern & Serial & P1 & t, _
LinkToFile:=True, SaveWithDocument:=True, _
Left:=.Range("A10").Left, Top:=.Range("G20").Top, Width:=450, Height:=500)
.Name = "ABC"
.LockAspectRatio = True
End With
End With
End Sub
The Help page for AddPicture says there's 7 required parameters.
I have a workbook with 2 sheets (one to place the data and another for options).
The one with the data it has some buttons (at row 1), some textBox and DropBox (at row 2) and at row 3 are the headers of the table with all the data below.
The sheet with the options for the moment has only one button to recreate the menu (the TextBox and DropBox at row 2 in the data sheet)
However when pressing the button to run the macro it gives error 400 with no description and a red x signal. Sometimes it gives error when re-creating and first textBox, sometimes the second or third as well (never the fourth or the fifth).
Why does such 400 error happen ? What causing it ?
When trying debug the code i placed some Debug.Print in some places and after running 3 times (after clicking in button 3 times this is the output in the immediate window.
-----------Running createMenu-----------
TextBox5 DIM done
TextBox5 Set done
TextBox6 Delete
-----------Running createMenu-----------
TextBox5 Delete
TextBox5 DIM done
TextBox5 Set done
TextBox6 DIM done
TextBox6 Set done
TextBox7 Delete
-----------Running createMenu-----------
TextBox5 Delete
The code below (the one to recreate the menus) is placed in the data worksheet.
Sub createMenu()
Debug.Print "-----------Running createMenu-----------"
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Sheets("Dados1")
With ws
.Range("A2").NumberFormat = "0"
.Range("B2").NumberFormat = "dd-mm-yyyy"
.Range("C2:D2").Merge
.Range("C2:D2").NumberFormat = "hh:mm:ss"
Call newTextBox(.Range("E2"))
Application.Wait (Now + TimeValue("0:00:02"))
Call newTextBox(.Range("F2"))
Application.Wait (Now + TimeValue("0:00:02"))
Call newTextBox(.Range("G2"))
Application.Wait (Now + TimeValue("0:00:02"))
Call newTextBox(.Range("H2"))
Application.Wait (Now + TimeValue("0:00:02"))
Call newTextBox(.Range("I2"))
Call newDropBox(.Range("J2"), "=Opções!A1:A14")
Call newDropBox(.Range("K2"), "=Opções!B1:B2")
.Range("A2:N2").HorizontalAlignment = xlCenter
End With
End Sub
Sub newDropBox(t As Range, list As String)
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Sheets("Dados1")
With ws.Range(t.Address).Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=list
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End Sub
Sub newTextBox(t As Range)
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Sheets("Dados1")
With ws
Dim OLEObj As OLEObjects
If .OLEObjects.Count > 0 Then
Dim x As Integer
For x = 1 To .OLEObjects.Count
If .OLEObjects(x).Name = "TextBox" & t.Column Then
.OLEObjects(x).Delete
Debug.Print "TextBox" & t.Column & " Delete"
End If
Next x
End If
Dim myTextBox As OLEObject
Debug.Print "TextBox" & t.Column; " DIM done"
Set myTextBox = .OLEObjects.Add("Forms.TextBox.1")
Debug.Print "TextBox" & t.Column; " Set done"
With myTextBox
.Name = "TextBox" & t.Column
.LinkedCell = t.Address
.Left = t.Cells.Left
.Top = t.Cells.Top
.Width = t.Cells.Width
.Height = t.Cells.Height
.Object.BackColor = 16777152
.Object.BorderStyle = 1
.Object.BorderColor = 0
End With
End With
End Sub
So i find out the reason ...
So when i am doing the for loop he started by finding (lets say 2 OLEObjects).
If the in the first cycle of the loop the wanted object is found he delete one of the objects making it the total OLEObjects count to less 1.
There for when cycling to the second OLEObjects he will not find it, and throw such 400 error.
So the fix i done was exit the loop when the target OLEObjects is found.
Sub newTextBox(t As Range)
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Sheets("Dados1")
With ws
Dim OLEObj As OLEObjects
If .OLEObjects.Count > 0 Then
Dim x As Integer
For x = 1 To .OLEObjects.Count
If .OLEObjects(x).Name = "TextBox" & t.Column Then
.OLEObjects(x).Delete
Exit For
End If
Next x
End If
Dim myTextBox As OLEObject
Set myTextBox = .OLEObjects.Add("Forms.TextBox.1")
With myTextBox
.Name = "TextBox" & t.Column
.LinkedCell = t.Address
.Left = t.Cells.Left
.Top = t.Cells.Top
.Width = t.Cells.Width
.Height = t.Cells.Height
.Object.BackColor = 16777152
.Object.BorderStyle = 1
.Object.BorderColor = 0
End With
End With
End Sub
UPDATE: Upon further research in the object browser... it appears that an MSForms.TextBox implements neither the .Name property or _Exit events - only _Change events. Is there a way to determine which specific TextBox generated a change event?
Alternately is it possible to use the MSForms.Control with this technique? The Control object implements the .Name property and _Exit event.
Can you listen for a TextBox exit event? Similarly to how a normal TextBox event would work? E.g.
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Update a certain label based on the value of the TextBox
End Sub
The following doesn't catch the exit event. Moreover, while I can see the .Name property of the TextBox which generated the event for MyTextBox in the locals window, I cannot access that info to determine which label to act on.
This class technique was adapted from this post, and this post, which caught the change events.
Class clsTextBox:
Private WithEvents MyTextBox As MSForms.TextBox
Public Property Set Control(tb As MSForms.TextBox)
Set MyTextBox = tb
End Property
' Want to handle this event, but it's not caught when exiting the TextBox control
Private Sub MyTextBox_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Debug.Print me.Control.name
'Update a certain label based on the value of the TextBox
Stop
End Sub
' Catching this event but can't identify the control which triggered it
Private Sub MyTextBox_Change()
Debug.Print MyTextBox.Value ' <--- This prints the correct value
Debug.Print Me.Control.Name ' <--- ERROR here on any variation of Me or MyTextBox
'Update a certain label based on the value of the TextBox
Stop
End Sub
I have a series of dynamically created controls which need listeners. Code follows:
Option Explicit
Dim tbCollection As Collection
Private Sub UserForm_Initialize()
Dim ctrl As MSForms.Control
Dim obj As clsTextBox
Dim acftNumber As Long
Dim mPage As MSForms.MultiPage ' Control
Dim lbl_acftName As MSForms.Label
Dim lbl_currentHrs As MSForms.Label
Dim lbl_hrsDUE As MSForms.Label
Dim lbl_dateXFRIn As MSForms.Label
Dim lbl_dateXFROut As MSForms.Label
Dim lbl_hrsOnXFROut As MSForms.Label
Dim txb_currentHrs As MSForms.TextBox
Dim txb_hrsDUE As MSForms.TextBox
Dim txb_dateXFRIn As MSForms.TextBox
Dim txb_dateXFROut As MSForms.TextBox
Dim txb_hrsOnXFROut As MSForms.TextBox
Dim i As Double
Dim pgName As String
Dim acftName As String
' Correct for border size calculations bug in Excel 2016
Me.Height = 249.75
Me.Width = 350.25
acftNumber = Range("aircraft").Count 'Unknown value from 3 to 10
Set mPage = Me.multipage_file_week 'set Multipage variable
For i = 1 To acftNumber
'set name/title for new page
pgName = "pg_acft_" & i
acftName = Range("aircraft").Cells(i, 1).Value
'mPage.Pages.Add pgName, pgTitle
With mPage 'add acft tab
' add the aircraft page to the multipage
.Pages.Add pgName, acftName
' Aircraft Name Label
Set lbl_acftName = .Pages(i).Controls.Add("Forms.Label.1", "lbl_acftName_" & i, True)
With lbl_acftName
.Caption = acftName
.Font = "Arial"
.Font.Size = 12
.Font.Bold = True
.Left = 10
.Width = 55
.Top = 0
End With
' Current Hours Label and TextBox
Set lbl_currentHrs = .Pages(i).Controls.Add("Forms.Label.1", "lbl_currentHrs_" & i, True)
With lbl_currentHrs
.Caption = "Current Asset Hours:"
.TextAlign = fmTextAlignRight
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 20
.Width = 120
.Top = 25
End With
Set txb_currentHrs = .Pages(i).Controls.Add("Forms.TextBox.1", "txb_currentHrs_" & i, True)
With txb_currentHrs
.Value = "16004.5"
.Text = "16004.5"
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 150
.Width = 70
.Top = 25
End With
' Hours DUE Label and TextBox
Set lbl_hrsDUE = .Pages(i).Controls.Add("Forms.Label.1", "lbl_hrsDUE_" & i, True)
With lbl_hrsDUE
.Caption = "Hours next HMC DUE:"
.TextAlign = fmTextAlignRight
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 20
.Width = 120
.Top = 50
End With
Set txb_hrsDUE = .Pages(i).Controls.Add("Forms.TextBox.1", "txb_hrsDUE_" & i, True)
With txb_hrsDUE
.Value = "16004.5"
.Text = "16004.5"
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 150
.Width = 70
.Top = 50
End With
' Date XFR In Label and TextBox
Set lbl_dateXFRIn = .Pages(i).Controls.Add("Forms.Label.1", "lbl_dateXFRIn_" & i, True)
With lbl_dateXFRIn
.Caption = "Estimated arrival date:"
.TextAlign = fmTextAlignRight
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 20
.Width = 120
.Top = 75
End With
Set txb_dateXFRIn = .Pages(i).Controls.Add("Forms.TextBox.1", "txb_hrsDUE_" & i, True)
With txb_dateXFRIn
.Value = "4/16/2019"
.Text = "4/16/2019"
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 150
.Width = 70
.Top = 75
End With
' Date XFR Out Label and TextBox
Set lbl_dateXFROut = .Pages(i).Controls.Add("Forms.Label.1", "lbl_dateXFROut_" & i, True)
With lbl_dateXFROut
.Caption = "Estimated departure date:"
.TextAlign = fmTextAlignRight
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 20
.Width = 120
.Top = 100
End With
Set txb_dateXFROut = .Pages(i).Controls.Add("Forms.TextBox.1", "txb_hrsDUE_" & i, True)
With txb_dateXFROut
.Value = "4/16/2019"
.Text = "4/16/2019"
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 150
.Width = 70
.Top = 100
End With
' Hours on XFR Out Label and TextBox
Set lbl_hrsOnXFROut = .Pages(i).Controls.Add("Forms.Label.1", "lbl_hrsOnXFROut_" & i, True)
With lbl_hrsOnXFROut
.Caption = "Desired hours remaining on departure:"
.TextAlign = fmTextAlignLeft
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 20
.Width = 170
.Top = 125
End With
Set txb_hrsOnXFROut = .Pages(i).Controls.Add("Forms.TextBox.1", "txb_hrsDUE_" & i, True)
With txb_hrsOnXFROut
.Value = "35"
.Text = "35"
.Font = "Arial"
.Font.Size = 10
.Font.Bold = False
.Left = 200
.Width = 35
.Top = 125
End With
End With
'Debug
Debug.Print Me.multipage_file_week.Pages(i).Name & ":"
For Each ctrl In Me.multipage_file_week.Pages(i).Controls
Debug.Print " - " & ctrl.Name
Next ctrl
Next i
mPage.Value = 0
Me.Caption = FILE_WEEK_FORM_TITLE
Set tbCollection = New Collection
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.TextBox Then
Set obj = New clsTextBox
Set obj.Control = ctrl
tbCollection.Add obj
End If
Next ctrl
Set obj = Nothing
End Sub
MSForms.Control defines the Enter and Exit events: if you need to handle TextBox.Change, then you need two WithEvents variables:
Private WithEvents TextBoxEvents As MSForms.TextBox
Private WithEvents ControlEvents As MSForms.Control
Public Property Set Control(ByVal tb As Object)
Set TextBoxEvents = tb
Set ControlEvents = tb
End Property
MSForms.Control is also the interface through which you get to access properties like Name, Top, Left, Visible, etc.
Tip: Never type event handler procedure signatures by hand. Select the source interface from the dropdown in the upper-left corner of the code pane, then select an event to handle from the upper-right dropdown; let the VBE generate the members with the correct signature. If you're in a handler procedure and the upper-left dropdown says "(general)", you're not in an event handler.
EDIT
While the above code compiles fine and the MSForms.Control interface does expose the events we're looking to handle...
?TypeOf tb Is MSForms.Control
True
?TypeOf tb Is MSForms.TextBox
True
...there's a bit of COM hackery going on behind the scenes; there's enough smokes & mirrors for VBA to successfully compile the above, but, basically, you're looking at a glitch in The Matrix (Rubberduck's resolver has similar "nope" issues with MSForms controls): there isn't any obvious way to get VBA to bind a dynamic control object to its MSForms.Control events.
With the help of the ConnectToConnectionPoint API you can catch the Event (Every Event, also Enter and Exit) for every control.
Have a look here: Trigger Enter field behaviour through class for a control
For Exit it will be
Public Sub myExit(ByVal Cancel As MSForms.ReturnBoolean)
Attribute myExit.VB_UserMemId = -2147384829
'code
End Sub
I have used some code that will allow a user to store a picture in the comments of a cell using:
Application.ActiveCell.AddComment.Shape.Fill.UserPicture (fName)
I now want to write something that iterates through the comments of a worksheet and exports all the pictures used above into separate picture files. I am not sure how to reach the right object to do this.
Thanks
Martin
I cobbled some code together from a few sources. How does this work?
Sub extractCommentImage()
'Borrowed from: https://excelribbon.tips.net/T011165_Moving_Comment_Background_Pictures_to_Cells.html
Dim cmt As Comment
Dim cel As Range
Dim bvisible As Boolean
For Each cmt In ActiveSheet.Comments
With cmt
bvisible = .Visible
.Visible = True
Set cel = .Parent.Offset(0, 1)
.Shape.CopyPicture appearance:=xlScreen, Format:=xlPicture
cel.PasteSpecial
selection.ShapeRange.LockAspectRatio = msoFalse
.Visible = bvisible
.Shape.Fill.OneColorGradient msoGradientFromCenter, 1, 1
End With 'cmt
Next cmt
ExportMyPicture
End Sub
And the "Export" sub:
Sub ExportMyPicture()
'borrowed from: https://stackoverflow.com/questions/18232987/export-pictures-from-excel-file-into-jpg-using-vba
Dim MyChart As String, MyPicture As String, pic As Object
Dim PicWidth As Long, PicHeight As Long, num As Long
Dim shtName as String
num = 1
Application.ScreenUpdating = False
shtName = ActiveSheet.Name
For Each pic In ActiveSheet.Pictures
MyPicture = pic.Name
With pic
PicHeight = .ShapeRange.Height
PicWidth = .ShapeRange.Width
End With
Charts.Add
ActiveChart.Location Where:=xlLocationAsObject, Name:=shtName
selection.Border.LineStyle = 0
MyChart = Split(ActiveChart.Name, " ")(1) & " 1"
With ActiveSheet
With .Shapes(MyChart)
.Width = PicWidth
.Height = PicHeight
End With
.Shapes(MyPicture).Copy
With ActiveChart
.ChartArea.Select
.Paste
End With
.ChartObjects(1).Chart.Export Filename:="C:\Users\[CHANGE THIS]\Desktop\MyPic " & num & ".jpg", FilterName:="jpg"
num = num + 1
.Shapes(MyChart).Cut
End With
Next pic
Application.ScreenUpdating = True
Exit Sub
End Sub