Scenario: I have tons of images in a single worksheet,and many of them are overlapping with each other.
How can I write a VBA code so when user click on any image in that worksheet and Excel will automatically bring that image to the front?
If you have an object myObject that you want to bring to the front you use
myObject.ShapeRange.Zorder msoBringToFront
http://msdn.microsoft.com/en-us/library/office/aa213680(v=office.11).aspx
Your object might for example be the selection:
set myObject = Selection
As for responding to a click - that's trickier. There doesn't appear to be an event for "selecting a picture" . But there is a solution...
You can make a single macro called Picture_click(), and assign that macro to each picture. There doesn't appear to be an event-driven way to achieve this, but the following works:
Add the following to a module:
Sub picture_click()
ActiveSheet.Shapes(Application.Caller).Select
Selection.ShapeRange.ZOrder (msoBringToFront)
End Sub
Sub connect_all()
Dim sh As Shape
For Each sh In ActiveSheet.Shapes
sh.OnAction = "picture_click"
Next sh
End Sub
You have to run the connect_all sub just once, to assign the picture_click macro to each shape. Now, when you click a picture (or other shape) it comes to the front.
Note - the Application.Caller tells you what object was clicked - in other words, what caused the call to picture_click. This is necessary because the "click" doesn't cause the picture to be selected yet - that happens after the macro has run. So you can't just use the selection. Tricky, that.
I referenced this earlier post to come up with this solution - specifically, RichJ's solution.
afterthought
If you don't want the picture to be selected after you clicked it, you can modify the picture_click() sub to the following:
Sub picture_click()
ActiveSheet.Shapes(Application.Caller).ZOrder msoBringToFront
End Sub
This will move the picture to the front but doesn't select it. There is something to be said for that approach.
With every shape, assign the BringToFront macro, then put the following in a module
Sub BrintToFront
Selection.ShapeRange.ZOrder msoBringToFront
end sub
Assign this macro to all Shapes:
Sub lux()
ActiveSheet.Shapes(Application.Caller).ZOrder msoBringToFront
End Sub
Related
I've been trying to reproduce a checkbox on Excel with 2 images (1 for Tick and 1 for Untick), but I got a problem because I simply never coded in VBA; apart from macros.
I got multiple checkboxes that are meant to be ticked/unticked.
I could record a macro for each of them, but doing so would be tedious and unefficient (there's 22 checkboxes in total)
The Macro Code looks like this.
Sub Tick()
ActiveSheet.Shapes.Range(Array("Picture 23")).Select
Selection.ShapeRange.ZOrder msoSendToBack
End Sub
Sub Untick()
ActiveSheet.Shapes.Range(Array("Picture 22")).Select
Selection.ShapeRange.ZOrder msoSendToBack
End Sub
My question is easy : How do I fetch the reference of the image I clicked in order to inject this same reference to the code and set its ZOrder ?
I can't use Excel's Checkboxes because they're too small.
Try following
Sub TickToggle()
On Error GoTo EH
Dim caller As Variant
caller = Application.caller
If Not IsError(caller) Then
ActiveSheet.Shapes(caller).ZOrder msoSendToBack
Select Case caller
Case "Checkbox1_tick":
' your code for when the checkbox1 is unticked
Case "Checkbox1_untick":
' your code for when the checkbox1 is ticked
End Select
End If
EH:
End Sub
Also, try using more meaningful names for those shapes (like above) in order to use select case on the caller value and do different things depending on what has been clicked. You can assign TickToggle to all checkbox shapes, this is preferred (re-usability).
I am trying since 2 days to find how to do the following without finding anything that suits the aim:
Steps by order :
user open excel file
he chose between folowing :
Paste an image directly in the worksheet (may be an limited area)
activate some video in the workbook (may be a webcam for start)
he select with a button to activate his clicks detection
he clicks anywhere on the picture and i get the coordinates of clicked points
So far i've seen ppl using (and tested myself) :
mouse event ==> this does not work as i need to know the name of what he is clicking on and it may be a brand new picture he just pasted
BeforeDoubleClick (same, i'd prefer avoid doubleclick but even then it doesnt work when i click on something else but cells)
Selectionchange ==> doesnt work if im not clicking on cells
Place hidden button over the area i want : i cant click a button if its not visible, and it becomes visible when i click it if i put as transparent
If anyone has ideas about this...
(nb: im not a pro of vba so i may have missed something)
Just forgot : my issue is not getting the coordinates of mouse, its just triggering the macro when i want, for now im jsut trying to get a simple msgbox to see if trigger works.
Thanks if anyone has any ideas
BR
Not sure if this fits your need (for example couldn't test it with a video).
a) Place a "button" of any kind on your sheet. I usually use a square shape for that and format it a little bit (color, shade, text). Assign the subroutine SetEvents to it.
b) Declare a global variable that remembers that click-activation is active
Option Explicit
Global EventCatchingActive As Boolean
c) In the event routine of your button, set the OnAction-method for all shapes of the sheet - see the routine setEvents. This ensures that even newly added images handle the click event.
Sub setEvents()
' This routine is called from the magic button.
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1) ' Set this to whatever sheet you need
Dim button As Shape
Set button = ws.Shapes(Application.Caller)
If EventCatchingActive Then
EventCatchingActive = False
button.TextFrame2.TextRange.Characters.Text = "Start Clicking"
Else
Debug.Print "Setting EventHandler"
Dim sh As Shape
For Each sh In ThisWorkbook.Sheets(1).Shapes
' Debug.Print sh.Name, sh.Type
If sh.Name <> button.Name Then sh.OnAction = "ClickedMe"
Next
EventCatchingActive = True
button.TextFrame2.TextRange.Characters.Text = "Stop Clicking"
End If
End Sub
d) Declare a routine that is called if any of the shapes is clicked. With Application.Caller you can check what was clicked.
Sub ClickedMe(Optional target As Range = Nothing)
If Not EventCatchingActive Then Exit Sub
If target Is Nothing Then
Debug.Print "I clicked on " & Application.Caller
Else
Debug.Print "I clicked on cell " & target.Address
End If
End Sub
(note that code of steps b) to d) goes into a regular module)
e) If you also want to handle clicks on a cell, add the following into the sheet-module of the worksheet you are dealing with.
Private Sub Worksheet_SelectionChange(ByVal target As Range)
ClickedMe target
End Sub
I am currently working on an Excel tool that I have equipped with one button and one shape-object.
The button is a select button to "select" the shape object. The idea is to Select a shape-object a Picture and change its color after selecting it.
I was able to locate the problem to the clicked Sub of the Select button.
To check if I'm correct I have written a the Macro Select_MyClicked and afterword used the call instruction to invoke the macro from within the Clicked-function of the select button.
Sub Select_MyClicked()
Dim ElementName As String
Dim Shp As Object
Set Shp = Sheets("Tabelle1").Shapes(ElementName)
Shp.Select
End Sub
==================================================================
Private Sub CommandButton3_Click()
Call Select_MyClicked
End Sub
==================================================================
What is interesting now is:
When I use the Button the Image is selected but in the Picture format register there i nothing selectable
If I cklick on the Image itselfe or use the Select_MyClicked Macro indepentently everything in the picture format register is selectable
I also tried to write the select instruction directly into the Button-Clicked private sub. Same result nothing selectable
What I want to do is select an image and change its color. My second question is does somebody know how to open the Colorpennel (with the many colored Rectangles) using vba ?
You need to reference the Shape by its Name. I assigned the name "myshape" to the Shape before running:
Sub Select_MyClicked()
Dim ElementName As String
Dim Shp As Shape
ElementName = "myshape"
Set Shp = Sheets("Tabelle1").Shapes(ElementName)
Shp.Select
End Sub
The code runs even if Tabelle1 is not the active sheet.
I have finally find the solution. It seems like it makes a difference which button you use. In my case it had to be the control elements not the activeX elements
I have a worksheet that runs a weightlifting meet. Last year I had created a tab that would give information on the current lifter and on who was lifting next.
left side - Display, right side - input tab
When I input an "x" in columns R, S, T, or W on the data tab, it changes the information in the BenchGenerator tab, like so:
Updated Display tab
What I want to do is make a userform display to run on a different screen so people can see this information. I had accomplished this last year by widening excel and using two view windows - display on the second screen and running the meet on the computer. It was ok but very clunky looking. With a floating userform tab, it would look fantastic. I am new to this, but got the form floating:
Private Sub Worksheet_Change(ByVal Target As Range)
UserForm1.Show (vbModeless)
End Sub
And got the labels to initially populate:
Userform Display
Using this code:
Private Sub UserForm_Activate()
UserForm1.Label1.Caption = Sheets("BenchGenerator").Range("c4").Value
UserForm1.Label2.Caption = Sheets("BenchGenerator").Range("c5").Value
UserForm1.Label3.Caption = Sheets("BenchGenerator").Range("c6").Value
UserForm1.Label4.Caption = Sheets("BenchGenerator").Range("d3").Value
UserForm1.Label5.Caption = Sheets("BenchGenerator").Range("d4").Value
UserForm1.Label6.Caption = Sheets("BenchGenerator").Range("d5").Value
UserForm1.Label7.Caption = Sheets("BenchGenerator").Range("d6").Value
End Sub
What it doesn't currently do is update the captions when I input the "x" in the data tab.
As I mentioned, this is my first foray into userforms and looking through mountains of code trying to figure this out, it will not be my last as there is lots to accomplish with them.
Thanks in advance for any help!
You're pretty close to getting this to work. The problem is that your calling a new form every time a change occurs.
Declare your form as an object outside of the Sub that creates (Show) it.
You can then access it to update labels from another Sub that has the same scope.
Create an UpdateForm sub for example and call it from your Worksheet_Change event.
Try this, place the following code in a new Module:
Dim myForm As Object
Sub launchForm()
Set myForm = UserForm1
myForm.Show (vbModeless)
End Sub
Sub updateForm()
Dim wks As Worksheet
Set wks = Sheets("BenchGenerator")
'Update label values here
myForm.Label1.Caption = wks.Range("C4").Value
myForm.Label2.Caption = wks.Range("C5").Value
myForm.Label3.Caption = wks.Range("C6").Value
myForm.Label4.Caption = wks.Range("D3").Value
myForm.Label5.Caption = wks.Range("D4").Value
myForm.Label6.Caption = wks.Range("D5").Value
myForm.Label7.Caption = wks.Range("D6").Value
End Sub
If you use Worksheet_Change to update the form you'll want to verify the form exist or just skip any errors in the event if it doesn't.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
updateForm
End Sub
Not sure if there is an easier way to do it, but I made a concatenation routine to batch out my label setup and updates to quickly create/copy/paste all the code.
Just in case anyone didn't know how to do this
I am looking to write a macro which copies formatting from one graph and applies it to multiple other graphs.
What I am struggling to do is determine a way to allow the user to set the template chart and then select the multiple other charts. While this could be done with a combo box if the user knew the chart name, I am trying to do it without them knowing the chart name.
As such I was thinking of having a user dialog box where the user can select the base chart, and then select the charts to apply the formatting to. Just like refedit for a range. However I cannot figure out how to reference to a graph from within a user form.
Can this be done, and if so, how?
Here is what will get you started.
Place Two ComboBoxes and two Image Controls on the userform.
Let's say your worksheet looks like this
In the UserForm_Initialize() event populate the Chart names in both the comboboxes. For example
Dim ws As Worksheet
'~~> Prepare your form
Private Sub UserForm_Initialize()
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim ChartObj As ChartObject
For Each ChartObj In ActiveSheet.ChartObjects
ComboBox1.AddItem ChartObj.Name
ComboBox2.AddItem ChartObj.Name
Next ChartObj
End Sub
So when you run the form, it will look like this
In the click event of the comboboxes, use the Stephen Bullen's PastePicture code from HERE to show the chart in the userform. For example
Private Sub ComboBox1_Click()
ws.Shapes(ComboBox1.Value).CopyPicture
Set Me.Image1.Picture = PastePicture(xlPicture)
End Sub
Private Sub ComboBox2_Click()
ws.Shapes(ComboBox2.Value).CopyPicture
Set Me.Image2.Picture = PastePicture(xlPicture)
End Sub
This is how the form will look.
From there on, Now you have the names of the charts. Simply use them to work as you please.
Hope this helps.
The following code should allow you to do stuff with the selected chart area(s), where you can either select one or many charts:
Public Sub ProcessSelectedCharts()
Dim i As Integer
Dim chart_obj As ChartObject
Dim chart_area As chartArea
If TypeOf Selection Is DrawingObjects Then
For i = 1 To Selection.Count
If TypeOf Selection(i) Is ChartObject Then
Set chart_obj = Selection(i)
Set chart_area = chart_obj.Chart.chartArea
Call ProcessChart(chart_area)
End If
Next i
ElseIf TypeOf Selection Is chartArea Then
Set chart_area = Selection
Call ProcessChart(chart_area)
End If
End Sub
Public Sub ProcessChart(obj As chartArea)
' Do something...
End Sub
You may want to refine this a little, i.e. this should work if the user selects the actual charts, but may fail if he only selects a particular element within the chart.
Ok, the next question is, when do you invoke this from your user form. So first of all, your user form should be modal of course, to allow the user the select anything. So how do you notice when the users actually selects anything?
I can think of three methods, and I'll list them from best to worst (the last 2 only described very briefly as I wouldn't recommend using them):
Use the "Worksheet_SelectionChange" event on your worksheet, and have it call a method within your userform to inform it that the selection has changed. Now you'll just need to check if, and which charts have been selected (see code above), and run your algorithm.
Run a timer in your userform and regularly check the active selection.
Hook mouse events by DLL calls and register any mouse clicks, then check for selection changes.
That should allow you to create a ref-edit like feature for selecting charts on your worksheet from a userform.