Nested If/Else/End If within Select Case - excel

I have an Excel 2010 form. I am trying to change the row color based on several variables.
I do understand that this can be accomplished with conditional formatting and have got that to work, but cutting and pasting, as my users will likely do, kills the formatting. I was hoping that VBA would fix that. Possibly there is some other solution I am unaware of.
This is what I want to happen (the so called logic)
on Sheet3
Columns (a – w)
rows (2 – 10485)
upon a change in any field, $x2, or a past due date in $T2
if(AND($X2="Open",$T2<>"",$T2<=TODAY()) then all row red ($a2-$x2)
if(AND($X2="Open",$T2="",$T2>TODAY()) then all row white ($a2-$x2)
=$X2="Completed" then all row grey ($a2-$x2)
=$X2="Rescinded" then $X2 = orange and $A2 thru $W2 = grey
The x field will use a drop down and be either ( blank, open, completed, or rescinded )
This is the code I have tried to hobble together and failed with.....
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("A2:X1048567")) Is Nothing Then Exit Sub
Select Case Cells(Target.Row, "X").Value
Case "Open"
If Cells(Target.Row, "T").Value <> "" And T2 <= TODAY() Then 'Range(Cells(Target.Row, "A"), Cells(Target.Row, "F")).Interior.ColorIndex = 3
Else
Range(Cells(Target.Row, "A"), Cells(Target.Row, "F")).Interior.ColorIndex = x1None
End Select
Case "Completed"
Range(Cells(Target.Row, "A"), Cells(Target.Row, "F")).Interior.ColorIndex = 15
Case "Rescinded"
Range(Cells(Target.Row, "A"), Cells(Target.Row, "F")).Interior.ColorIndex = 15
Range(Cells(Target.Row, "A"), Cells(Target.Row, "F")).Interior.ColorIndex = 46
Case ""
Range(Cells(Target.Row, "A"), Cells(Target.Row, "F")).Interior.ColorIndex = xlNone
End Select
End Sub

There were a few discrepancies between what you described and what your code sample indicated so I went with the former.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A:X")) Is Nothing Then
On Error GoTo safe_exit
Application.EnableEvents = False
Dim rw As Long, rng As Range
For Each rng In Intersect(Target, Range("A:X"))
rw = rng.Row
If rw > 1 Then
Select Case LCase(Cells(rw, "X").Value2)
Case "open"
If Cells(rw, "T").Value <> "" And Cells(rw, "T").Value <= Date Then
Cells(rw, "A").Resize(1, 24).Interior.ColorIndex = 3
Else
Cells(rw, "A").Resize(1, 24).Interior.Pattern = xlNone
End If
Case "completed"
Cells(rw, "A").Resize(1, 24).Interior.ColorIndex = 15
Case "rescinded"
Cells(rw, "A").Resize(1, 23).Interior.ColorIndex = 15
Cells(rw, "X").Interior.ColorIndex = 46
Case Else
Cells(rw, "A").Resize(1, 24).Interior.Pattern = xlNone 'use pattern to turn off interior fill
End Select
End If
Next rng
End If
safe_exit:
Application.EnableEvents = True
End Sub
That should also handle multiple entries like those received from pasting a number of values into the sheet. By 'white' I assumed that you meant to remove any fill color, not actually provide a white fill color.

Related

vba error when delete values in couple rows: Run-time error '13': Type mismatch

I have a problem with my VBA code. Generally, each line of code works as it should, but if I try to delete values (even empty cells) of at least two lines in the E column (select and delete), I get
Run-time error '13': Type mismatch
I read that it was because of not declaring a variable, but I don't know what is missing.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCellsKolumnE As Range
Set KeyCellsKolumnE = Range("E2:E100")
If Not Application.Intersect(KeyCellsKolumnE, Range(Target.Address)) _
Is Nothing Then
If Range(Target.Address).Value = "TEXT1" _
Or Range(Target.Address).Value = "TEXT2" Then
Range(Target.Address).Offset(, 3).Value = "TEXT3"
ElseIf Range(Target.Address).Value = "TEXT4" _
Or Range(Target.Address).Value = "TEXT5" _
Or Range(Target.Address).Value = "TEXT6" Then
Range(Target.Address).Offset(, 3).Value = "TEXT7"
ElseIf Range(Target.Address).Value = "TEXT7" Then
Range(Target.Address).Offset(, 3).Value = "TEXT7"
Range(Target.Address).Offset(, 10).Value = "TEXT8"
ElseIf Range(Target.Address).Value = "" Then
Range(Target.Address).Offset(, 3).Value = ""
Else
Range(Target.Address).Offset(, 3).Value = ""
End If
End If
End Sub
As BigBen pointed out, the main issue should be the multicell Target, which calls for a loop
Also, you might want to ensure the multicell Target is compeletly inside column E
I also turned the If ElseIf EndIf syntax into a Select Case one
Finally, I throw in the good coding pratice to avoid multiple recursive callings in such an event handler
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCellsKolumnE As Range
Set KeyCellsKolumnE = Range("E2:E100")
If Not Application.Intersect(KeyCellsKolumnE, Target) Is Nothing And Target.Columns.CountLarge = 1 Then ' make sure Target is completely inside column E
On Error GoTo SafeExit
Application.EnableEvents = False ' disable events to prevent recursive calling
Dim cel As Range
For Each cel In Target ' loop through each Target cell
With cel ' reference current cell
Select Case .Value
Case "TEXT1", "TEXT2"
cel.Offset(, 3).Value = "TEXT3"
Case "TEXT4", "TEXT5", "TEXT6"
.Offset(, 3).Value = "TEXT7"
Case "TEXT7"
.Offset(, 3).Value = "TEXT7"
.Offset(, 10).Value = "TEXT8"
Case Else
.Offset(, 3).ClearContents
End Select
End With
Next
End If
SafeExit:
Application.EnableEvents = True ' restore events back
End Sub

VBA : combine range with row insert and merging

here you see the lines for merging certain cells when a row is inserted.
Range(Cells(ActiveCell.row, "H"), Cells(ActiveCell.row, "L")).mergeCells = True
Range("H" & ActiveCell.row + 1).Resize(, 5).Merge
i would like to add a range value but i can't find how or where to add it in the existing code.
the range in the excel is "H3752":"L4990", so only in that range the cells are to be merged, and not in the entire worksheet.
kinds regards.
The below code should work:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Cells(Target.Row + Target.Rows.Count, Target.Item(1, 1).Column).ID = Target.Address
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Item(1, 1).ID <> "" Then
'Code for if row is deleted
Else
'Code for if row is inserted
If Target.Row >= 3752 And Target.Row <= 4990 Then
Range(Cells(Target.Row, "H"), Cells(Target.Row, "L")).MergeCells = True
Range("H" & Target.Row + 1).Resize(, 5).Merge
End If
End If
Target.Item(1, 1).ID = ""
Cells(Target.Row + Target.Rows.Count, Target.Item(1, 1).Column).ID = Target.Address
End Sub
To change what rows you are looking at you can change this line: If Target.Row >= 3752 And Target.Row <= 4990 Then If you are trying to change the columns you can change this letters in this section:
Range(Cells(Target.Row, "H"), Cells(Target.Row, "L")).MergeCells = True
Range("H" & Target.Row + 1).Resize(, 5).Merge
works like a charm! but if i secure the excel file i do get an error now : "1004 while executing : error defined by the application or object"

How to colour cell in column C automatically in a colour when the sum of the values of cells next to it in column A and B is 5? (Excel-VBA)

In column A and B there will be numbers entered manually. column C gives out the sum automatically.
I would like to program in excel-VBA the following:
the colour of the cells in column C changes depending on the entered
numbers in A and B:
when the sum of cell A and B is less than 5: red
when the sum of the values in A and B is at least 5 AND value in cell B is at least 2: green
I think of using offset but I don't know how or if this would be the right command.
Thank you so much in advance, I am new to excel-vba and I don't know how to program it, and it will help me a lot to dig deeper into this programming language!
A non-VBA method:
Select cell C2 (the first cell to apply formatting to).
Select Conditional Formatting from the Home ribbon.
Select New Rule.
Select Use a formula to determine which cells to format.
Add the formula =SUM($A2:$B2)<5 and change the format to red.
Click OK.
Select New Rule again.
Select Use a formula to determine which cells to format.
Add the formula =AND(SUM($A2:$B2)>=5,$B2>=2) and change the format to green.
Click OK.
Select the Format Painter from the Home ribbon and copy the format down, or drag the cell down to copy down.
Using VBA:
This code will update the font colour in column C when the values in column A:B are manually updated. If you want the cells to update based on a formula you'll have to use the Worksheet_Calculate and check each value in columns A:B.
Private Sub Worksheet_Change(ByVal Target As Range)
'Check that a value is being changed in column A:B.
If Not Intersect(Target, Columns(1).Resize(, 2)) Is Nothing Then
With Target
'Check both values are numbers.
If IsNumeric(Cells(.Row, 1)) And IsNumeric(Cells(.Row, 2)) Then
'Change colour based on numeric values.
If Cells(.Row, 1) + Cells(.Row, 2) < 5 Then
Cells(.Row, 3).Font.Color = RGB(255, 0, 0)
ElseIf Cells(.Row, 1) + Cells(.Row, 2) >= 5 And Cells(.Row, 2) >= 2 Then
Cells(.Row, 3).Font.Color = RGB(0, 255, 0)
Else
Cells(.Row, 3).Font.Color = RGB(0, 0, 0)
End If
Else
'If not numeric change font to black.
Cells(.Row, 3).Font.Color = RGB(0, 0, 0)
End If
End With
End If
End Sub
Use conditional formatting applied through VBA or manually on the worksheet's Home tab.
Option Explicit
Sub rgy()
With Worksheets("sheet1")
With .Range("C:C")
With .FormatConditions
.Delete
With .Add(Type:=xlExpression, Formula1:="=AND(COUNT($A1:$B1)=2, SUM($A1:$B1)=0)")
.Interior.Color = vbRed
End With
With .Add(Type:=xlExpression, Formula1:="=AND(COUNT($A1:$B1)=2, SUM($A1:$B1)>=5)")
.Interior.Color = vbGreen
End With
With .Add(Type:=xlExpression, Formula1:="=AND(COUNT($A1:$B1)=2, SUM($A1:$B1)>0, SUM($A1:$B1)<5)")
.Interior.Color = vbYellow
End With
End With
End With
End With
End Sub
Try this macro;
Dim cel As Range, lRow As Long
lRow = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).Row
For Each cel In Range("C2:C" & lRow)
If cel.Value < "5" Then cel.Interior.Color = vbRed
If cel.Value = "5" Or cel.Offset(, -1).Value >= "2" Then cel.Interior.Color = vbGreen
Next cel
You could easily use conditional formatting
Try:
Option Explicit
Sub Test()
Dim LastRow As Long, i As Long
With ThisWorkbook.Worksheets("Sheet1")
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRow
If .Range("C" & i).Value < 5 Then
.Range("C" & i).Interior.Color = vbRed
ElseIf .Range("C" & i).Value >= 5 And .Range("B" & i).Value >= 2 Then
.Range("C" & i).Interior.Color = vbGreen
End If
Next i
End With
End Sub

Automate formula to selected rows for vise versa calculation

I want to filldown the formula below to row 4 to row 40:
If Target.Address = Range("E13").Address Then
ActiveSheet.Range("H13").Value = ActiveSheet.Range("E13").Value * ActiveSheet.Range("G13")
ElseIf Target.Address = Range("H13").Address Then
ActiveSheet.Range("E13").Value = ActiveSheet.Range("H13").Value / ActiveSheet.Range("G13")
End If
How can I do this?
I'll assume from your use of Target that the code is from a Worksheet_Change event procedure.
Private Sub Worksheet_Change(ByVal Target As Range)
if not intersect(target, Range("E4:E40, H4:H40")) is nothing then
on error goto safe_exit
application.enableevents = false
dim t as range
for each t in intersect(target, Range("E4:E40, H4:H40"))
select case t.column
case 5
cells(t.row, "H") = cells(t.row, "E") * cells(t.row, "G")
case 8
'you might want to make sure cells(t.row, "G") isn't zero
cells(t.row, "E") = cells(t.row, "H") / cells(t.row, "G")
end select
next t
End If
safe_exit:
application.enableevents = true
End Sub

VBA code to display message box if value in another cell contains specific text

I am new to VBA...looking for code that will only allow me to enter a value in a column if the value in one or more of the three cells immediately to the left "contains" the word "Other". I've successfully written the code so that if the value in one or more of the cells is "Other" I am restricted from entering a value, but have not been successful in using ISERROR and FIND so that the code looks for text that includes "other". Here is what I have right now...
If Target.Column = 15 And Target <> "" Then
If Cells(Target.Row, Target.Column - 1).Value <> "Other" _
Or Cells(Target.Row, Target.Column - 2).Value <> "Other" _
Or Cells(Target.Row, Target.Column - 3).Value <> "Other" _
Then
Target.Value = ""
MsgBox "First Select 'Other' value in one or more of the 'Excluded Employee' Columns to the left"
Exit Sub
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub
Any suggestions would be most appreciated!
If Target.Column = 15 And Target <> "" Then
If InStr(1, Cells(Target.Row, Target.Column - 1).Value, "Other") = 0 _
And InStr(1, Cells(Target.Row, Target.Column - 2).Value, "Other") = 0 _
And InStr(1, Cells(Target.Row, Target.Column - 3).Value, "Other") = 0 _
Then
Target.Value = ""
MsgBox "First Select 'Other' value in one or more of the 'Excluded Employee' Columns to the left"
Exit Sub
End If
End If
exitHandler:
Application.EnableEvents = True
End Sub
You can use COUNTIF with a wildcard to look for at least once cell containing other, i.e.:
If target.Column = 15 And target.Value <> "" Then
If Application.WorksheetFunction.CountIf(target.Offset(0, -3).Resize(1, 3), "*other*") = 0 Then
target.Value = ""
MsgBox "First Select 'Other' value in one or more of the 'Excluded Employee' Columns to the left"
Exit Sub
End If
End If

Resources