Loop rows of column until empty in excel VBA - excel

I have a sheet with a column "N" that contains 30 rows with checkbox inside each one
in vba i want to make a loop that stops at the empty cell, means row 31 , i tried this way :
Private Sub CommandButton1_Click()
Range("N9").Select
Do
If CheckBox1.Value = True Then Call do_OM
ActiveCell.Offset(1, 0).Select
Loop while ActiveCell.value = ""
End Sub
this loop works for only one row , which means a cell with checkbox is an empty cell , while what i want is to stop at cell with no checkbox .. what to do ?
+
How to say " If CheckBox(row number).Value = True ? "
Thanks in advance :)

EDIT
This part will iterate through the non-Active X checkboxes
Since the checkbox isn't tied to the sheet, there isn't really a way to say CheckBox(row number). Also makes sense because there could be multiple boxes on one row.
If the names of the checkboxes align with the row number, however, then you can iterate through them. Well, you can iterate through them anyway, but yeah.
You could do something like:
For i = 1 To 30
ActiveSheet.CheckBoxes(i).Value
Next i
or
For Each chk In ActiveSheet.CheckBoxes
chk.Value
Next chk
To iterate through the boxes. Second one would obviously go through the entire sheet.
I don't think you can check a cell for a box, but you can check what cell the box is in, by using .TopLeftCell.Row which should return the row of the top left corner of the object. Then you could cross-reference that (and perhaps .TopLeftCell.Column) with your range using Intersect.
Excel VBA - Ckeck if cell contains a checkbox Might be of interest. But as I said, it's not really checking if a cell has a check box, it's going through all the checkboxes and checking if any of them are in the cell, using Intersect as I suggested. You can argue that the end result is the same however.
Edit For the comment: This is for ACTIVE X Boxes
Dim nm As Object
Set nm = ActiveSheet.CheckBox1
nm.TopLeftCell.Row
'Iteration
For Each nm In ActiveSheet.OLEObjects
If TypeName(nm.Object) = "CheckBox" Then
debug.print nm.TopLeftCell.row
If nm.Object.Value = True Then ' do stuff
End If
Next nm

ActiveX Checkboxes
Remove, replace or out-comment the Debug.Print lines with something you need e.g. do_OM (Call is considered deprecated).
Note this: ole.Name, but ole.Object.Value.
Option Explicit
Sub CheckBoxExample()
Dim ole As OLEObject
For Each ole In ActiveSheet.OLEObjects
If TypeName(ole.Object) = "CheckBox" Then
Debug.Print
Debug.Print ole.Name, ole.TopLeftCell.Address(0, 0), _
ole.BottomRightCell.Address(0, 0)
If ole.Object.Value = True Then
'do_OM
Debug.Print "Check Box '" & ole.Name & "' is ticked."
Else
Debug.Print "Check Box '" & ole.Name & "' is not ticked."
End If
End If
Next ole
End Sub
Sub CheckBoxExample2()
Dim ole As OLEObject
For Each ole In ActiveSheet.OLEObjects
If TypeName(ole.Object) = "CheckBox" Then
Debug.Print ole.Name, ole.TopLeftCell.Address(0, 0), _
ole.BottomRightCell.Address(0, 0)
With ole.Object
Debug.Print .Caption, .Value
End With
End If
Next ole
End Sub

Related

Call a hiding macro with a checkbox

I wanted to make a checkbox, calling a macro that hides and unhides columns on Excel worksheet with specific value in cell, but it is not working
I tried the following VBA script
Sub Hide_Forecasts()
Dim c As Range
For Each c In Range("E12:CF12").Cells
If c.Value = "Forecast" Then
c.EntireColumn.Hidden = True
End If
Next c
End Sub
Sub Unhide_Forecasts()
Dim c As Range
For Each c In Range("E12:CF12").Cells
If c.Value = "Forecast" Then
c.EntireColumn.Hidden = False
End If
Next c
End Sub
Sub CheckBox_For()
If CheckBox1.Value = True Then
Call Hide_Forecasts
Else
Call Unhide_Forecasts
End If
End Sub
Please help me out
You haven't said what type of checkbox you're using - Form Control or ActiveX Control.
For an ActiveX Control right-click the control and select View Code.
Use this code that sits behind the worksheet (CheckBox1 will be named after your checkbox).
Private Sub CheckBox1_Click()
Dim Cell As Range
For Each Cell In Me.Range("E12:CF12")
If Cell.Value = "Forecast" Then
'Checkbox returns TRUE/FALSE - Hidden takes TRUE/FALSE so just connect the two up.
Cell.EntireColumn.Hidden = Me.CheckBox1.Value
End If
Next Cell
End Sub
For a Form Control right-click the control and select Assign Macro.
Place this code in a normal module.
Sheet1 is the codename for the sheet (that's the name not in brackets in the Project Explorer).
'Form Control can have three values:
' 1 = Checked
' -4146 = Unchecked
' 2 = Mixed - ignoring that this value may occur.
Public Sub Checkbox_For()
Dim ChkValue As Boolean
'Is value different from -4146? Returns TRUE = Checked or Mixed / FALSE = Unchecked
ChkValue = Sheet1.Shapes("Check Box 1").OLEFormat.Object.Value <> -4146
Dim Cell As Range
For Each Cell In Sheet1.Range("E12:CF12")
If Cell.Value = "Forecast" Then
Cell.EntireColumn.Hidden = ChkValue
End If
Next Cell
End Sub

Multiple selection based on checkboxes

I have a UserForm where I have 6 check boxes. The role of check box is to select a unique range in Excel. Each checkbox corresponds to a different range in the Excel sheet.
I want to know what methodology can you use to ensure that when a user select a combination of checkboxes max of 6, Excel selects the corresponding ranges of the selected checkbox.
For example:
Checkbox1 programmed to select range A1
Checkbox2 programmed to select range H3
Checkbox3 programmed to select range F6
If User ticks Checkbox1 and Checkbox2 then how can you tell Excel to select A1 and H3 without using If statements since the combination of 6 check boxes would mean a lot of If statements.
Is there anyway when Checkbox1 is selected it keeps that selection in memory and adds it to the next selection.
Thanks
You would loop over the checkboxes, and build a range using Application.Union() (plenty of examples of that here on SO). When you're done looping then select the built-up range.
Or you can build a string like "H3,F6" and use Range(rangeString).Select
For example:
Sub CheckSelection()
Dim s As String, i As Long, sep
For i = 1 To 6
With Me.Controls("Checkbox" & i)
If .Value = True Then
s = s & sep & .Tag 'ranges are stored in checkboxes' Tag property
sep = ","
End If
End With
Next i
If Len(s) = 0 Then s = "A1" 'default selection if none chosen...
ActiveSheet.Range(s).Select
Debug.Print s
End Sub
Private Sub CheckBox1_Click()
CheckSelection
End Sub
'...
' etc
'...
Private Sub CheckBox6_Click()
CheckSelection
End Sub

Is it possible to track the current row where a checkbox is placed and then copy this rows column C

I'm currently working on a line of code that puts checkboxes in every row on Column A (Every row but row A1, so it starts at A2) in Excel. These checkboxes are connected to their neighbour Column B where it puts its true or false data.
Now my goal is:
If column B (decided by checkbox) is true, then copy the checkbox row location cell C value to the checkbox row location cell D. When this is not true it has to put a 0 in the target cell (D).
This line of vba is activated as soon as a checkbox will be clicked.
My current code is:
Sub TrueFalse()
If Range("B" & ActiveRow).Value = True Then
MsgBox "True"
ElseIf Range("B" & ActiveRow).Value = False Then
MsgBox "False"
End If
End Sub
I know "ActiveRow" doesn't work but it is to show where the rowcheck should be.
Hope someone can help, thanks in advance!
Its not clear to me the reason you are using check boxes in this way?
You could achieve something similar using data input validation instead and avoid the hassle of using forms for the checkboxes.
E.g. allow only two values in the range of cell A2:A99 (e.g. "Y" or "N"), or possibly only allow one value and an empty cell (e.g. "X" or blank). Then use VBA to detect data entry into column "A" and use an offset from the active cell to do the work e.g.
if Activecell.value="X" Then
Activecell.offset(0,1) = "whatever you want to write to the cell right of the checked cell"
Is this the sort of thing you are try to do?
If the Checkbox is connected via the Cell Link, i.e Format Control | Control Tab | Cell Link then you can get the row of the relevant checkbox using
Sub TrueFalse()
Debug.Print Range(ActiveSheet.CheckBoxes(Application.Caller).LinkedCell).Row
End Sub
So your code becomes
Sub TrueFalse()
Dim ActiveRow As Long
ActiveRow = Range(ActiveSheet.CheckBoxes(Application.Caller).LinkedCell).Row
If Range("B" & ActiveRow).Value = True Then
MsgBox "True"
ElseIf Range("B" & ActiveRow).Value = False Then
MsgBox "False"
End If
End Sub
Edit
You can also change the above to work like
Sub TrueFalse()
Dim CellAddress As String
CellAddress = ActiveSheet.CheckBoxes(Application.Caller).LinkedCell
If Range(CellAddress).Value = True Then
MsgBox "True"
ElseIf Range(CellAddress).Value = False Then
MsgBox "False"
End If
End Sub

Auto-tabbing between fields in Excel Workbook

The following VBA script for an Excel sheet allows an individual to type text into a cell and then automatically jump to the next cell in the array once they hit enter.
However, this requires someone to type into every cell for the script to advance to the next cell in the array below and does not recognize tab, only enter.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim tabArray As Variant
Dim i As Long
tabArray = Array("B5", "C6", "D7", "E8")
Application.ScreenUpdating = False
For i = LBound(tabArray) To UBound(tabArray)
If tabArray(i) = Target.Address(0, 0) Then
If i = UBound(tabArray) Then
Me.Range(tabArray(LBound(tabArray))).Select
Else
Me.Range(tabArray(i + 1)).Select
End If
End If
Next i
Application.ScreenUpdating = True
End Sub
I'd like to let the person hit tab or enter if they want to skip the given field and advance without typing anything in the cell.
You can also just protect the sheet and have the input cells unlocked.
Right Click on the Cell, choose "Format cells".
Then, go to Protection Tab, and uncheck "Locked".
Once the input cells are unlocked, go to the "Review" Ribbon, and click on Protect Sheet. Uncheck "Select locked cells" and it should only allow you to click on the cells that are unlocked, and can press Tab repeatedly to go to the next available cell.
Protecting the sheet and unlocking the data-entry cells as suggested by #Basher is probably a better solution IMO, but this sort-of works. Couple of notes:
To "break into" the tab sequence you need to select one of the data-entry cells
To "break out" of the tab sequence (so you can select some other cell maybe) you can make a multi-cell selection.
Code:
Dim lastCellAddress As String
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim tabArray As Variant
Dim i As Long, addr, mCurr, indx, mPrev
If Target.Cells.CountLarge = 1 Then
tabArray = Array("B5", "C6", "D7", "E8")
addr = Target.Address(False, False)
mCurr = Application.Match(addr, tabArray, 0)
If IsError(mCurr) Then 'current selection isn't a data entry cell
If lastCellAddress <> "" Then
'was user previously in a data entry cell?
mPrev = Application.Match(lastCellAddress, tabArray, 0)
If Not IsError(mPrev) Then
'mPrev is 1-based but tabArray is 0-based...
indx = IIf((mPrev - 1) < UBound(tabArray), mPrev, 0)
On Error GoTo haveError
Application.EnableEvents = False
Me.Range(tabArray(indx)).Select '<< select the next entry cell
Application.EnableEvents = True
End If
End If
End If
lastCellAddress = Selection.Address(False, False)
Else
lastCellAddress = "" 'breaks out of the sequence
End If
Exit Sub
haveError:
Debug.Print Err.Description
Application.EnableEvents = True
End Sub
You don't need VBA to achieve this task - it's a built-in Excel functionality.
Simply select your data entry range and after inputting the desired value into the first cell hit TAB, it will take you to the next highlighted cell - either to the right of the current one or to the next row if you were at the end of the row.

Is it possible to return the names of checkboxes in Excel VBA?

I'm currently working with a couple of worksheets that contain hundreds of checkboxes. The code behind these checkboxes works fine, but I'm looking for a way to list the names of the checkboxes per column, i.e. I need to know the names of all checkboxes in column G, for instance.
Does anyone know if this is possible?
Thanks a lot in advance!
Consider using the TopLeftCell property
Sub ListCheckBoxes()
Dim ole As OLEObject
'Loop through all the active x controls
For Each ole In Sheet1.OLEObjects
'Only care about checkboxes
If TypeName(ole.Object) = "CheckBox" Then
'Check topleftcell property
If ole.TopLeftCell.Column = Sheet1.Range("G1").Column Then
'print out list
Debug.Print ole.TopLeftCell.Address, ole.Name
End If
End If
Next ole
End Sub
If you align a control to column G (hold down ALT whilst moving to align) select properties and find out the left position of the control
You can then use this code to identify which controls from Sheet1 have left alignment equal to what you need.
Sub test()
lngcolumnGLeft = 288 'pseudo position of object aligned to column G
'cycle through all objects
With Sheet1
For Each obj In .OLEObjects
If obj.Left = lngcolumnGLeft Then
.Range("G" & .Rows.Count).End(xlUp).Offset(1, 0).Value = obj.Name
End If
Next obj
End With
End Sub
The code below will work if you specify the column you want to check.
For example, if you want to search for all checkboxes in column E you specify 5 and the code checks for any checkbox that is within the bounds of the left most part of column E and column F.
Sub ListCheckBoxNames()
Dim col As Long, cb As OLEObject
col = 5 //e.g. A=1, B=2, C=3 etc...you need to change this as appropriate
For Each cb In Worksheets(1).OLEObjects
If cb.Left >= Columns(col).Left And cb.Left < Columns(col + 1).Left Then
Debug.Print cb.Name
End If
Next cb
End Sub

Resources