How to check powerpoint slide items for a table - vba

I want to insert data from excel into a powerpoint table. So far my code does that function, but when it is used with a real powerpoint file, there are many items in a slide, and I do not address the right one. How can I go through a list of items in a slide and execute my code once that item is a table?
Edit: Office 2007 / And I was asked to paste my code:
Sub AktualisierePowerpointVonExcel()
Dim AnzahlZeilen As Long
Dim AnzahlSlides As Long
Dim App As Object
Dim CurrSlide As Object
Dim AktuelleIterationenFuerSlides As Long
Dim AktuelleIterationenFuerZielZeilen As Long
Dim z As Long
Dim SHP As Shape
On Error GoTo Fehler
z = 1
AnzahlZeilen = Range("A65536").End(xlUp).Row
Set App = CreateObject("PowerPoint.Application")
App.Visible = msoTrue
App.Presentations.Open "c:\Users\X\Desktop\1.pptm"
AnzahlSlides = App.ActivePresentation.Slides.Count
If (AnzahlZeilen / 6) > AnzahlSlides Then
MsgBox "Zu wenig Slides für Einträge" & "Anzahl Slides:" & AnzahlSlides & "Anzahl Zeilen:" & AnzahlZeilen & "Benötigte Anzahl An Folien:" & (AnzahlZeilen / 6)
Exit Sub
Else
For AktuelleIterationenFuerSlides = 1 To AnzahlSlides
Set CurrSlide = App.ActivePresentation.Slides(AktuelleIterationenFuerSlides)
For AktuelleIterationenFuerZielZeilen = 1 To 6
For Each SHP In CurrSlide.Shapes
If SHP.HasTable Then
Worksheets("Tabelle2").Cells(z, 1).Copy
SHP.Table.Cell(AktuelleIterationenFuerZielZeilen, 1).Shape.TextFrame.TextRange.Paste
Worksheets("Tabelle2").Cells(z, 2).Copy
SHP.Table.Cell(AktuelleIterationenFuerZielZeilen, 1).Shape.TextFrame.TextRange.Paste
Worksheets("Tabelle2").Cells(z, 3).Copy
SHP.Table.Cell(AktuelleIterationenFuerZielZeilen, 1).Shape.TextFrame.TextRange.Paste
z = z + 1
On Error Resume Next
End If
Next
Next
Next
End If
Fehler:
MsgBox "Fehler in Sub Fehler0" & vbCrLf & "Fehlernummer: " & Err.Number & _
vbCrLf & "Fehlerbeschreibung: " & Err.Description
End Sub

Checking Shape.Type isn't reliable any longer. Shape.Type = msoTable IF the user's inserted a table onto a slide, but if they've added a table to a content placeholder, the type will be different. This is more trustworthy:
If Shape.HasTable Then
MsgBox "It's a table."
End If

This is complete procedure which allows to check which slide shape is table. You will need to loop to check .Type property of each Shape. If one is Table there you are...:
Sub Check_if_shape_is_table()
Dim CurrSlide As Slide
Set CurrSlide = ActivePresentation.Slides(1) 'just for test- change accordingly
'your copy code here:
Worksheets("Tabelle2").Cells(Z, 1).Copy
Dim SHP As Shape
For Each SHP In CurrSlide.Shapes
If SHP.Type = msoTable Then
'change references to your cell accordingly
SHP.Table.Cell(AktuelleIterationenFuerZielZeilen, 1).Shape.TextFrame.TextRange.Paste
End If
Next
End Sub
Above code will apply value to cell in each table in your slide. Assuming there is only one table it will work ok.
Alternative solution. If there are more tables and you need to add value to the last table (!!) you could do this way:
Sub Check_if_shape_is_table_FEW_TABLES()
Dim CurrSlide As Slide
Set CurrSlide = ActivePresentation.Slides(1) 'just for test change accordingly
'your copy code here:
Worksheets("Tabelle2").Cells(Z, 1).Copy
Dim lastTableSHP As Shape
Dim SHP As Shape
For Each SHP In CurrSlide.Shapes
If SHP.Type = msoTable Then
'this will set temp variable of lastTableSHP
Set lastTableSHP = SHP
End If
Next
'apply value to the last table in the slide
lastTableSHP.Table.Cell(AktuelleIterationenFuerZielZeilen, 1).Shape.TextFrame.TextRange.Paste
End Sub

Related

Text Alignment in VBA PowerPoint

Is there a way to align the text from right to left (it's Arabic) on all slides in a PowerPoint Presentation with a macro ? (I'm using O365).
In a Microsoft example I found this :
Application.ActivePresentation.Slides(1).Shapes(2) _
.TextFrame.TextRange.ParagraphFormat.Alignment = ppAlignLeft
But i think that this example aligns the paragraphs of form 2 on slide 1 of the active presentation to the left.
So i don't know how to do it with all the shapes/slides types.
The professional coders may improve it, but I think this one should help you. You just have to select all slides before you click it, if you want the entire presentation to be done in one move. I think it is better than any entire-presentation-solution, because it gives you the opportunity to choose.
Option Explicit
Sub AlignAllTextLeft()
Dim osld As Slide
Dim oshp As Shape
Dim notesshp As Shape
Dim i As Long
Dim j As Long
Dim x As Long
On Error GoTo ErMsg
If MsgBox("You are going to change the text alignment of all text on all selected slides to left" & vbCrLf & "Continue?", vbYesNo) <> vbYes Then Exit Sub
For Each osld In ActiveWindow.Selection.SlideRange
For Each oshp In osld.Shapes
If oshp.HasTextFrame Then
oshp.TextFrame2.TextRange.ParagraphFormat.Alignment = msoAlignLeft
End If
If oshp.HasTable Then
For i = 1 To oshp.Table.Rows.Count
For j = 1 To oshp.Table.Columns.Count
oshp.Table.Rows.Item(i).Cells(j).Shape.TextFrame2.TextRange.ParagraphFormat.Alignment = msoAlignLeft
Next j
Next i
End If
Next oshp
For Each notesshp In osld.NotesPage.Shapes
If notesshp.HasTextFrame Then
notesshp.TextFrame2.TextRange.ParagraphFormat.Alignment = msoAlignLeft
End If
Next notesshp
Next osld
For Each osld In ActiveWindow.Selection.SlideRange
For Each oshp In osld.Shapes
With oshp
Select Case .Type
Case Is = msoGroup
For x = 1 To .GroupItems.Count
If .GroupItems(x).HasTextFrame Then
oshp.TextFrame2.TextRange.ParagraphFormat.Alignment = msoAlignLeft
End If
Next x
End Select
End With
Next oshp
Next
Exit Sub
ErMsg:
MsgBox "Please do not place the cursor between two slides"
End Sub

How could I make this code run faster and smoother?

Three issues.
This code is running in 4-5 minutes for me with the database that I currently have. Normally it will be a database with 100~ columns. I want to make this faster.
Another issue I have is that I keep getting two different pop-ups:
"File now Available for Editing"
"User is currently editing workbook, would you like to run in read-only mode?"
Very annoying, but nothing I can't live with.
Lastly, I also sometimes get an error on this line:
pptSlide.Shapes.PasteSpecial DataType:=ppPasteHTML, Link:=msoFalse But all I have to do is re-run the program and it'll go away.
I'm looking for any suggestions to make this code run a little faster and smoother, any recommendations are welcome.
Thanks!
Public Sub averageScoreRelay()
' 1. Run from PPT and open an Excel file
' 2. Start at slide 1 and find a box that contains the words "iq_", if it has those words then it will have numbers after it like so "iq_43" or "iq_43, iq_56,iq_72".
' 3. find those words and numbers in the opened Excel file after splitting and re-formating string.
' 3. Copy column into a new sheets and repeat for all "iq_'s" until sheets 2 has a table.
' 4. Copy table from xl Paste Table into ppt
' 5. Do this for every slide
'Timer start
Dim StartTime As Double
Dim SecondsElapsed As Double
StartTime = Timer
'Create variables
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim pptSlide As Slide
Dim Shpe As Shape
Dim pptText As String
Dim pptPres As Object
Dim iq_Array As Variant
Dim arrayLoop As Integer
Dim i As Integer
Dim myShape As Object
Dim colNumb As Integer
Dim size As Integer
Dim k As Integer
Dim lRows As Long
Dim lCols As Long
' Create new excel instance and open relevant workbook
Set xlApp = New Excel.Application
'xlApp.Visible = True 'Make Excel visible
Set xlWB = xlApp.Workbooks.Open("file.xlsx", True, False, , , , True, Notify:=False) 'Open relevant workbook
If xlWB Is Nothing Then ' may not need this if statement. check later.
MsgBox ("Error retrieving Average Score Report, Check file path")
Exit Sub
End If
xlApp.DisplayAlerts = False
With xlWB.Worksheets("Sheet1")
colNumb = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
'Create a new blank Sheet in excel, should be "Sheet2"
xlWB.Worksheets.Add After:=xlWB.ActiveSheet
'Make pptPres the ppt active
Set pptPres = PowerPoint.ActivePresentation
'Loop through each pptSlide and check for IQ text box, grab avgScore values and create pptTable
For Each pptSlide In pptPres.Slides
pptSlide.Select
'searches through shapes in the slide
For Each Shpe In pptSlide.Shapes
k = 1
'Identify if there is text frame
If Shpe.HasTextFrame Then
'Identify if there's text in text frame
If Shpe.TextFrame.HasText Then
'Set pptText as the Text in the box, then make it lowercase and trim Spaces and Enters
pptText = Shpe.TextFrame.TextRange
pptText = LCase(Replace(pptText, " ", vbNullString))
pptText = Replace(Replace(Replace(pptText, vbCrLf, vbNullString), vbCr, vbNullString), vbLf, vbNullString)
'Identify if within text there is "iq_"
If InStr(1, pptText, "iq_") > 0 Then
'set iq_Array as an array of the split iq's
iq_Array = Split(pptText, ",")
'Find size of the array
size = UBound(iq_Array) - LBound(iq_Array)
'loop for each iq_ in the array'
For arrayLoop = 0 To size
'Statement that will take iq_'s in the form "iq_9" or "iq_99" or "iq_999"
If iq_Array(arrayLoop) Like "iq_#" Or iq_Array(arrayLoop) Like "iq_##" Or iq_Array(arrayLoop) Like "iq_###" Then
'loops for checking each column
For i = 1 To colNumb
'Copies the first column (role column) for every slide that needs it
If i = 1 And arrayLoop = 0 Then
'copy column
xlWB.Worksheets("Sheet1").Columns(1).Copy
'paste column in Sheet2 which was newly created
xlWB.Worksheets("Sheet2").Paste Destination:=xlWB.Worksheets("Sheet2").Columns(1)
'If this is not the role column, then check to see if the iq_'s match from ppt to xl
ElseIf xlWB.Worksheets("Sheet1").Cells(1, i) = iq_Array(arrayLoop) And i <> 1 Then
'Serves to paste in the next column of Sheet2 so that we end up with a table
k = k + 1
'same as above
xlWB.Worksheets("Sheet1").Columns(i).Copy
xlWB.Worksheets("Sheet2").Paste Destination:=xlWB.Worksheets("Sheet2").Columns(k)
'Go to next array
GoTo Line2
End If
Next i
'Same as above, just this one is for iq_'s with form "iq_45,46,47" instead of "iq_45,iq_46,iq_47"
ElseIf (iq_Array(0) Like "iq_#" Or iq_Array(0) Like "iq_##" Or iq_Array(0) Like "iq_###") And (IsNumeric(iq_Array(arrayLoop)) And Len(iq_Array(arrayLoop)) <= 3) Then
For i = 1 To colNumb
If i = 1 And arrayLoop = 0 Then
xlWB.Worksheets("Sheet1").Columns(1).Copy
xlWB.Worksheets("Sheet2").Paste Destination:=xlWB.Worksheets("Sheet2").Columns(1)
ElseIf xlWB.Worksheets("Sheet1").Cells(1, i) = ("iq_" & iq_Array(arrayLoop)) And i <> 1 Then 'if iq in ppt = iq in xl and if not the first cell then execute
k = k + 1
xlWB.Worksheets("Sheet1").Columns(i).Copy
xlWB.Worksheets("Sheet2").Paste Destination:=xlWB.Worksheets("Sheet2").Columns(k)
GoTo Line2
End If
Next i
End If
Line2:
Next arrayLoop
End If
End If
End If
Next Shpe
'calculate last row and last column on sheet2. aka. find Table size
With xlWB.Worksheets("Sheet2")
lRows = .Cells(.Rows.Count, 1).End(xlUp).Row
lCols = .Cells(1, .Columns.Count).End(xlToLeft).Column
'If only one column then go to next slide
If lRows = .Cells(1, 1).End(xlUp).Row And lCols = .Cells(1, 1).End(xlToLeft).Column Then
GoTo Line1
End If
'Copy table
.Range(.Cells(1, 1), .Cells(lRows, lCols)).Copy
End With
'Paste Table into ppt
pptSlide.Shapes.PasteSpecial DataType:=ppPasteHTML, Link:=msoFalse
'Recently pasted shape is the last shape on slide, so it will be the same as count of shapes on slide
Set myShape = pptSlide.Shapes(pptSlide.Shapes.Count)
'Set position:
myShape.Left = -200
myShape.Top = 200
'Clear Sheet2 for next slide
xlWB.Worksheets("Sheet2").Range("A1:P10").Clear
Line1:
Next pptSlide
xlWB.Worksheets("Sheet2").Delete
xlWB.Close
xlApp.Quit
xlApp.DisplayAlerts = True
'End Timer
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
End Sub

How to make a range bar chart

Hey I'm new to forums and this is my first post. I am new to vba in excel, but have written thinkscript in ThinkorSwim.
If anyone is familiar with a range stock chart, thats what Im going after.
I found code for a line chart, and am using it, but it is based on where price is at any given time. I want to modify this line chart to only plot values when they are above or below a range so that it resembles a candlestick chart with no wicks. Once data enters that range, I only want it to update whenever a new high or low is made in that range. The ranges need to be preset (ex. 50 ticks) Once the range is exceeded, I want the data plotted in the next range up, and repeat the process. Time and dates should be ignored, and only plot based on price action.
Does anyone have any ideas?
Option Explicit
'Update the values between the quotes here:
Private Const sChartWSName = "Chart"
Private Const sSourceWSName = "Sheet1"
Private Const sTableName = "tblValues"
Public RunTime As Double
Private Sub Chart_Setup()
'Create the structure needed to preserve and chart data
Dim wsChart As Worksheet
Dim lstObject As ListObject
Dim cht As Chart
Dim shp As Button
'Create sheet if necessary
Set wsChart = Worksheets.Add
wsChart.Name = sChartWSName
'Set up listobject to hold data
With wsChart
.Range("A1").Value = "Time"
.Range("B1").Value = "Value"
Set lstObject = .ListObjects.Add( _
SourceType:=xlSrcRange, _
Source:=.Range("A1:B1"), _
xllistobjecthasheaders:=xlYes)
lstObject.Name = sTableName
.Range("A2").NumberFormat = "h:mm:ss AM/PM (mmm-d)"
.Columns("A:A").ColumnWidth = 25
.Select
End With
'Create the chart
With ActiveSheet
.Shapes.AddChart.Select
Set cht = ActiveChart
With cht
.ChartType = xlLine
.SetSourceData Source:=Range(sTableName)
.PlotBy = xlColumns
.Legend.Delete
.Axes(xlCategory).CategoryType = xlCategoryScale
With .SeriesCollection(1).Format.Range
.Visible = msoTrue
.Weight = 1.25
End With
End With
End With
'Add buttons to start/stop the routine
Set shp = ActiveSheet.Buttons.Add(242.25, 0, 83.75, 33.75)
With shp
.OnAction = "Chart_Initialize"
.Characters.Text = "Restart Plotting"
End With
Set shp = ActiveSheet.Buttons.Add(326.25, 0, 83.75, 33.75)
With shp
.OnAction = "Chart_Stop"
.Characters.Text = "Stop Plotting"
End With
End Sub
Public Sub Chart_Initialize()
'Initialize the routine
Dim wsTarget As Worksheet
Dim lstObject As ListObject
'Make sure worksheet exists
On Error Resume Next
Set wsTarget = Worksheets(sChartWSName)
If Err.Number <> 0 Then
Call Chart_Setup
Set wsTarget = Worksheets(sChartWSName)
End If
On Error GoTo 0
'Check if chart data exists
With Worksheets(sChartWSName)
Set lstObject = .ListObjects(sTableName)
If lstObject.ListRows.Count > 0 Then
Select Case MsgBox("You already have data. Do you want to clear it and start fresh?", vbYesNoCancel, "Clear out old data?")
Case Is = vbYes
'User wants to clear the data
lstObject.DataBodyRange.Delete
Case Is = vbCancel
'User cancelled so exit routine
Exit Sub
Case Is = vbNo
'User just wants to append to existing table
End Select
End If
'Begin appending
Call Chart_AppendData
End With
End Sub
Private Sub Chart_AppendData()
'Append data to the chart table
Dim lstObject As ListObject
Dim lRow As Long
With Worksheets(sChartWSName)
Set lstObject = .ListObjects(sTableName)
If lstObject.ListRows.Count = 0 Then
lRow = .Range("A1").End(xlDown).Row
End If
If lRow = 0 Then
lRow = .Range("A" & .Rows.Count).End(xlUp).Offset(1, 0).Row
End If
If lRow > 2 Then
If .Range("B" & lRow - 1).Value = Worksheets(sSourceWSName).Range("C10").Value Then
'Data is a match, so do nothing
Else
'Data needs appending
.Range("A" & lRow).Value = CDate(Now)
.Range("B" & lRow).Value = Worksheets(sSourceWSName).Range("C10").Value
End If
Else
'Data needs appending
.Range("A" & lRow).Value = CDate(Now)
.Range("B" & lRow).Value = Worksheets(sSourceWSName).Range("C10").Value
End If
End With
RunTime = Now + TimeValue("00:00:01")
Application.OnTime RunTime, "Chart_AppendData"
End Sub
Public Sub Chart_Stop()
'Stop capturing data
On Error Resume Next
Application.OnTime EarliestTime:=RunTime, Procedure:="Chart_AppendData", Schedule:=False
End Sub
Take your sheet of data and filter... example would be:
Columns("A:C").Sort key1:=Range("C2"), _
order1:=xlAscending, header:=xlYes
Sort info: https://msdn.microsoft.com/en-us/library/office/ff840646.aspx
You then can define to select your desired range. Assuming column A is x-axis and B is y-axis (where your parameters for modifying need to be assessed):
Dim High1 as integer
Dim Low1 as integer
High1 = Match(Max(B:B),B:B) 'This isn't tested, just an idea
Low1 = Match(Max(B:B)+50,B:B) 'Again, not tested
and using those defined parameters:
.Range(Cells(High1,1),Cells(Low1,2).Select
This should give an idea for High1/Low1, where you can work through how you want to define the row that the max value occurs.
You then CreateObject for the Chart you want, having selected the data range you are going to use.

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

VBA code to save a single slide as a .ppt

I have a code which saves my specified slide as a PNG:
Dim userName As String
userName = Slide322.TextBox1.Text
'Save slide
ActivePresentation.Slides(302).Export _
filename:="C:\Users\Jessica\Dropbox\Uni\DISSERTATION\Questionnaire\Tools\Results\" & userName & ".png", FilterName:="PNG"
However, I want to save the slide as a .PPT so that I can open it at a later date and edit the text on that slide.
I have tried using the .SaveAs syntax, but I get an error message every time and it just won't recognise any 'Save' type expressions.
I have searched, and searched for the answer to this... Can anyone please help?
Try:
ActivePresentation.Slides(1).Export "c:\temp\slide1.ppt", "PPT"
Alternative:
Use SaveCopy to save a copy of the presentation
Open the saved copy (with or without a window)
Delete all the slides up to the one you want to keep
Delete all the slides after the one you want to keep
Save again.
Close the presentation
Like so:
Sub TestMe()
SaveSlide 5, "c:\temp\slide5.pptx"
End Sub
Sub SaveSlide(lSlideNum As Long, sFileName As String)
Dim oTempPres As Presentation
Dim x As Long
ActivePresentation.SaveCopyAs sFileName
' open the saved copy windowlessly
Set oTempPres = Presentations.Open(sFileName, , , False)
For x = 1 To lSlideNum - 1
oTempPres.Slides(1).Delete
Next
' What was slide number lSlideNum is now slide 1
For x = oTempPres.Slides.Count To 2 Step -1
oTempPres.Slides(x).Delete
Next
oTempPres.Save
oTempPres.Close
End Sub
Obviously, you'll want to add a few safety ropes ... don't try to export slide 15 of a 12-slide presentation, etc.
You could possibly try this code which:
creating new presentation
copying slide to it
saving & closing new presentation.
Sub SaveSeparateSlide()
Dim curPres As Presentation
Set curPres = ActivePresentation
Dim newPres As Presentation
Set newPres = Presentations.Add
'change slide number here:
curPres.Slides(1).Copy
newPres.Slides.Paste
'change your path and name here:
newPres.SaveAs "single slide presentation.pptx"
newPres.Close
End Sub
You will need to adjust that code a bit but I think you'll cope :)
Sub SplitFile()
Dim lSlidesPerFile As Long
Dim lTotalSlides As Long
Dim oSourcePres As Presentation
Dim otargetPres As Presentation
Dim sFolder As String
Dim sExt As String
Dim sBaseName As String
Dim lCounter As Long
Dim lPresentationsCount As Long ' how many will we split it into
Dim x As Long
Dim lWindowStart As Long
Dim lWindowEnd As Long
Dim sSplitPresName As String
On Error GoTo ErrorHandler
Set oSourcePres = ActivePresentation
If Not oSourcePres.Saved Then
MsgBox "Please save your presentation then try again"
Exit Sub
End If
lSlidesPerFile = CLng(InputBox("How many slides per file?", "Split Presentation"))
lTotalSlides = oSourcePres.Slides.Count
sFolder = ActivePresentation.Path & "\"
sExt = Mid$(ActivePresentation.Name, InStr(ActivePresentation.Name, ".") + 1)
sBaseName = Mid$(ActivePresentation.Name, 1, InStr(ActivePresentation.Name, ".") - 1)
If (lTotalSlides / lSlidesPerFile) - (lTotalSlides \ lSlidesPerFile) > 0 Then
lPresentationsCount = lTotalSlides \ lSlidesPerFile + 1
Else
lPresentationsCount = lTotalSlides \ lSlidesPerFile
End If
If Not lTotalSlides > lSlidesPerFile Then
MsgBox "There are fewer than " & CStr(lSlidesPerFile) & " slides in this presentation."
Exit Sub
End If
For lCounter = 1 To lPresentationsCount
' which slides will we leave in the presentation?
lWindowEnd = lSlidesPerFile * lCounter
If lWindowEnd > oSourcePres.Slides.Count Then
' odd number of leftover slides in last presentation
lWindowEnd = oSourcePres.Slides.Count
lWindowStart = ((oSourcePres.Slides.Count \ lSlidesPerFile) * lSlidesPerFile) + 1
Else
lWindowStart = lWindowEnd - lSlidesPerFile + 1
End If
' Make a copy of the presentation and open it
sSplitPresName = sFolder & sBaseName & _
"_" & CStr(lWindowStart) & "-" & CStr(lWindowEnd) & "." & sExt
oSourcePres.SaveCopyAs sSplitPresName, ppSaveAsDefault
Set otargetPres = Presentations.Open(sSplitPresName, , , True)
With otargetPres
For x = .Slides.Count To lWindowEnd + 1 Step -1
.Slides(x).Delete
Next
For x = lWindowStart - 1 To 1 Step -1
.Slides(x).Delete
Next
.Save
.Close
End With
Next ' lpresentationscount
NormalExit:
Exit Sub
ErrorHandler:
MsgBox "Error encountered"
Resume NormalExit
End Sub
ActivePresentation.Slides(1).Export "1.ppt", "PPT"
Above code exports Slide#1 to an 'old' type ppt format.
The 2nd one of the following 2 macros can save a copy in a 'new' pptx format which is more compatible. It's actually the mixture of Steve's two methods. But it doesn't bother to delete the rest of the slides.
Sub SaveEachPage2PPT()
Dim sld As Slide
Dim l#
With ActivePresentation
For Each sld In .Slides
l = l + 1
sld.Export .Path & "\" & l & ".ppt", "PPT"
Next sld
End With
End Sub
Sub SaveEachPage2PPTX()
Dim sld As Slide
Dim l#
Dim ppt As Presentation
Dim pptFile$
With ActivePresentation
For Each sld In .Slides
l = l + 1
pptFile = .Path & "\" & l & ".ppt"
sld.Export pptFile, "PPT"
Set ppt = Presentations.Open(pptFile, , , False)
ppt.SaveCopyAs pptFile & "x", ppSaveAsOpenXMLPresentation
ppt.Close
Kill pptFile
Next sld
End With
If Not ppt Is Nothing Then Set ppt = Nothing
End Sub
The following script will help you save the individual slides of your presentation as seperate pptx files. I modified #Steve Rindsberg code to achieve this.
Just change the following in the code
Change K:\PRESENTATION_YOU_ARE_EXPORTING.pptx with the file path of the presentation you are exporting.
Change K:\FOLDER PATH WHERE PPTX SHOULD BE EXPORTED\ with the folder path where the exported presentations should be saved.
Remember to add \ at the end of the folder path in Step 2.
Sub ExportSlidesToIndividualPPPTX()
Dim oPPT As Presentation, oSlide As Slide
Dim sPath As String
Dim oTempPres As Presentation
Dim x As Long
' Location of PPTX File
Set oPPT = Presentations.Open(FileName:="K:\PRESENTATION_YOU_ARE_EXPORTING.pptx")
' Location Where Individual Slides Should Be Saved
' Add \ in the end
sPath = "K:\FOLDER PATH WHERE PPTX SHOULD BE EXPORTED\"
For Each oSlide In oPPT.Slides
lSlideNum = oSlide.SlideNumber
sFileName = sPath & "Slide - " & lSlideNum & ".pptx"
oPPT.SaveCopyAs sFileName
' open the saved copy windowlessly
Set oTempPres = Presentations.Open(sFileName, , , False)
' Delete all slides before the slide you want to save
For x = 1 To lSlideNum - 1
oTempPres.Slides(1).Delete
Next
' Delete all slides after the slide you want to save
For x = oTempPres.Slides.Count To 2 Step -1
oTempPres.Slides(x).Delete
Next
oTempPres.Save
oTempPres.Close
Next
Set oPPT = Nothing
End Sub