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.
Related
I am trying since 2 days to find how to do the following without finding anything that suits the aim:
Steps by order :
user open excel file
he chose between folowing :
Paste an image directly in the worksheet (may be an limited area)
activate some video in the workbook (may be a webcam for start)
he select with a button to activate his clicks detection
he clicks anywhere on the picture and i get the coordinates of clicked points
So far i've seen ppl using (and tested myself) :
mouse event ==> this does not work as i need to know the name of what he is clicking on and it may be a brand new picture he just pasted
BeforeDoubleClick (same, i'd prefer avoid doubleclick but even then it doesnt work when i click on something else but cells)
Selectionchange ==> doesnt work if im not clicking on cells
Place hidden button over the area i want : i cant click a button if its not visible, and it becomes visible when i click it if i put as transparent
If anyone has ideas about this...
(nb: im not a pro of vba so i may have missed something)
Just forgot : my issue is not getting the coordinates of mouse, its just triggering the macro when i want, for now im jsut trying to get a simple msgbox to see if trigger works.
Thanks if anyone has any ideas
BR
Not sure if this fits your need (for example couldn't test it with a video).
a) Place a "button" of any kind on your sheet. I usually use a square shape for that and format it a little bit (color, shade, text). Assign the subroutine SetEvents to it.
b) Declare a global variable that remembers that click-activation is active
Option Explicit
Global EventCatchingActive As Boolean
c) In the event routine of your button, set the OnAction-method for all shapes of the sheet - see the routine setEvents. This ensures that even newly added images handle the click event.
Sub setEvents()
' This routine is called from the magic button.
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1) ' Set this to whatever sheet you need
Dim button As Shape
Set button = ws.Shapes(Application.Caller)
If EventCatchingActive Then
EventCatchingActive = False
button.TextFrame2.TextRange.Characters.Text = "Start Clicking"
Else
Debug.Print "Setting EventHandler"
Dim sh As Shape
For Each sh In ThisWorkbook.Sheets(1).Shapes
' Debug.Print sh.Name, sh.Type
If sh.Name <> button.Name Then sh.OnAction = "ClickedMe"
Next
EventCatchingActive = True
button.TextFrame2.TextRange.Characters.Text = "Stop Clicking"
End If
End Sub
d) Declare a routine that is called if any of the shapes is clicked. With Application.Caller you can check what was clicked.
Sub ClickedMe(Optional target As Range = Nothing)
If Not EventCatchingActive Then Exit Sub
If target Is Nothing Then
Debug.Print "I clicked on " & Application.Caller
Else
Debug.Print "I clicked on cell " & target.Address
End If
End Sub
(note that code of steps b) to d) goes into a regular module)
e) If you also want to handle clicks on a cell, add the following into the sheet-module of the worksheet you are dealing with.
Private Sub Worksheet_SelectionChange(ByVal target As Range)
ClickedMe target
End Sub
I have looked at some examples for my question but couldn't find an answer that works.
Background:
I have a list of items (let's say apple, orange, banana) in Sheet1 (A2:A77, which is already a defined range with the name "Liste").
I then have on another sheet (Let's say Sheet2) with several cells where a userform (created with vba code) pops up where the user can choose an item and click OK.
However, due to the nature of the userform (and the list), you can have spelling errors etc and it will still be accepted. So I would like to create a check where it matches the input to the given list (to prevent users from putting anything else in). The userform/code is on purpose to keep it searchable (rather than just a simple data validation list).
Issue:
I tried to create this with vba code that checks the input, matches it to the Sheet1 list and if there is no match, shows a msgbox with a statement. This partially worked (for some letters but not others, very strange).
Here is the code I had:
Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim rSearchRng As Range
Dim vFindvar As Variant
If Not Intersect([B7:B26], Target) Is Nothing Then
Set rSearchRng = Sheet4.Range("Liste")
Set vFindvar = rSearchRng.Find(Target.Value)
If Not vFindvar Is Nothing Then
MsgBox "The Audit Project Name you have entered is not valid. Please try again!", vbExclamation, "Error!"
Selection.ClearContents
End If
End If
Application.EnableEvents = True
End Sub
So I was thinking of creating this error message instead with a simple data validation.
Data validation
I have tried the "list" option (and put it equal to the named range) but that did nothing (no error box showed up)
I have tried "Custom" with the following formula 'SUMPRODUCT(--(B12=Liste)>0)=TRUE (I found this on a post which worked for others when I tried it in the cell it gave me the expected "TRUE/FALSE" results) but still nothing shows up
UPDATE
Tigeravatars data validation recommendations work if you don't have a userform (see comments below).
For it to work with a UserForm, I changed the 'MatchEntry' to TRUE and also deleted any unwanted "change events" from my ComboBox code. The final code I use now is below:
Dim a()
Private Sub CommandButton2_Click()
End Sub
Private Sub UserForm_Initialize()
a = [Liste].Value
Me.ComboBox1.List = a
End Sub
Private Sub ComboBox1_Change()
Set d1 = CreateObject("Scripting.Dictionary")
tmp = UCase(Me.ComboBox1) & "*"
For Each c In a
If UCase(c) Like tmp Then d1(c) = ""
Next c
Me.ComboBox1.List = d1.keys
Me.ComboBox1.DropDown
End Sub
Private Sub CommandButton1_Click()
ActiveCell = Me.ComboBox1
Unload Me
End Sub
Private Sub cmdClose_Click()
Unload Me
End Sub
I thought I show it here in case anyone stumbles across my question.
Thank you!
Select your cells where you want to put the data validation
With the cells selected, go to Data Tab -> Validation
Set "Allow" to "List" and set the Source to =Liste as shown here:
Next go to the "Error Alert" tab and set "Style" to "Warning" and enter the desired text in "Title" and "Error Message" as shown here:
Test it out. You should now have a drop-down list of valid choices, and if you attempt to manually enter an invalid choice you'll get the error message you specified.
As a note, if you want the data validation to completely disallow/prevent any entry not in the list, you'll need to set the Error Allert -> Style to be "Stop" instead of "Warning".
EDIT:
Per comments, it can't be a drop-down list. I highly recommend using a drop-down list for this because it will be the most effective way to cut down on time entering data as well as reduce errors from typos. However, if it absolutely cannot be a drop-down list, then you can use a Custom Data Validation and set the formula to =ISNUMBER(MATCH(B7,Liste,0)) (we are using B7 here because it is the first cell in the range of cells that contains this data validation).
Try the following formula:
=NOT(ISERROR(FIND("-"&A1&"-",(TEXTJOIN(,"-",TRUE,Sheet1!A1:A77)))))
That combines all the texts and then see if what's in the cell occurs in the list. I put it between dashes to prevent it from accepting partials.
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
I am working on pulling data out of a standardized form in excel. There is a Forms Control CheckBox that I need the state of. Apparently the only way to get this is from the cell link, where the value is placed into a cell. The problem is, whomever put this form together did not set a cell link. Is there any way to do this using VBA at run time. There are many of these forms that I must go through, so I'm trying to avoid doing it manually.
I think you are referring to a forms checkbox control placed on a worksheet, in which case you can get the state of the control without setting a cell link. Like this:
Sub HTH()
Dim iLoop As Integer
'// Get value of check box by its index
MsgBox (GetCheckBoxState(1))
'// Get value of check box by its name
MsgBox (GetCheckBoxState("Check Box 1"))
'// Loop through all checkboxes and get values
For iLoop = 1 To ActiveSheet.CheckBoxes.Count
MsgBox (GetCheckBoxState(iLoop))
Next
End Sub
Function GetCheckBoxState(vCheckBox As Variant) As String
Select Case ActiveSheet.CheckBoxes(vCheckBox).Value
Case xlOn
GetCheckBoxState = "Checked"
Case xlOff
GetCheckBoxState = "UnChecked"
Case xlMixed
GetCheckBoxState = "Mixed"
End Select
End Function
If you are referring to a check box control on a userform then as Tim pointed out it should be a case of something like:
MsgBox (UserForm1.CheckBox1.Value)
I set up a excel sheet with drop-down menus for some of the cells. The
user can only select values from that list and an error message pops up
when something is typed it that is not in the list (via Data Validation
Error Alert).
So this works all fine ... But when the user copy paste into the cells then validation doesnt work. How to make validation effective in case of copy paste.
I have searched and found one solution but its not working.
Here is the code that I have found. but its not working any more..It always return true enven I copy paste worng
Private Sub Worksheet_Change(ByVal Target As Range)
If HasValidation(Range(ActiveCell.Address)) Then
Exit Sub
Else
Application.Undo
MsgBox "Your last operation was canceled." & _
"It would have deleted data validation rules.", vbCritical
End If
End Sub
Private Function HasValidation(r) As Boolean
On Error Resume Next
x = r.Validation.Type
If Err.Number = 0 Then HasValidation = True Else HasValidation = False
End Function
It looks like you took the code from this page:
http://www.j-walk.com/ss/excel/tips/tip98.htm
When Worksheet_Change fires, your code always refers to the active cell, not the target where the copy/paste operation is being performed.
Change
ActiveCell.Address
to
Target.Address
and see if that works.
The "Target.Address" worked for me as mentioned by #JimmyPena.
But the solution still brings a bug, that if one tries to add another validation after adding the above mentioned VB code, the user is fired with the amount of message boxes produced by the vb code which is applied to the number of cells (viz. You will have to click on "OK" of the message box provided by the VB code for the number of cells the VB code has been applied to.. If code applied to 40 cells then you have to click "OK" 40 times... phew..)
Can you please try to help to add another condition to help this?
Or the last way that remains to only add the VB code after adding all the validations.