First time posting, hope this all makes sense. I have created a graphic in excel that shows 88 lines 1. In another worksheet there are rows of data documented what is on each line 2 When a line is clicked on the graphic I want the corresponding data from the other worksheet to pop up 3
I have managed it achieve this by making a transparent button/shape over each line to hide and show a linked image 4. However, I've had to create a separate button and macro for each line with 100+ lines this seems every inefficient. this is the code I used :
Sub LINE1A1()
With ActiveSheet.Shapes("Rectangle 9").TextFrame2.TextRange.Characters
If .Text = "Hide" Then
.Text = "Show"
ActiveSheet.Shapes("Picture 3").Visible = False
Else
.Text = "Hide"
With ActiveSheet.Shapes("Rectangle 9")
ActiveSheet.Shapes("Picture 3").Left = .Left + .Width
ActiveSheet.Shapes("Picture 3").Top = .Top + .Height
ActiveSheet.Shapes("Picture 3").Visible = True
End With
End If
End With
End Sub
What would be a better way to achieve this? side not I used linked image as the data and range of data is subject to changes as each line could have more than 1 row of data.
You can create those buttons or shapes with a macro (as you said for example 100 buttons) and move them with a macro so they are in the right place. They are going to use the same macro. It will just do a different thing depending where the button is or maybe better depending on its name.
There is a nice tutorial.
https://www.youtube.com/watch?v=bF28JhlC7yc&index=18&list=PLpOAvcoMay5SE3XTp2YN2v6NcJuXKM9KX
Here's a simple example where a common Sub uses Application.Caller to figure out which shape triggered it.
Sub Tester()
Dim s As Shape, c, s2 As Shape
c = Application.Caller '<< name of your clicked shape
Debug.Print c
Set s = ActiveSheet.Shapes(c) '<< the clicked shape
With s.TextFrame2.TextRange.Characters
'here you need some way to transform the name of the clicked
' shape to get the name of the other shape to be shown/hidden/moved
Set s2 = ActiveSheet.Shapes(c & "_linked")
s2.Visible = (.Text = "Show")
.Text = IIf(.Text = "Show", "Hide", "Show") 'toggle text
End With
End Sub
Related
I am working with 5 different buttons that have a single Icon visible in each Button Group. All in 1 Module (If that matters) to hide/unhide row ranges.
So far I have this, but I get a 438 error. I was thinking that I would stack the buttons and toggle them. But I would rather just toggle the icon within the Group.
BTW: I am using Text (No Fill) as the parameter because I don't know another way.
There really isn't much out there that talks about working with Shape Buttons that I can find.
Sub HideInactive()
Call TurnOffStuff 'sub that turns off calculation and screenUpdating
With ActiveSheet.Shapes("HideInactive_Button1")
If .TextFrame.Characters.Text = "Hide" Then 'invisible text on the button
.Shapes("HideInactive_Button2") = HIDE 'Hides the "show" button
StartRow = 13
EndRow = 250
ColNum = 10
For i = StartRow To EndRow
If Cells(i, ColNum).Value = "0" Then
Rows(i).EntireRow.Hidden = True
Else
Rows(i).EntireRow.Hidden = False
End If
Next i
.TextFrame.Characters.Text = "Show"
.Shapes("HideInactive_Button1").Visible = HIDE 'Exposes the "show" button
Range("J13").Select 'moves the active cell to the top of the range
Else
Rows("13:250").EntireRow.Hidden = False 'resets the range view
.TextFrame.Characters.Text = "Hide"
.Shapes.Range("HideInactive_Button2").Visible = HIDE 'Exposes "hide" button
Range("J13").Select
End If
End With
HIDE = Not (HIDE)
Call TurnOnStuff
End Sub
I need something that I can reuse for many buttons just by renaming the shapes and the ranges.
Thank you for the help. I appreciate your time!
I have found a simple script that allows for hiding or showing a picture using the text in a shape. I like the functionality and would like to apply it to our list of employees. However, the way it is constructed right now would require me to add one macro for each person and that is not sustainable in the long run.
Is there a way to re-write this script so it sets the name of the picture based on the name of the employee that is located in column A? Then it would be really simple to just insert images and name them with the Employee name.
I also see that the button is mentioned in the code. So this also needs to be written more dynamically. Could I use a normal format control instead of a shape? (The button does not need to change the displayed text as in this script.)
I really would appreciate your help here. This would look really smooth and I think others would make good use of a VBA like this too.
Sub Macro1()
With ActiveSheet.Shapes("Rounded Rectangle 4").TextFrame2.TextRange.Characters
'Check if shape text is equal to "Hide"
If .Text = "Hide" Then
'Change shape text to "Show"
.Text = "Show"
'Hide shape
ActiveSheet.Shapes("Picture 1").Visible = False
'Continue here if shape is not equal to "Hide"
Else
'Change text to "Hide"
.Text = "Hide"
With ActiveSheet.Shapes("Rounded Rectangle 4")
'Move image named "Picture1" based to lower right corner of shape
ActiveSheet.Shapes("Picture 1").Left = .Left + .Width
ActiveSheet.Shapes("Picture 1").Top = .Top + .Height
'Show image
ActiveSheet.Shapes("Picture 1").Visible = True
End With
End If
End With
End Sub
Reference: https://www.get-digital-help.com/show-and-hide-a-picture-vba/
Example data:
First, I'd like to say that you would be much better off designing something like this in MS Access as opposed to Excel. There are lots of tutorials showing how to build exactly this with Access Forms. It would certainly be much easier to maintain.
That being said, your question was about doing this in Excel and I'll answer that with a simple implementation suggestion. Just bare in mind, it comes with what I would consider "messy" maintenance.
First, you have a bunch of shapes representing the show/hide buttons. Each of these shapes would need to have their own unique name (not important what the name is for this case) and each of them would need to be positioned inside the cell for the row they are meant to operate on (as shown in your example photo).
Next, each employee's photo would need to be named the same as your employee name (the value in column A in your example).
Lastly, you would need to set the "Assigned Macro" of each show/hide button to the same method (I've named my Button_Click()). That method implementation looks like this:
Sub Button_Click()
Dim clickedButton As Shape
Dim employeePhoto As Shape
Dim clickedButtonRow As Long
Dim employeeName As String
'// gets the row number in whcih the clicked button resides
Set clickedButton = ActiveSheet.Shapes(Application.Caller)
clickedButtonRow = clickedButton.TopLeftCell.Row
'// gets the employee name (column A in this case)
employeeName = ActiveSheet.Range("A" & clickedButtonRow).Value
Set employeePhoto = ActiveSheet.Shapes(employeeName)
With clickedButton
' //set the position of the employee photo
employeePhoto.Top = .Top + .Height
employeePhoto.Left = .Left + .Width
With .TextFrame.Characters
'// set the visibility of the associated employee picture based on the text state of the button
employeePhoto.Visible = .Text = "Show"
'// swap the label on the button
If ActiveSheet.Shapes(employeeName).Visible Then
.Text = "Hide"
Else
.Text = "Show"
End If
End With
End With
End Sub
When applying the solution from ArcherBird I discovered a need to add a button in the headline to hide/show all pictures. This provides for a better user experience.
I added this script to the sheet (not in a module) and connected it to a button.
In my document I have our company logo in the headline and I kept this visible at all times.
I hope somebody find this set-up useful! :-)
Dim c As Boolean
Sub Button4_Click()
c = c Xor True
ActiveSheet.Pictures.Visible = c
ActiveSheet.Pictures("CompanyLogo").Visible = True
End Sub
I have 70 check boxes on a sheet.
I would like each Checkbox - when clicked to fill a Rectangle around that Checkbox.
If Checkbox is not clicked - the Rectangle will not be filled.
My issue is that I try to apply this code to each checkbox - but I am getting a compile error: "compile error ambiguous name detected boxcheck"
How do I prevent the compile error?
Note: Each Checkbox will have it's own unique name (1-70), and each Rectangle will have its own Unique Name (1-70). This way each Checkbox should only fill the Rectangle that the VBA IF/THEN code references. I do NOT want 1 Checkbox to fill all rectangles.
Here is my code:
Sub BoxCheck()
If ActiveSheet.Shapes("Check Box 1").ControlFormat.Value = 1 Then
ActiveSheet.Shapes("Rectangle 1").Fill.ForeColor.SchemeColor = 3
End If
If ActiveSheet.Shapes("Check Box 1").ControlFormat.Value = -4146 Then
ActiveSheet.Shapes("Rectangle 1").Fill.ForeColor.SchemeColor = 1
End If
End Sub
It could be throwing you an error if you have multiple subs within a module that are named the exact same. If you copy your original code, or the one below and simply replace the # for the rectangle and box number it pertains to, it might clear up the error.
Sub BoxCheck#()
If ActiveSheet.Shapes("Check Box #").ControlFormat.Value = 1 Then
ActiveSheet.Shapes("Rectangle #").Fill.ForeColor.SchemeColor = 3
End If
If ActiveSheet.Shapes("Check Box #").ControlFormat.Value = -4146 Then
ActiveSheet.Shapes("Rectangle #").Fill.ForeColor.SchemeColor = 1
End If
End Sub
Another option would be to put each BoxCheck into a different module, but that seems excessive, especially because you have 70 of them
You can link all of your check boxes to a single sub and use Application.Caller to figure out which one called the method:
Sub BoxCheck()
Dim shp, rectName as string
Set shp = ActiveSheet.Shapes(Application.Caller)
rectName = Replace(Application.Caller, "Check Box ", "Rectangle ")
ActiveSheet.Shapes(rectName).Fill.ForeColor.SchemeColor = _
IIf(shp.ControlFormat.Value = 1, 3, 1)
End Sub
I currently have code used for three ListBoxes in a worksheet (Box1, Box2, Box3), which are all filled with the same values. One box is single select, and the other two are multi select. I am having rendering issues (with the boxes growing in size when other people open the file) and thought it might be worth switching over to forms ListBoxes. I have not yet been able to get the code to translate.
Currently I have this function to populate the boxes:
Sub FillBox(MyBox As MSForms.ListBox, MultiType As Integer, DataArray As Variant)
With MyBox
.Clear
.MultiSelect = MultiType
For j = 1 To UBound(DataArray)
.AddItem DataArray(j)
Next j
End With
End Sub
To glean a value from the single-select box, Box1, I use:
Sheets(2).Cells(1,1) = Box1.Value
To obtain values from Box2 and Box3 this type of code is employed:
For k = 0 To Box2.ListCount - 1
If Box2.Selected(k) = True Then
Sheets(2).Cells(k+1,2) = Box2.List(k)
End If
Next k
I have been unable to get these same functions to work for a forms ListBox, including .Clear, .Selected(), .List(), etc. What is the alternative syntax for these types of operations? Or, if anything, is there a way to avoid bad rendering of ActiveX ListBoxes?
This is the rendering problem that has kicked off this whole thing in the first place:
I had the same problem and here is my solution:
I delete a list box, add it and fill it every time I open a book. So in this case a box will be in a range "B3:D17" every time
Private Sub Workbook_Open()
Set ws = Sheets("Hoja1")
ws.OLEObjects("ListBox1").Delete
Set Rng = ws.Range("B3:D17")
Set mylist = ws.Range("G3:G7")
ws.OLEObjects.Add(ClassType:="Forms.ListBox.1", Link:=False, _
DisplayAsIcon:=False, Left:=Rng.Left, Top:=Rng.Top, _
Width:=Rng.Width, Height:=Rng.Height).Name = "ListBox1"
ws.OLEObjects("ListBox1").ListFillRange = mylist.Address
End Sub
I found out another way, even better:
Resize your listbox on workbook open
Private Sub Workbook_Open()
Set ws = Sheets("Hoja1")
Set Rng = ws.Range("B3:D17")
With ws.Shapes.Range(Array("ListBox1"))
.Left = Rng.Left
.Top = Rng.Top
.Width = Rng.Width
.Height = Rng.Height
End With
End Sub
Within Excel, I have created a group of shapes, these comprise of some check boxes and a white rectangle. I've named these "grouponeone". I have also created a rectangle called "oneonebutton"
What I would like to happen is that when the rectangle "oneonebutton" is inactive the text frame references a a named cell (call it "namedcell"). When clicked it changes to "Select Options" and the group is shown underneath the button. The check boxes, when clicked plot scatter values on a graph. When clicked again it reverts back to initial state.
This is my code so far, but I'm stuck and being new to VBA I've been hacking about with out much luck. Help very much appreciated.
Sub checkboxmacro()
If SelShp.TextFrame2.TextRange.Characters.Text = Range("namedcell") Then
group11.Visible= False
SelShp.TextFrame2.TextRange.Characters.Text = "Select Options"
Else
group11.Visible = True
SelShp.TextFrame2.TextRange.Characters.Text = Range("experimentoneonename")
End If
End Sub
Cheers in advance
What you have so far looks OK to me (some suggested changes below).
Sub Tester()
Const STR_SELECT As String = "Select Options (click here when done)"
Dim shp As Shape, tr As TextRange2, grp As Shape
Set shp = ActiveSheet.Shapes(Application.Caller)
Set tr = shp.TextFrame2.TextRange
Set grp = ActiveSheet.Shapes("grpOne")
If tr.Characters.Text <> STR_SELECT Then
tr.Characters.Text = STR_SELECT
grp.Visible = True
Else
tr.Characters.Text = ActiveSheet.Range("namedcell")
grp.Visible = False
End If
End Sub
How to proceed might depend in part on what type of checkboxes you have.
Eg: if you use Forms checkboxes then you can link them all up tp something like the sub below (switching the action you take based on the name of the checkbox)
Sub Checker()
Dim ac As String
ac = Application.Caller
Debug.Print ac, ActiveSheet.CheckBoxes(ac).Value
'do something based on checkbox name and value...
End Sub