I am looking to write a generalized PowerPoint macro to group specific shapes together. The problem is I do not know the specific shape names ahead of time as my slidedeck changes slighty each time. Here is my situation: I have a collection of PowerPoint shapes whose names start with the prefix "rc". For example they could be "rc48", "rc49","rc50","rc51". They are always in increasing numerical order and the only "rc" named shapes on the slide. Following these shapes, I have a collection of shapes with the prefix "tx" (they are not the only "tx" shapes in the slide but they do always follow the "rc" shapes) and there are always an equivilant number of "tx" objects following the "rc" objects. So in this example I would have "tx52", "tx53","tx54","tx55".
What I would like to do is group these pairs of objects together. So group1 would be ("rc48","tx52"). group2 would be ("rc49","tx53") and so on.
I know very little about coding in VBA, but my approach in other programming languages would be to find the positions of the "rc" shapes in the sequential shape names vector and then count length(rcshapes_vector) past the "rc" positions to find the "tx" shapes I need and then loop over these pairs.
I realize this is a complicated question, but any help would be greatly appreciated.
Working with vba code in PowerPoint is really painful because you don't have a lot of functions such as Excel vba but I hope the following ideas can help you:
You can validate the type of Shape like If oShp.Type = msoTextBox Then or If oShp.Type = msoPicture Then.
Also for each Shape you can validate the top or left property to find the position in the slide.
If you are sure your shapes have those names, maybe you can try with:
Dim oShp As Shape
For Each oShp In ActivePresentation.Slides(SldNumber).Shapes
If oShp.Name = "rc49" Then
Do Something
End If
next
Related
I'm adding some shapes to the slide and group them together with the code provided.
' Inserting shapes like this
Set sld = Application.ActiveWindow.View.Slide
Set sDesc = sld.Shapes.AddTextbox(msoTextOrientationHorizontal, startX, picStartY, boxWidth, 20)
[...]
' Group shapes together
sld.Shapes.Range(Array(sBox.Name, sLogo.Name, sDesc.Name)).Group
But if there is a placeholder for shapes (see picture, not sure what the correct term is) on the slide I get an error saying that it can't be grouped. It seems like the shapes replace this placeholder and the error appears.
Any suggestions?
Run-time error '-2147024891 (80070005)':
Grouping is disabled for the selected shapes
It's exactly as the error message states (which may well be a first for VBA error messages!). You cannot group placeholders with other shapes.
I battled with this - I was generating shapes and needed to group the ones I had generated.
Using shape names is really the only viable approach I could find.
ZOrderPosition looked good (and is the index number) but the number of shapes returned from ThisSlide.Shapes is not a full indexed collection of all the shapes (I think because the Shapes collection returned treats a shape with type group as a single shape and does not include its underlying shapes). E.g. the ZOrderPosition I got for a generated shape was 103 but the ThisSlide.Shapes collection only returned 57 shapes so indexing that for 103 threw an out of bounds exception.
I initially solved the problem by adding a generated shape number to the shape name which worked as long as I didn't run the routine twice (it was a VSTO add in) which ended up generating duplicate shape names.
The solution I found was to make every name unique by adding the shapes' .Top property as an integer to the shape name - e.g.
GeneratedShape.name = "added_" & cint(GeneratedShape.top) & AddedShapeNo
I need to know is selected shape word art or not.
Shape has property "Type" (returns enum MsoShapeType).
When I insert word art and check this property - it returns msoAutoShape instead of msoTextEffect (with AutoShapeType==msoShapeRectangle).
How can I check that spae is word art (not usual rectangle with textbox) ?
Thanks!
If you select either the overall smartart shape or click into text within the smartart shape or select one of the shapes within the smart art, ActiveWindow.Selection.ShapeRange(1) will return the smartart shape.
So
If ActiveWindow.Selection.ShapeRange(1).HasSmartArt Then
Debug.Print "It's smart art"
End if
[edited]
But as you've pointed out, this is for smartart, not word art. My error, sorry.
There isn't a WordArt shape as such; it's more like any shape that has had WordArt formatting applied to the shape as a whole or to text within the shape. That'd include formatting like glow, reflection, shadow and so on, or could be one of the WordArt presets, pre-selected combinations of these different effects. I've added an example that'll help identify shapes or ranges of text within shape that have these presets applied. I don't see any simple way of checking for user-applied WordArt formats other than looking at each run and each text box for each of the various properties (glow, reflection etc) that might be applied. Unfortunately, there's no WordArtFormat = None to tell us we can ignore it. It's either going to be one of the presets or -2, which can mean any of several things.
Sub WordArtist()
Dim oSh As Shape
Dim oRng As TextRange2
' Has word art formatting been applied to
' entire shape?
Set oSh = ActiveWindow.Selection.ShapeRange(1)
Debug.Print oSh.TextFrame2.WordArtFormat
' Has it been applied to individual chunks of
' text within the shape
For Each oRng In oSh.TextFrame2.TextRange.Runs
Debug.Print oRng.Font.WordArtFormat
Next
' Note:
' A result of -2 for the entire shape could mean
' - No text in the shape; not really word art
' - Mixed formatting
' - Text/shape has had glow/shadow/reflection etc applied
' rather than one of the preset WordArt selections
End Sub
I am trying to create a new PowerPoint plug-in. I have run into a problem for a case where I want to determine if for a given shape on slide 1, whether the same shape also exists on the next slide.
Is there a way by which I can compare shapes from different slides and determine whether they are the same?
I can probably compare the type, dimensions, text and other similar properties, but this may not be the right way to solve this problem. Is there a better way to do this?
Something like this will return an "identical" shape from another slide if it meets your criteria. You could have it return True/False instead if you prefer:
Function SameShape(oThisShape As Shape, oOtherSlide As Slide) As Shape
Dim oSh As Shape
For Each oSh In oOtherSlide.Shapes
If oSh.Type = oThisShape.Type Then
If oSh.Height = oThisShape.Height Then
If oSh.Width = oThisShape.Width Then
' other conditions here as required
Set SameShape = oSh
Exit Function
End If
End If
End If
Next
End Function
One caveat: if the shape's .Type = msoPlaceholder, you'll also need to look to see whether .PlaceholderFormat.ContainedType is the same.
What is an "identical" Shape for you?
All shapes hafe different IDs so you cannot compare them, but you could compare the Size, the location (Shape.Width, Shape.Height etc.) and maybe the content (a chart, a table or text?).
If enough Properties are equal they might be considered as equal.
I have a Visio drawing and I want to be able to Select shapes from it and paste them to other sheets depending on certain variables.
What is the code for selecting the different shapes on the page. I am trying this but it is not working.
Dim vsoSelection As Visio.Selection
vsoSelection.Select Visio.Shape(1), visSelect
What am I missing here?
and also is it possible to get the strings entered into text boxes into Visio?
I am assuming you're getting an error because your vsoSelection object is nothing. So you need to do:
Set vsoSelection = ActiveWindow.Selection
I have a report that is generated in PowerPoint, and underneath many of the graphs, there is text that tells the reader to refer to pages in the appendix. I would like to be able to dynamically reference these slides.
For example, under a graph I might have the text "Please see appendix page 54", but I need the 54 to be linked to a slide so that if I insert another slide it will say 55.
Is this possible to do in VBA? I do not expect somebody to write my code for me, I would just like to know if this is a reasonable thing to do before I spend hours attempting to do it.
Side note: I feel horrible asking a question about MS Office on here, but since I believe it would need to be implemented in VBA (I don't think this functionality is built in by default) I think that it is a relevant question.
No need to feel horrible asking this here.
How one might do this:
In PPT, shapes, slides and even the presentation itself can have an associated tag collection; named string values. For example, assuming a reference to the shape in oSh, you can do:
oSh.Tags.Add "AssociatedSlideId", "293"
In this case, you'd apply this tag to your graph; the 293 would be the SlideID of the slide you want to reference. Each slide has a unique SlideID assigned when it's created; the SlideID won't change when you move the slide around/add/delete slides.
To read the tag from the shape:
Debug.Print oSh.Tags("AssociatedSlideId")
In this case, that'd return "293". Feed that to FindBySlideID to get the SlideIndex of the slide (ie, the ordinal position of the slide in the presentation). Or ask it for SlideNumber if you want the number of the slide that'll appear in number placeholders (usually, but not always the same as slide index).
Debug.Print ActivePresentation.Slides.FindBySlideID(clng("293")).SlideIndex
You might also tag the textbox or other shape that you want to use to hold the reference, then write a function along the lines of:
Function ShapeTaggedWith(oSl as Slide, sTagName as String, sTagValue as String) as Shape
This would iterate through the shapes on slide oSl looking for one with a tag named sTagName, value = sTagValue and return it to the caller if found.
Now you can find the shape that's nominated as your caption for the graph, let's call it, and change its text to match the SlideIndex (or SlideNumber) of the slide the chart's supposed to reference.
Hope that's all moderately clear; if not, that's why the StackOverflow gods gave us comments.