Crop Image to circle shape with 1:1 aspect ratio - vba

Am trying to get a script which will crop image in a circle shape with aspect ratio 1:1, below are the script I am trying but it's cropping in oval shape.
Sub CropToCircle()
Dim shp As Shape
Set shp = ActivePresentation.Slides(1).Shapes(1)
If shp.Type = msoLinkedPicture Or shp.Type = msoPicture Then
shp.AutoShapeType = msoShapeOval
End If
End Sub
Can anyone please help me in this.
Thanks in advance.

The dimensions of the whatever crop shape you choose are dependent on the original shape. If you have a square shape and apply msoShapeOval, your crop area will be a circle. But if your original image shape is rectangular you have two options:
If the .LockAspectRatio of the shape is msoFalse, then you can modify the width or height to create a square image, then apply your crop and it will come out as a circle.
If the .LockAspectRatio of the shape is msoTrue and you can't change it (i.e. it would distort the original image in an undesireable way), then you need a different approach.
Starting out with a single slide in a presentation and a single (image) shape on the slide
The idea is to add a rectangle overlaid in the same size (width and height) as the original image, then create a circle on top of the rectangle in the size (diameter) you need. In the example below, I'm using a (random) circle size of 80% of the height of the original image. Then, combine the two shapes (rectangle and circle) into a single shape -- a rectangle with a hole in the middle. Finally, set the background and border colors of the mask shape to be the same as the slide background.
Option Explicit
Sub CropToCircle()
Dim ppt As Presentation
Set ppt = ActivePresentation
Dim theSlide As Slide
Set theSlide = ppt.Slides(1)
Dim ogPicture As Shape
Set ogPicture = theSlide.Shapes(1)
With ogPicture
If (.Type = msoLinkedPicture) Or (.Type = msoPicture) Then
Dim maskRectangle As Shape
Dim maskCircle As Shape
Set maskRectangle = theSlide.Shapes.AddShape(Type:=msoShapeRectangle, _
Left:=.Left, _
Top:=.Top, _
Width:=.Width, _
Height:=.Height)
'--- randomly decided the circle mask should be 80% of the
' height of the original image
Const MASK_SIZE As Double = 0.8
Dim circleDiameter As Double
circleDiameter = .Height * MASK_SIZE
Set maskCircle = theSlide.Shapes.AddShape(Type:=msoShapeOval, _
Left:=(.Left + ((.Width / 2) - (circleDiameter / 2))), _
Top:=(.Top + (.Height * ((1# - MASK_SIZE) / 2#))), _
Width:=circleDiameter, _
Height:=circleDiameter)
Dim maskShapes As Variant
maskShapes = Array(maskRectangle.Name, maskCircle.Name)
theSlide.Shapes.Range(maskShapes).MergeShapes msoMergeCombine
'--- find the shape we just created
Dim maskShape As Shape
For Each maskShape In theSlide.Shapes
If maskShape.Name <> .Name Then
Exit For
End If
Next maskShape
'--- the color of the new make shape and it's border has to match
' the color of the slide background, assuming it's solid
maskShape.Fill.ForeColor = theSlide.Background.Fill.BackColor
maskShape.Line.ForeColor = theSlide.Background.Fill.BackColor
'--- optionally group the mask and the original image
theSlide.Shapes.Range(Array(.Name, maskShape.Name)).Group
End If
End With
End Sub
The result looks like this:
Clearly, this is not a true crop and only an approximation and will only work if your slide background is a solid color (not a pattern or gradient).

This approach would be much more simple compared to other alternatives.
// Crop 1:1
shape.Select();
CommandBars.ExecuteMso("PictureCropAspectRatio1To1");
// To convert to oval
if (shape.AutoShapeType != MsoAutoShapeType.msoShapeOval &&
shape.Type == MsoShapeType.msoPicture)
{
shape.AutoShapeType = MsoAutoShapeType.msoShapeOval;
}

Related

Avoid overlapping shapes in Visio

I recorded a macro to add custom shapes from stencils and assigned to command button.
When adding shapes multiple times, the shapes are adding on top of existing shapes that I added previously. Is there any way to stop that happening?
Sub Circle ()
Dim DiagramServices As Integer.
DiagramSevices=ActiveDocument.DiagramServicesEnabled.
ActiveDocument.DiagramServicesEnabled = visServiceVersion140 + visServiceVersion150.
ActiveDocument.Windows.ItemEx("Test").Activate.
Application.ActiveWindow.Page.Drop Application.Documents.Item("Custom.vssx").Masters.ItemU("Circle"),9,7.
ActiveDocument.DiagramServicesEnabled = DiagramServices.
End Sub.
#Fallen, please try this code
Sub ForFallen()
' determine variable for spatially related shapes
Dim vsoReturnedSelection As Visio.Selection
' define the shape
Dim sh As Shape
' determine variable coordinates of the shape
Dim x As Integer, y As Integer
' assign initial coordinates of the shape
x = 7
y = 9
' drop shape to the point with initial coordinates
Set sh = ActivePage.Drop(Application.Documents.Item("Custom.vssx").Masters.ItemU("Circle"), x, y)
' get the set of spatially related shapes for dropped shape position
Set rel = sh.SpatialNeighbors(visSpatialOverlap, 0.25, 0)
' if shape overlapped other shapes start next loop
If rel.Count > 0 Then
' this loop is repeated until there are no overlapped shapes left under the shape
Do
' increment X-position for 2 inches
x = x + 2
' move shape to new position
sh.SetCenter x, y
' obtaining a set of spatially related shapes for a new location of shape
Set rel = sh.SpatialNeighbors(visSpatialOverlap, 0.25, 0)
Loop While rel.Count > 0
End If
End Sub
Read more about SpatialNeighbors property and SetCenter method…

Create Centered Shapes beneath selected ones

I wrote code to create circles beneath selected objects in a slide.
The total shapes it can work on is limited to 100 (or whatever number I
choose).
How to set it to any value?
I tried to enter "n", "x" and others. Debug would not let it through.
More importantly, the newly created shapes seem to be aligned,
however at a closer look they need manual intervention to
correct the positioning.
The behavior does not seem consistent across files: on the .pptm
where the macro is stored the shapes are perfect circles (no matter
if the selection is made of squares or rectangles), on
another one they are distorted.
Sub CreateNewShapeAndAlign()
Dim Shp(1 To 100) As Shape
Dim Shp_Cntr As Long
Dim Shp_Mid As Long
Dim New_Shapes As Shape
Dim Ratio As Double
Dim x, y As Integer
Ratio = 1.4
Set myDocument = ActivePresentation.Slides(ActiveWindow.View.Slide.SlideNumber)
For Each Shp(1) In ActiveWindow.Selection.ShapeRange
Shp_Cntr = Shp(1).Left + Shp(1).Width / 2
Shp_Mid = Shp(1).Top + Shp(1).Height / 2
x = ActiveWindow.Selection.ShapeRange.Count
For y = 1 To x
If Shp(1) Is Nothing Then
Set Shp(1) = ActivePresentation.Slides.Range.Shapes(y)
Else
Set Shp(y) = ActivePresentation.Slides(ActiveWindow.View.Slide.SlideNumber).Shapes(y)
End If
Next y
Set New_Shape = myDocument.Shapes.AddShape(Type:=msoShapeOval, Left:=Shp_Cntr - ((Shp(1).Width * Ratio) / 2), Top:=Shp_Mid - ((Shp(1).Height * Ratio) / 2), Width:=Shp(1).Width * Ratio, Height:=Shp(1).Height * Ratio)
New_Shape.Fill.ForeColor.RGB = RGB(100, 100, 100)
New_Shape.Line.Visible = msoFalse
Next
ActiveWindow.Selection.ShapeRange.ZOrder msoBringToFront
End Sub
Below the working code:
I removed any reference to the number of shapes, it was that easy
The alignment is fixed by setting the variables center and middle to
Single (as per clarification by Steve Rindsberg above)
I forced the shapes to be circles by passing the width value to the height
I further cleaned up and removed unnecessary loops I had left from previous attempts at aligning the shapes. I guess variable Ratio should be Single as well, however I don't think it matters so much as it has only two digits after the comma so there is nothing to round.
Sub CreateUnderneath()
Dim Shp As Shape
Dim Shp_Cntr As Single 'Center of Selected Shapes
Dim Shp_Mid As Single 'Middle of Selected Shapes
Dim New_Shape As Shape
Dim Ratio As Double 'Size of new shape relative to selected one underneath
Ratio = 1.45
Set myDocument = ActivePresentation.Slides(ActiveWindow.View.Slide.SlideNumber)
If ActiveWindow.Selection.Type = 0 Then
MsgBox "Nothing has been selected"
Else
For Each Shp In ActiveWindow.Selection.ShapeRange'.GroupItems 'to have it work inside groups
Shp_Cntr = Shp.Left + Shp.Width / 2
Shp_Mid = Shp.Top + Shp.Height / 2
' Circle
Set New_Shape = myDocument.Shapes.AddShape(Type:=msoShapeOval, Left:=Shp_Cntr - ((Shp.Width * Ratio) / 2), Top:=Shp_Mid - ((Shp.Width * Ratio) / 2), Width:=Shp.Width * Ratio, Height:=Shp.Width * Ratio)
New_Shape.Fill.ForeColor.RGB = RGB(0, 0, 0)
New_Shape.Line.Weight = 0.75
New_Shape.Line.Visible = msoFalse
New_Shape.LockAspectRatio = msoTrue
New_Shape.Name = "ShepeBelow"
Next
ActiveWindow.Selection.ShapeRange.ZOrder msoBringToFront
End If
End Sub

How do I select format an active selection of words in a textbox

I'm trying to explore how do I apply some formatting to only few selected words in a textbox but so far unable to accomplish this myself.
Somehow with the code I created below, I can only use it to select all the words in the textbox instead of just a few words I want.
It would be great if anyone can provide me a simpler/ existing codes that can help me solve this please ?
Thanks in advance
Sub ActiveTextRange()
Dim sld As slide
Dim sh As Shape
Dim wordcount As Long, j As Long, x As Long, y As Long, z As Long
wordcount = ActiveWindow.Selection.ShapeRange(1).textFrame.TextRange.Words.Count
With ActiveWindow.Selection.ShapeRange(1)
.textFrame.TextRange.Words(Start:=1, Length:=wordcount).Font.Color.RGB = RGB(230, 0, 0)
End With
End Sub
The following might help. Key to this is being able to track the location of the specific text you want to change in amongst larger chunks of text; my suggestion is to format each bit of text as you add it to the shape. Cheers.
Option Explicit
Sub ActiveTextRange()
Dim vPresentation As presentation
Dim vSlide As Slide
Dim vShape As Shape
Dim vAddThisText As String
' Create a new presentation, add a slide and a rectangle shape
Set vPresentation = Application.Presentations.Add
Set vSlide = vPresentation.Slides.Add(vPresentation.Slides.Count + 1, ppLayoutBlank)
Set vShape = vSlide.Shapes.AddShape(msoShapeRectangle, 10, 10, 600, 300)
' Make the shape white with a 3pt dark red border
vShape.Fill.ForeColor.RGB = rgbWhite
With vShape.Line
.ForeColor.RGB = rgbDarkRed
.Weight = 3
End With
' Setup the shape to be left aligned, font color, top anchored, etc
With vShape.TextFrame
.TextRange.Paragraphs.ParagraphFormat.Alignment = ppAlignCenter
.TextRange.Font.Color.RGB = rgbBlack
.VerticalAnchor = msoAnchorMiddle
.TextRange.ParagraphFormat.SpaceAfter = 6
.TextRange.ParagraphFormat.WordWrap = msoCTrue
End With
' And now format the word red, which is the 7th character and is 3 long
vAddThisText = "Hello Red World"
vShape.TextFrame.TextRange.InsertAfter vAddThisText
With vShape.TextFrame.TextRange.Characters(7, 3)
.Font.Color.RGB = rgbRed
' and change other attributes if needed etc
End With
End Sub
And the output is ...
This colors the second and third words red in a Title placeholder. After Words, the first number is the starting position and the second number is the length:
Sub ColorWords()
Dim objSlide As Slide
Dim objShape As Shape
For Each objSlide In ActivePresentation.Slides
For Each objShape In objSlide.Shapes
If objShape.Type = msoPlaceholder Then
If objShape.PlaceholderFormat.Type = ppPlaceholderTitle Or objShape.PlaceholderFormat.Type = ppPlaceholderCenterTitle Then
With objShape.TextFrame2.TextRange.Words(2, 2).Font.Fill
.Solid
.ForeColor.RGB = RGB(255, 0, 0)
End With
End If
End If
Next objShape
Next objSlide
End Sub
To color a word selection, use:
ActiveWindow.Selection.TextRange.Font.Color.RGB = RGB(Red:=255, Green:=0, Blue:=0)
OK. I think I better understand the ask ... but I'm assuming in this response you're selecting text ... rather than just a shape itself. So you're editing the powerpoint, select some text in a shape, and want to run a macro to format(?) It should be as simple as creating the following in a code module (and then I created a custom access toolbar link to run the macro at the top of PowerPoint to make it quick):
Option Explicit
Sub ActiveTextRange()
ActiveWindow.Selection.TextRange.Font.Color.RGB = rgbRed
End Sub
Before:
Select the text "Red" and run macro:
Btw ... if you want to select just the shape and have some logic choose the text, the concept is a mix of this and my first answer.

Align a shape within a different shape and naming shapes using VBA (macros) PowerPoint

I would like to align ( in this case center)a shape( round cornered rectangle) within sharp cornered rectangle in a slide i.e the center point of both shapes should be equal using VBA without using 'Selection'.I am thinking to reference them via names(Like, wherever these two shapes come as a bunch, macro should align them) but not sure how to start.
Excuse me for the layman's explanation. Any thoughts would really be helpful and push me to start.
You'll have to set up a loop to check each shape in the slide, finding if its Type is an AutoShape, then if its AutoShapeType is msoShapeRoundedRectangle or msoShapeRectangle. As each are found, you would store the name of each in a variable. If both are found then you would get the left, top, width and height measurements for each and set those values so the centers align.
Sub CenterShapes()
Dim oSlide As Slide
Dim oShape As Shape
Dim bFoundRRect As Boolean, bFoundRect As Boolean
Dim RRectName$, RectName$
For Each oSlide In ActivePresentation.Slides
For Each oShape In oSlide.Shapes
If oShape.Type = msoAutoShape Then
If oShape.AutoShapeType = msoShapeRoundedRectangle Then
bFoundRRect = True
RRectName$ = oShape.Name
End If
If oShape.AutoShapeType = msoShapeRectangle Then
bFoundRect = True
RectName$ = oShape.Name
End If
End If
Next oShape
If bFoundRRect = True And bFoundRect = True Then
RRectVCenter = oSlide.Shapes(RRectName$).Top + (oSlide.Shapes(RRectName$).Height / 2)
RRectHCenter = oSlide.Shapes(RRectName$).Left + (oSlide.Shapes(RRectName$).Width / 2)
RectVCenter = oSlide.Shapes(RectName$).Top + (oSlide.Shapes(RectName$).Height / 2)
RectHCenter = oSlide.Shapes(RectName$).Left + (oSlide.Shapes(RectName$).Width / 2)
VDif = RRectVCenter - RectVCenter
HDif = RRectHCenter - RectHCenter
oSlide.Shapes(RectName$).Top = oSlide.Shapes(RectName$).Top + VDif
oSlide.Shapes(RectName$).Left = oSlide.Shapes(RectName$).Left + HDif
End If
Next oSlide
End Sub
This example assumes you know, or determine with your code, the names of the shapes you want to align. Then it's a quick manner of setting up a ShapeRange and using the built-in alignment functions in PowerPoint.
Option Explicit
Sub AlignMe()
Dim theseShapeNames As Variant
theseShapeNames = Array("Rectangle 3", "Rectangle 4", "Rectangle 5")
Dim thisSlide As Slide
Dim theseShapes As ShapeRange
Set thisSlide = ActivePresentation.Slides(1)
Set theseShapes = thisSlide.Shapes.Range(theseShapeNames)
theseShapes.Align msoAlignCenters, msoFalse
End Sub

In PowerPoint 2010/2013, how to keep watermark always on top using VBA

I am using a small VBA program to apply some text in the background. I am able to apply watermark but if I use any image in the presentation then the watermark goes behind that image. Is there any way to keep the watermark always in front.
I am using this code to apply watermark :
Dim cntDesigns As Integer
cntDesigns = ActivePresentation.Designs.Count
For iter = 1 To cntDesigns
Dim curDesign As Design
Set curDesign = ActivePresentation.Designs.Item(iter)
' EnumerateMasters
Dim masterCount As Integer
masterCount = 1
Dim masters(100) As Master
Set masters(masterCount) = curDesign.SlideMaster
Dim cntLayouts As Integer
cntLayouts = curDesign.SlideMaster.CustomLayouts.Count
For Layout = 1 To cntLayouts
Dim curLayout As CustomLayout
Set curLayout = curDesign.SlideMaster.CustomLayouts(Layout)
If curLayout.DisplayMasterShapes = msoFalse Then
masterCount = masterCount + 1
Set masters(masterCount) = curLayout
End If
Next Layout
For masterIter = 1 To masterCount
Dim shape As shape
Set shape = masters(masterIter).Shapes.AddTextbox(msoTextOrientationHorizontal, 0#, 0#, 100#, 100#)
shape.TextEffect.Text = "Watermark"
shape.Height = 100
shape.Width = 100
shape.TextFrame2.WordWrap = msoTrue
shape.TextFrame2.WarpFormat = msoWarpFormat1
shape.Left = 100
shape.Top = 200
Next masterIter
Next iter
No, anything you put on top of something will cover it up. There's no "Keep this shape on top" command.
You can, however, trap one or more events that are likely to happen often (selection change, for example) and let that event trigger code that looks at each shape on the slide(s) and moves your watermark shape to front if it's not already there.