How to keep shape from not moving and resizing new shape - excel

I'm trying to make a code to resize a shape to a defined size after inserting. I have successfully made it work but the problem is, whenever I insert a new one then run the code, the other shapes keep moving out from their initial location.
The shape I'm inserting is from a sign pad add-in, my output is shown
It supposed to be inside each cell and stay in it.
I have tried adding object position to the code "Don't move or size with cell" using the code : .Placement = xlFreeFloating; but still keeps moving.
My Code is:
Option Explicit
Public Sub ResizePicture()
Dim x As Integer
For x = 1 To 35
On Error GoTo endProc
ActiveSheet.Shapes("SigPlus" & x).Height = 32.5984251969
ActiveSheet.Shapes("SigPlus" & x).Width = 113.3858267717
ActiveSheet.Shapes("SigPlus" & x).IncrementTop 4.5651968504
On Error GoTo endProc
Next x
endProc:
Exit Sub
End Sub
Thanks in Advance

Thanks for your suggestion FunThomas, I manage to make it work now based on that code, my code is:
Option Explicit
Public Sub ResizePicture()
Dim sh As Shape, ws2 As Worksheet
Dim Cel As Range
Dim Rng As Range
Set ws2 = Worksheets("Rev.0")
Set Rng = Selection
For Each Cel In Rng
With Cel
Set sh = ws2.Shapes(ws2.Shapes.Count) 'get last shape, i.e. pasted picture
If .Height / sh.Height < .Width / sh.Width Then
sh.ScaleHeight .Height / sh.Height, msoFalse
Else
sh.ScaleWidth .Width / sh.Width, msoFalse
End If
End With
Next Cel
End Sub

Related

Picture Group set to Range

Apologies another noob question. I have been tasked with writing a document within excel, the front cover has a lot of images on it and i have grouped these images together. As there is a risk that the user could move this group. I want to set it so each time that sheet is selected it moves back to its original location. I have looked over the web and i can't seem to find anything for a group of images.
I have tried this and it doesnt work at all. :(
Private Sub Worksheet_Activate()
Dim PicGroup As GroupShapes
With Range("A1")
PicGroup.Name = "HeaderGrp"
PicGroup.Visible = True
PicGroup.Top = .Top
PicGroup.Left = .Left
End With
End Sub
So my group of images I have called HeaderGrp I have put this on Activate Worksheet in VBA and i want this to always move or fix to cells A1.
I would also love this to fit to the page width and length if anyone knows how to do that.
Snapshot of what i would like: -
1) on sheet selection, image group moves to the correct location.
2) image group auto adjusts to page width and height.
Thank you in advance,
This works for me. Pictures appear to be treated as a type of Shape.
Private Sub Worksheet_Activate()
Dim p As Shape
With activesheet
Set p = .Shapes("Pics") 'name
p.Top = .Range("a1").Top
p.Left = .Range("a1").Left
End With
End Sub
This piece of code should get your grouped images:
Option Explicit
Private Sub Worksheet_Activate()
Dim shp As Shape
Dim PicGroup As GroupShapes
'loop through all your shapes
For Each shp In Me.Shapes
'if the shape is grouped then
'set your PicGroup variable
'and exit the loop
If shp.Type = msoGroup Then
Set PicGroup = shp.GroupItems
Exit For
End If
Next shp
With Range("A1")
PicGroup.Name = "HeaderGrp"
PicGroup.Visible = True
PicGroup.Top = .Top
PicGroup.Left = .Left
End With
End Sub

Excel VBA: If statement with shape fill (favourite button)

I'm trying to make a favourite button, but the stage I'm on is trying to make the button have no fill and upon click have it show a fill. I have also set up a button to insert the star. Code below:
Sub favourite_btn()
Dim star_shp As Shape
Dim clLeft As Double
Dim clTop As Double
Dim clWidth As Double
Dim clHeight As Double
Set cl = Range("A1")
With star_shp
clLeft = cl.Left
clTop = cl.Top
clWidth = 50
clHeight = 50
End With
Set star_shp = ActiveSheet.Shapes.AddShape(msoShape5pointStar, clLeft, clTop, clWidth, clHeight)
With star_shp
.Line.Visible = msoTrue
'.Fill.Visible = msoFalse
.Fill.ForeColor.RGB = 16777215
End With
End Sub
Sub star_fill()
Set ws3 = Sheets("Sheet1")
Dim shp As Shape
Set shp = ActiveSheet.Shapes("5-Point Star 7")
Dim test As String
Debug.Print shp.Fill.ForeColor.RGB
If shp.Fill.ForeColor.RGB = 16777215 Then 'if it is transparent
shp.Fill.ForeColor.RGB = 65535 'make it yellow
test = ws3.Shapes(Application.Caller).TopLeftCell.Offset(0, 1).Value
MsgBox test
Else
shp.Fill.ForeColor.RGB = 16777215 'otherwise back to transparent
End If
End Sub
and I getting an error when I click on the star (which triggers the star_fill macro "the index into the specified collection is out of bounds" and it highlights the line "Set shp = ActiveSheet.Shapes(star_shp)" in the star_Fill sub. I thought it was because I hadn't set the star_shp variable as a public variable but I did that and it still throws this error.
Any ideas? Would appreciate any help! Thanks
EDIT: Updated my code to reflect the changes as suggested in the comments below. Currently I'm trying to not refer to the Star shape by it's specific name and instead refer to it by it's variable as defined in the first subroutine. So my question is around how to make a variable a global variable so a different subroutine can refer to it
Updated code - toggle between yellow and transparent fill:
Sub star_fill()
Dim shp As Shape
Set shp = ActiveSheet.Shapes("5-Point Star 4")
Debug.Print shp.Fill.ForeColor.RGB
If shp.Fill.ForeColor.RGB = 16777215 Then 'if it is transparent
shp.Fill.ForeColor.RGB = 65535 'make it yellow
Else
shp.Fill.ForeColor.RGB = 16777215 'otherwise back to transparent
End If
End Sub
Update #2:
Public variable will only work if you specify it outside of your Sub routine (the variable value always lives and dies within a given routine, if embedded within the routine). So you would need to do do the following:
Public star_shp as Shape
Sub favourite_btn()
...
However, Public variable approach is not error-proof because it could also lose its reference to the shape (for example, closing and opening the file).
An alternative would be to have a routine to create the shape (like your favourite_btn sub) and a completely separate routine to dictate the shapes' behavior. The example below will work for any shape created by your routine and even if your routine is used to create multiple (different) shapes.
Note the use of:
.OnAction = "star_fill" which assigns your star_fill subroutine to a created shape.
Application.Caller which is used to bind user's selected shape to the subroutine star_fill. Thanks to this line we are no longer in need of creating a Public Variable star_shp.
Sub favourite_btn()
Dim star_shp As Shape
Dim clLeft As Double
Dim clTop As Double
Dim clWidth As Double
Dim clHeight As Double
Dim cl As Range
Set cl = Range("A1")
Set star_shp = ActiveSheet.Shapes.AddShape(msoShape5pointStar, cl.Left, cl.Top, 50, 50)
With star_shp
.Line.Visible = msoTrue
'.Fill.Visible = msoFalse
.Fill.ForeColor.RGB = 16777215
.OnAction = "star_fill"
End With
End Sub
Sub star_fill()
Dim star_shp As Shape
On Error Resume Next
Set star_shp = ActiveSheet.Shapes(Application.Caller)
On Error GoTo 0
If Not star_shp Is Nothing Then
If star_shp.Fill.ForeColor.RGB = 16777215 Then 'if it is transparent
star_shp.Fill.ForeColor.RGB = 65535 'make it yellow
Else
star_shp.Fill.ForeColor.RGB = 16777215 'otherwise back to transparent
End If
End If
End Sub
ActiveSheet.shapes accepts a number as input, and finds the nth shape. You already have your shape (star_shp), so there's no need to try to get it again!
If you don't already have it, however, you'll need to find it by iterating through all shapes in the active sheet looking for star_shp. I recommend tagging it somehow with a persistent identifier (naming it, perhaps?) and looking for that, but make sure you test what happens when the user copies it.
Dim shp As Shape
For Each shp In ActiveSheet.shapes
If shp.name = "sparklesthethird" Then
Msgbox("found it")
Exit For
Endif
Next

Replacing image in cell with Text "1"

I have an excel that has 1 column with picture in each cell, that picture determines something but i would like to change it to 1 instead. There is only 1 picture, and to my exact, the column is J;Name =PO history/release documentation . Can someone help me to do it with VBA Thank you!
Public Sub Replace_Picture()
Const Replace_Text = "OK"
Dim shp as Shape
For Each shp In ActiveSheet.Shapes
If shp.TopLeftCell.Address = shp.BottomRightCell.Address Then
shp.TopLeftCell.Value = Replace_Text
shp.Delete
End If
Next
Set shp = Nothing
End Sub
I tried the above code but its not working and const replace_text is in red.
I just want to change those cells with the picture to "1", while those blanks will be leave it to be.
I guess you want to delete the PO history shapes from SAP.
you may have a try by below VBA code.
Another way is you may 'Copy+Paste' data from SAP directly instead of 'Export to Excel'
Sub Replace_Shapes()
Dim Shp As Shape
Dim Shp_Address
For Each Shp In ActiveSheet.Shapes
If Shp.Type = msoPicture Then
'Identify the address of Shape by TopLeft
Shp_Address = Shp.TopLeftCell.Address
Range(Shp_Address) = 1
Shp.Delete
End If Next
End Sub

Excel VBA error 1004 when trying to delete buttons from a range of cells

I'm having issues with deleting a range of cells that contains ActiveX command buttons in it, as the code below will throw an error 1004 "Application-defined or object-defined error" on the intersect part when debugging.
Sub DeleteShapes()
Dim rng As Range
Dim sh As Shape
Set rng = Range("I7:K61")
With Sheets("ADB")
For Each sh In .Shapes
If Not Intersect(sh.TopLeftCell, .Range(rng)) Is Nothing Then
sh.Delete
End If
Next
End With
End Sub
The sheet is not locked, and I made sure that all cells within the ranges are not locked as well. No merged cells too. I've tried other combinations of codes, but it still results in that error 1004. The code is in a module.
Strange thing is, if I add a code to ignore the error, it deletes the buttons without issues. However, a strange issue popped up, wherein the dropdown box from data validations fail to show up after deleting the buttons. The only way for it to show up is to save the workbook. Deleting the buttons after saving causes the disappearance of the dropdown again.
Any solutions to this?
EDIT: It looks like I'm experiencing some sort of "Phantom drop down" object with Type 8 based on VBasic2008's code. I've created a new sheet and tried to copy some of the old ones, then it persisted again.
Further experimentation shows that it's coming from my Data Validation cells. Yet strangely enough, removing the data validation doesn't remove the drop down object. Clearing the entire sheet causes the object to still persist. I had to delete the sheet to get rid of it..
Is Data Validation being considered a Form Control? It shouldn't be.. right?
EDIT: How I generate my buttons
Public Sub GenerateButtons()
Dim i As Long
Dim shp As Object
Dim ILeft As Double
Dim dblTop As Double
Dim dblWidth As Double
Dim dblHeight As Double
Dim lrow As Long
lrow = Cells(Rows.count, 1).End(xlUp).Row
With Sheets("ADB")
ILeft = .Columns("I:I").Left
dblWidth = .Columns("I:I").Width
For i = 7 To lrow
dblHeight = .Rows(i).Height
dblTop = .Rows(i).Top
Set shp = .Buttons.Add(ILeft, dblTop, dblWidth, dblHeight)
shp.OnAction = "Copy1st"
shp.Characters.Text = "Copy " & .Cells(i, 6).Value
Next i
End With
End Sub
Shapes
In VBE's object browser search for msoShapeType and you will notice that
there are several shape types. In your case probably:
msoFormControl (8) - Drop downs
msoOLEControlObject (12) - Buttons and stuff.
Anyway try this code first to determine what you want to delete.
Sub ShapeTypes()
Dim shshape As Shape
Const c1 = " , "
Const r1 = vbCr
Dim str1 As String
str1 = "Shape Types in ActiveSheet"
For Each shshape In ActiveSheet.Shapes
str1 = str1 & r1 & Space(1) & shshape.Name & c1 & shshape.Type
Next
Debug.Print str1
End Sub
The following code deletes all msoOLEControlObject typed shapes on the ActiveSheet (Which I am assuming you want to delete):
Sub ShapesDelete()
Dim shshape As Shape
For Each shshape In ActiveSheet.Shapes
If shshape.Type = 12 Then
shshape.Delete
End If
Next
End Sub
Finally your code:
Sub DeleteShapes()
Const cStrRange As String = "I7:K61"
Const cStrSheet As String = "ADB"
Dim sh As Shape
With Sheets(cStrSheet)
For Each sh In .Shapes
If sh.Type = 12 Then 'or msoOLEControlObject
On Error Resume Next
If Intersect(sh.TopLeftCell, .Range(cStrRange)) Then
If Not Err Then
sh.Delete
End If
End If
End If
Next
End With
End Sub
I still haven't figured out the reason behind the error, but it is handled and all the buttons get deleted.
New Version:
Sub DeleteShapes()
Const cStrRange As String = "I7:K61"
Const cStrSheet As String = "ADB"
Dim sh As Shape
With Sheets(cStrSheet)
For Each sh In .Shapes
If sh.Type = 8 Then 'or msoFormControl
On Error Resume Next
If Not Intersect(sh.TopLeftCell, .Range(cStrRange)) Is Nothing Then
If Left(sh.Name,4) = "Butt" then
sh.Delete
End If
End If
End If
Next
End With
End Sub
No need for error handling since the WRONG Intercept line was causing the error.

Keep Listbox at top of Scrolling Worksheet [duplicate]

I have an excel workbook with two shapes on Sheet1 like below
My Requirement is when the user is navigating towards right side of sheet i.e. Towards headers24, header25 and so on ,I want the two shapes on the sheet to move towards the right side with the user.
Can someone Please suggests any ideas for this.
Thanks
Try this.. yep, its easy..
Place this code in the worksheet module where the shapes exist.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
With ActiveSheet.Shapes(1)
.Left = ActiveWindow.VisibleRange(2, 2).Left
.Top = ActiveWindow.VisibleRange(2, 2).Top
End With
End Sub
The coordinate (2, 2) is where you want the shape to be fixed at as you scroll along with the keyboard.
But, it would be annoying to work without the scroll bar on a huge worksheet. so alternatively I think you can use refresh ontime, place this code in a Module
Private eTime
Sub ScreenRefresh()
With ThisWorkbook.Worksheets("Sheet1").Shapes(1)
.Left = ThisWorkbook.Windows(1).VisibleRange(2, 2).Left
.Top = ThisWorkbook.Windows(1).VisibleRange(2, 2).Top
End With
End Sub
Sub StartTimedRefresh()
Call ScreenRefresh
eTime = Now + TimeValue("00:00:01")
Application.OnTime eTime, "StartTimedRefresh"
End Sub
Sub StopTimer()
Application.OnTime eTime, "StartTimedRefresh", , False
End Sub
And the following code in Sheet1 (where the shapes are in)
Private Sub Worksheet_Activate()
Call StartTimedRefresh
End Sub
Private Sub Worksheet_Deactivate()
Call StopTimer
End Sub
First create the shape:
Sub Creator()
Dim shp As Shape
Set shp = ActiveSheet.Shapes.AddShape(1, 100, 10, 60, 60)
shp.TextFrame.Characters.Text = "I will follow"
shp.Name = "MyButton"
End Sub
Then in the worksheet code area:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sh As Shape, r As Range
Set sh = ActiveSheet.Shapes("MyButton")
Set r = ActiveCell
sh.Top = r.Offset(-1, -2).Top
sh.Left = r.Offset(-1, -2).Left
End Sub
If you move the active cell back and forth, the box will move with it.
Note:
This is only demo code. You still need to:
add protection to prevent trying to move the Shape "off-screen"
setting the proper offsets from ActiveCell based on the size of the Shape

Resources