Powerpoint VBA to insert image and change size - vba

I think this could solve problems for a lot of people doing tedious pasting of images from one directory into powerpoint then resizing them.
My problem is that I have 16 images all in one directory which need updating each month and it's very slow to do it one by one. The task is:
Open directory
Open first image
Paste image into powerpoint
Reposition image to top left
Resize image to height 550 by width 960 (fills A4 page)
Send image to back
Move to next slide
Repeat for second image
Continue until no more images in directory
Directory is (e.g.) "C:\Users\xxxxxx\Documents\Work\Procurement Project\Slides"
First image name is (e.g.) "01 Summary", second is "02 Client Contracts" etc etc
I think I need a str and a path and a table for the str to add to path to create each new path using i and i + 1 etc
I think I then need some code that's a bit like this:
Sub Picture_size_and_position()
Dim oShape As Shape
Dim oPresentation As Presentation
Dim oSlide As Slide
Dim oSelection As Selection
ActiveWindow.View.GotoSlide oSlide.SlideIndex
With ActiveWindow.Selection.ShapeRange
.LockAspectRatio = msoFalse
.Height = 550
.Width = 960
.Left = 0
.Top = 0
End With
End Sub
Then I'm sure I need a looping function to repeat this until there's nothing left in the directory using some combination of i and j...but the whole code is way beyond me, very frustratingly.
Could someone offer some tips, please? Much much appreciated!
Thank you!

Sub ImportABunch()
Dim strTemp As String
Dim strPath As String
Dim strFileSpec As String
Dim oSld As Slide
Dim oPic As Shape
' Edit these to suit:
strPath = "C:\Users\username\"
strFileSpec = "*.png"
strTemp = Dir(strPath & strFileSpec)
i = 1
Do While strTemp <> ""
Set oSld = ActivePresentation.Slides(i)
Set oPic = oSld.Shapes.AddPicture(FileName:=strPath & strTemp, _
LinkToFile:=msoFalse, _
SaveWithDocument:=msoTrue, _
Left:=0, _
Top:=0, _
Width:=960, _
Height:=550)
i = i + 1
With oPic
.LockAspectRatio = msoFalse
.ZOrder msoSendToBack
End With
' Or (with thanks to David Marcovitz) make the picture as big as possible on the slide
' without changing the proportions
' Leave the above commented out, uncomment this instead:
' With oPic
' If 3 * .width > 4 * .height Then
' .width = ActivePresentation.PageSetup.Slidewidth
' .Top = 0.5 * (ActivePresentation.PageSetup.Slideheight - .height)
' Else
' .height = ActivePresentation.PageSetup.Slideheight
' .Left = 0.5 * (ActivePresentation.PageSetup.Slidewidth - .width)
' End If
' End With
' Optionally, add the full path of the picture to the image as a tag:
'With oPic
' .Tags.Add "OriginalPath", strPath & strTemp
'End With
' Get the next file that meets the spec and go round again
strTemp = Dir
Loop
End Sub
Credit to http://www.pptfaq.com/index.html - Great little site!

Have an idea to automate it/or upon manual launch of a new Macro Enabled PowerPoint Template file. To automate macro upon file open, add customUI: onLoad="ImagesToPowerPoint". Search "CustomUI Editor" for it.
Note I have not fully tested the automation part.
Option Explicit
Sub ImagesToPowerPoint()
Const FileType As String = "*.png"
Dim sSaveFilePath As String, sSaveFileName As String, sImagesFolder As String
Dim oLayout As CustomLayout, oSlide As Slide, i As Long, sFile As String
sImagesFolder = Environ("USERPROFILE") & "\Documents\Work\Procurement Project\Slides\"
' Prepare auto save PowerPoint file name
sSaveFilePath = Environ("USERPROFILE") & "\Documents\Work\PowerPoints\"
sSaveFileName = Format(Now, "yyyy_mmdd") & "_Procurement.pptx"
With ActivePresentation
' Use the first layout for all new slides
Set oLayout = .SlideMaster.CustomLayouts(1)
' Start processing all files in the folder
sFile = Dir(sImagesFolder & FileType)
Do Until sFile = ""
' Add new slide
Set oSlide = .Slides.AddSlide(.Slides.Count, oLayout)
' Delete all the shapes from that layout
For i = oSlide.Shapes.Count To 1 Step -1
oSlide.Shapes(i).Delete
Next
' Add the image to slide
With oSlide.Shapes.AddPicture(sImagesFolder & sFile, msoFalse, msoTrue, 0, 0, oLayout.Width, oLayout.Height)
.LockAspectRatio = msoFalse
.AlternativeText = Now & " | " & sImagesFolder & sFile
End With
sFile = Dir
Loop
.SaveAs sSaveFilePath & sSaveFileName
End With
Presentations(sSaveFileName).Close
If Presentations.Count = 0 Then Application.Quit
End Sub

Related

Insert a picture into an InlineShape

I’m writing a Document in which I have to include many Pictures. In the ongoing process the Pictures get changed many times.
My idea was to include Rectangle Shapes as placeholders and give them a suitable name. I created a Macro that selects the Shape, deletes the old Picture and inserts the new one into the Shape.
Sub InsertImage(Shape As String, Picture As String, Hight As Integer)
Dim shp As Word.Shape
Dim strFile As String
Dim strExt As String
strFile = "C:\Pictures"
strExt = ".png"
ActiveDocument.Shapes.Range(Array(Shape)).Select
Selection.TypeBackspace
Set shp = ActiveDocument.Shapes.AddPicture(Anchor:=Selection.Range, FileName:= _
strFile & "\" & Picture & strExt, LinkToFile:=False, SaveWithDocument:=True)
With shp
.LockAspectRatio = msoTrue
.Height = CentimetersToPoints(Hight)
End With
End Sub
Sub Insert1()
InsertImage "Shape01", "Pic01", 10
End Sub
I want this for floating Shapes as well as for InlineShapes.
When I set my Placeholder Shapes to InlineShapes the TypeBackspace line deletes the InlineShape and the picture does not get inserted into the InlineShape.
Thank you very much for the help. After many struggles, the solution with Tables + Bookmarks works perfekt.
Here is the code:
Sub InsertPic(Pic As String, Cut As Single)
Dim strFile As String
Dim strExt As String
Dim ils As InlineShape
strFile = "C:\Pictures“
strExt = ".png"
Application.ScreenUpdating = False
ActiveDocument.Bookmarks(Pic).Select
Selection.Delete
Set ils = Selection.InlineShapes.AddPicture(FileName:= _
strFile & "/" & Pic & strExt, _
LinkToFile:=False, SaveWithDocument:=True)
With ils
.PictureFormat.CropBottom = CentimetersToPoints(Cut)
.LockAspectRatio = msoTrue
.Height = .Range.Cells(1).Height
If .Width > .Range.Cells(1).Width Then
.Width = .Range.Cells(1).Width
End If
End With
ActiveDocument.Bookmarks.Add (Pic)
Application.ScreenUpdating = True
End Sub
Sub Insert01()
InsertPic "Image01", 20
MsgBox "Done"
End Sub
Some explanation:
For this code, the Bookmark and the Picture need the same Name. I made this to avoid mix-ups.
With the Selection.Delete command, the Bookmark gets also deleted, so I just added a new Bookmark with the same name at the end. I’m sure there are more elegant ways to solve this, but this solution works.
I have had many struggles because i wanted to crop the Picure. But the size gets changed to the size of the table-cell when its inserted and the cutting step comes afterwards. So the Picturs wasn´t filling the complete cell size. Therefore, I added a part to resize the Image to the table-cell Size. As well, im sure there are better ways to overcome this ...
Because of this resizing, the Makro needs a bit of time (at least for my document). So I disabled the Screenupdating.

VBA powerpoint - Macro for formatting notes

I'm trying to make a macro that can change all the text in all the notes of a powerpoint presentation to a specified font and fontsize (given through InputBoxes).
It seems to work but not in all the slides, some slides it just resets the fontsize to something way larger than what was given. anyone know what could go wrong?
Sub FormatNotes()
Dim intSlide As Integer
Dim strNotes As String
Dim nts As TextRange
Dim strFont, intSize
intSize = InputBox("Please enter font size", "fontsize", "12")
strFont = InputBox("Please enter font", "font type", "Calibri")
With ActivePresentation
For intSlide = 1 To .Slides.Count
Set nts = ActivePresentation.Slides(intSlide).NotesPage. _
Shapes.Placeholders(2).TextFrame.TextRange
With nts
If intSize = "" Then intSize = 12
.Paragraphs.Font.Size = intSize
.Paragraphs.Font.Name = strFont
End With
Next intSlide
End With
MsgBox ("FormatNotes uitgevoerd")
End Sub
Seems to work to me. I also tried it after deleting .Paragraphs as you don't need that if you want to set the whole text to the same type face and size. Do you have an example of it not working for investigation?
By the way, did you know that Notes formatting is not shown by default in PowerPoint and has to be turned on in the Outline view?
Original question is why code did not work for all slides. I think it has to do with fact the code used Placeholder(2) as hard value, so the code only works with TextRange in that Placeholder. If the NotesPage has more than one Placeholder, the code will not work for the other Placeholders.
My code shown here uses .HasTextFrame to determine if a Placeholder has text, and only attempts to set font size and type if this is true. (I used debug.print to see how far the code got, you can comment it out.)
Sub FormatNotes()
' Written 2020-08-29 P.Irving for myself
Dim mySlide As Integer, myPlace As Integer
Dim myNotes As String
Const mySize = "11", myFont = "Calibri"
With ActivePresentation ' qualify macro name
Debug.Print "Slide#", "LEN(Notes)", "LEFT(Notes,50)"
For mySlide = 1 To .Slides.Count
myNotes = ""
For myPlace = 1 To ActivePresentation.Slides(mySlide). _
NotesPage.Shapes.Placeholders.Count
' code copied from learn.microsoft.com/en-us/office/_
' vba/api/powerpoint.textrange.font
' this code does not attempt to SET nts
With ActivePresentation.Slides(mySlide). _
NotesPage.Shapes.Placeholders(myPlace)
If .HasTextFrame Then
With .TextFrame.TextRange.Font
.Size = mySize
.Name = myFont
'.Bold = True
'.Color.RGB = RGB(255, 127, 255)
End With
myNotes = myNotes & _
ActivePresentation.Slides(mySlide). _
NotesPage.Shapes.Placeholders(myPlace). _
TextFrame.TextRange
End If ' .HasText
End With
Next myPlace
Debug.Print mySlide, Len(myNotes), Left(myNotes, 50)
Next mySlide
End With
MsgBox "Applied to " & ActivePresentation.Slides.Count & " slides", _
vbOKOnly, "FormatNotes"
End Sub

Trouble with VBA Do While loop in macro to copy slide and change picture in powerpoint

I am attempting my first macro in powerpoint. I am simply trying to copy a 'reference' slide and replace one picture. I will do this for all pictures in a folder. The script I have adds all the slides, but then adds all the pictures to the final slide. I don't understand why this is the case since the Duplicate Slide code and the Add Picture code are in the same while loop. Can someone tell me why?
Sub LoopThroughFiles()
Dim StrFile As String
Dim Folder As String
Dim sld As Slide
Dim referencesld As Slide
Set referencesld = ActivePresentation.Slides(1)
Dim i As Integer
Dim shp As Shape
i = 1
Folder = "c:\E1B8\ScriptTesting\MISC\PPT\SampleData2\"
StrFile = Dir(Folder & "*")
Set referencesld = ActivePresentation.Slides(1)
Set shp = referencesld.Shapes(5)
Do While Len(StrFile) > 0
Debug.Print Folder & StrFile
referencesld.Duplicate
i = i + 1
Set sld = ActivePresentation.Slides(i)
With shp
sld.Shapes.AddPicture(Folder & StrFile, msoFalse, msoTrue, .Left, .Top, .Width, .Height).IncrementRotation 360#
End With
sld.Shapes(5).Delete
StrFile = Dir
Loop
End Sub
Thanks!!
You can use a variable when duplicating the slide, forget the "i" variable, it is not needed:
delete the lines
referencesld.Duplicate
i = i + 1
Set sld = ActivePresentation.Slides(i)
An insert "Set sld = referencesld.Duplicate" in the place
...
Debug.Print Folder & StrFile
Set sld = referencesld.Duplicate
With shp
sld.Shapes.AddPicture(Folder & StrFile, msoFalse, msoTrue, .Left, .Top, .Width, .Height).IncrementRotation 360#
End With
...
Untested
You can see "Duplicate" reference in http://msdn.microsoft.com/library/office/ff745804(v=office.15).aspx
Aside: I think it is weird to use the "with" keyword on the argument (shape) instead of the object you are working on (the slide).
[edited: Make it clear to understand what to do]
I hope to help.

How to add a file from the active document directory

I have a document that creates a template page from a VBA script every time I need to insert a specific item into my document, its a great time saver, this includes an image. I have got a working foundation whereby it inserts the image and text wraps it where I want it to be, however the file path is an absolute one. I would like the file path to specify that the image file is within the same directory as the active document so that if I move the directory to a different location this macro will not be broken.
The problem is a little beyond my vba skills, I have worked out I should probably use the ActiveDocument.Path command but I am not sure how to. I appreciate your help. Thank you
Below is my code so far:
Sub Inser_Wrapped_Image()
Dim shp As Shape
Set shp = ActiveDocument.Shapes.AddPicture( _
FileName:="C:\Users\Edoardo\Documents\My Work\PhD\SkyDrive\Tutoring\Houria\Image Replacement.jpg", _
SaveWithDocument:=True, _
Anchor:=Selection.Range)
With shp
.WrapFormat.Type = wdSquare
.Left = 246
.Top = 50
.Width = 250
.Height = 188
End With
End Sub
I have tried writing it as follows but word freezes for a few seconds and then does nothing:
Sub Insert_image()
Dim shp As Shape
Set shp = ActiveDocument.Shapes.AddPicture( _
FileName:=ActiveDocument.Path & "\Image.jpg", _
SaveWithDocument:=True, _
Anchor:=Selection.Range)
End Sub
Try this:
Sub Inser_Wrapped_Image()
Dim shp As Shape
Dim imgpath As String
imgpath = ThisDocument.Path
imgpath = imgpath & "\" & "Image Replacement.jpg"
Set shp = ThisDocument.Shapes.AddPicture( _
FileName:=imgpath, SaveWithDocument:=True, _
Anchor:=Selection.Range)
With shp
.WrapFormat.Type = wdWrapSquare
.Left = 246
.Top = 50
.Width = 250
.Height = 188
End With
End Sub
I used ThisDocument to explicitly load the picture to the document that contains the macro.
It will work both ways thought if you want to stick to ActiveDocument.

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