Mark cells on excel VBA if they are merged when double clicked - vba

I am puuting a check mark on double click on certain cells. My code looks like this :
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Range("AA38:AK48,M32:M40,M42:M52,M54:M69")) Is Nothing Then
Cancel = True
If VarType(Target.Value) = vbBoolean Then
Target.Value = Not (Target.Value)
Else
Target.Value = IIf(Target.Value = "ü", Null, "ü")
End If
End If
End Sub
But on the Merged cellls AA-AK it gives me an error

Try it like this...
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not Intersect(Target, Range("AA38:AK48,M32:M40,M42:M52,M54:M69")) Is Nothing Then
Cancel = True
If VarType(Target.Cells(1).Value) = vbBoolean Then
Target.Cells(1).Value = Not (Target.Cells(1).Value)
Else
Target.Cells(1).Value = IIf(Target.Cells(1).Value = "ü", Null, "ü")
End If
End If
End Sub

Related

Writing to multiple cells using If Target.Address = " " Then

I have basic code that allows the values written to this cell to be summed while maintaining the cumulative value. So if I were to type "4" into the cell, and then type "10" into the cell, the result would be "14" (not just the second value entered of "10"). Here is what I have and I must say that it works.
#
Option Explicit
Dim oldvalue As Double
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.Address = "$J$5" Then
On Error GoTo fixit
Application.EnableEvents = False
If Target.Value = 0 Then oldvalue = 0
Target.Value = 1 * Target.Value + oldvalue
oldvalue = Target.Value
fixit:
Application.EnableEvents = True
End If
End Sub
#
However, I want to apply this treatment to more than just cell J5. Say for example, I want the same code logic applied to cell R5 as well.
Thur far I have tried using
OR
and I have also tried using
If Not Intersect (Target, Range("J5:R5")) Is Nothing Then
But each of these approaches ties the two cells together (so that what I enter into one gets summed into both - each cell is summing values added to the other). I can't figure it out to save my life, so took to this forum in the hopes of finding someone smarter than me.
Maybe (this is assuming existing logic is correct....not sure why you set old value to 0 if Target = 0 and what value the *1 adds?)
Option Explicit
Dim oldvalueJ As Double
Dim oldValueR As Double
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
On Error GoTo fixit
Application.EnableEvents = False
Select Case Target.Address
Case "$J$5"
If Target = 0 Then oldvalueJ = 0
Target = Target + oldvalueJ
oldvalueJ = Target
Case "$R$5"
If Target = 0 Then oldValueR = 0
Target = Target + oldValueR
oldValueR = Target
End Select
fixit:
Application.EnableEvents = True
End Sub
This is a bit more dynamic by allowing you to add unlimited cells; it also validates user input
Standard Module
Option Explicit 'Generic Module
Public Const WS1_MEM_RNG = "C5,J5,R5" 'Sheet1 memory cells
Public prevWs1Vals As Object
Public Sub SetPreviousWS1Vals()
Dim c As Range
For Each c In Sheet1.Range(WS1_MEM_RNG).Cells
If Len(c.Value2) > 0 Then prevWs1Vals(c.Address) = c.Value2
Next
End Sub
Sheet1 Module
Option Explicit 'Sheet1 Module
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Target.CountLarge = 1 Then
If Not Intersect(Target, Me.Range(WS1_MEM_RNG)) Is Nothing Then GetPrevious Target
End If
End Sub
Private Sub GetPrevious(ByVal cel As Range)
Dim adr As String: adr = cel.Address
Application.EnableEvents = False
If Not IsError(cel.Value) And IsNumeric(cel.Value2) And Not IsNull(cel.Value) Then
If IsDate(cel.Value) Then
cel.NumberFormat = "General"
cel.Value2 = prevWs1Vals(adr)
Else
If cel.Value2 = 0 Then prevWs1Vals(adr) = 0
cel.Value2 = cel.Value2 + prevWs1Vals(adr)
prevWs1Vals(adr) = cel.Value2
End If
Else
cel.Value2 = prevWs1Vals(adr)
End If
Application.EnableEvents = True
End Sub
ThisWorkbook Module
Option Explicit 'ThisWorkbook Module
Private Sub Workbook_Open()
If prevWs1Vals Is Nothing Then Set prevWs1Vals = CreateObject("Scripting.Dictionary")
SetPreviousWS1Vals
End Sub
It can also enforce positives only
use commas to separate ranges, and add a Worksheet_SelectionChange() event to record the last user selected cell
Option Explicit
Dim oldvalue As String
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If Intersect(Target, Range("J5,R5")) Is Nothing Then Exit Sub
If Target.Value = 0 Then Exit Sub
On Error GoTo fixit
Application.EnableEvents = False
Target.Value = Target.Value + oldvalue
fixit:
Application.EnableEvents = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.CountLarge = 1 Then oldvalue = Target.Value
End Sub

When I remove data, code will stuck

I have excel sheet with dropdown list and when I choose anything from the list
macro will vlookup for requested value. But when I want to remove values from those cells, that I select them and press delete, it will show me "#N/A" and the excel is frozen, I cant do anything. Could you advise me, how can I avoid it, please?
Option Explicit
Private Sub Worksheet_Change()
Dim Target As Range
Dim selectedNa As Integer, selectedNum As Integer
selectedNa = Target.Value
If Target.Column = 10 Then
selectedNum = Application.VLookup(selectedNa, ActiveSheet.Range("dropdown"), 2, False)
If Not IsError(selectedNum) Then
Target.Value = selectedNum
Else: Exit Sub
End If
Else: Exit Sub
End If
End Sub
Try the following:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim selectedNa As Long, selectedNum As Variant
If Target.Column = 10 And Not IsEmpty(Target) Then 'selectedNa <> vbNullString Then '
Application.EnableEvents = False
On Error GoTo errhand
selectedNa = Target.Value
selectedNum = Application.VLookup(selectedNa, ActiveSheet.Range("dropdown"), 2, False)
If Not IsError(selectedNum) Then
Target.Value = selectedNum
End If
Application.EnableEvents = True
End If
Exit Sub
errhand:
If Err.Number <> 0 Then
Application.EnableEvents = True
End If
End Sub
Change your posted code to
Option Explicit
Private Sub Worksheet_Change(ByVal target As Range)
Dim selectedNa As Integer, selectedNum As Integer
On Error GoTo EH
Application.EnableEvents = False
selectedNa = target.Value
If target.Column = 10 Then
selectedNum = Application.VLookup(selectedNa, ActiveSheet.Range("dropdown"), 2, False)
If Not IsError(selectedNum) Then
target.Value = selectedNum
End If
End If
EH:
Application.EnableEvents = True
Debug.Print Err.Number, Err.Description
End Sub
The code HAS TO be put into the sheet module.
Have a look at the immediate window after you have changed or deleted a value in your sheet.
It looks like this is what you want, based on the information provided:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim CheckCells As Range
Dim ChangedCell As Range
Set CheckCells = Intersect(Me.Columns(10), Target)
Application.EnableEvents = False
If Not CheckCells Is Nothing Then
For Each ChangedCell In CheckCells.Cells
If Len(ChangedCell.Value) > 0 And WorksheetFunction.CountIf(Me.Range("dropdown"), ChangedCell.Value) > 0 Then
ChangedCell.Value = WorksheetFunction.VLookup(ChangedCell.Value, Me.Range("dropdown").Resize(, 2), 2, False)
End If
Next ChangedCell
End If
Application.EnableEvents = True
End Sub

VBA to change cell color when double clicked and then change it back when double clicked again

My current code changes cell color to yellow with a single click and then changes it back to nothing when clicked again. I was wondering if I can do that this time changing it to green (Color Index = 10) when double clicked and then back to nothing when double clicked again. Here's my current code:
Private Sub Worksheet_BeforeDoubleClick(ByVal target As Range, Cancel As Boolean)
Cancel = True
Worksheet_SelectionChange target
End Sub
Private Sub Worksheet_SelectionChange(ByVal target As Range)If
Intersect(target, Range("B9:AF129")) Is Nothing Then Exit Sub
If target.Interior.ColorIndex = xlNone Then
target.Interior.ColorIndex = 6
ElseIf target.Interior.ColorIndex = 6 Then
target.Interior.ColorIndex = xlNone
End If
End Sub
Sort-of works...
Private Sub Worksheet_BeforeDoubleClick(ByVal target As Range, Cancel As Boolean)
Cancel = ToggleColor(target, vbGreen)
Debug.Print "double"
End Sub
Private Sub Worksheet_SelectionChange(ByVal target As Range)
ToggleColor target, vbYellow
Debug.Print "single"
End Sub
Private Function ToggleColor(rng As Range, clr As Long) As Boolean
If Intersect(rng, Me.Range("B9:AF129")) Is Nothing Then Exit Function
If rng.Cells.CountLarge > 1 Then Exit Function
With rng.Interior
If .ColorIndex = xlNone Or .Color <> clr Then
.Color = clr
Else
.ColorIndex = xlNone
End If
End With
ToggleColor = True 'to cancel the double-click
End Function

VBA to check if any cell is not blank in given range

I have the below code that will throw a prompt when a particular sheet is empty before saving the workbook.
Purpose of code: To check, if value of drop-down is "yes" in Main Sheet and if "yes", check if given range on a particular sheet is blank. If "yes", throw a prompt and change the drop down value to "No" on main sheet.
Concern: For loop in the code will check if any cell is empty in given range, instead, I want a code to check if there is an entry in any one cell in given range. Lets say given range is E10:G19, if we have an entry in E10, It should come out of the code and should not throw a prompt and should throw only if all the cells in given range is empty.
Question: What should replace my For loop that can serve my purpose?
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim ws As Worksheet
Dim Rvalue As Range
Dim cell As Range
Set Rvalue = Sheets("Uni-corp").Range("E10:G19")
If Worksheets("Main").Range("E29").Value = "YES" Then
For Each cell In Rvalue
If IsEmpty(cell) Then
bOk = True
Exit For
Else: bOk = False
End If
Next
If bOk Then
If MsgBox("Sheet is blank", vbOKCancel + vbInformation) = vbOK Then
Worksheets("Main").Range("E29").Value = "NO"
Cancel = True
End If
End If
End If
End Sub
Here you go:
Option Explicit
Public Function b_is_range_empty(my_rng As Range)
If Application.WorksheetFunction.CountA(my_rng) > 0 Then
b_is_range_empty = False
Else
b_is_range_empty = True
End If
End Function
Public Sub TestMe()
Debug.Print b_is_range_empty(Selection)
End Sub
The idea is to use the built-in formula in Excel - CountA. It is optimized for faster search. In the test it works with selection of the area.
Edit:
In stead of this:
For Each cell In Rvalue
If IsEmpty(cell) Then
bOk = True
Exit For
Else: bOk = False
End If
Next
Write simply this:
bOK = b_is_range_empty(Rvalue)
Maybe you're after something like this:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If UCase(Worksheets("Main").Range("E29").Value) <> "YES" Then Exit Sub
If WorksheetFunction.CountA(Worksheets("Uni-corp").Range("E10:G19")) > 0 Then Exit Sub
If MsgBox("Sheet is blank", vbOKCancel + vbInformation) = vbOK Then
Worksheets("Main").Range("E29").Value = "NO"
Cancel = True '<--| this will make the macro not save the workbook
End If
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim ws As Worksheet
Dim Rvalue As Range
Dim cell As Range
Set Rvalue = Sheets("Uni-corp").Range("E10:G19")
If Worksheets("Main").Range("E29").Value = "YES" Then
For Each cell In Rvalue
If IsEmpty(cell)<>true Then
bOk = false
Exit For
Else: bOk = true
End If
Next
If bOk Then
If MsgBox("Sheet is blank", vbOKCancel + vbInformation) = vbOK Then
Worksheets("Main").Range("E29").Value = "NO"
Cancel = True
End If
End If
If bOk=false Then
If MsgBox("Sheet is not blank", vbOKCancel + vbInformation) = vbOK Then
Worksheets("Main").Range("E29").Value = "Yes"
Cancel = True
End If
End If
End If
End Sub
You appear to be exiting your for loop when the first cell is empty, you will want it to only exit when it finds a value instead:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim ws As Worksheet
Dim Rvalue As Range
Dim cell As Range
Set Rvalue = Sheets("Uni-corp").Range("E10:G19")
If Worksheets("Main").Range("E29").Value = "YES" Then
For Each cell In Rvalue
If IsEmpty(cell) Then
bOk = True
'Exit For moved to Else section
Else: bOk = False
Exit for
End If
Next
If bOk Then
If MsgBox("Sheet is blank", vbOKCancel + vbInformation) = vbOK Then
Worksheets("Main").Range("E29").Value = "NO"
Cancel = True
End If
End If
End If
End Sub

Inputbox, empty input clears cell

I'm trying to make a macro which checks a cell for changes. If the cell changes a user has to provide a date. When cancel is pressed or the field is left blank, another cell should be cleared. When cancel is pressed the cell gets cleared, but when 'ok' is pressed without providing a date I get an error. My code is as follows:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myValue As Date
If Target.Address = "$E$17" Then
myValue = Application.InputBox("Geef de revisiedatum op, DD/MM/JJ", "Revisie datum")
Range("$I$17").Value = myValue
If myValue = False Then
Range("$I$17") = ""
Exit Sub
End If
End If
If Target.Address = "$E$20" Then
myValue = Application.InputBox("Geef de revisiedatum op, DD/MM/JJ", "Revisie datum")
Range("$I$20").Value = myValue
If myValue = False Then
Range("$I$20") = ""
Exit Sub
End If
End If
End Sub
This is because you have myvalue declared as a date. When no value is returned it is a string that a date can't handle.
Change myValue to a string. Then your checks for myValue = False will change to If myValue = "" then.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myValue As String
If Target.Address = "$E$17" Then
myValue = Application.InputBox("Geef de revisiedatum op, DD/MM/JJ", "Revisie datum")
Range("$I$17").Value = myValue
If myValue = "" Then
Range("$I$17") = ""
Exit Sub
End If
End If
If Target.Address = "$E$20" Then
myValue = Application.InputBox("Geef de revisiedatum op, DD/MM/JJ", "Revisie datum")
Range("$I$20").Value = myValue
If myValue = "" Then
Range("$I$20") = ""
Exit Sub
End If
End If
End Sub