I have an Excel file with a few charts and the attached dashboard (as can be seen in the image).
I am copying the charts objects from Excel to PowerPoint, but not sure what is the best way of copying the attached dashboard to PowerPoint, as it consists of a range of Excel cells, some Indicators using Conditional Formatting, and a circle object.
I don't want to copy it as a picture, because then it looks like it's out-of-focus in PowerPoint.
I have added a section of my code (not the whole thing as it's very long), just want to know the method of copying this dashboard image.
Public Sub UpdatePowerPoint(PowerPointFile)
'Add a reference to the Microsoft PowerPoint Library by:
'1. Go to Tools in the VBA menu
'2. Click on Reference
'3. Scroll down to Microsoft PowerPoint X.0 Object Library, check the box, and press Okay
Dim ppProgram As PowerPoint.Application
Dim ppPres As PowerPoint.Presentation
Dim ppFullPath As String
Dim ppName As String
Dim activeSlide As PowerPoint.Slide
Dim cht As Excel.ChartObject
Dim cht_count As Integer
Dim myShape As Object
Dim myChart As Object
Dim SlideNum, GPLRank As Integer
Dim ProjectIPPNum, ProjectName As String
Dim ShapeNum As Integer
Dim ExpenseActual, ExpenseBalance As Long
Dim StageStat As String
Dim nextKD As String
Dim shapeStageStat As Shape
On Error Resume Next
Set ppProgram = GetObject(, "PowerPoint.Application")
On Error GoTo 0
ppFullPath = PowerPointFile
If ppProgram Is Nothing Then
Set ppProgram = New PowerPoint.Application
i = 1
Else
If ppProgram.Presentations.Count > 0 Then
ppName = Mid(ppFullPath, InStrRev(ppFullPath, "\") + 1, Len(ppFullPath))
i = 1
ppCount = ppProgram.Presentations.Count
Do Until i = ppCount + 1
If ppProgram.Presentations.Item(i).Name = ppName Then
Set ppPres = ppProgram.Presentations.Item(i)
GoTo OnePager_Pres_Found
Else
i = i + 1
End If
Loop
End If
End If
ppProgram.Presentations.Open Filename:=PowerPointFile ' 'PowerPointFile = "C:\Test.pptx"
Set ppPres = ppProgram.Presentations.Item(i)
OnePager_Pres_Found:
ppPres.Windows(1).Activate ' activate the One-Pager Presentation in case you have several open, and the One_pager is currently not the app "on-focus"
' loop through all PowerPoint Slides, and copy all Chart objects from Excel
For ProjectCounter = 0 To NumberofProjectShts
Worksheets(ProjectShtName(ProjectCounter)).Activate
GPLRank = ActiveSheet.Cells(12, 2)
SlideNum = ActiveSheet.Cells(24, 2)
ProjectIPPNum = ActiveSheet.Cells(2, 2)
ProjectName = ActiveSheet.Cells(3, 2)
StageStat = ActiveSheet.Cells(20, 2)
nextKD = ActiveSheet.Cells(18, 2)
ExpenseActual = ActiveSheet.Cells(33, 4)
ExpenseBalance = ActiveSheet.Cells(33, 5)
On Error GoTo Error_PPTSlideNum_Handler
ppProgram.ActivePresentation.Slides(SlideNum).Select
Set myShape = ppProgram.ActivePresentation.Slides(SlideNum).Shapes
' --- loop throughout the Slide shapes and search for the Shape of type chart, then delete the old ones
For i = myShape.Count To 1 Step -1
If myShape.Item(i).HasChart Or myShape.Item(i).Type = msoEmbeddedOLEObject Or myShape.Item(i).Type = msoPicture Then
myShape.Item(i).Delete
Else
If myShape.Item(i).Left > 600 Then
myShape.Item(i).Delete
Else
Select Case myShape.Item(i).AutoShapeType
Case msoShapeOval, msoShapeOctagon, msoShapeIsoscelesTriangle
myShape.Item(i).Delete
End Select
End If
End If
Next
'Show the PowerPoint
ppProgram.Visible = True
' select the 1-Pager Slide number which we will update the charts with the Excel Charts
Set activeSlide = ppProgram.ActivePresentation.Slides(SlideNum)
' --- copy the dasboard (with Stage Status indicator) from Excel to Powerpoint , as Embedded Excel object ---
' this is the part I've added to copy the dashboard from Excel to PowerPoint slide
Columns("F:G").ColumnWidth = 7.71
Columns("H:J").ColumnWidth = 4.71
Rows("1:4").RowHeight = 18.75
ActiveSheet.Range("F1:J4").Copy ' .Select
' Paste to PowerPoint and position
Set myShape = ppProgram.ActivePresentation.Slides(SlideNum).Shapes.PasteSpecial(ppPasteMetafilePicture, msoFalse)
' Set Dashboard object properties:
myShape.Left = 536 ' 7.44"
myShape.Top = 7 ' 0.1"
' --- Loop through each chart in the Excel worksheet and paste them into the PowerPoint ---
For Each cht In ActiveSheet.ChartObjects
'go to the 1-Pager Slide number where we will update the charts with the Excel Charts
Set activeSlide = ppProgram.ActivePresentation.Slides(SlideNum)
'Copy the chart and paste it into the PowerPoint as a Metafile Picture
cht.Select
ActiveChart.ChartArea.Copy
If cht.Name = "RiskRadar_Chart" Then ' change paste setting only for Radar type chart, to look nicer in PowerPoint
Set myChart = ppProgram.ActivePresentation.Slides(SlideNum).Shapes.PasteSpecial(ppPasteMetafilePicture, msoFalse)
Else
Set myChart = ppProgram.ActivePresentation.Slides(SlideNum).Shapes.PasteSpecial(ppPasteDefault, msoFalse) 'ppPasteShape
End If
'Adjust the positioning of the Chart on Powerpoint Slide , each inch is 72 points
Select Case cht.Name
Case "Timeline_Chart" ' 1 ' Timeline Chart
myChart.Left = 11 ' 0.16"
myChart.Top = 403 ' 5.55"
Case "Budget_Chart" ' 2 ' Man-Hours Chart
myChart.Left = 387 ' 5.37"
myChart.Top = 284 ' 3.94"
Case "Expense_Chart" ' 3 ' Expense Chart
myChart.Left = 387 ' 5.37"
myChart.Top = 347 ' 4.81"
Case "RiskRadar_Chart" ' 4 ' Risk-Radar Chart
myChart.Left = 449 ' 6.23"
myChart.Top = 7 ' 0.1"
End Select
Next
' --- Add Stage Status indicator with Next KD text inside (except PARK) ----
Select Case StageStat
Case "Green"
With activeSlide.Shapes.AddShape(msoShapeOval, 652, 16, 32, 32) ' Left, Top , Width ,Height
.Fill.ForeColor.RGB = RGB(0, 128, 0) ' color Green
.Fill.Solid
.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
.Line.Weight = 0.75
.TextFrame.TextRange.Font.color.RGB = RGB(0, 0, 0) ' Shape Text Color
.TextFrame.TextRange.Characters.Text = nextKD ' Text inside Shape
.TextFrame2.TextRange.Font.Size = 14 ' Adjust Font Size
.TextFrame2.TextRange.Font.Name = "Arial" ' Adjust Font Style
.TextFrame.TextRange.Paragraphs.ParagraphFormat.Alignment = ppAlignCenter ' Center Align Text
.TextFrame2.VerticalAnchor = msoAnchorMiddle ' Vertically Align Text to Middle
.TextFrame2.MarginLeft = 0
.TextFrame2.MarginRight = 0
End With
Case "Yellow"
With activeSlide.Shapes.AddShape(msoShapeRectangle, 652, 16, 32, 32) ' Left, Top , Width ,Height
.Fill.ForeColor.RGB = RGB(255, 255, 0) ' color Yellow
.Fill.Solid
.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
.Line.Weight = 0.75
.TextFrame.TextRange.Font.color.RGB = RGB(0, 0, 0) ' Shape Text Color
.TextFrame.TextRange.Characters.Text = nextKD ' Text inside Shape
.TextFrame2.TextRange.Font.Size = 14 ' Adjust Font Size
.TextFrame2.TextRange.Font.Name = "Arial" ' Adjust Font Style
.TextFrame.TextRange.Paragraphs.ParagraphFormat.Alignment = ppAlignCenter ' Center Align Text
.TextFrame2.VerticalAnchor = msoAnchorMiddle ' Vertically Align Text to Middle
.TextFrame2.MarginLeft = 0
.TextFrame2.MarginRight = 0
End With
Case "Red"
With activeSlide.Shapes.AddShape(msoShapeIsoscelesTriangle, 652, 16, 36, 36) ' Left, Top , Width ,Height
.Fill.ForeColor.RGB = RGB(255, 0, 0) ' color Red
.Fill.Solid
.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
.Line.Weight = 0.75
.TextFrame.TextRange.Font.color.RGB = RGB(0, 0, 0) ' Shape Text Color
.TextFrame.TextRange.Characters.Text = nextKD ' Text inside Shape
.TextFrame2.TextRange.Font.Size = 14 ' Adjust Font Size
.TextFrame2.TextRange.Font.Name = "Arial" ' Adjust Font Style
.TextFrame.TextRange.Paragraphs.ParagraphFormat.Alignment = ppAlignCenter ' Center Align Text
.TextFrame2.VerticalAnchor = msoAnchorMiddle ' Vertically Align Text to Middle
.TextFrame2.MarginLeft = 0
.TextFrame2.MarginRight = 0
.TextFrame2.Column.Number = 2
End With
End Select
Error_PPTSlideNum_Handler:
If Err.Number <> 0 Then
Err.Clear
MsgBox "Project " & ProjectName & " Slide Number " & SlideNum & " not found in selected PowerPoint. " & _
vbCrLf & "Update your Slide Number according to it's position.", vbInformation, "PowerPoint Slide Number Error"
End If
Next ' ProjectCounter = 0 To NumberofProjectShts
AppActivate ("Microsoft PowerPoint")
Set activeSlide = Nothing
Set ppProgram = Nothing
Set ppPres = Nothing
End Sub
You can try with the sample example shown here. Lot of effort goes to properly naming the ranges for various parameters which is done in Excel worksheet. I have also shown a snapshot of the name manager to give you an idea and also the snapshot of final output of the dashboard in the PowerPoint.
Option Explicit
Dim PP As Object
Dim PP_File As Object
Dim PP_Slide As Object
Private Sub CopyandPastetoPPT(myRangeName As String, myTitle As String, myScaleHeight As Single, myScaleWidth As Single)
Dim NextShape As Integer
Dim ReportDate As String
ReportDate = Range("myReportDate").Value & " / Week " & Range("myReportWeek").Value & " - "
Application.GoTo Reference:=myRangeName
Selection.CopyPicture Appearance:=xlScreen, Format:=xlPicture
Range("A1").Select
PP.ActivePresentation.Slides.Add PP.ActivePresentation.Slides.Count + 1, 11
Set PP_Slide = PP_File.Slides(PP.ActivePresentation.Slides.Count)
PP_Slide.Shapes.Title.TextFrame.TextRange.Text = ReportDate & myTitle
NextShape = PP_Slide.Shapes.Count + 1
PP_Slide.Shapes.PasteSpecial 2
PP_Slide.Shapes(NextShape).ScaleHeight myScaleHeight, 1
PP_Slide.Shapes(NextShape).ScaleWidth myScaleWidth, 1
PP_Slide.Shapes(NextShape).Left = PP_File.PageSetup.SlideWidth \ 2 - PP_Slide.Shapes(NextShape).Width \ 2
PP_Slide.Shapes(NextShape).Top = 90
End Sub
Sub ExportToPPT()
Dim ActFileName As Variant
Dim ScaleFactor As Single
On Error GoTo ErrorHandling
ActFileName = Application.GetOpenFilename("Microsoft PowerPoint-Files (*.ppt), *.ppt")
ScaleFactor = Range("myScaleFactor").Value
Set PP = CreateObject("Powerpoint.Application")
If ActFileName = False Then
PP.Activate
PP.Presentations.Add
Set PP_File = PP.ActivePresentation
Else
PP.Activate
Set PP_File = PP.Presentations.Open(ActFileName)
End If
PP.Visible = True
CopyandPastetoPPT "myDashboard01", Range("myInputStartTitles").Offset(1, 0).Value, ScaleFactor, ScaleFactor
Set PP_Slide = Nothing
Set PP_File = Nothing
Set PP = Nothing
Worksheets(1).Activate
Exit Sub
ErrorHandling:
Set PP_Slide = Nothing
Set PP_File = Nothing
Set PP = Nothing
MsgBox "Error No.: " & Err.Number & vbNewLine & vbNewLine & "Description: " & Err.Description, vbCritical, "Error"
End Sub
Related
I'm trying to insert a textbox below a chosen image with Inline text wrapping and position it at the left bottom of the image. I'm using the below code without much success. I'm not too sure whether to use a ShapeRange or an InlineShape. Any pointers?
Dim shp As Object
'Set shp = Selection.ShapeRange(1)
'Set rng = shp.Anchor
Set shp = Selection.InlineShapes(1)
Set rng = shp.Range
With ActiveDocument.Shapes.AddTextbox(Orientation:=msoTextOrientationHorizontal, Left:=shp.Left, Top:=(shp.Top + shp.Height), Width:=shp.Width / 3, Height:=shp.Height / 6, Anchor:=rng)
.TextFrame.TextRange.Font.Size = 14
.TextFrame.TextRange.Font.Color = RGB(186, 14, 29)
.TextFrame.TextRange.Font.Name = "Sabon MT"
.TextFrame.TextRange = "T"
End With
I managed to find a solution for getting the coordinates for the shape from here: http://www.vbaexpress.com/forum/archive/index.php/t-48831.html
Here's my code:
Sub AddTextBox
Set shp = Selection.InlineShapes(1)
Set rng = shp.Range
Set tb = ActiveDocument.Shapes.AddTextbox(1, fcnXCoord, fcnYCoord + shp.Height, shp.Width, shp.Height / 6)
End Sub
Function fcnXCoord() As Double
fcnXCoord = Selection.Information(wdHorizontalPositionRelativeToPage)
End Function
Function fcnYCoord() As Double
fcnYCoord = Selection.Information(wdVerticalPositionRelativeToPage)
End Function
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
I have a PowerPoint 2010 presentation with a table on one slide.
I want to create a VBA modeless form that will work like a pallete of
formats/colors for formatting cells of that table.
Basically, the buttons on the form would just simulate clicking
specific Shading color in Table Tools/Design menu.
example:
I place the cursor to the cell then click on a button in activated modeless form. The shading of that cell will change according to the color in the code.
The reason I want to do this is that some other people will use it and the colors must be easily accessible (format painter doesn't not seem to copy the shading)
But I cannot find a way to make this VBA. I have tried recording macro in Word (not possible in PP) with no success.
Try this... (Not polished code, but should give you what you need(ed))
Public sub TblCellColorFill()
Dim X As Integer
Dim Y As Integer
Dim oTbl as Table
set oTbl = ActiveWindow.Selection.Shaperange(1).Table 'Only works is a single table shape is selected - add some checks in your final code!
For X = 1 To otbl.Columns.Count
For Y = 1 To otbl.Rows.Count
With otbl.Cell(Y, X)
If .Selected <> False Then 'Strange bug - will ignore if statement entirely if you use "= True"
'Debug.Print "Test worked " & Now
'We have the shape we need
.shape.Fill.ForeColor.RGB = RGB(100, 150, 200) 'Add your color here
End If
End With
Next 'y
Next 'x
End Sub
For table styling in MSPowerPoint 2013 I use
Sub STYLE_TABLE_2()
' Change table style
' Two rows Dark Gray and White Font
' Next odd rows Light Gray/ even Moderate Gray/ and Black Font
Dim iCols As Integer
Dim iRows As Integer
Dim oTbl As Table
' Debug.Print (ActiveWindow.Selection.ShapeRange(1).Type)
With ActiveWindow.Selection
If .Type = ppSelectionShapes Then ' Shape is selected ppSelectionShapes=2 ppSelectionSlides=3 ppSelectionNone=0
If .ShapeRange(1).Type = msoTable Then ' If first shape Type=19 is msoTable
' (--- note not all table-looking shapes are Table style Can be Type=14 msoPlaceholder
Debug.Print ("We are certain inside table") '
Set oTbl = ActiveWindow.Selection.ShapeRange(1).Table 'Only works if single table or its part is selected
For iCols = 1 To oTbl.Columns.Count
For iRows = 1 To oTbl.Rows.Count
With oTbl.Cell(iRows, iCols)
.Shape.TextFrame.TextRange.Font.Name = "Arial"
.Shape.TextFrame.TextRange.Font.Size = 12
If iRows Mod 2 <> 0 Then ' Odd numbers
Debug.Print ("Ymod2 2") '
.Shape.Fill.ForeColor.RGB = RGB(236, 234, 241)
Else
.Shape.Fill.ForeColor.RGB = RGB(215, 210, 225)
End If
If (.Selected <> False) And (iRows < 3) Then 'Cannot be "= True"
.Shape.Fill.ForeColor.RGB = RGB(166, 166, 166)
.Shape.TextFrame.TextRange.Font.Name = "Arial"
.Shape.TextFrame.TextRange.Font.Color = RGB(255, 255, 255)
.Shape.TextFrame.TextRange.Font.Size = 12
End If
End With
Next 'iRows
Next 'iCols
End If
End If
End With
End Sub
So i have been struggling with this for the past few days, i have this powerpoint 2007 presentation that i fill with information from a button in a from in a access file using VBA.
And in the first slide (and only by now) i have a table that will receive part of the information, however i can't make the table content break to another slide if the table exceeds the bottom of the slide, it just goes out of range.
I have the method to create a the new slide, and that works fine. But i can't seem to find an example that could get me started.
I think i should be something like check the table bottom exceeds slide bottom if it does create a new slide, cut the overlap cells and paste them in the new slide?
Thanks in Advance.
The code example:
' Open PowerPoint
Dim pptobj As PowerPoint.Application
Dim Presentation As PowerPoint.Presentation
Dim oSl as Slide
Set pptobj = New PowerPoint.Application
Set pptobj = CreateObject("Powerpoint.Application")
pptobj.Activate
Set Presentation = pptobj.Presentations.Open("C:\Users\some.pptx")
pptobj.Visible = True
pptobj.WindowState = ppWindowMaximized
If ((Len(Forms!Some!Name> 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableNome").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!Name))
End If
Set oSl = pptobj.ActivePresentation.Slides(1)
With oSl
.Shapes("TableCategory").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = (CStr(Forms!CVLong!TxtCategory))
.Shapes("TableEmail").Table.Cell(1, 2).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!TxtEmail))
.Shapes("TableData").Table.Cell(1, 2).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!TxtTlf))
.Shapes("TableData").Table.Cell(2, 2).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!TxtCell))
End With
Dim oSh as Shape
Dim overhang
Set oSh = pptobj.ActivePresentation.Slides(1).Shapes.AddTable(1, 3, 50, 100, 493)
'One
If ((Len(Forms!Some!One)) > 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(1, 3).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!One)) & vbNewLine & vbNewLine
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(1, 1).Shape.TextFrame.TextRange.Text = "One"
End If
'Two
If (Len(Forms!Some!Two> 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(5, 3).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!Two)) & vbNewLine
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(5, 1).Shape.TextFrame.TextRange.Text = "Two"
End If
'Three
If (Len(Forms!Some!Three) > 0) Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(4, 3).Shape.TextFrame.TextRange.Text = (CStr(Forms!Some!Three)) & vbNewLine & vbNewLine
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(4, 1).Shape.TextFrame.TextRange.Text = "Three"
End If
'Add Slide
Dim Sld As Slide
Dim x As Integer
x = 1
Set Sld = pptobj.ActivePresentation.Slides.Add(Index:=pptobj.ActivePresentation.Slides.Count + 1, Layout:=ppLayoutBlank)
For Each Sld In pptobj.ActivePresentation.Slides
If x >= 2 Then
pptobj.ActivePresentation.Slides(1).Shapes("Text Placeholder 15").Copy
pptobj.ActivePresentation.Slides(x).Shapes.Paste
pptobj.ActivePresentation.Slides(x).Shapes("Text Placeholder 15").ZOrder msoSendToBack
pptobj.ActivePresentation.Slides(x).Shapes("Text Placeholder 15").Height = 810
pptobj.ActivePresentation.Slides(x).Shapes("Text Placeholder 15").Top = 19
End If
x = x + 1
Next
End If
'Put table top border
Dim n As Integer
Dim r As Integer
n = 3
r = 1
While r <= n
If Len(pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(r, 3).Shape.TextFrame.TextRange.Text) > 0 Then
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(r, 3).Borders(ppBorderTop).Visible = msoTrue
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Cell(r, 3).Borders(ppBorderTop).ForeColor.RGB = RGB(220, 105, 0)
Else
pptobj.ActivePresentation.Slides(1).Shapes("TableInfo").Table.Rows(r).Delete
n = n - 1
r = r - 1
End If
r = r + 1
Wend
'Add Photo
pptobj.ActivePresentation.Slides(1).Shapes.AddPicture(FileName:="\\someplace\" & [Id] & ".jpg", linktofile:=mostrue, savewithdocument:=msoTrue, Left:=52, Top:=115).Select
With pptobj.ActivePresentation.Slides(1).Shapes("Picture 7")
.LockAspectRatio = msoTrue
.Width = 85
.Left = 38
.Top = 80
End With
'add footer
Dim page As Integer
page = 1
Dim s As Slide
For Each s In pptobj.ActivePresentation.Slides
On Error Resume Next
Set oSh = s.HeadersFooters.Footer
If Err.Number <> 0 Then
Call s.Master.Shapes.AddPlaceholder(ppPlaceholderFooter, 219, 805, 342, 19)
End If
On Error GoTo 0
s.HeadersFooters.Footer.Visible = msoTrue
s.HeadersFooters.Footer.Text = (CStr(Forms!Some!Name)) & " - Page " & page & " of " & pptobj.ActivePresentation.Slides.Count
page = page + 1
Next
The following code snippet may give you some inspiration. Right now it just determines that the table is too large and gives you a message. Without more information about the type of data and how you obtained it, it's hard to give an answer to the second part of the problem. Most likely you would create a table, add one row at a time and check the size of the table; when the table gets too large (or within a certain distance from the bottom) you create a new slide and continue the process. That is probably better than creating a table that's too large, then trying to figure out where to cut it.
Here is the code:
Sub createTable()
Dim oSl As Slide
Dim oSh As Shape
Dim overhang
Set oSl = ActivePresentation.Slides(1)
Set oSh = oSl.Shapes.AddTable(28, 3)
overhang = ActivePresentation.PageSetup.SlideHeight - (oSh.Height + oSh.Top)
If overhang > 0 Then
MsgBox "the table fits"
Else
MsgBox "the table is too big!"
End If
End Sub
I'm trying to replace all shape objects on the slide (pictures) with shape objects of another type (rectangular shape). I can delete old object and create new, but i will loose all animation information and sequence order. Is it possible to store animation information and order in timeline, and copy it to the new shape object?
Well, i have found a solution myself, hope someone could find it useful. So, it is not necessary to copy animation information from old shape to a new one, just cycle through sequence's items and replace the shape object refrence to the new shape. Like this:
On Error Resume Next
Dim shp1 As Shape 'old shape
Set shp1 = ActivePresentation.Slides(1).Shapes(3)
Dim shp2 As Shape 'new shape
Set shp2 = ActivePresentation.Slides(1).Shapes.AddPicture("c:\imgres2.jpg", msoFalse, msoTrue, 0, 0) 'it is important to create new shape before cycling through existing ones.
For i = ActivePresentation.Slides(1).TimeLine.MainSequence.count To 1 Step -1
'using "is" opeartor to compare refrences
If shp1 Is ActivePresentation.Slides(1).TimeLine.MainSequence.Item(i).Shape Then
ActivePresentation.Slides(1).TimeLine.MainSequence.Item(i).Shape = shp2
End If
Next i
shp1.Delete 'delete the old shape
Try something like this code to copy the animation into new added shape:
Sub PasteAnimationBehaviours()
Dim SHP As Shape 'for existing shape
Set SHP = ActivePresentation.Slides(1).Shapes(1)
SHP.PickupAnimation
Dim newSHP As Shape 'pasting to new shape
Set newSHP = ActivePresentation.Slides(1).Shapes.AddShape(msoShapeRectangle, 100, 100, 100, 100)
newSHP.ApplyAnimation
End Sub
Added after comment: If you only need to replace type of shape try to use something like this:
Sub ShapeSubstition()
Dim SHP As Shape 'for existing shape
'test for 1st shape in 1st slide
Set SHP = ActivePresentation.Slides(1).Shapes(1)
SHP.AutoShapeType = msoShapeRectangle 'to rectangle
SHP.AutoShapeType = msoShapeOval 'to oval
End Sub
I think it is probably easier to just use the "Animation Painter" command button to copy the animations and apply them to another object. The Animation Painter functions in the same way as the Format Painter. After you have copied the desired animations, you can reorder the individual animations using the Animation Pane.
This code shows how to copy effects from one shape to another. Select a shape before running routine "SetSourceShape" and select one or more shapes before running "PaintEffects".
Option Explicit
' resources:
' http://msdn.microsoft.com/en-us/library/aa168134(v=office.11).aspx
' http://msdn.microsoft.com/en-us/library/aa168135(office.11).aspx
' http://skp.mvps.org/ppttimeline1.htm
' uses functions from:
' https://answers.microsoft.com/en-us/msoffice/forum/all/how-to-copy-paste-animation-effect-in-powerpoint/c0f255c0-167a-4a12-ae37-1e713ee1d8df
Public MySourceShapeId As Long
Public MySourceSlideIndex As Long ' need this with shape id for unique selection
Sub SetSourceShape() ' sets source shape id value if successfull
Dim oShp As PowerPoint.Shape
Dim myShp As PowerPoint.Shape
Dim oSld As Slide
Dim oEffect As Effect
Dim HowMany As Long
Dim FoundEffect As Boolean
HowMany = 0 ' default value for nothing selected
MySourceShapeId = 0 ' default value for nothing available to copy
MySourceSlideIndex = 0
FoundEffect = False ' default value unless selected shape has any effect(s)
On Error Resume Next ' handles error when nothing is selected
HowMany = ActiveWindow.Selection.ShapeRange.Count
On Error GoTo 0 ' restore normal error handling
If HowMany = 0 Then
MsgBox "Nothing is selected"
Else
If HowMany = 1 Then
Set oShp = ActiveWindow.Selection.ShapeRange(1) ' selection on a single slide
For Each oEffect In ActiveWindow.Selection.SlideRange(1).TimeLine.MainSequence
If oEffect.Shape.Id = oShp.Id Then
MySourceShapeId = oShp.Id
MySourceSlideIndex = ActiveWindow.Selection.SlideRange(1).SlideIndex
FoundEffect = True
End If
Next
If FoundEffect Then
MsgBox "Source is selected, Slide: " & MySourceSlideIndex & ", ShapeID: " & MySourceShapeId
Else
MsgBox "Selected item has no effect(s)"
End If
Else
MsgBox "Select only one item"
End If
End If
End Sub
Sub PaintEffects()
Dim oShp As PowerPoint.Shape
Dim oEffect As Effect
Dim HowMany As Long
Dim msg As String
HowMany = 0 ' default value for nothing selected
If MySourceShapeId = 0 Then
MsgBox "No source is selected"
Exit Sub
End If
On Error Resume Next ' handles error when nothing is selected
HowMany = ActiveWindow.Selection.ShapeRange.Count
On Error GoTo 0 ' restore normal error handling
If HowMany = 0 Then
MsgBox "Nothing is selected to paint"
Else
' make sure source is not in this selection
If ActiveWindow.Selection.SlideRange(1).SlideIndex = MySourceSlideIndex Then ' check shapes
For Each oShp In ActiveWindow.Selection.ShapeRange
If oShp.Id = MySourceShapeId Then ' complain
MsgBox "Target selection must not include source item"
Exit Sub
End If
Next
End If
' OK, proceed
For Each oShp In ActiveWindow.Selection.ShapeRange
For Each oEffect In ActivePresentation.Slides(MySourceSlideIndex).TimeLine.MainSequence
If oEffect.Shape.Id = MySourceShapeId Then
Call TransferEffects(oEffect, ActiveWindow.Selection.SlideRange(1), oShp)
End If
Next
Next
End If
End Sub
Sub TransferEffects(oEffectA As PowerPoint.Effect, oSlide As Slide, oShape As PowerPoint.Shape)
Dim oEffectB As Effect
Dim IsMotion As Boolean
Set oEffectB = oSlide.TimeLine.MainSequence.AddEffect(oShape, oEffectA.EffectType)
DoEvents
On Error Resume Next
oEffectB.EffectParameters.Amount = oEffectA.EffectParameters.Amount
If Err.Number = 0 Then
Select Case oEffectA.EffectParameters.Color2.Type
Case Is = msoColorTypeScheme
oEffectB.EffectParameters.Color2.SchemeColor = oEffectA.EffectParameters.Color2.SchemeColor
Case Is = msoColorTypeRGB
oEffectB.EffectParameters.Color2.RGB = oEffectA.EffectParameters.Color2.RGB
End Select
End If
oEffectB.EffectParameters.Direction = oEffectA.EffectParameters.Direction
oEffectB.EffectParameters.FontName = oEffectA.EffectParameters.FontName
If oEffectA.EffectType <> msoAnimEffectGrowShrink Then
oEffectB.EffectParameters.Size = oEffectA.EffectParameters.Size
Else
oEffectB.Behaviors(1).ScaleEffect.ByX = oEffectA.Behaviors(1).ScaleEffect.ByX
oEffectB.Behaviors(1).ScaleEffect.ByY = oEffectA.Behaviors(1).ScaleEffect.ByY
End If
oEffectB.Timing.Duration = oEffectA.Timing.Duration
oEffectB.Timing.Accelerate = oEffectA.Timing.Accelerate
oEffectB.Timing.AutoReverse = oEffectA.Timing.AutoReverse
oEffectB.Timing.Decelerate = oEffectA.Timing.Decelerate
oEffectB.Timing.Restart = oEffectA.Timing.Restart
oEffectB.Timing.RewindAtEnd = oEffectA.Timing.RewindAtEnd
oEffectB.Timing.SmoothStart = oEffectA.Timing.SmoothStart
oEffectB.Timing.SmoothEnd = oEffectA.Timing.SmoothEnd
oEffectB.Exit = oEffectA.Exit
oEffectB.Timing.TriggerType = oEffectA.Timing.TriggerType
oEffectB.Timing.TriggerDelayTime = oEffectA.Timing.TriggerDelayTime
oEffectB.Timing.RepeatCount = oEffectA.Timing.RepeatCount
oEffectB.Timing.RepeatDuration = oEffectA.Timing.RepeatDuration
oEffectB.Timing.Speed = oEffectA.Timing.Speed
With oSlide.TimeLine.MainSequence
If oEffectA.Shape.HasTextFrame Then
Call .ConvertToAnimateBackground(oEffectB, oEffectA.EffectInformation.AnimateBackground)
Else
Call .ConvertToAnimateBackground(oEffectB, True)
End If
Select Case oEffectA.EffectInformation.AfterEffect
Case 2 ' Hide
Call .ConvertToAfterEffect(oEffectB, oEffectA.EffectInformation.AfterEffect)
Case 1 ' Dim
Call .ConvertToAfterEffect(oEffectB, oEffectA.EffectInformation.AfterEffect, oEffectA.EffectInformation.Dim)
Case 3 ' Hide on click
Call .ConvertToAfterEffect(oEffectB, oEffectA.EffectInformation.AfterEffect)
End Select
Call .ConvertToAnimateInReverse(oEffectB, oEffectA.EffectInformation.AnimateTextInReverse)
Call .ConvertToTextUnitEffect(oEffectB, oEffectA.EffectInformation.TextUnitEffect)
End With
Err.Clear
oEffectB.EffectParameters.Relative = oEffectA.EffectParameters.Relative
If Err.Number <> 0 Then
IsMotion = False
Else
IsMotion = True
End If
If IsMotion Then
oEffectB.Behaviors(1).MotionEffect.Path = oEffectA.Behaviors(1).MotionEffect.Path
On Error GoTo 0
If Sgn(Val(oEffectA.Behaviors(1).Timing.Speed)) = -1 Then
oEffectB.Behaviors(1).MotionEffect.Path = Left(oEffectA.Behaviors(1).MotionEffect.Path, 1) & " " & ReversePathInfo(Trim(Mid(oEffectA.Behaviors(1).MotionEffect.Path, 2)))
End If
End If
Exit Sub
errHandler:
If MsgBox(Err.Number & " " & Err.Description & vbCrLf & "Do you wish to continue?", vbQuestion + vbYesNo, "APP_NAME") = vbYes Then
Resume Next
End If
End Sub
Function ReversePathInfo(sPath As String) As String
Dim sItems() As String
Dim i As Integer
Dim sPositions() As String
Dim sReversedPath As String
Dim sClosedPath As String
If Not IsNumeric(Right(sPath, 1)) Then
sClosedPath = Right(sPath, 1)
sPath = Left(sPath, Len(sPath) - 1)
End If
sPath = Replace(sPath, " ", "~")
sItems = Split(sPath, "~")
ReDim sPositions(0 To UBound(sItems))
For i = LBound(sItems) To UBound(sItems)
If Left(sItems(i), 1) = "L" Then sPositions(i) = "L"
If Left(sItems(i), 1) = "C" Then sPositions(i) = "C"
If Left(sItems(i), 1) = "c" Then sPositions(i) = "c"
If Left(sItems(i), 1) = "l" Then sPositions(i) = "l"
Next i
For i = LBound(sPositions) To UBound(sPositions)
If LCase(sPositions(i)) = "c" Then
sPositions(i + 2) = sPositions(i)
sPositions(i) = ""
i = i + 2
End If
Next i
For i = UBound(sItems) To LBound(sItems) Step -1
Select Case Left(sItems(i), 1)
Case "L", "C", "c", "l"
sItems(i) = Trim(Mid(sItems(i), 2))
End Select
sReversedPath = sReversedPath & sItems(i) & " " & sPositions(i) & IIf(sPositions(i) <> "", " ", "")
Next i
ReversePathInfo = Trim(sReversedPath) & IIf(sClosedPath = "", "", " " & sClosedPath)
End Function