VBA Excel to PPT export - vba

I'm trying to transfer some code from one workbook to another and I'm having trouble figuring out why it's not working. I transferred the sheets into the new workbook and made the necessary updates in the code to reference the correct sheets. Everything else between the workbooks is consistent, but I keep receiving a compile error : User-defined type not defined. I tried debugging but I'm not sure what it's pointing to. Thanks in advance.
Sub CreatePP()
Dim ppApp As Object
Dim ppSlide As Object
On Error Resume Next
Set ppApp = GetObject(, "Powerpoint.Application")
On Error GoTo 0
If ppApp Is Nothing Then
Set ppApp = CreateObject("Powerpoint.Application")
ppApp.Visible = True
ppApp.Presentations.Add
End If
Dim MySheets, i As Long
MySheets = Array(Sheet44, Sheet45, Sheet46, Sheet47, Sheet43, Sheet42, Sheet41, Sheet40, Sheet48) 'these are sheet codenames not sheet name.
MyRanges = Array("A1:Q45", "A1:Q45", "A1:Q45", "A1:Q45", "A1:Q45", "A1:Q45", "A1:Q45", "A1:Q45", "A1:Q45")
For i = LBound(MySheets) To UBound(MySheets)
If ppApp.ActivePresentation.Slides.Count = 0 Then
Set ppSlide = ppApp.ActivePresentation.Slides.Add(1, 12) 'ppLayoutBlank
Else
ppApp.ActivePresentation.Slides.Add ppApp.ActivePresentation.Slides.Count + 1, 12
Set ppSlide = ppApp.ActivePresentation.Slides(ppApp.ActivePresentation.Slides.Count)
End If
Copy_Paste_to_PowerPoint ppApp, ppSlide, MySheets(i), MySheets(i).Range(MyRanges(i)), xl_Bitmap
Next
End Sub
Sub Copy_Paste_to_PowerPoint(ByRef ppApp As Object, ByRef ppSlide As Object, ByVal ObjectSheet As Worksheet, _
ByRef PasteObject As Object, Optional ByVal Paste_Type As PasteFormat)
Dim PasteRange As Boolean
Dim objChart As ChartObject
Dim lngSU As Long
Select Case TypeName(PasteObject)
Case "Range"
If Not TypeName(Selection) = "Range" Then Application.GoTo PasteObject.Cells(1)
PasteRange = True
Case "Chart": Set objChart = PasteObject.Parent
Case "ChartObject": Set objChart = PasteObject
Case Else
MsgBox PasteObject.Name & " is not a valid object to paste. Macro will exit", vbCritical
Exit Sub
End Select
With Application
lngSU = .ScreenUpdating
.ScreenUpdating = 0
End With
ppApp.ActiveWindow.View.GotoSlide ppSlide.SlideNumber
On Error GoTo -1: On Error GoTo 0
DoEvents
If PasteRange Then
If Paste_Type = xl_Bitmap Then
'//Paste Range as Picture
PasteObject.CopyPicture Appearance:=1, Format:=-4147
ppSlide.Shapes.Paste.Select
ElseIf Paste_Type = xl_HTML Then
'//Paste Range as HTML
PasteObject.Copy
ppSlide.Shapes.PasteSpecial(8, link:=1).Select 'ppPasteHTML
ElseIf Paste_Type = xl_Link Then
'//Paste Range as Linked
PasteObject.Copy
ppSlide.Shapes.PasteSpecial(0, link:=1).Select 'ppPasteDefault
End If
Else
If Paste_Type = xl_Link Then
'//Copy & Paste Chart Linked
objChart.Chart.ChartArea.Copy
ppSlide.Shapes.PasteSpecial(link:=True).Select
Else
'//Copy & Paste Chart Not Linked
objChart.Chart.CopyPicture Appearance:=1, Size:=1, Format:=2
ppSlide.Shapes.Paste.Select
End If
End If
'//Center pasted object in the slide
With ppApp.ActiveWindow
If .Height > .Selection.ShapeRange.Height Then
.Selection.ShapeRange.LockAspectRatio = True
.Selection.ShapeRange.Height = .Height * 0.82
End If
If .Selection.ShapeRange.Width > 708 Then
.Selection.ShapeRange.LockAspectRatio = True
.Selection.ShapeRange.Width = 708
End If
.Selection.ShapeRange.Align msoAlignCenters, True
.Selection.ShapeRange.Align msoAlignMiddles, True
End With
With Application
.CutCopyMode = False
.ScreenUpdating = lngSU
End With
'AppActivate ("Microsoft Excel")
End Sub

When you copied that Copy_Paste_to_PowerPoint function you forgot to copy the enum.
Public Enum PasteFormat
xl_Link = 0
xl_HTML = 1
xl_Bitmap = 2
End Enum
Did you get it from somewhere like here? It looks a bit like that version. It looks like you or whoever you got that from stripped out the attribution. You really should put a comment attributing the source of your snippets in there. Not only is it a legal requirement of places like stackoverflow, but it's also quite useful for figuring out what code does, where it came from, and what might be wrong with it.

Related

Copy and paste large number of charts from Excel to PowerPoint via VBA

The task is to loop through an Excel workbook with multiple sheets and copy all the charts contained in the workbook into a PowerPoint presentation, one chart per slide and always the same layout.
Sub PPT_Example()
Dim pptApp As PowerPoint.Application
Dim pptPres As PowerPoint.Presentation
Dim sh As Worksheet
Dim ch As ChartObject
Set pptApp = New PowerPoint.Application
pptApp.Visible = True
Set pptPres = pptApp.Presentations.Add
pptPres.PageSetup.SlideSize = PpSlideSizeType.ppSlideSizeOnScreen16x9
For Each sh In ActiveWorkbook.Sheets
For Each ch In sh.ChartObjects
Dim pptSlide As Slide
Dim Title As Object
Dim Box As Object
Dim Txt As Object
Set pptSlide = pptPres.Slides.Add(pptPres.Slides.Count + 1, ppLayoutBlank)
ch.Copy
With pptSlide.Shapes.Paste
.Top = Application.CentimetersToPoints(3.3)
.Left = Application.CentimetersToPoints(0.76)
.Width = Application.CentimetersToPoints(16)
.Height = Application.CentimetersToPoints(10.16)
End With
'Insert Box
Set Box = pptSlide.Shapes.AddShape(Type:=msoShapeRectangle, _
Left:=Application.CentimetersToPoints(17.1), _
Top:=Application.CentimetersToPoints(3.3), _
Width:=Application.CentimetersToPoints(7.22), _
Height:=Application.CentimetersToPoints(9.29))
Prop_Box.Name = "Box"
pptSlide.Shapes("Box").Fill.ForeColor.RGB = RGB(219, 233, 255)
pptSlide.Shapes("Box").Line.ForeColor.RGB = RGB(0, 102, 255)
'Insert the text box
Set Txt = pptSlide.Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, _
Left:=Application.CentimetersToPoints(17.1), _
Top:=Application.CentimetersToPoints(3.3), _
Width:=Application.CentimetersToPoints(7.22), _
Height:=Application.CentimetersToPoints(9.29))
Txt.Name = "Txt"
pptSlide.Shapes("Txt").TextFrame.TextRange.Font.Size = 14
pptSlide.Shapes("Txt").TextFrame.TextRange.Font.Bold = msoCTrue
pptSlide.Shapes("Txt").TextFrame.TextRange.Font.Name = "Arial"
pptSlide.Shapes("Txt").TextFrame.TextRange.Text = "Sample Text"
'Clear the Clipboard
Dim oData As New DataObject 'object to use the clipboard
oData.SetText Text:=Empty 'Clear
oData.PutInClipboard
Next
Next
End Sub
The code works on my example (2 sheets, 3 charts total) but not if I apply it to the real thing, which is a workbook with 10-15 sheets and 8 charts per sheet. At some (random?) point, the code stops and gives me this error.
Run-time error:
Shapes (unknown member): Invalid request. Clipboard is empty or contains data which may not be pasted here.
I noted that the code crashed earlier, the more objects I put on the slides (which is why I left the text and the box in my example, although not strictly neccessary). Given that and the error message, I assumed the clipboard might not be cleared properly after each loop, so I put in a section to clear the clipboard but it didn't solve the issue.
After the chart is copied, try adding DoEvents and pausing the macro for a few seconds before pasting it into your slide. And the same thing after it's pasted into your slide.
So, for example, first add the following function to pause your code . . .
Sub PauseMacro(ByVal secs As Long)
Dim endTime As Single
endTime = Timer + secs
Do
DoEvents
Loop Until Timer > endTime
End Sub
Then try something like this . . .
ch.Copy
DoEvents
PauseMacro 5 'pause for 5 seconds
With pptSlide.Shapes.Paste
DoEvents
PauseMacro 5 'pause for 5 seconds
.Top = Application.CentimetersToPoints(3.3)
.Left = Application.CentimetersToPoints(0.76)
.Width = Application.CentimetersToPoints(16)
.Height = Application.CentimetersToPoints(10.16)
End With
You may find through testing that you can pause for less than 5 seconds, maybe 3 seconds.
My approach is to split out potentially time-consuming operations into separate functions (see "'' Call as a Function" below). When a function is called, and then has to return, it seems that Excel/VBA/the-little-green-men-running-everything make sure that whatever operation it is waits until the operation is finished (the chart is totally added to the clipboard, the clipboard contents are totally pasted, the shape is totally instantiated, etc.) before continuing.
This also means not necessarily forcing a delay during execution that might not be needed (the Do Until or Loop Until or Wait that is often suggested).
So your code might look like this (caveat: untested)
Sub PPT_Example()
Dim pptApp As PowerPoint.Application
Dim pptPres As PowerPoint.Presentation
Dim sh As Worksheet
Dim ch As ChartObject
Set pptApp = New PowerPoint.Application
pptApp.Visible = True
Set pptPres = pptApp.Presentations.Add
pptPres.PageSetup.SlideSize = PpSlideSizeType.ppSlideSizeOnScreen16x9
For Each sh In ActiveWorkbook.Sheets
For Each ch In sh.ChartObjects
Dim pptSlide As Slide
Dim Title As Object
Dim Box As Object
Dim Txt As Object
Set pptSlide = NewSlide(pptPres) '' Call as a Function
ch.Copy
Dim shp As PowerPoint.Shape
Set shp = NewShape(pptSlide) '' Call as a Function
With shp
.Top = Application.CentimetersToPoints(3.3)
.Left = Application.CentimetersToPoints(0.76)
.Width = Application.CentimetersToPoints(16)
.Height = Application.CentimetersToPoints(10.16)
End With
'Insert Box
Set Box = NewBox(pptSlide) '' Call as a Function
Prop_Box.Name = "Box"
pptSlide.Shapes("Box").Fill.ForeColor.RGB = RGB(219, 233, 255)
pptSlide.Shapes("Box").Line.ForeColor.RGB = RGB(0, 102, 255)
'Insert the text box
Set Txt = NewTextBox(pptSlide) '' Call as a Function
Txt.Name = "Txt"
pptSlide.Shapes("Txt").TextFrame.TextRange.Font.Size = 14
pptSlide.Shapes("Txt").TextFrame.TextRange.Font.Bold = msoCTrue
pptSlide.Shapes("Txt").TextFrame.TextRange.Font.Name = "Arial"
pptSlide.Shapes("Txt").TextFrame.TextRange.Text = "Sample Text"
'Clear the Clipboard
Dim oData As New DataObject 'object to use the clipboard
oData.SetText Text:=Empty 'Clear
oData.PutInClipboard
Next
Next
End Sub
Function NewSlide(pptPres As PowerPoint.Presentation) As PowerPoint.Slide
Set NewSlide = pptPres.Slides.Add(pptPres.Slides.Count + 1, ppLayoutBlank)
End Function
Function NewShape(pptSlide As PowerPoint.Slide) As PowerPoint.Shape
Set NewShape = pptSlide.Shapes.Paste
End Function
Function NewBox(pptSlide As PowerPoint.Slide) As Object
Set Box = pptSlide.Shapes.AddShape(Type:=msoShapeRectangle, _
Left:=Application.CentimetersToPoints(17.1), _
Top:=Application.CentimetersToPoints(3.3), _
Width:=Application.CentimetersToPoints(7.22), _
Height:=Application.CentimetersToPoints(9.29))
End Function
Function NewTextBox(pptSlide As PowerPoint.Slide) As Object
Set NewTextBox = pptSlide.Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, _
Left:=Application.CentimetersToPoints(17.1), _
Top:=Application.CentimetersToPoints(3.3), _
Width:=Application.CentimetersToPoints(7.22), _
Height:=Application.CentimetersToPoints(9.29))
End Function

Autocomplete code for a worksheet in Excel not working in other worksheets using VB

My goal was to make autocomplete active for dropdowns and I have achieved it for a single worksheet but duplicating the code to other worksheets is not working.
I started by creating a combo Box on the initial worksheet containing the drop downs and then made the following changes-
Changed the name to TempCombo in the Name field
Selected 1-fmMatchEntryComplete in the MatchEntry field;
I then inserted the following code for that worksheet:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'Update by Extendoffice: 2017/8/15
Dim xCombox As OLEObject
Dim xStr As String
Dim xWs As Worksheet
Set xWs = Application.ActiveSheet
On Error Resume Next
Set xCombox = xWs.OLEObjects("TempCombo")
With xCombox
.ListFillRange = ""
.LinkedCell = ""
.Visible = False
End With
If Target.Validation.Type = 3 Then
Target.Validation.InCellDropdown = False
Cancel = True
xStr = Target.Validation.Formula1
xStr = Right(xStr, Len(xStr) - 1)
If xStr = "" Then Exit Sub
With xCombox
.Visible = True
.Left = Target.Left
.Top = Target.Top
.Width = Target.Width + 5
.Height = Target.Height + 5
.ListFillRange = xStr
.LinkedCell = Target.Address
End With
xCombox.Activate
Me.TempCombo.DropDown
End If
End Sub
Private Sub TempCombo_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal
`Shift As Integer)`
Select Case KeyCode
Case 9
Application.ActiveCell.Offset(0, 1).Activate
Case 13
Application.ActiveCell.Offset(1, 0).Activate
End Select
End Sub
This implementation works perfectly for that sheet but when i attempt to use the same code on another worksheet on the same file the autocomplete function doesn't work.
I attempted modification of the combobox name on sheet2 to TempCombo2 and changed the following line:
Set xCombox = xWs.OLEObjects("TempCombo")
to
Set xCombox = xWs.OLEObjects("TempCombo2")
The autocomplete function fails to work on sheet 2 even though no error is thrown.
This is a pretty interesting idea, I like it.
I was able to get this to work on multiple sheets with the following modifications:
Removed Cancel = True, this line was throwing an error and Cancel is not an argument in Worksheet_SelectionChange; I don't think this is doing anything.
Copied the code to the second sheet's code module (it has to be in each sheet module that you want it to run on)
updated Set xCombox = xWs.OLEObjects("TempCombo") to Set xCombox = xWs.OLEObjects("TempCombo2")
Me.TempCombo.DropDown updated to Me.TempCombo2.DropDown since that is what I named the combo box on the second sheet
Also, not a change as much as an assumption, it seems it only works with the ActiveX controls, so I assume that's what you are using when you add the new box.
As a follow up I was able to get it to work using the workbook module as long as the combo box is named "TempCombo" on all sheets (you have to add a combobox named "TempCombo" to each sheet). Going this route, you only need the code once, on the workbook module , and it uses the combo box that is local to each sheet.
TO TEST - In a new workbook: add list validation to a range using a range reference, put some values in the list range, add an ActiveX combobox to the sheet and name it "TempCombo", put the following code in the workbook module, then click anywhere in the range that has the list validation enabled.
One other note, make sure you aren't still in design mode on the developer tab!
Option Explicit
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
'Update by Extendoffice: 2017/8/15
Dim xCombox As OLEObject
Dim xStr As String
Dim xWs As Worksheet
Set xWs = Sh
On Error Resume Next
Set xCombox = xWs.OLEObjects("TempCombo")
With xCombox
.ListFillRange = ""
.LinkedCell = ""
.Visible = False
End With
If Target.Validation.Type = 3 Then
Target.Validation.InCellDropdown = False
'Cancel = True
xStr = Target.Validation.Formula1
xStr = Right(xStr, Len(xStr) - 1)
If xStr = "" Then Exit Sub
With xCombox
.Visible = True
.Left = Target.Left
.Top = Target.Top
.Width = Target.Width + 5
.Height = Target.Height + 5
.ListFillRange = xStr
.LinkedCell = Target.Address
End With
xCombox.Activate
Sh.TempCombo.DropDown
End If
End Sub
Private Sub TempCombo_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 9
Application.ActiveCell.Offset(0, 1).Activate
Case 13
Application.ActiveCell.Offset(1, 0).Activate
End Select
End Sub

Office update killed my VBA code to paste Excel tables to an existing PowerPoint file and slides

After a recent Office 365 update, my code to copy tables from Excel to Power Point stopped working.
Previous code:
Sub GeneratePresentation()
Dim pptApp As PowerPoint.Application
Dim pptPrez As PowerPoint.Presentation
Dim pSlide As PowerPoint.Slide
Dim objPPT As Object
Dim myRange As Excel.Range
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
MonthNo = Month(Worksheets("inputs").Range("B3"))
MonthData = Worksheets("inputs").Cells(MonthNo + 10, 9)
If MonthData = "" Then
MsgBox "Please update losses"
Else
FilePath = "\\Model\"
Filename = "Template Monthly reports.pptx"
file = FilePath & Filename
Set pptPrez = objPPT.Presentations.Open(file)
Set pptApp = GetObject(Class:="PowerPoint.Application")
Set pptPrez = pptApp.ActivePresentation
'Slide 1 title 1
Set pSlide = pptPrez.Slides(1)
Sheets("01").Range("D3") = "= ""Midstream Monthly Production Report "" & Text(Inputs!B3, ""Mmmm YYYY"") & "" - internal"""
Sheets("01").Range("D3").Copy
Set osh = pSlide.Shapes.PasteSpecial(ppPasteDefault)(1)
With osh
.Top = 160
.Left = 135
.Height = 80
.Width = 550
End With
Code continues to paste tables and pictures. then
End if
End sub
I get the following error:
VBA error Run-time '-2147188160 (80048240)': Shapes (unknown member)
I have tried most variants of paste but it only lets me paste pictures or text. I noticed that the VBA refernce library revision seems to have reduced to Microsoft PowerPoint 14.0 Object library when I am fairly sure it was build 15 or 16 before. Would this be the cause?
I have come up with a solution which is to use
'Slide 1 title 1
i = 1
Set pSlide = pptPrez.Slides(i)
Sheets("01").Range("D3") = "= ""Midstream Monthly Production Report "" & Text(Inputs!B3, ""Mmmm YYYY"") & "" - internal"""
Sheets("01").Range("D3").Copy
pptPrez.Windows(1).Activate
pptPrez.Windows(1).View.GotoSlide i
pptPrez.Slides(i).Shapes("Title").Select
pptApp.CommandBars.ExecuteMso ("PasteSourceFormatting")
With pptPrez.Slides(i)
With .Shapes("Title")
.LockAspectRatio = msoFalse
.Top = 160
.Left = 135
.Height = 70
.Width = 550
'.TextFrame.TextRange.Font.Name = "Futura Bold"
'.TextFrame.TextRange.Font.Size = 24
'.TextFrame.TextRange.ParagraphFormat.Alignment = ppAlignLeft
'.TextFrame.TextRange.ParagraphFormat.WordWrap = msoTrue
End With
End With
For the alternative, I have to create all the tables manually then name them and select them in the code which works, but it seems less consistent and reliable requiring the windows to be active being more to go wrong.
Any ideas how to get the first code working again? I can paste manually still but it seems not using pastespecial. Why would an update remove this ability? I've tried proven code from this forum using this paste function but it won't work either which used to, It's definitely the update as all our computers now have the same issue which I find hard to believe too.
I decided to write an answer instead of a bunch of comments, since I wanted to post my code.
Those Office 365 updates have caught me a time or three. But I don't know what's the problem.
The code fails on PasteSpecial? PasteSpecial is a relative newcomer to PowerPoint VBA, but I thought it was around for Office 14 (2010). The reference to version 14.0 of the PowerPoint library is strange. Can you go to Tools > References and scroll to version 16.0? If so, check that one instead. What version of Office are you using: go to File tab > Account, and find the version number and build number.
Why do you have both CreateObject and GetObject. For PowerPoint, you only need to do this once, using CreateObject. If PowerPoint is running, CreateObject returns the running instance; if not, it returns a new instance. Probably not important, but it adds clutter. Move CreateObject up to where GetObject is, and change objPPT to pptApp (since you don't need both).
Also, you've used three variables which are not declared. Declare MonthNo and MonthData as Variant and osh as PowerPoint.Shape (actually, in my code I renamed it pptShape and pSlide to pptSlide for consistency).
With the additional modification to use the active presentation instead of opening one at a given path and file name, your code works fine for me. I'm running Version 1711, Build 8711.2037, for what it's worth.
And here's the code that ran fine for me.
Sub GeneratePresentation()
Dim pptApp As PowerPoint.Application
Dim pptPrez As PowerPoint.Presentation
Dim pptSlide As PowerPoint.Slide
Dim myRange As Excel.Range
Dim pptShape As PowerPoint.Shape
Dim MonthNo As Variant
Dim MonthData As Variant
MonthNo = Month(Worksheets("inputs").Range("B3"))
MonthData = Worksheets("inputs").Cells(MonthNo + 10, 9)
If MonthData = "" Then
MsgBox "Please update losses"
Else
Set pptApp = GetObject(Class:="PowerPoint.Application")
Set pptPrez = pptApp.ActivePresentation
'' JP - use active presentation instead of opening one
''FilePath = "\\Model\"
''Filename = "Template Monthly reports.pptx"
''file = FilePath & Filename
''Set pptPrez = objPPT.Presentations.Open(file)
Set pptPrez = pptApp.ActivePresentation
'Slide 1 title 1
Set pptSlide = pptPrez.Slides(1)
Sheets("01").Range("D3") = "= ""Midstream Monthly Production Report "" _
& Text(Inputs!B3, ""Mmmm YYYY"") & "" - internal"""
Sheets("01").Range("D3").Copy
Set pptShape = pptSlide.Shapes.PasteSpecial(ppPasteDefault)(1)
With pptShape
.Top = 160
.Left = 135
.Height = 80
.Width = 550
End With
End If
End Sub
I have updated the alternative solution which might help others as it does a few things; copies tables to an existing presentation and slides updating old shapes and new shapes, copies pictures to new slides with a pop up box to allow a choice in pasting a table.
I made a function to do this to reduce the main code and make it easier to manage as I had dozens of copies and pastes. I haven't pasted everything but showed some of the different ways to paste:
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
Private pptApp As PowerPoint.Application
Private pptPres As PowerPoint.Presentation
Private pSlide As PowerPoint.Slide
Private TTop, TLeft As Variant
Private TableCount, SlideNo As Integer
Private MyRange As Excel.Range
Private ShapeName As String
Private Function CreateTable()
Dim l As Long
Set pSlide = pptPres.Slides(SlideNo)
MyRange.Copy
pptPres.Windows(1).Activate
pptPres.Windows(1).View.GotoSlide SlideNo
With pptPres.Slides(SlideNo)
If ShapeName = isblank Then
Else
pptPres.Slides(SlideNo).Shapes(ShapeName).Select
End If
For l = 1 To 100
DoEvents
Next l
pptApp.CommandBars.ExecuteMso ("PasteSourceFormatting")
For l = 1 To 500
DoEvents
Next l
pptApp.CommandBars.ReleaseFocus
NoShapes = pSlide.Shapes.Count
If ShapeName = isblank Then
pptPres.Slides(SlideNo).Shapes(NoShapes).Name = "Table" & TableCount
pptPres.Slides(SlideNo).Shapes(ShapeName).Select
With .Shapes("Table" & TableCount)
.LockAspectRatio = msoFalse
If TTop = isblank Then
Else
.Top = TTop
End If
If TLeft = isblank Then
Else
.Left = TLeft
End If
End With
TableCount = TableCount + 1
Else
End If
End With
ShapeName = ""
TLeft = ""
TTop = ""
Application.CutCopyMode = False
End Function
Sub GeneratePresentation()
Dim FilePath, Filename, file As String
Dim MonthNo, MonthData As Variant
Dim x, y As Variant
Dim UpdateRecords As Integer
Dim WB As Excel.Workbook
FilePath = "\\\Model\"
Filename = "Template Weekly Report.pptx"
file = FilePath & Filename
Set pptApp = New PowerPoint.Application
Set pptPres = pptApp.Presentations.Open(file) ' using a specific presentation or template
Set pptPres = pptApp.ActivePresentation
TableCount = 1
'Slide 1 title 1
SlideNo = 1
Sheets("01").Range("D3") = "= ""Weekly Report """
Sheets("01").Range("D4") = "= ""For Week No. ""&TEXT(WEEKNUM(NOW(),16),""#"")& "" - internal"""
Set MyRange = Sheets("0" & SlideNo).Range("D3:D4")
TTop = 160
TLeft = 135
Call CreateTable
'Slide 1 title 2
Sheets("01").Range("D7").Formula = "=DAY(Entry!B4)&LOOKUP(DAY(Entry!B4),{1,2,3,4,21,22,23,24,31;""st"",""nd"",""rd"",""th"",""st"",""nd"",""rd"",""th"",""st""})&TEXT(Entry!B4,"" mmmm yyy"")"
Set MyRange = Sheets("0" & SlideNo).Range("D7")
TTop = 280
TLeft = 135
Call CreateTable
'slide 2 table 1
SlideNo = 2
Set MyRange = Sheets("0" & SlideNo).Range("B33:T40")
TTop = 380
Call CreateTable
'Slide 2 chart 1
ActiveWorkbook.Sheets("0" & SlideNo).ChartObjects("Chart 1").Copy
Set osh = pSlide.Shapes.PasteSpecial(ppPasteMetafilePicture)(1)
With osh
.Top = 98
.Left = 35
.Width = 430
End With
'Slide 3 table 1
SlideNo = 3
Set pSlide = pptPres.Slides(SlideNo)
UpdateRecords = MsgBox("Update Records", vbYesNo, "Update Records?")
If UpdateRecord = yes Then
Set MyRange = Sheets("0" & SlideNo).Range("E17:I20")
TTop = 330
Call CreateTable
Else
End If
pptPres.Windows(1).Activate
pptPres.Windows(1).View.GotoSlide 1
End Sub
I hope this is helpful.
If you have any recommendation let me know.
Jon

Pasting chart fails when outside of viewable screen area

Whilst this proven method has worked for people and works for me in the general sense, I receive "Error 1004: Method 'Paste' of object '_Chart' failed." However, on the 5th iteration of the loop this method failure occurs. I have tried isolating each component of the Array and the 6th and 7th elements always fail, but when the 5th element is used in isolation or as the starting point of the loop it succeeds. I have also tried clearing the clipboard at different stages of the process to see if that helps and tested the object property of the "cht" object.
Sub PicturesCopy()
'Define path variables
Path = "C:\Users\khill\Documents\Macro Tests\"
PathSC = Path & "Master Cockpit\"
FileMCP = "Master_Daily sales cockpit.xlsm"
Set wbMCP = Workbooks(FileMCP)
Dim cht As ChartObject
Dim rngList, fileList As Variant
rngList = Array("B2:Y19", "B22:U39", "B43:O58", "B61:R76", "B81:J96", "B101:AD118", "B122:V139")
fileList = Array("Fig 1a", "Fig 1b", "Fig 2a", "Fig 2b", "Fig 2c", "Fig 3a", "Fig 3b")
For x = 0 To UBound(rngList)
'Application.CutCopyMode = True
With wbMCP.Worksheets("Graphs")
Debug.Print rngList(x)
Dim rgExp As Range: Set rgExp = .Range(rngList(x))
Debug.Print x
rgExp.CopyPicture Appearance:=xlScreen, Format:=xlPicture
End With
''' Create an empty chart with exact size of range copied
Set cht = wbMCP.Worksheets("Pictures").ChartObjects.Add(Left:=rgExp.Left, Top:=rgExp.Top, _
Width:=rgExp.Width, Height:=rgExp.Height)
cht.Name = "PicChart"
With cht
.Chart.Paste
Debug.Print fileList(x)
.Chart.Export "C:\Users\khill\Documents\Macro Tests\Pics\" & fileList(x) & ".jpg"
.Delete
'Application.CutCopyMode = False
End With
Set cht = Nothing
Set rgExp = Nothing
Next x
End Sub
Have you tried using a clipboard viewer to verify that the rgExp.CopyPicture operation has done what you expect when Debug.Print x shows 5 (6th iteration)?
Assuming you are using some version of Windows, there are some tips on how to view clipboard here, depending on version:
View & Manage Clipboard In Windows 10 / 8 / 7
http://www.thewindowsclub.com/windows-clipboard-manager-viewer
Ok. I found the problem. The charts have to be contained within the viewable screen to be pasted by the clipboard. so you can either zoom out (not ideal because the images are saved small and therefore pixelated) or zoom to the new Chart area/select the position where the chart object is placed in the first place. My solution was to zoom to the range. Adjusted Code is below. Hope this helps someone else :)
Sub PicturesCopy()
'Define path variables
Path = "C:\Users\khill\Documents\Macro Tests\"
PathSC = Path & "Master Cockpit\"
FileMCP = "Master_Daily sales cockpit.xlsm"
Set wbMCP = Workbooks(FileMCP)
Dim cht As ChartObject
Dim rngList, fileList As Variant
rngList = Array("B2:Y19", "B22:U39", "B43:O58", "B61:R76", "B81:J96", "B101:AD118", "B122:V139")
fileList = Array("Fig 1a", "Fig 1b", "Fig 2a", "Fig 2b", "Fig 2c", "Fig 3a", "Fig 3b")
For x = 0 To UBound(rngList)
'Application.CutCopyMode = True
With wbMCP.Worksheets("Graphs")
Debug.Print rngList(x)
Dim rgExp As Range: Set rgExp = .Range(rngList(x))
Debug.Print x
rgExp.CopyPicture Appearance:=xlScreen, Format:=xlPicture
End With
''' Create an empty chart with exact size of range copied
Set cht = wbMCP.Worksheets("Pictures").ChartObjects.Add(Left:=rgExp.Left, Top:=rgExp.Top, _
Width:=rgExp.Width, Height:=rgExp.Height)
cht.Name = "PicChart"
'Use ZoomToRange sub to re-size the window as appropriate
ZoomToRange ZoomThisRange:=Range(rngList(x)), PreserveRows:=True
With cht
.Chart.Paste
Debug.Print fileList(x)
.Chart.Export "C:\Users\khill\Documents\Macro Tests\Pics\" & fileList(x) & ".jpg"
.Delete
'Application.CutCopyMode = False
End With
Set cht = Nothing
Set rgExp = Nothing
Next x
End Sub
The ZoomToRange macro that is called in the above is as follows:
Sub ZoomToRange(ByVal ZoomThisRange As Range, _
ByVal PreserveRows As Boolean)
'###################################
'This macro resizes the window and''
'zoom properties to be appropriate''
'for our use''''''''''''''''''''''''
'###################################
'Turn alerts and screen updating off
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Declare variable type
Dim Wind As Window
'Create variable for window
Set Wind = ActiveWindow
'Zooming to specified range set to true
Application.GoTo ZoomThisRange(1, 1), True
'Select the resized range
With ZoomThisRange
If PreserveRows = True Then
.Resize(.Rows.Count, 1).Select
Else
.Resize(1, .Columns.Count).Select
End If
End With
'Set zoom and visible range to specified range
With Wind
.Zoom = True
.VisibleRange(1, 1).Select
End With
End Sub

Copy and paste rows from Excel to Powerpoint

Ok, here is what I am looking for (Im new, so be gentle):
Copy and paste (default format) from excel to powerpoint (from just the one sheet)
I can only fit so many rows in ppt - so after a slide fills, I want ppt to create a new slide
Same title for each slide is fine!
I only need columns B:K copied over
That's it, however I am stuck :( I know the below code is NOT the best way to write this and it contains errors in which I am sure will be easy to spot. I cannot find how to do this anywhere on the net.
This is what I have so far:
Sub ExcelRangeToPowerPoint()
Dim rng As Excel.Range
Dim PowerPointApp As PowerPoint.Application
Dim myPresentation As PowerPoint.Presentation
Dim mySlide As PowerPoint.Slide
Dim myShapeRange As PowerPoint.Shape
Dim i As Integer
'Create an Instance of PowerPoint
On Error Resume Next
'Is PowerPoint already opened?
Set PowerPointApp = GetObject(class:="PowerPoint.Application")
'Clear the error between errors
Err.Clear
'If PowerPoint is not already open then open PowerPoint
If PowerPointApp Is Nothing Then Set PowerPointApp = CreateObject(class:="PowerPoint.Application")
'Make PowerPoint Visible and Active
PowerPointApp.Visible = True
PowerPointApp.Activate
'Create a New Presentation
Set myPresentation = PowerPointApp.Presentations.Add
'Add a slide to the Presentation
Set mySlide = myPresentation.Slides.Add(1, ppLayoutTitleOnly)
For i = 1 To 6
'need to set focus to slde 1
PowerPointApp.ActiveWindow.View.GotoSlide (1)
'Deletes Title
'mySlide.Shapes.Title.Delete
'builds new title
mySlide.Shapes.AddShape Type:=msoShapeRectangle, left:=9, Top:=6, Width:=702, Height:=30
mySlide.Shapes(mySlide.Shapes.Count).Line.Visible = msoTrue
mySlide.Shapes(mySlide.Shapes.Count).TextFrame.TextRange.Font.Size = 20
mySlide.Shapes(mySlide.Shapes.Count).TextFrame.TextRange.Font.Color.RGB = RGB(0, 0, 0)
mySlide.Shapes(mySlide.Shapes.Count).TextFrame.TextRange.ParagraphFormat.Alignment = ppAlignLeft
mySlide.Shapes(mySlide.Shapes.Count).TextFrame.TextRange.Text = "Current Full Initiative Details – Branded Book as of " & Date
mySlide.Shapes(mySlide.Shapes.Count).Name = "I am TITLE"
mySlide.Shapes(mySlide.Shapes.Count).Line.ForeColor.RGB = RGB(0, 0, 0)
mySlide.Shapes(mySlide.Shapes.Count).Line.Weight = 1
mySlide.Shapes(mySlide.Shapes.Count).Fill.Visible = msoTrue
mySlide.Shapes(mySlide.Shapes.Count).Fill.ForeColor.RGB = RGB(255, 255, 255)
'Copy Range from Excel
Set rng = ActiveWorkbook.Worksheets("RAW").Range("B1:K23")
'Copy Excel Range
rng.Copy
'Paste to PowerPoint and position
PowerPointApp.ActiveWindow.View.PasteSpecial DataType:=ppPasteDefault
Set myShapeRange = mySlide.Shapes(mySlide.Shapes.Count)
'Set position:
myShapeRange.left = 10
myShapeRange.Top = 42
myShapeRange.Height = 492
myShapeRange.Width = 702
ActiveWorkbook.Sheets("RAW").Rows("2:23").Delete
Call myPresentation.Slides.Add(1, PpSlideLayout.ppLayoutTitleOnly)
'Clear The Clipboard
Application.CutCopyMode = False
Next i
End Sub
As requested in comments, here is the code I use to copy a slide from a master PPT template to the report PPT.
There is some extraneous code in there to provide status updates on the form we use to drive the process, as well as a debugging flag that I can toggle on/off at run time - these can both be removed.
This will serve as a starting point to finding the proper solution for your situation, and is not a complete answer to the question as asked.
'I've chosen to declare these globally, though it's probably not the best way:
Dim PPTObj As PowerPoint.Application
Dim PPTMaster As PowerPoint.Presentation
Dim PPTClinic As PowerPoint.Presentation
Private Sub InsertPPT(ByVal SlideName As String, ByVal StatusText As String)
Dim Shp As PowerPoint.Shape
Dim Top As Single
Dim Left As Single
Dim Height As Single
Dim width As Single
PPTMaster.Slides(SlideName).Copy
PPTClinic.Slides.Paste
Form_Master.ProcessStatus.Value = StatusText & " InsertPPT"
With PPTClinic.Slides(PPTClinic.Slides.count)
If Debugging Then
.Select
End If
.Design = PPTMaster.Slides(SlideName).Design 'this ensures we get all the right formatting - only seems to be necessary 1 time, but we'll just do it on all
.ColorScheme = PPTMaster.Slides(SlideName).ColorScheme
.FollowMasterBackground = PPTMaster.Slides(SlideName).FollowMasterBackground
For Each Shp In .Shapes 'loop through all the shapes on the slide
If Debugging Then
' .Select
Shp.Select
End If
Form_Master.ProcessStatus.Value = StatusText & " InsertPPT-" & Shp.Name
If Shp.Type = msoLinkedOLEObject Then 'when we find a linked one
ReLinkShape Shp, TempVars!NewXLName
'need to store off top, left, width, height
Top = Shp.Top
Left = Shp.Left
Height = Shp.Height
width = Shp.width
Shp.LinkFormat.Update 'and force the link to refresh
MySleep 2, "S" 'hopefully, the 2 second pause will allow everything to update properly before moving on.
'then reset them here - they seem to change shape when I update them
Shp.LockAspectRatio = msoFalse
Shp.Top = Top
Shp.Left = Left
Shp.width = width
Shp.Height = Height
ElseIf Shp.Name = "SlideName" And Not Debugging Then 'if it's the "SlideName" tag
Shp.Delete 'delete it (unless we're debugging)
End If
Next
End With
Form_Master.ProcessStatus.Value = StatusText
End Sub
Private Sub ReLinkShape(ByRef Shp As PowerPoint.Shape, ByVal NewDestination As String)
Dim Link() As String
Dim link2() As String
If Shp.Type = msoLinkedOLEObject Then 'when we find a linked one
Link = Split(Shp.LinkFormat.SourceFullName, "!") 'update the link to point to the new clinic spreadsheet instead of the master
If InStr(1, Link(2), "]") > 0 Then
link2 = Split(Link(2), "]")
Link(2) = "[" & TempVars!ClinicName & ".xlsx]" & link2(1)
End If
Shp.LinkFormat.SourceFullName = NewDestination & "!" & Link(1) & "!" & Link(2)
End If
End Sub
Public Sub MySleep(ByRef Unit As Double, ByRef UOM As String)
Dim Pause As Date
Pause = DateAdd(UOM, Unit, Now())
While Now < Pause
DoEvents
Wend
End Sub