Excel VBA - event change doesn't work - excel

I'm quite new to VBA but so far I'm coming along. Till this moment, where I'm stuck with this challenge.
My goal is to select a percentage (10, 90 or 100) from a drop down menu in a cell in column B, C, D or E and when one of the percentages is selected, I want the same cell to calculate the selected percentage of the value in column A.
So when the cell in column A has a value of "500" and in the same row in Column C I select "90" I want 90 to be replaced with 450 (0.9*500)
The code given here is what I've got so far, including some code already 'borrowed' from another topic. Though it works in a new, clean excel Sheet, it won't work in the document where I want it to work.
Do some of you have any ideas where the flaw can be found?
(I even created a commandbutton with only the task: Application.EnableEvents = True)
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not Intersect(Target, Range("B:D")) Is Nothing Then
Application.EnableEvents = False
If Target.Value = 90 Then Target.Value = 0.9 * Cells(Target, 1).Value
ElseIf Target.Value = 10 Then Target.Value = 0.1 * Cells(Target, 1).Value
ElseIf Target.Value = 100 Then Target.Value = Cells(Target, 1).Value
Else
MsgBox "Not a valid percentage"
End If
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub

Sounds like you want Workbook_SheetChange event. Add your logic to ThisWorkbook in VBA editor.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
MsgBox "Cell changed. Target: " & Target.Worksheet.Name & "!" & Target.Address
End Sub
With the above code added to ThisWorkbook changes on any sheet in the workbook will trigger the event.

You don't need VBA to do what you're asking. Data Validation, and a formula will work:

meaning you got stopped by an error while application.enableevents=false, and u ran the thing again without application.enableevents=true in between ...
i actually have a button for this issue, just when i'm debugging code, or in the VB editor, Ctrl+G, in the immediate window , you can write application.enableevents=true

Related

Multiple VBA targets for data validation on a single sheet

There are similar posts relating to my question, but I have struggled to adapt them to my problem. I currently have the following code which works just fine:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Application.ScreenUpdating = True
Set Target = Range("B4")
If Target.Value = "Yes" Then
Call DropDownListOn
Else
Call DropDownListOff
End If
Application.EnableEvents = True
End Sub
and the macros that are being called are:
Option Explicit
Sub DropDownListOn()
Sheet1.Activate
Sheet1.Range("A5").Value = "Plot default probability"
Sheet1.Range("B5").Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Formula1:="Yes, No"
End Sub
and
Option Explicit
Sub DropDownListOff()
Sheet1.Range("A5").Value = ""
Sheet1.Range("B5").Validation.Delete
End Sub
Essentially what it does is as follows: Cell B4 is dropdown list. If "Yes" is chosen, then by calling the macro "DropDownListOn", it generates a new dropdown list in cell B5. This part works just fine; but, say, that once the dropdown list in cell B5 appears, I want to call another macro if B5 is chosen to be "Yes" (e.g., generating another dropdown list in cell B6). Given that only one target can be assigned to each sheet, this does not seem to be very straightforward. There seem to be suggestions for ways around this obstacle on Stackoverflow, but I struggle to adopt these to my own case. Any help and/or sample code will very much be appreciated.
Please, try the next updated event:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) = "B4" Then
If Target.Value = "Yes" Then
Call DropDownListOn 'it let it creating the drop-down in "B5", TRIGGERING the change event
'but delete the charts ONE BY ONE!
Else
Application.EnableEvents = False
Call DropDownListOff 'the event is not triggered here.
'if you want to also clear "B6", you should place such a code line in the above Sub...
Application.EnableEvents = True
End If
ElseIf Target.Address(0, 0) = "B5" Then
Application.EnableEvents = False
'Place here the sub able to create the drop-down validation in "B6"
'it let it creating something else, but without triggering the event
Application.EnableEvents = Trud
End If
End Sub

How to apply code to all the following rows

I have this code but it only work for my first row.
It is suppose to look if the checkbox on B, C or D is checked, and if so, a date + username will automaticaly fill in F and G.
here is a picture of my table:
This is what my code looks like:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("B2") Or Range("C2") Or Range("D2") = True Then
Range("G2").Value = Environ("Username")
Range("F2").Value = Date
Else
Range("F2:G2").ClearContents
End If
End Sub
Enter this code in a regular module, select all your checkboxes and right-click >> assign macro then choose ReviewRows.
This will run the check whenever a checkbox is clicked - a bit of overhead since all rows will be checked, but should not be a big deal.
Sub ReviewRows()
Dim n As Long
For n = 1 To 100 'for example
With Sheet1.Rows(n)
If Application.CountIf(.Cells(2).Resize(1, 3), "TRUE") > 0 Then
If Len(.Cells(6).Value) = 0 Then 'only enter if currently empty?
.Cells(6) = Date
.Cells(7) = Environ("Username")
End If
Else
.Cells(6).Resize(1, 2).ClearContents
End If
End With
Next n
End Sub
If you want to be more precise then Application.Caller will give you the name of the checkbox which was clicked, and you can use that to find the appropriate row to check via the linkedCell.
Sub ReviewRows()
Dim n As Long, shp As CheckBox, c As Range, ws As Worksheet
Set ws = ActiveSheet
On Error Resume Next 'ignore error in case calling object is not a checkbox
Set shp = ActiveSheet.CheckBoxes(Application.Caller) 'get the clicked checkbox
On Error GoTo 0 'stop ignoring errors
If Not shp Is Nothing Then 'got a checkbox ?
If shp.LinkedCell <> "" Then 'does it have a linked cell ?
With ws.Range(shp.LinkedCell).EntireRow
If Application.CountIf(.Cells(2).Resize(1, 3), "TRUE") > 0 Then
If Len(.Cells(6).Value) = 0 Then 'only enter if currently empty?
.Cells(6) = Date
.Cells(7) = Environ("Username")
End If
Else
.Cells(6).Resize(1, 2).ClearContents
End If
End With
End If 'has linked cell
End If 'was a checkbox
End Sub
However this appraoch is sensitive to the exact positioning of your checkbox
You have a long way to go!
Unfortunately, If Range("B2") Or Range("C2") Or Range("D2") = True Then is beyond repair. In fact, your entire concept is.
Start with the concept: Technically speaking, checkboxes aren't on the worksheet. They are on a layer that is superimposed over the worksheet. They don't cause a worksheet event, nor are they responding to worksheet events. The good thing is that they have their own.
If Range("B2") Or Range("C2") Or Range("D2") = True Then conflates Range with Range.Value. One is an object (the cell), the other one of the object's properties. So, to insert sense into your syntax it would have to read, like, If Range("B2").Value = True Or Range("C2").Value = True Or Range("D2").Value = True Then. However this won't work because the trigger is wrong. The Worksheet_Change event won't fire when when a checkbox changes a cell's value, and the SelectionChange event is far too common to let it run indiscriminately in the hope of sometimes being right (like the broken clock that shows the correct time twice a day).
The answer, therefore is to capture the checkbox's click event.
Private Sub CheckBox1_Click()
If CheckBox1.Value = vbTrue Then
MsgBox "Clicked"
End If
End Sub
Whatever you want to do when the checkbox is checked must be done where it now shows a MsgBox. You can also take action when it is being unchecked.

Excel VBA Target.Address being modified and causing Error 13 type mismatch

Prototypical post: New to VBA, unable to resolve an issue after having read multiple posts/websites, and now turning to all the fantastic people here who's posts have gotten me this far.
I have a worksheet with data validation in column C (list; forced-choice Yes/No options). If user selects "No" in C7, then C9:C11 need to automatically and immediately populate as "No." I have gotten this to work by the following:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$C$7" And Target.Value = "No" Then
Range("$C$9").Value = "No"
Range("$C$10").Value = "No"
Range("$C$11").Value = "No"
End If
End Sub
I also have a text box on the same worksheet (i.e., Sheet5) that when clicked fires a macro which clears the contents of C6:C7. This Reset macro is in a module under General.
Sub C_B_Reset()
Sheet5.Range("C6:C7").ClearContents
End Sub
Individually, these work fine, but when both exist it results in Type 13 error at the Target.Address after the Reset macro is fired. After firing the Reset macro, the "If Target.Address" portion resolves to the range referenced in the Reset macro (i.e., C6:C7). Because "If Target.Address" expects a single, absolute cell reference (e.g., $C$7), it is throwing the mismatch code because it instead is resolving to (C6:C7) when the mouse is hovered over it.
Even if the Reset macro is completely deleted, the same issue happens if the following is used in the Target.Address code:
Range("$C$9:$C$11").Value = "No"
The Target.Address then resolves to "$C$9:$C$11" and throws the Type 13 mismatch error.
It appears that if "Range" is used to refer to a range of cells in any other macro, it automatically gets assigned as Target.Address. However, this doesn't happen if Range only refers to single cells (which is why there are separate lines for C9 to C11 in the Worksheet_Change code).
I'm sure I'm using incorrect terminology, but I hope I explained it well enough, because I sure would appreciate some help.
Thanks for taking a look,
"Excel VBA Target.Address being modified and causing Error 13 type mismatch"
Target.Address isn't the problem here... Target is the cell(s) that were changed, so Target.Address will be $C$6:$C$7 when you clear both C6 and C7.
The main problem is this:
... And Target.Value = "No" ...
This will fail with a Type Mismatch error when Target is a multi-cell range, because then Target.Value is a 2D Variant array, which you can't compare to "No".
Also, the normal approach is to use Intersect instead of considering Target.Address.
If you're only concerned about C7, then perhaps write like this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("C7")) Is Nothing Then
If Me.Range("C7").Value = "No" Then
On Error GoTo SafeExit
Application.EnableEvents = False ' Avoid re-triggering the event
Me.Range("C9:C11").Value = "No"
End If
End If
SafeExit:
Application.EnableEvents = True
End Sub
Consider:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$C$7" And Target.Value = "No" Then
Application.EnableEvents = False
Range("$C$9").Value = "No"
Range("$C$10").Value = "No"
Range("$C$11").Value = "No"
Application.EnableEvents = True
End If
End Sub
and:
Sub C_B_Reset()
Application.EnableEvents = False
Sheet5.Range("C6:C7").ClearContents
Application.EnableEvents = True
End Sub
EDIT#1:
Try this event macro instead:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$C$7" Then
If Target.Value = "No" Then
Application.EnableEvents = False
Range("$C$9").Value = "No"
Range("$C$10").Value = "No"
Range("$C$11").Value = "No"
Application.EnableEvents = True
End If
End If
End Sub

Excel VBA - I think I am assigning a value to a cell but it isn't working

Line: Target("D12").Value = 10 'This doesn't put anything into the cell.
Trying to figure out the simplest first. Later I wish this to fill in 3 of the 4 columns, depending on which was entered into manually. This will have a few hundred rows. right now I am entering everything manually.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False '<--| disable events handling
On Error GoTo ErrorHandler '<--| be sure to catch any error and enable events handling back
Select Case Target.Column
Case "3"
'Me.Unprotect
MsgBox Target.Address
'MsgBox "Column" & Target.Cells.Column
'boo = Target.Cells.Column + 1
Target("D12").Value = 10
MsgBox Target("D12").Value
'Me.Protect
End Select
ErrorHandler:
Application.EnableEvents = True
End Sub

Embeding Checkbox to a specific cells

I'm current working with VBA which is quite new for me. I'am trying to embeeded my checkbox into it specific cells so that each time the cells (row) is hidden, the checkbox will be hidden also with the cell.
below is the code I'm currently using to insert the Checkbox
ActiveSheet.CheckBoxes.Add(Cells(lRow, "A").Left, _
Cells(lRow, "A").Top, _
72, 17.25).Select
With Selection
.Caption = ""
.Value = xlOff
.LinkedCell = "C" & i
.Display3DShading = False
End With
Thanks.
AFAIK, I don't think so.
There's also no known Event to trap hiding and un-hiding of rows (again AFAIK).
The closest I can give is something like:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error GoTo halt
Application.EnableEvents = False
Dim cb As CheckBox
Set cb = Me.Shapes("Check Box 1").OLEFormat.Object
cb.Top = Me.Range("cbrange").Top
cb.Visible = IIf(Me.Range("cbrange").Height = 0, False, True)
forward:
Application.EnableEvents = True
Exit Sub
halt:
MsgBox Err.Description
Resume forward
End Sub
This doesn't automatically hides the Checkbox, not until you select another range.
Take note that we used a named range which is the range that contains your Checkbox.
This is to make sure that the Checkbox stays with that cell even if the you insert rows. HTH somehow.

Resources