Replace existing image in MS PowerPoint with a new image using VBA - vba

I'm updating my MS PowerPoint by pasting images on different slides using VBA.
Rest of the code is working fine. What I'm unable to do is delete the existing image on all the slides and paste the new image. Currently it paste the new image on top of old image, but old image remains. I'm using below code:
Dim pptApp As PowerPoint.Application
Set pptApp = CreateObject("PowerPoint.Application")
pptApp.Visible = msoTrue
xlApp.Worksheets(2).Range("M2:S12").Copy
Set shp1 = ActivePresentation.Slides(17).Shapes.PasteSpecial(ppPasteEnhancedMetafile)(1)
With shp1
.Left = 370
.Top = 100
.Height = 360
.Width = 340
End With
Being a newbie to VBA, I dont know where and how to add delete command in above code. Any kind of help would be appreciated.

This (thanks, L42) will work for single msoPicture shapes on a slide, but if there's more than one shape, it may miss some:
Dim s As Shape
For Each s In ActivePresentation.Slides(17).Shapes
If s.Type = 13 Then s.Delete '13 is msoPicture
Next
Why? Suppose you have three shapes on the slide. We iterate through the shapes collection, find that the first shape is a picture and delete it. Now there are two shapes in the shapes collection, but VBA's counter doesn't take account of changes in the collection count. It looks at the second shape in the collection, but that's now what WAS the third shape on the slide, so the code will miss shape #2 altogether.
It's more reliable to use something like this:
Dim x as Long
For x = ActivePresentation.Slides(17).Shapes.Count to 1 Step -1
If ActivePresentation.Slides(17).Shapes(x).Type = msoPicture Then
ActivePresentation.Slides(17).Shapes(x).Delete
End If
Next

Edit1: As what Steve pointed out, the first posted solution is unreliable; also as confirmed in this POST by Doug.
To delete all pictures using loop, take Steve's approach as explained in his post.
Now, if you just want to delete all the pictures, you can try this:
ActivePresentation.Slides(17).Shapes.Range.Delete
But this deletes all shapes, not only pictures but textboxes, lines, shapes etc.
To delete only pictures, below is another approach using loop.
Dim s As Shape, pictodel As Variant
For Each s In ActivePresentation.Slides(17).Shapes
If s.Type = 13 Then
If IsArray(pictodel) Then
ReDim Preserve pictodel(UBound(pictodel) + 1)
pictodel(UBound(pictodel)) = s.Name
Else
pictodel = Array(s.Name)
End If
End If
Next
ActivePresentation.Slides(17).Shapes.Range(pictodel).Delete
Hope this helps but a simpler solution would be Steve's. :)

Related

Powerpoint VBA Make duplicated shape view active to select for grouping

I have a library of eight images on my PowerPoint slide. Based on a userform input, some of the components get duplicated and renamed by adding a "1" or "2" after the original image's name so that they are differentiable. I then want to group the new images (I am building up an item from the component images). I am able to duplicate the images and line them up correctly, but I am having trouble grouping them. Note that I am not always grouping the same number of items, it is dependent on user inputs.
I receive the error "Shape (unknown member): Invalid request. To select a shape, its view must be active."
I searched and attempted to implement several strategies from the help forums but am coming up empty.
PLEASE HELP!!!
-Kevin
Part of code below because it is very long, but this is where my first problem arises:
Dim Cargo As Shape, Cargo_Dup as Shape, Chemical as Shape, Chemical_Dup as Shape
Set Cargo = ActivePresentation.Slides(2).Shapes("Cargo")
Set Chemical = ActivePresentation.Slides(2).Shapes("Chemical")
Cargo.Name = "Cargo"
Chemical.Name = "Chemical"
With ActivePresentation
Set Cargo_Dup = ActivePresentation.Slides(2).Shapes("Cargo")
With Cargo_Dup.Duplicate
.Name = "Cargo_1st"
.Left = 0
.Top = 540
End With
'CHEMICAL
If Input1 = "Chemical" Then
Set Chemical_Dup = ActivePresentation.Slides(2).Shapes("Chemical")
With Chemical_Dup.Duplicate
.Name = "Chemical" & 1
.Left = 36.74352
.Top = 540 + 0.36
End With
'''''WHERE PROBLEM ARISES'''''
ActivePresentation.Slides(2).Shapes("Cargo_1st").Select
ActivePresentation.Slides(2).Shapes("Chemical1").Select msoFalse
Set Vehicle = ActiveWindow.Selection.ShapeRange.Group
Vehicle.Name = "Vehicle"
'Elseif with a bunch for options where addition grouping occurs
I need some kind of keyboard macro to type this for me:
Never select anything unless you absolutely have to.
You nearly never absolutely have to.
You're asking how to make a view active so that you can select something.
I figure that's the wrong question.
It's more useful to know how to work with shapes WITHOUT having to select them.
Grouping shapes w/o selecting them is a bit tricky, but it can be done.
Here's an example of how you might go about this:
Sub GroupWithoutSelecting()
Dim oSl As Slide
Dim oSh As Shape
Dim aShapes() As String
Set oSl = ActivePresentation.Slides(2) ' or whichever slide you like
ReDim aShapes(1 To 1)
With oSl
For Each oSh In .Shapes
If oSh.Type <> msoPlaceholder Then ' can't group placeholders
' Substitute the real condition you want to use
' for selecting shapes to be grouped here
If oSh.Type = msoAutoShape Then
' add it to the array
aShapes(UBound(aShapes)) = oSh.Name
ReDim Preserve aShapes(1 To UBound(aShapes) + 1)
End If
End If
Next
' eliminate the last (empty) element in the array
ReDim Preserve aShapes(1 To UBound(aShapes) - 1)
' Create a shaperange from the array members and group the shaperange
.Shapes.Range(aShapes).Group
End With ' oSl
End Sub

Crop an Image (Enhanced Metafile) in PPT 2007

Can anyone help me with an issue in PPT 2007.
I have an image (a chart from excel pasted as 'Picture (Enhanced Metafile)') in a slide. I just need to crop this image to fit in the slide. I tried following code, but to no avail:
'1:
With ActivePresentation.Slides(1).Shapes(1)
.PictureFormat.CropLeft = 10
.PictureFormat.CropTop = 10
.PictureFormat.CropRight = 10
.PictureFormat.CropBottom = 10
End With
'Runtime error "ActiveX Component can't create object
'2:
ActiveWindow.Selection.ShapeRange.PictureFormat.CropRight = 10
ActiveWindow.Selection.ShapeRange.PictureFormat.CropLeft = 10
ActiveWindow.Selection.ShapeRange.PictureFormat.CropBottom = 10
ActiveWindow.Selection.ShapeRange.PictureFormat.CropTop = 10
'Object doesnt support this property or method
Any suggestion is most welcome.
This works with EMFs pasted from Excel:
Dim oSh as Shape
Set oSh = ActiveWindow.Selection.ShapeRange(1)
' Note: ShapeRange(1), not just ShapeRange
' That's the problem with your second example
With oSh
.CropLeft = 10
' etc
End With
The fact that it's yelling about an activex object in the first example makes me wonder whether the first shape is really an EMF, which would not be an ActiveX object.

Programmatically copy shapes with source formatting (PowerPoint 2007)

I need to be able to copy shapes (chart, table, etc.) programmatically from one slide to another in PowerPoint 2007 keeping their original colors. The source and destination slides are in different presentations which have different themes.
These shapes might be complex and include a lot of colors, e.g., charts, tables, etc. The destination slide must maintain its theme, so I cannot simply copy the entire original slide colorScheme.
When copying a shape manually in PowerPoint, I get an option to "Keep Source Formatting". This copies all the original colors of the shape, converting theme colors into absolute RGB values.
What is the simplest way to do this programmatically?
You need to go to the slide and use Application.CommandBars.ExecuteMso
If you don't need to return to the previously selected slide afterwards, you can skip DoEvents and the second call to Application.CommandBars.ExecuteMso
It seemed like the position of the new shape was sometimes a little bit skewed after pasting, so I obtain a reference to the last shape in the Shapes collection of the second slide and copy the position of the original shape.
At least on my machine, without DoEvents, the macro would do nothing when I executed it (but it would work if I stepped through it).
Sub CopySelectedShapeToNextSlide()
Dim oShape As Shape
Dim oSlide As Slide
Dim nextSlide As Slide
Dim newShape As Shape
Set oShape = Application.ActiveWindow.Selection.ShapeRange(1)
Set oSlide = Application.ActiveWindow.Selection.SlideRange(1)
Set nextSlide = oSlide.Parent.Slides(oSlide.SlideIndex + 1)
oShape.Copy
Application.ActiveWindow.View.GotoSlide nextSlide.SlideIndex
Application.CommandBars.ExecuteMso "PasteSourceFormatting"
Set newShape = nextSlide.Shapes(nextSlide.Shapes.Count)
newShape.Left = oShape.Left
newShape.Top = oShape.Top
DoEvents
Application.ActiveWindow.View.GotoSlide oSlide.SlideIndex
Debug.Print newShape.Name
End Sub

How to switch between "active paper" and "slides" in Power Point VBA

I have a simple question regarding PowerPoint VBA:
Which VBA code should I use to switch between the "active sheet of paper" (I am sorry I don't know how to name it properly), in which I am doing something with the object(s), and the file (or "field", again sorry for my poor terminology) where all the slides are ?
For example, if I want to move a selected object in the "active sheet of paper" I would use this macro:
ActiveWindow.Selection.ShapeRange.IncrementLeft
6#
and if I want to copy the selected slide in the slides file, I would use this code:
ActiveWindow.Selection.Copy
ActiveWindow.View.Paste
But how can I connect these two pieces of script? Let's say I want to move an object in the "active sheet of paper", then copy this whole "sheet", then create its twin in the slides field, and then jump into the twin sheet of paper to do something with objects there?
Shortly, how do I switch from "paper" to "slides" and back to "paper" in VBA?
(Again, I am sorry for terrible terminology here, I hope you understand what I mean here.)
Thank you all in advance.
If you record a macro in PowerPoint and examine the code, you'll see that it uses the Selection object for just about everything. That's sometimes useful (because it means it's more likely that the code will do what you want if you select another object), but for anything more than a very short macro, it's probably better to refer to the objects directly, as in the following code:
Sub Test()
' Get the active presentation
Dim oPresentation As Presentation
Set oPresentation = ActivePresentation
' Get the first slide in the presentation
Dim oSlide As Slide
Set oSlide = oPresentation.Slides(1)
' Get the first shape on the slide
Dim oShape As Shape
Set oShape = oSlide.Shapes(1)
' Nudge the shape to the right
oShape.Left = oShape.Left + 1
' Copy the whole slide
oSlide.Copy
' Paste the slide as a new slide at position 2
Dim oNewSlides As SlideRange
Set oNewSlides = oPresentation.Slides.Paste(2)
' Get a reference to the slide we pasted
Dim oNewSlide As Slide
Set oNewSlide = oNewSlides(1)
' Get the first shape on the NEW slide
Dim oNewShape As Shape
Set oNewShape = oNewSlide.Shapes(1)
' Nudge the shape to the right
oNewShape.Left = oNewShape.Left + 1
End Sub
Note that pretty much every object has a Select method, so if you do want to explicitly select something, you can. In some cases, you may need to change the active window's view type first - so for example, you can't select a shape on a slide while in slide-sorter view.

Visual Basic Macro in Word to Resize/Center/Delete All Images

I found a VBA macro online that resizes all the images in a Word document:
Sub ResizeAllImages()
''# make all images (both inline and floating)
''# 11 cm wide while preserving aspect ratio
Dim oShp As Shape
Dim oILShp As InlineShape
For Each oShp In ActiveDocument.Shapes
With oShp
.Height = AspectHt(.Width, .Height, _
CentimetersToPoints(11))
.Width = CentimetersToPoints(11)
End With
Next
For Each oILShp In ActiveDocument.InlineShapes
With oILShp
.Height = AspectHt(.Width, .Height, _
CentimetersToPoints(11))
.Width = CentimetersToPoints(11)
End With
Next
End Sub
I couldn't find the name of a method that I could use to center-align all images.
Does anyone know what I need to add, and where I would have to add it?
Lastly, I'd like to delete images that I find to be too small.
How would I do... If width of shape is smaller than 5, and height of shape is smaller than 5, delete the shape.
For easier reading of large amounts of online text, I sometimes like to paste everything in word, and then rearrange it.
I replace every period-whitespace, with a period-manual line, which gives me a new line for each sentence.. I read better when it's like that. Since I'm pasting everything, the graphics comes too, so I'd like to be able to control the size of all the images, and get rid of any unnecessary images.
I think you cannot center-align images. You can center-align paragraphs. Perhaps something like this will help you:
For Each oILShp In ActiveDocument.InlineShapes
oILShp.Select
Selection.ParagraphFormat.Alignment = wdAlignParagraphCenter
Next
For deletion, just call Delete for each Shape object satisfying your conditions.
http://yuriy-okhmat.blogspot.co.uk/2011/07/how-to-resize-all-images-in-word.html
Has the full code including definition of AspectHt
Code to delete small pictures:
Sub DeleteSmallPictures()
Dim iShp As InlineShape
For Each iShp In ActiveDocument.InlineShapes
With iShp
If .Width < CentimetersToPoints(5) Then
iShp.Delete
End If
End With
Next iShp
End Sub