I have created a Userform with several option buttons as part of a larger macro. The UserForm will load if there is a specific calculation error and will ask the user to select a method to correct the error. One option enables a RefEdit control and allows the user to select a new starting cell (and skip the errors and cells between the current and newly defined range).
I have used the _Exit event to set up some error checking (e.g. to ensure a valid range is selected or to ensure the range is a 1x1 range), but I have been unable to find a way to force the RefEdit control to "reinitialize." I have tried using the RefEdit.SetFocus method but this is not producing the result I want.
Basically, is there a command I can use that mirrors the act of clicking the dropbutton on the RefEdit control?
Private Sub RefEdit_NewStartCell_Exit(ByVal Cancel As MSForms.ReturnBoolean)
On Error Resume Next
Set UserRange = Range(RefEdit_NewStartCell.Text)
If Err.Number <> 0 Then
MsgBox "Invalid range selected"
RefEdit_NewStartCell.SetFocus
End If
On Error GoTo 0
This is not a "real" answer, but a workaround (most times excel crashed using a RefEdit, so i could not run tests... sorry)
Do it with your RefEdit if u want (i have used a textbox):
Private Sub TextBox1_Enter()
On Error Resume Next
Set UserRange = Nothing
UserForm1.Hide
While UserRange.Count <> 1
Set UserRange = Application.InputBox("Select Range", , , , , , , 8)
Wend
CommandButton1.SetFocus
TextBox1.Value = UserRange.Address
UserForm1.Show
End Sub
Hopefully someone got a better answer soon ^.^;
At least the inputbox will only return a valid range (no need to check that)
Related
I am using VBA to add data validation to my cells. However instead of using the AlertStyle argument provided in the Add method, I want to create a custom error handler. Reason being, the AlertStyles provided by VBA do not force the user to abort cell editing if an incorrect value is added. The user can select "Retry" or "Cancel", and sometimes, when they hit "Cancel", all cell contents are lost (if there was only one value previously in the cell. If there was more than one value previously in the cell, no values are lost). So I'd rather create an error handler that exits the Sub when the user enters invalid data.
Here's my attempt:
Sub customised_validation_dates_2()
With ActiveSheet.Range("Date_Entry").Validation
On Error GoTo err
.Delete
.Add Type:=xlValidateDate, _
Operator:=xlBetween, Formula1:="01/01/2000", Formula2:="=TODAY()"
.IgnoreBlank = True
err: Exit Sub
End With
End Sub
but when an invalid date is entered, a message box still pops up, prompting the user to either retry data entry or cancel data entry, but like I said, if there is exactly one value previously in the cell and the user hits "Cancel", the cell value is lost.
extra context:
I have another macro running that allows the user to enter multiple values in one cell. So what I am trying to do is, if in the cell there is already another value, and the user tries adding another value that is invalid, I want to exit cell editing without giving the user the option to retry or cancel data entry, which is the root of my issue (because when they hit "cancel" and there is already a value in the cell, that other value gets erased).
I think you've gotten confused about your errors. Your code relating to errors (on error and err) is related to VBA errors and has nothing to do with cell validation.
To illustrate a error walkthrough example...
Sub exampleOfErrorHandling()
Dim aResponse As String
aResponse = InputBox("Enter something. Text will trigger an error while a nubmer will be accepted.")
If aResponse = "" Then Exit Sub
'programs procedure to jump to section problem with an error
On Error GoTo ProblemZone
Dim anyNumber As Integer 'variable will only accept number
anyNumber = aResponse
On Error GoTo 0 'sets errors to be handled in default method
MsgBox anyNumber & " is a valid number"
'section where other code would typically be inserted
Exit Sub 'where normal code would end
ProblemZone:
'section to handle errors
Dim tryAgain As Long
tryAgain = MsgBox(aResponse & " is not a number. Try again?", vbYesNo + vbCritical)
If tryAgain = vbYes Then Call exampleOfErrorHandling
End Sub
What it appears you want is something with cell validation. You might consider trying the record macro while setting validation to capture exactly what you want. Then engineer that to set the validation as you prefer.
Alternatively, you could use the change event to remove prior values if they don't meet requirement. Here's example of requiring cell A2 to be numeric. Note this must be in the sheet module, not the typical Modules section.
Private Sub Worksheet_Change(ByVal Target As Range)
'cell A2 must be a number
If Not Intersect(Target, Me.Range("A2")) Is Nothing Then
If Not IsNumeric(Me.Range("A2")) Then
MsgBox "A2 is not numeric"
Application.Undo
End If
End If
End Sub
I've created a drop down menu through data validation for workbook navigation. The following is a snippet of code I have for the drop down box to change worksheets in the workbook:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then _
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets("Imported Data").Visible = False
End Sub
The code is meant to hide all other worksheets that are accessible by the drop down list besides the one selected. I have about 10 tabs and this code has worked perfectly to achieve the basic goal of navigation. However, some pages have formulas and when you update data in the cells meant for calculations the workbook jumps to a random worksheet in the workbook that is not at all referenced in this sub.
Is there some way to have my worksheets not try to do anything with this sub unless the dropdown menu itself is changed?
Bonus (less important) Question: is there a way to make the drop box default to (blank) unless the menu itself is accessed?
Then _
The space followed by an underscore _ means that the current statement isn't finished yet but continues on the next line. Right now the last 3 lines will run whenever there is a change in the worksheet. Put the entire code in If-Endif.
Also avoid unnecessary use of On Error Resume Next. Use proper error handling.
You need to make the sheet visible before you activate it and not vice versa.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets("Imported Data").Visible = False
End If
Letscontinue:
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
is there a way to make the drop box default to (blank) unless the menu itself is accessed?
If you have created it with Data Valdation then insert a blank value in the list.
The below code is written into the code of a Sheet (called "Start page") rather than connected to a button.
For reference, cell C17 asks the user of the sheet if they're ready to start, and they have a data validation in D17 linking to M2 (Yes) and M3 (No).
The idea is that when the user selects Yes, the code kicks in and auto-advances to the next sheet ("Selection page"). If they select No, a pop-up box will display advising the workbook will close (I've not written this code yet).
The problem is, whilst I can't see what's wrong with this code, whenever the user selects anything from the data validation, nothing happens.
I'd be really grateful if someone could review the code to see what I'm missing. I've tried Range("D17") and Range("D17").Value but still nothing.
Thanks
EDIT - latest code listed below
Private Sub Worksheet_Change()
Dim output As Integer
Application.ScreenUpdating = False
Dim output As Integer
If Sheets("Start page").Range("D17") Is Nothing Then GoTo ExitHandler
If Sheets("Start page").Range("D17") = Sheets("Start page").Range("M2") Then
Sheets("Selection page").Activate
Else
output = MsgBox("This sheet will now close.", vbCritical, "Closing")
Activebook.Close
ExitHandler:
Application.ScreenUpdating = True
End Sub
Currently, you have nothing triggering the code. You probably want to tie this into a Worksheet event, such as Worksheet_Change or Worksheet_SeletionChange
The quick way to check what Events are available is to go to the top of the Code Pane, select the "Worksheet" object from the Left drop-down, and select the Even from the Right drop-down. This will also automatically add the correct Parameter list:
The "Change" event will occur when any cell on the Worksheet is Changed - while the "SelectionChange" event will happen when you select something new, even if you haven't altered the old thing
For the "Change" event of the Worksheet there is 1 Parameter, ByVal Target As Range - this is the Range of Cells that have been changed. So, for example, you can use MsgBox "Row " & Target.Row & " was changed" to display a message telling you which row the changed cell is on.
Since the Event will automatically pass the Argument to the Sub, you need to have the Parameter there to 'catch' it.
I use the SendKeys method, for user-friendliness, with an InputBox, for selecting multiple cells to use for calculations.
I want to avoid having the user hold CTRL while clicking each cell or pressing Shift-F8 to select multiple cells.
I want the InputBox to pop up and to select cells that are not necessarily right next to one another, without having to do anything else.
Here is a sample of what I have.
Sub CalculateIt()
Dim calcRange As Range
On Error Resume Next
SendKeys "+{F8}"
Set calcRange = Application.InputBox("Select the cells you would like to use.", Type:=8)
If Err.Number = 424 Then Exit Sub
Dim stuff As Double
For Each calcCell in calcRange
If IsNumeric(calcCell.Value) Then stuff = stuff + calcCell.Value
Next calcCell
MsgBox "The Solution: " & Sqr(stuff)
End Sub
I want to avoid using the SendKeys method because I've read a lot about it being finicky and fragile, and that it can cause problems. I have run into some scenarios where it doesn't work and I have to hold CTRL or do Shift-F8 anyways.
Possible solution... Add a checkbox to the worksheet then go into the Microsoft Excel Objects | ThisWorkbook window and enter the following code. If the checkbox is checked, then whatever formula you'd like executed will be as the user clicks each cell.
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Dim nbrCell As Double
If IsNumeric(ActiveCell.Value) Then nbrCell = ActiveCell.Value Else nbrCell = 0
If ActiveSheet.CheckBox1.Value = True Then ActiveSheet.Range("A1").Value = ActiveSheet.Range("A1").Value + nbrCell
End Sub
You can also add a second checkbox to remove selected cells if you're concerned the user might accidentally click on the wrong cell and want that value removed.
I have a macro which is basically working as I want (alerting the user when two conflicting checkboxes are selected) - code below. The 1 in G2 is the value generated to indicate this case.
The error message fires on SelectionChange, but this appears to be only when another cell is selected by mouse. The worksheet contains a series of checkboxes for the user to select from, and the intention is for the user to only use the checkboxes, never needing to select or input directly into cells. In which case, the error message would never fire even when the scenario described has occurred.
Is there a way of having a msgbox macro trigger by the update of any checkbox on the sheet?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("G2") = 1 Then
MsgBox "ERROR - Select AND Reject checked"
End If
End Sub
Also, I would like to extend the range to apply to all the cells in column G, I just can't seem to get this to work for me. I have seen a few examples citing "G:G" but I have so far only got this to work for one cell.
Apologies in advance for any glaring errors, I've used Excel for a while now - but I'm brand new to using VBA.
Mutually exclusive options are usually indicated with option buttons (also known as radio buttons) instead of checkboxes. Is there any reason you're not using option buttons for this task?
As far as calling the same code for all checkboxes, the checkboxes would have to be Form Controls (not ActiveX Controls), and you could assign them to this macro:
Sub CheckBox_Clicked()
Dim chk As CheckBox
Set chk = ActiveSheet.CheckBoxes(Application.Caller)
MsgBox chk.Name
End Sub
And lastly, for your SelectionChange event to monitor an entire column, it would look similar to this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim ClickedCell As Range
Dim rngClicked As Range
Application.EnableEvents = False
Set rngClicked = Intersect(Columns("G"), Target)
If Not rngClicked Is Nothing Then
For Each ClickedCell In rngClicked.Cells
If ClickedCell.Value = 1 Then MsgBox "ERROR - Select AND Reject checked"
Next ClickedCell
End If
Application.EnableEvents = True
End Sub