Create Centered Shapes beneath selected ones - vba

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

Related

How to get rid of white space between picture boxes in VB.NET?

For fun I'm trying to recreate the first level of one my favorite games, Fire Emblem 7. I got a picture of the map online. I've broken down the image into "squares" with each square assigned a picture box to display the image. This is because each square needs to have certain properties such as terrain values, units inside them, etc.
The actual image is quite small (240 x 160), so I want to be able to scale it to any user defined value. The size of each square should be 16c x 16c with a scaler of c (all map dimensions are divisible by 16). For some reason, when c > 1, white lines appear between the squares. I've check the code and it looks like the squares should be adjacent with no empty spaces regardless of c.
I have provided a piece of my code and links to the images of different values of c below. Thank you for you help.
'This Sub Creates The Map From Initial Image And Assigns Part Of Image to Each Square
Public Sub New(Name As String, Image As Image)
Dim cropRect As Rectangle
Dim cropImage As Bitmap
Me.Name = Name
Me.Image = Image
Height = Me.Image.Height / 16
Width = Me.Image.Width / 16
ReDim Squares(Height - 1, Width - 1)
For i = 0 To Height - 1
For j = 0 To Width - 1
cropRect = New Rectangle(16 * j, 16 * i, 16, 16)
cropImage = New Bitmap(16, 16)
Graphics.FromImage(cropImage).DrawImage(Me.Image, 0, 0, cropRect, GraphicsUnit.Pixel)
Squares(i, j) = New Square(cropImage)
Next
Next
End Sub
'This Sub Sizes Each Square With User Defined Scale Value
Public Sub Draw(Scale As Double)
For i = 0 To Height - 1
For j = 0 To Width - 1
With Squares(i, j).Box
.Size = New Size(16 * Scale, 16 * Scale)
.Location = New Point(16 * j * Scale, 16 * i * Scale)
.SizeMode = PictureBoxSizeMode.StretchImage
End With
Next
Next
End Sub

Line up shapes to have coincident edges Visio VBA

I have used VBA in the past mostly with excel, but I am not very experienced.
I want to cycle through multiple boxes and make each of them have coincident edges. Like they are sitting on top of each other. I am having trouble identifying the position of the first shape in my selection. I've tried a number of different objects including selection.shaperange.
Dim shp As Visio.Shape
Dim shp1 As Visio.Shape
Dim Pos As Double
Set shp1 = ActiveWindow.Selection.ShapeRange.Item
Pos = shp1.Cells("PinY")
For Each shp In Application.ActiveWindow.Selection
'Change the cell name to the one you want
If shp <> ActiveWindow.Selection.Item(1) Then
Pos = Pos + 6
End If
shp.CellsSRC(visSectionControls, visRowXFormOut, visXFormPinY).FormulaU = Pos & "mm"
Pos = shp.Cells("PinY")
Next shp
End Sub
Can you help me get the position of the first selected item and then I may be able to figure out the rest.
This code will abut the left sides of all but the first-selected shape with the right side of the first-selected shape:
Option Explicit
Public Sub AbutLeftsToPrimaryRight()
Dim sel As Visio.Selection
Set sel = Visio.ActiveWindow.Selection
If (sel.Count < 2) Then
Debug.Print "Select two or more shapes (Use Shift + Click)!"
GoTo Cleanup
End If
Dim shp0 As Visio.Shape
Dim shp As Visio.Shape
'// Get the selection and the primary selected shape,
'// which is item(1). See also: Selection.PrimaryItem
Set shp0 = sel(1)
'// Quick calculate the right side of shp0:
'// PinX - LocPinX + Width.
Dim dRight0 As Double
dRight0 = shp0.CellsU("PinX").ResultIU - shp0.CellsU("LocPinX").ResultIU + shp0.CellsU("Width").ResultIU
'// If shapes are rotated, flipped, or not rectangular,
'// then you'll need to use shp.BoundingBox, which
'// is more complicated
Dim dLeft As Double
Dim dx As Double, px As Double
Dim i As Integer
For i = 2 To sel.Count
'// Get the ith shape:
Set shp = sel(i)
'// Get its Pin:
px = shp.CellsU("PinX").ResultIU
'// Calculate the left side of the shape:
'// PinX - LocPinX:
dLeft = px - shp.CellsU("LocPinX").ResultIU
'// The offset:
dx = dLeft - dRight0
'// Set the new pin:
shp.CellsU("PinX").ResultIUForce = px - dx
Next i
Cleanup:
Set shp0 = Nothing
Set shp = Nothing
Set sel = Nothing
End Sub
Hope this helps!

Crop Image to circle shape with 1:1 aspect ratio

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;
}

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

VBA code to adjust image size in PowerPoint 2016

I am in my first week of learning VBA, and I am looking for a VBA code that will help me resize and reposition pictures pasted into PowerPoint 2016. The desired picture format details are below:
Size
- Height = 3.39"
- Width = 6.67"
- Rotation = 0
- Scale Height = 62%
- Scale Width = 62%
- Aspect Ratio = Locked
- Relative to original picture size = true
Position
- Horizontal position = 0
- Top Left Corner
- Vertical position = 2.06
- Top Left Corner
Any help would be greatly appreciated.
Below is the code that worked for me. Thanks for the support.
Sub ResizeAll()
For Each tSlide In ActiveWindow.Presentation.Slides
tSlide.Select
With tSlide.Shapes.Item(1)
'assume a blank slide with one image added only
.Select
.Height = 72 * 3.39
.Width = 72 * 6.67
'algin middle (Horizontal Center)
.Left = 0
.Top = ActivePresentation.PageSetup.SlideHeight / 3.25
End With
Next
End Sub
Okay, so this macro will adjust the details of every picture within your powerpoint.
Sub AdjustImages()
Dim curSlide As Slide
Dim curShape As Shape
For Each curSlide In ActivePresentation.Slides
For Each curShape In curSlide.Shapes
With curShape
'size:
''1 inch = 72 points
.Height = 72 * 3.39
.Width = 72 * 6.67
.ScaleHeight 0.62, msoTrue
.ScaleWidth 0.62, msoTrue
.LockAspectRatio = msoTrue
'position:
.Rotation = 0
.Left = 0
.Top = 2.06
'Relative to original picture size = true
End With
Next curShape
Next curSlide
End Sub
The only part of your question that I don't really understand is when you mention it being "relative to original picture size = true". I can't seem to find an attribute that matches that.