VBA Moving Objects

giuliano95

New Member
Joined
May 7, 2019
Messages
10
Hello,

I am new in the forum,

I am having a problem with VBA,

I have an excel file, with an N number of shapes which are all the same and increase with the time, lets say there is one extra shape a week,

All the shape are aligned in 4 columns from the newest to the oldest ( 1 is the newest and 8 the oldest) in reality they are much more than 8

1 2 3 4
5 6 7 8

I would need a macro that every time I add a new one switch the shapes so I have a blank space to paste my new one instead of the 1 shape ie

1 2 3 4
5 6 7 8

has anybody ever done it or can help?
I am trying on internet but I am not managing to make it work

Thank you in advance
 
I will not post anything further at this stage to give you the opportunity to test @mikerickson code and sort out any issues
- testing more than one code at once gets messy :eek:
I will post an alternative solution for you to consider when I visit the site in 2 days' time
 
Last edited:
Upvote 0

Excel Facts

Repeat Last Command
Pressing F4 adds dollar signs when editing a formula. When not editing, F4 repeats last command.
OMG. it works exactly at the way i wanted it.. really thank you a lot,

Can I ask you instead if i want it in a 5 grid or 3 grid what is the logic of the code to make it go?

Thank you a lot,
super appreciated


If you have shapes on a sheet, the following code will put it in a N row, 4 column grid.
(Adjust the HGap and VGap constants to your taste.)

Adjust the LeaveBlank variable will leave blank places.
LeaveBlank = 0 will put the first shape in the top left corner of the grid, row 1 column 1
LeaveBlank = 1 will put the top left existing shape in row 1 column 2

You can either run it on existing sheet with LeaveBlank = 1 and put your new shape in the space left in row 1 column 1.
Or you can put your new shape on the existing sheet with the New shape as the top left shape on the sheet and then run the program with LeaveBlank = 0.

This will ignore controls on the sheet from the Forms menu, to allow you to run it by a button.

Code:
Sub test()
    Dim oneShape As Shape
    Dim minTop As Single, minLeft As Single
    Dim maxHeight As Single, maxWidth As Single
    Dim hIndex As Long, vIndex As Long
    Dim LeaveBlank As Long
    Dim currShapes As Collection
    Dim i As Long
    Dim flag As Boolean

    Const HGap As Single = 30: Rem adjust
    Const VGap As Single = 10: Rem adjust
    LeaveBlank = 1: Rem adjust
    
    minTop = 9e+15: minLeft = 9e+15
    For Each oneShape In ActiveSheet.Shapes
        If oneShape.Type <> msoFormControl Then
            With oneShape
                If .Top < minTop Then minTop = .Top
                If .Left < minLeft Then minLeft = .Left
                If maxHeight < .Height Then maxHeight = .Height
                If maxWidth < .Width Then maxWidth = .Width
            End With
        End If
    Next oneShape
    
    For Each oneShape In ActiveSheet.Shapes
        If oneShape.Type <> msoFormControl Then
            With oneShape
                .Top = minTop + Int((.Top - minTop) / maxHeight) * (maxHeight + VGap)
                .Left = minLeft + Int((.Left - minLeft) / maxWidth) * (maxWidth + HGap)
            End With
        End If
    Next oneShape
    Application.ScreenUpdating = True
    
    Set currShapes = New Collection
    For Each oneShape In ActiveSheet.Shapes
        If oneShape.Type <> msoFormControl Then
            flag = False
            For i = 1 To currShapes.Count
                If oneShape.Top < currShapes(i).Top Then
                    currShapes.Add Item:=oneShape, before:=i
                    flag = True
                    Exit For
                ElseIf oneShape.Top = currShapes(i).Top Then
                    If oneShape.Left < currShapes(i).Left Then
                        currShapes.Add Item:=oneShape, before:=i
                        flag = True
                        Exit For
                    End If
                End If
            Next i
            If Not flag Then currShapes.Add Item:=oneShape
        End If
    Next oneShape
    
    hIndex = LeaveBlank:  vIndex = 0
    
    For Each oneShape In currShapes
        oneShape.Top = minTop + vIndex * (maxHeight + VGap)
        oneShape.Left = minLeft + hIndex * (maxWidth + HGap)
        hIndex = hIndex + 1
        If 3 < hIndex Then
            hIndex = 0
            vIndex = vIndex + 1
        End If
    Next oneShape
End Sub
Note that this does not know "old" or "new", it snaps existing shapes to a grid and then shift those shapes within the grid.
If the exisitign shapes are "newest in R1 C1, next newest in R1 C2, next newest in R1 C3,..." it will maintain that new>>old order in the shifted grid.
 
Upvote 0
To change the number of columns, change the three in this line. (in the last For oneShape loop)

Code:
If 3 < hIndex Then
 
Upvote 0
Any Excel VBA book can get you started on VBA. This problem is more a case of general proceedure programming. The VBA is just expressing the proceedure.
 
Upvote 0
OMG. it works exactly at the way i wanted it

Looks like you already have everything you require :)
 
Last edited:
Upvote 0

Forum statistics

Threads
1,221,310
Messages
6,159,173
Members
451,543
Latest member
cesymcox

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top