I want to make a sub that inserts a picture if checkbox is checked and deletes it if it's unchecked, this is what i've got so far, and the first part (insert when checked) works fine. Any ideas, please?
Dim chbx
Set chbx = ActiveSheet.CheckBoxes.Add(240, 15, 144, 15.75)
chbx.Characters.Text = "DisplacementPicturesIns"
chbx.OnAction = "DisplacementPicturesIns"
If chbx.Value = True Then
chbx.OnAction = True
Elseif chbx.Value = False Then
....
End If
I dunno if you still need this but here is a solution that i made to select/unselect my checkboxes elements.
you can change between the if statement to do what ever you want :)
Sub SelectAll()
Dim chkbx As CheckBox
Dim cbv As Long
cbv = Sheets("Feuil1").CheckBoxes(Application.Caller).Value
If cbv = 1 Then
For Each chkbx In Sheets("Feuil1").CheckBoxes
chkbx.Value = xlOn
Next
Else
For Each chkbx In Sheets("Feuil1").CheckBoxes
chkbx.Value = xlOff
Next
End If
End Sub
Like it was pointed out in the notes, your code doesnt make much sense.
the OnAction holds the name of the method to be called once the checkbox is ticked/unticked.
Also, your condition is only being tested once, after the creation of the Checkbox control and thats it. if you want your condition to be tested every time, it must be placed inside the sub that is called on the ticking/unticking event.
My suggestion: give the checkbox a name, and then refer to it inside the sub and check it's value:
Public Sub Example()
With ActiveSheet.CheckBoxes.Add(240, 15, 144, 15.75)
.Characters.Text = "DisplacementPicturesIns"
.Name = "myCheckBox"
.OnAction = "myCheckBox_Click"
End With
End Sub
Sub myCheckBox_Click()
Dim chbx
Set chbx = ActiveSheet.CheckBoxes("myCheckBox")
If chbx.Value = 1 Then
DisplacementPicturesIns
Else
'do other stuff
End If
End Sub
Related
I have a Sub to change the background color of OptionButton in a group when clicked but i can't get this work fluently without any delay when switch the colorm too slow. Is there better aproach?
There are 50 OptionButtons with a unique caption each
class module
Public WithEvents Opt As MSForms.OptionButton
Private Sub Opt_Click()
Application.ScreenUpdating = False
Call toggleColor(Opt)
Application.ScreenUpdating = True
End Sub
Sub toggleColor(opt As Object)
For Each ctl In Worksheets("controls").OLEObjects
If TypeName(ctl.Object) = "OptionButton" Then
If ctl.Object.Caption <> optCaption.Caption Then
ctl.Object.BackColor = &H80000011
Else
opt.BackColor = &H80000016
End If
End If
Next ctl
End Sub
Seems like you only need to set the color for 2 options, not 50 - you just need to remember between calls which one is the odd one out, reset that one, then set the color for opt.
ToggleColor insn't instance-specific (since you're passing in opt), so that could be in a regular module and re-worked to something like:
Sub toggleColor(opt As Object)
Static optPrev As Object 'previous selection (if any)
If Not optPrev Is Nothing Then
optPrev.BackColor = &H80000011 'un-flag previous
End If
opt.BackColor = &H80000016 'flag the clicked one
Set optPrev = opt 'remember it for next time
End Sub
I've a dashboard that uses a userform box field with checkboxes to choose what data to display on a chart.
My code is very copy and pasted.
Private Sub CommandButton21_Click()
UserForm1.Show
If Worksheets("Data Directorate").Range("X4").Value = True Then UserForm1.CheckBox1 = True
If Worksheets("Data Directorate").Range("X5").Value = True Then UserForm1.CheckBox2 = True
If Worksheets("Data Directorate").Range("X6").Value = True Then UserForm1.CheckBox3 = True
Is there a way to use a loop to do this?
I've more repeated code later on:
Private Sub CheckBox1_Click()
Select Case CheckBox1.Value
Case True
Worksheets("Data Directorate").Range("X4").Value = True
Case False
Worksheets("Data Directorate").Range("X4").Value = False
End Select
End Sub
This repeats for 24 check boxes. Would it be possible to loop this?
All great advice posted in this thread, so I'd like to add something that can maybe help to simplify your loops. Controls have a Tag property which, as best I can tell, does nothing other than to store additional information about the control.
Using this to our advantage, we can include the linked cell in the Tag property for each checkbox. (For example, enter X4 into the Tag for linkage to cell X4). This permits for less of the information to be hardcoded, which makes it more adaptable.
Finally, the code would look like this.
Private Sub UserForm_Click()
For Each octrl In Me.Controls
If TypeName(octrl) = "CheckBox" Then
Sheet1.Range(octrl.Tag).Value = octrl.Value
End If
Next octrl
End Sub
My approach in this scenario would be:
Set ControlSource property of the checkboxes to appropriate cells, leave only:
UserForm1.Show
One thing to simplify: instead of using If statements, just make the two sides equal. Like this:
Private Sub CommandButton21_Click()
UserForm1.Show
UserForm1.CheckBox1 = Worksheets("Data Directorate").Range("X4").Value
And the other one:
Private Sub CheckBox1_Click()
Worksheets("Data Directorate").Range("X4").Value = CheckBox1.Value
End Sub
I recommend using the change event instead of the click event. Some user might use Tab and Space, then the click event won't trigger. Like this:
Private Sub CheckBox1_Change()
...
About looping through the checkboxes in the CommandButton21_Click event, that depends on the order of your checkboxes and your table. This might work, but you will have to try it on your table (the order of the checkboxes compared to the order of your cells can ruin the game...)
Dim contr As control
dim i as integer
i=4
For Each contr In UserForm1.Controls
If TypeName(contr) = "CheckBox" Then
contr.Value = cells(i,24).Value 'column 24 is column X
i=i+1
End If
Next
A possible variation to work when CheckBoxes are not in the expected order or get added/removed:
Dim contr As control
Dim J as Integer
Dim Offset as Integer
Offset = 3 'set this to the difference between 1 and the first row containing data
For Each contr In UserForm1.Controls
If TypeName(contr) = "CheckBox" Then
'set j to the checkboxes "number"
J = cInt(right(contr.name, len(contr.name) - len("CheckBox")))
'use the checkbox number + offset to find the row we want
contr.Value = cells(J + Offset,24).Value 'column 24 is column X
End If
Next
Hope this helps.
For the second portion of your question:
Private Sub CheckBox1_Click()
Worksheets("Data Directorate").Range("X4").Value = CheckBox1.Value
End Sub
You can group the checkboxes inside a given frame and try the the following
Sub Test()
Dim i As Long
i = 5
For Each cb In UserForm1.Frame1.Controls
If Worksheets("Data Directorate").Range("X" & i).Value = True Then cb.Value = True
i = i + 1
Next cb
End Sub
Help!
Below is my code for a start/stop button in Excel and now I'm getting a Compile error that is highlighting btnStart on the first line.
Sub btnStart()
ActiveSheet.Unprotect
Cells(Rows.Count, 5).End(xlUp).Offset(1) = Date
Cells(Rows.Count, 6).End(xlUp).Offset(1) = Now
Cells(Rows.Count, 7).End(xlUp).NumberFormat = "hh:mm"
Cells(Rows.Count, 8).End(xlUp).Offset(1) = Environ("username")
Me.btnStart().Enabled = False
Me.btnStop.Enabled = True
End Sub
Sub btnStop()
ActiveSheet.Unprotect
Cells(Rows.Count, 7).End(xlUp).Offset(1) = Now
Cells(Rows.Count, 7).End(xlUp).NumberFormat = "hh:mm"
Me.btnStart.Enabled = True
Me.btnStop.Enabled = False
End Sub
Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
If I understand correctly the buttons are on an excel sheet (not in a user form) so your issue because you are calling the buttons incorrectly. you can't simply call the named buttons you must look into the sheet.buttons property like this
ActiveSheet.Buttons("btnStart").
Also if you have named sheets I would use the sheetname rather than ActiveSheet
Sheets("sheetname").Buttons("btnStart").
One more note, that enabling/disabling a button works BUT it doesn't make the button appear enabled/disabled. To do this you also have to change the font color.
ActiveSheet.Buttons("btnStart").Font.ColorIndex = 15 '15 is grey, 1 is black
---- edit: code changed ---
REASON: After doing some more research it seems there are problems with my original solution. The most important is that the "enabled" property has no effect in excel 2010. Another route would be using activeX controls, BUT, a recent windows update (dec 2014) prevents activeX controls from running without deleting some system files (which would have to be done for each user, on every computer this code may run on -_- good job MS SOURCE)
This new solution should avoid all those problems. It uses two global variables start_btn_disabled and stop_btn_disabled I assume each button in your form (btnStart and btnStop) have a macro assigned to them? Simply check the global variable at the very beginning of the the sub if the button is disabled then quit the sub, so even though the click is still processed (it will always be processed in excel 2010 as stated before) the code doesn't run. So it behaves as though it was disabled. In my code I made a sub called btnStopClicked that would run when you click 'btnStop' In order to assign the macro to a button, right click the button, select "assign macro" and select the appropriate macro. I also created a similar sub for when you click the start button
'these are global variables and should be declared at the top of the module
'outside of any sub/function
'
'Note we use DISabled rather than enabled, because by default
'booleans = False. This means as soon as the form opens both these buttons
'will be enabled without any extra work.
'If you want to change this (make start button enabled and stop disabled,
'when the workbook opens simply change all the "stop_btn_disabled" to
'"stop_btn_enabled" and uncomment the following line) make sure you change the
'variable names so they make sense
'Dim stop_btn_enabled As Boolean 'initializes to false
Dim start_btn_disabled As Boolean 'intializes to false
Dim stop_btn_disabled As Boolean 'intializes to false
'Most of this code remains the same as before
Sub btnStart()
ActiveSheet.Unprotect
Cells(Rows.Count, 5).End(xlUp).Offset(1) = Date
Cells(Rows.Count, 6).End(xlUp).Offset(1) = Now
Cells(Rows.Count, 7).End(xlUp).NumberFormat = "hh:mm"
Cells(Rows.Count, 8).End(xlUp).Offset(1) = Environ("username")
'now we set the state of the global variable
start_btn_disabled = True
'makes the button appear greyed out
ActiveSheet.Buttons("btnStart").Font.ColorIndex = 15
'now we set the state of the global variable
stop_btn_disabled = False
'makes the button black like normal
ActiveSheet.Buttons("btnStop").Font.ColorIndex = 1
End Sub
Sub btnStop()
ActiveSheet.Unprotect
Cells(Rows.Count, 7).End(xlUp).Offset(1) = Now
Cells(Rows.Count, 7).End(xlUp).NumberFormat = "hh:mm"
'now we set the state of the global variable
stop_btn_disabled = True
'makes the button appear greyed out
ActiveSheet.Buttons("btnStop").Font.ColorIndex = 15
'now we set the state of the global variable
start_btn_disabled = False
'makes the button black like normal
ActiveSheet.Buttons("btnStart").Font.ColorIndex = 1
End Sub
'and now the real key is checking the globals before running the code
'when you click "btnStop" button this is the code that runs, you may have
'named the sub something different, I just named it this way so it's clear
'what the sub does
Sub StopBtnClicked()
'must be the first bit of code in the btn click sub
If (stop_btn_disabled) Then
Exit Sub
End If
'the rest of the code when you click stop button goes here
'the only way to get to this point is if the but is enabled
End Sub
Sub StartBtnClicked()
'must be the first bit of code in the btn click sub
If (start_btn_disabled) Then
Exit Sub
End If
'the rest of the code when you click start
End Sub
if this solves your problem, please mark it as the answer
Maybe try the following, I corrected one line
Sub btnStart()
ActiveSheet.Unprotect
Cells(Rows.Count, 5).End(xlUp).Offset(1) = Date
Cells(Rows.Count, 6).End(xlUp).Offset(1) = Now
Cells(Rows.Count, 7).End(xlUp).NumberFormat = "hh:mm"
Cells(Rows.Count, 8).End(xlUp).Offset(1) = Environ("username")
'Corrected line below
Me.btnStart.Enabled = False
Me.btnStop.Enabled = True
End Sub
Sub btnStop()
ActiveSheet.Unprotect
Cells(Rows.Count, 7).End(xlUp).Offset(1) = Now
Cells(Rows.Count, 7).End(xlUp).NumberFormat = "hh:mm"
Me.btnStart.Enabled = True
Me.btnStop.Enabled = False
End Sub
Sub Worksheet_SelectionChange(ByVal Target As Range)
End Sub
You need to use ActiveX buttons if you want to use the Enabled property:
Private Sub btnStart_Click()
Me.btnStart.Enabled = False
Me.btnStop.Enabled = True
End Sub
Private Sub btnStop_Click()
Me.btnStart.Enabled = True
Me.btnStop.Enabled = False
End Sub
Heres the Code that I put in the module1 from Tim Williams
Sub Tester()
Dim isOn As Boolean
With ActiveSheet
Application.Caller = MuddyBoots
isOn = (.CheckBoxes(Application.Caller).Value = xlOn)
.CheckBoxes("TabletUser").Visible = isOn
.CheckBoxes("WebUser").Visible = isOn
End With
End Sub
I have three checkboxes:
MuddyBoots
TabletUser
WebUser
When MuddyBoots is ticked I want TabletUser and WebUser to be visible and when MuddyBoots is unticked I want the two checkboxes TabletUser and WebUser to be invisible.
The code that works-ish is below:
Public Sub TestCheckbox()
Dim s As Shape
Set s = ActiveSheet.Shapes("MuddyBoots")
s.Select
If Selection.Value = xlOn Then
MsgBox "Checked"
ActiveSheet.CheckBoxes("TabletUser").Visible = True
ActiveSheet.CheckBoxes("WebUser").Visible = True
'code here
Else
MsgBox "Not checked"
ActiveSheet.CheckBoxes("WebUser").Visible = False
ActiveSheet.CheckBoxes("TabletUser").Visible = False
'code here
End If
End Sub
This removes the two checkboxes if MuddyBoots is unticked after you ok the pop up message. If I comment out the msgbox line it doesn't work. Then I have to restart the VBA code.
These are form controls.
I also get the error message: Cannot run the macro New User Form Macro'!CheckBox17_Click'. The macro may not be available in this workbook or all macros may be disabled. I have changed the name of the checkboxs in the name box and have triple checked the checkboxes and they have the correct names...
I want to know how to get this functionality working without the popup messages and without the error please.
Sub Tester()
Dim isOn As Boolean
With ActiveSheet
'Application.Caller = name of calling shape
isOn = (.CheckBoxes(Application.Caller).Value = xlOn)
.CheckBoxes("TabletUser").Visible = isOn
.CheckBoxes("WebUser").Visible = isOn
End With
End Sub
As the title states: in Excel 2010 how can I reference the object that a macro has been assigned to? I've created a spreadsheet with a form checkbox and assigned this macro to it:
Sub Toggle()
If ActiveSheet.Shapes("Checkbox1").OLEFormat.Object.Value = 1 Then
ActiveSheet.Shapes("Picture1").Visible = True
Else
ActiveSheet.Shapes("Picture1").Visible = False
End If
End Sub
The checkbox toggles whether or not a picture is visible and that's working fine but I'd like to reuse the script for multiple checkboxes.
The above code is specifically targeting Checkbox1 but I'd like it to target "this", the object I've assigned the macro to.
I feel like this should be really easy but I spent all evening on MSDN, excelforums.com and just googling around.
Thanks for your help!
Application.Caller is what you want
Sub Toggle()
Dim cb As String, shps As Shapes
cb = Application.Caller
Set shps = ActiveSheet.Shapes
shps("Picture1").Visible = (shps(cb).OLEFormat.Object.Value = 1)
End Sub
As far as I know that is not possible using VBA. Sure you could put the toggle code into a separate sub and re-use it. That might help a bit but you still need to specify the name of the checkbox.
Private Sub CheckBox1_Click()
Call Toggle("Checkbox1", "Picture1")
End Sub
Sub Toggle(ByVal Nm As String, ByVal pic As String)
If ActiveSheet.Shapes(Nm).OLEFormat.Object.Value = 1 Then
ActiveSheet.Shapes(pic).Visible = True
Else
ActiveSheet.Shapes(pic).Visible = False
End If
End Sub
You need to put the toggle sub in the same sheet as the checkbox code or else put the toggle sub in a module.