I am trying to do the following with Excel 2010 VBA:
set a toggle button on a form.
move to the worksheet
use the mouse to select groups (range) of cells
set a cell parameter (background colour) to the back colour of the toggle button
.
.
.
continue select cells or deselect the toggle button.
What I have so far is this but I get a global range error on the line setting the colour:
Public Sub ToggleButton1_Click()
Dim ActRange As Range
Dim ActSheet As Worksheet
Dim bgndColour As Variant
bgndColour = ToggleButton1.BackColor
Set ActSheet = ActiveSheet
Set ActRange = Selection
ActSheet.Select
ActRange.Select
Range(ActRange).Interior.Color = bgndColour
End Sub
ActRange is already a range. No need to use the Range() object
Try this
ActRange.Interior.Color = bgndColour
Your code can be reduced to
Public Sub ToggleButton1_Click()
If TypeName(Selection) <> "Range" Then
MsgBox "Select a range first."
Exit Sub
End If
Selection.Interior.Color = ToggleButton1.BackColor
End Sub
I dont like to add inecesary lines, I see you can resume your code in
Selection.Interior.Color = bgndColour
if that is not working what is wrong is your bgndcolour variable
Related
I have created a combo-box via VBA code.
Sub CreateFormControl()
ActiveSheet.DropDowns.Add(0, 0, 100, 15).Name = "ComboBox1"
ActiveSheet.Shapes("ComboBox1").ControlFormat.RemoveAllItems
Dim i As Integer
With ActiveSheet.Shapes("ComboBox1").ControlFormat
For i = 1 To 25
.AddItem i
Next i
End With
ActiveSheet.Shapes.Range(Array("ComboBox1")).Select
Selection.OnAction = "ComboBox1_Change"
Range("B2").Select
End Sub
The problem here is, when I select an item in the ComboBox, it gives me a
Run-time error 424. Object required
It doesn't show the value selected. I also tried to change my declaration, Sub CreateFormControl() to Public Sub CreateFormControl(), but it's still not working.
Sub ComboBox1_Change()
MsgBox (ComboBox1.Value) 'The error is here
End Sub
Try the code below, try to replace ActiveSheet with a qualifed Worksheet, like Worksheets("YoutSheetName").
Sub ComboBox1_Change()
Dim ws As Worksheet
Dim MyDropDown As DropDown
' try not to use ActiveSheet, replace "Sheet1" with your sheet's name
Set ws = Worksheets("Sheet1") ' ActiveSheet
Set MyDropDown = ws.Shapes("ComboBox1").OLEFormat.Object ' <-- set my Object with "ComboBo1" drop-down
MsgBox MyDropDown.List(MyDropDown.ListIndex) '<-- display the value of the selected item
End Sub
Below is a "cleaner" way to add a new DropDown to a Worksheet without using ActiveSheet, Select and Selection (just use fully qualified objects).
Sub CreateFormControl Code
Option Explicit
Sub CreateFormControl()
Dim MyDropDown As DropDown
Dim i As Long
' set the drop-down object to the new created drop-down (replace "Sheet1" with your sheet's name)
Set MyDropDown = Worksheets("Sheet1").DropDowns.Add(0, 0, 100, 15)
' modify the drop-down properties
With MyDropDown
.Name = "ComboBox1"
.RemoveAllItems
For i = 1 To 25
.AddItem i
Next i
.OnAction = "ComboBox1_Change"
End With
End Sub
I have a spreadsheet with 70 rows x 6 columns containing 420 option buttons in groups of 6 ie group1 = optionbutton1, 71.141,211,281 and 351. Group2 = Optionbutton2,72,142,282 and 352.
This is the code I have for changing the background colour based on the value of the button:
Private Sub OptionButton1_Change()
With OptionButton1
If .Value Then
.BackColor = vbRed ' or RGB(255, 0, 0)
Else
.BackColor = vbGreen ' or RGB(0,0,0)
End If
End With
End Sub
I need to do this for all 420 option buttons, but this could take a while to replicate and stands more chance of missing entries.
Is there a way of shortening this code or changing the code to apply to any option button on the worksheet to change to red on true or green when false?
It looks like you're using an ActiveX Option Button and, unfortunately, I don't believe there is a way to get around having to have code associated with the Change or Click Events of each Option Button if you want it to automatically change the Controls BackColor when the user changes an option.
An alternative would be to use the Form Controls Option Button as with these you can set them all to run the same code whenever their selection is changed. Taking this approach you could have a single Method which will loop through every Option Button on the Sheet and change it's background colour dependent on its value.
The following is an example of how you could do this. In the Visual Basic editor add a new Module to your project. This function would be called whenever your Option Button is changed, and it will work through every Option Button on the Sheet and change its colour.
Sub optionButtonChange()
Dim wb As Workbook
Dim ws As Worksheet
Dim formShape As shape
Set wb = ActiveWorkbook
Set ws = wb.ActiveSheet
For Each formShape In ws.Shapes
If formShape.Type = MsoShapeType.msoFormControl Then
If TypeName(formShape.OLEFormat.Object) = "OptionButton" Then
If formShape.OLEFormat.Object.Value = 1 Then
formShape.OLEFormat.Object.Interior.Color = vbRed
Else
formShape.OLEFormat.Object.Interior.Color = vbGreen
End If
End If
End If
Next
Set ws = Nothing
Set wb = Nothing
End Sub
Now for this to work you need to assign this to the Option Buttons 'macro' - you can do this manually by right clicking the Option Button and selecting it, or you can do it programmatically by applying it to every Option Button on the Sheet, as in the following example:
Sub changeOnAction()
Dim wb As Workbook
Dim ws As Worksheet
Dim formShape As shape
Set wb = ActiveWorkbook
Set ws = wb.ActiveSheet
For Each formShape In ws.Shapes
If formShape.Type = MsoShapeType.msoFormControl Then
If TypeName(formShape.OLEFormat.Object) = "OptionButton" Then
' Macro name format is "'<workbooks filename>'!functionToCall"
formShape.OnAction = "'" & wb.Name & "'!optionButtonChange"
End If
End If
Next
Set formShape = Nothing
Set ws = Nothing
Set wb = Nothing
End Sub
To use this, make sure the Sheet with your Option Buttons on is open and from the Visual Basic editor simply run the code. Once that is done clicking any Option Button on your Sheet will trigger the initial code example and they should all re-colour automatically.
Hi I have lots of sheets, in which I have a many cell on the column AI, which has checkbox in it.
I want to have an event handler on click of that checkbox on that column A1. I tried this code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("AI")) Is Nothing Then
MsgBox "Hello World"
End If
End If
End Sub
this code works on click of the cell not on the checkbox.
How to look for click on the checkbox? And also get the row number of the checkbox being clicked.
Thanks in advance.
You have to assign a macro to the Check Box. The below code will run when you tick a Check Box which the macro has been assigned to.
Option Explicit
Public Sub check_box_ticked()
Dim cbox As Integer
Dim wb As Workbook, ws As Worksheet, checkb as Shape
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
Set checkb = ws.Shapes("Check Box 1")
cbox = ws.CheckBoxes("Check Box 1").Value
If cbox = 1 Then 'if message box is ticked then run code
' You can also use BottomRightCell
MsgBox ("Row: " & checkb.TopLeftCell.Row & "Column: " & checkb.TopLeftCell.Column)
End If
End Sub
This will return the column and row number when the Check Box is ticked.
I'm trying to get a single macro that I can assign to my command buttons. I have multiple buttons that open different files so in each cell I include a different file path.
Currently my command buttons are looking for a specific cell reference and opening that value.
Is there any way I can get the macro to look for the value in the cell to which it is aligned?
I'm using two macros at the moment - one to create the buttons and then another to assign to the buttons. I am having to create a new macro for each button.
Macro to create button...
Sub Buttons()
Dim i As Long
Dim lRow2 As Integer
Dim shp As Object
Dim dblLeft As Double
Dim dblTop As Double
Dim dblWidth As Double
Dim dblHeight As Double
With Sheets("Print Schedule")
dblLeft = .Columns("A:A").Left 'All buttons have same Left position
dblWidth = .Columns("A:A").Width 'All buttons have same Width
For i = Range("E65536").End(xlUp).Offset(1, 0) To ActiveCell + 15
dblHeight = .Rows(i).Height 'Set Height to height of row
dblTop = .Rows(i).Top 'Set Top top of row
Set shp = .Buttons.Add(dblLeft, dblTop, dblWidth, dblHeight)
shp.Characters.Text = "Open Print Schedule"
Next i
End With
End Sub
Macros to open file...
Sub Mendip()
Dim myfile As String
myfile = Cells(6, 6).Value
Application.Workbooks.Open Filename:=myfile
End Sub
Please tell me there is a better way to do this!
When you create the form buttons as shown below then you can assign a common macro to them
And you can assign a macro like this
Sub Sample()
Dim shp As Shape
Set shp = ActiveSheet.Shapes(Application.Caller)
'MsgBox shp.TopLeftCell.Address
Select Case shp.TopLeftCell.Address
Case "$A$1"
'~~> Do Something
Case "$B$1"
'~~> Do Something
'
'~~> And So on
'
End Select
End Sub
EDIT:
One thing I forgot to mention. To assign the "Sample" macro to all buttons, Add the below line after you create the shape.
shp.OnAction = "Sample"
I'm trying to figure out how to delete all buttons within a range. I've seen plenty of examples on how to delete all buttons within a sheet but not a range. I created a range variable the contains every possible occurance of a button (this is used to reinitialize a form of variable size). The problem is that range doesnt support the object .Shapes or .Buttons.
Set totalTable = Range(ActiveCell, ActiveCell.Cells(1000, 1000))
For Each gen_btn In totalTable.Shapes
gen_btn.Delete
Next
Any help would be appreciated. Also, I can't use ActiveSheet becuase there are buttons which i want to keep and becuase the macro is called by a button. Hence the need for a range. Thank you.
This solution uses the Intersect method to see whether the shape is in your range and deletes the shape if it is.
Sub Delete_Shapes_In_Range()
Dim btn As Shape
Dim totalTable As Range
Set totalTable = Range(ActiveCell, ActiveCell.Cells(1000, 1000))
For Each btn In ActiveSheet.Shapes
If Not Intersect(btn_rng, totalTable) Is Nothing Then btn.Delete
Next btn
End Sub
Note that this code will not only delete buttons, but will also delete other shapes. If this is a concern, you can add an If statement to skip certain shapes. For example:
If Not btn.Name Like "Picture*" Then '<~~Will skip pictures
or
If Not btn.Name Like "*box*" Then '<~~Will skip textboxes
etc. This assumes that you haven't renamed the shapes since creating them.
I'll show you how to extract the "position" of a button (it's not optimal, but it works). Up to you to adapt it to make it work as it should. This will dislpay the row and column of the top-left cell touched by each button (in the ActiveSheet) in successive message boxes.
Sub Testing()
For Each butt In ActiveSheet.Buttons
MsgBox "Row : " & butt.TopLeftCell.Row & vbCrLf & "Column : " & butt.TopLeftCell.Column
Next butt
End Sub
The complete code:
Sub DeleteRangeButtons()
rng = "A1:A10" ' Place range here.
Dim btn As Button, ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
For Each btn In ws.Buttons
If isinrange(btn.TopLeftCell.Row, btn.TopLeftCell.Column, rng) Then
btn.Delete
End If
Next btn
Next ws
End Sub
Function isinrange(x, y, rng)
Cells(x, y).Activate
If Intersect(ActiveCell, Range(rng)) Is Nothing Then
isinrange = False
Else
isinrange = True
End If
End Function
Commenting on answer by ARich (which was useful to me) since I couldn't add a comment directly. It misses setting btn_rng, but btn.TopLeftCell could be used instead.
Also, I prefer
btn.Type = msoPicture
instead of
btn.Name Like "Picture.
Here is my method based on that:
Public Sub DeleteIntersectingPictures(ByVal sheetToDeleteIn As Worksheet, ByVal rangeToLookIn As range)
Dim noOfRowsInSheet As Long
Dim pictureItem As Shape
Dim pictureRange As range
For Each pictureItem In sheetToDeleteIn.Shapes
If pictureItem.Type = msoPicture Then
Set pictureRange = sheetToDeleteIn.range( _
pictureItem.TopLeftCell.Address & ":" & pictureItem.BottomRightCell.Address)
If Not Intersect(pictureRange, rangeToLookIn) Is Nothing Then
Call pictureItem.Delete
End If
End If
Next pictureItem
End Sub