how can i assign no in column A based on Value in B and if there is any Duplicated values assign the same no.? - excel

if Column "A" was empty how can i make excel assign unique no# to unique cells and duplicated no# to duplicated cells just like the image attached.

While I am sure there is probably an easier way to accomplish your task, this one seems to work okay (disclaimer: lightly tested).
So essentially, serialNumber attempts to find the highest value in Col A. If none is found, it's assigned a value of 1.
RetCel attempts to set itself to a previous cell that matches. If no match is found, it will assign the current serialNumber value. If a match is found, then it will use the value of the match.
serialNumber only increases itself when the value has been used.
Option Explicit
Sub AssignUnique()
On Error GoTo ErrHandler
Dim ws As Worksheet, RngA As Range, RngB As Range, cel As Range
Set ws = ThisWorkbook.Worksheets("Sheet3")
Set RngA = ws.UsedRange.Columns("A")
Set RngB = ws.UsedRange.Columns("B")
If RngA.Column = 2 Then
'In the event RngA is empty, UsedRange will make it col B
Set RngA = RngA.Offset(, -1)
Set RngB = RngB.Offset(, -1)
If RngA.Column <> 1 Then
Err.Raise vbObjectError + 1000, , "Error setting RngA"
End If
End If
Dim RetCel As Range, serialNumber As Long
serialNumber = WorksheetFunction.Max(RngA)
If serialNumber = 0 Then serialNumber = 1
For Each cel In RngB.Cells
Set RetCel = Nothing
On Error Resume Next
Set RetCel = ws.Cells.Find(cel.Value, After:=Cells(cel.Row - 1, 2), _
SearchDirection:=xlPrevious)
Debug.Print RetCel.Address
On Error GoTo ErrHandler
If cel.Value = vbNullString Then
'Do Nothing
ElseIf RetCel Is Nothing Then
cel.Offset(, -1).Value = serialNumber
serialNumber = serialNumber + 1
Else
cel.Offset(, -1).Value = RetCel.Offset(, -1).Value
If cel.Offset(, -1).Value = vbNullString Then
cel.Offset(, -1).Value = serialNumber
serialNumber = serialNumber + 1
End If
End If
Next cel
Exit Sub
ErrHandler:
MsgBox Err.Description, vbCritical, "Runtime # " & Err.Number
End Sub

Related

Change the values in a column depending upon different criteria

I want the values in Column D to change depending upon the value in Column A. Some values do not need to be amended at all if the conditions aren't met
Sub Test()
Application.ScreenUpdating = False
Dim startrow As Integer
Dim row As Integer
Dim c As Range
Dim Lastrow As Long
Application.ScreenUpdating = False
Lastrow = Cells(Rows.Count, "D").End(xlUp).row
For Each c In Range("D2:D" & Lastrow)
If Cells(row, 1) = "Bol" Then
c.Value = c.Value * 1.19
End If
If Cells(row, 1) = "Amazon" Then
c.Value = c.Value * 1.2
End If
Next
Application.ScreenUpdating = True
End Sub
I think I have an error in the lines beginning with c.Value = c.Value * .....
I'm new to VBA and just trying to make sense of it
I just provide this variant. It is working with array, so theoretically it is very quick. Probably no need to turn off the screen updating.
Sub test()
Dim lastRow As Long, i As Long
With Sheet1
lastRow = .Cells(Rows.Count, "D").End(xlUp).row
Dim vA As Variant 'Represents A2-A lastrow
vA = .Range("A2").Resize(lastRow - 1).Value
Dim vb As Variant 'Represents D2-D lastrow
vb = .Range("D2").Resize(lastRow - 1).Value
i = 0
Dim v As Variant
For Each v In vA
i = i + 1
If v = "Bol" Then
vb(i, 1) = vb(i, 1) * 1.19
ElseIf v = "Amazon" Then
vb(i, 1) = vb(i, 1) * 1.2
End If
Next v
.Range("D2").Resize(lastRow - 1).Value = vb ' Writing the values to the D column
End With
End Sub
You have to forecast and handle all possible conditions. Use this code please:
Sub Test()
Application.ScreenUpdating = False
Dim row As Integer
Dim Lastrow As Long
'I've assumed that you are working on sheet1
Lastrow = Sheets(1).Cells(Rows.Count, "D").End(xlUp).row
If Lastrow > 1 Then
For row = 2 To Lastrow
If Sheets(1).Cells(row, 1).Value = "Bol" Then
Sheets(1).Cells(row, 4).Value = Sheets(1).Cells(row, 4).Value * 1.19
End If
If Sheets(1).Cells(row, 1).Value = "Amazon" Then
Sheets(1).Cells(row, 4).Value = Sheets(1).Cells(row, 4).Value * 1.2
End If
Next
Else
MsgBox ("There is no data at column D")
End If
Application.ScreenUpdating = True
End Sub
There are quite a few ways to go about what you're trying to do. For what it's worth, this is how I would go about it. You had a few additional variables you didn't need, and your 'row' variable wasn't assigned a value at all.
Sub test2()
Dim lastRow As Long, _
i As Long
Application.ScreenUpdating = False
With Sheet1
lastRow = .Cells(Rows.Count, "D").End(xlUp).row
For i = 2 To lastRow
If .Cells(i, 1).Value = "Bol" Then
.Cells(i, 4).Value = .Cells(i, 4).Value * 1.19
End If
If .Cells(i, 1).Value = "Amazon" Then
.Cells(i, 4).Value = .Cells(i, 4).Value * 1.2
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
I kept is relatively simple, so hopefully you can follow what's going on. If you have a lot of "If" statements, it may be cleaner to use VBAs "Select Case".
Also the text strings as you have them set up are case sensitive. "Bol" does not equal "bol" maybe that doesn't matter, but something to be aware of. If the string you pass it is "amazon" it will not pass the 'If' test.
Another assumption I made was that your data is on Sheet1. You should get in the habit of fully qualifying your ranges, it will make your life a lot easier as your code gets more complicated.
Last bit, I'm assuming the values in column D are all numbers. If there is text in there, you may run in to problems multiplying it.
Good luck!
You can simplify your code, and make it easier to read, by looping trough column A instead of column D and using the If/ElseIf statement to test each cell for either of the two conditions. By setting your range and defining c as a range variable for each cell in the range, you only have to loop through each cell and test for the two conditions. If the cell contains Bol use the Offset property to multiple the current value in column D by 1.19; ElseIf the cell contains Amazon use the Offset property to multiple the current value in column D by 1.2. Comments provide in the code.
Application.ScreenUpdating = False
'use the With statement to define your workbook and sheet, change as needed
'Note: "ThisWorkbook" identifies the workbook which contains this code
With ThisWorkbook.Sheets("Sheet1")
'Define the range you want to loop through, using the column you want to test
Dim rng As Range: Set rng = .Range("A2", .Cells(.Rows.Count, "A").End(xlUp))
'Define the variable for each cell-range
Dim c As Range
'loop through each "c" in the range and if one of the conditions are met
For Each c In rng
If c = "Bol" Then
'then use the "Offset property" to modify the value in column D
c.Offset(, 3) = c.Offset(, 3).Value * 1.19
ElseIf c = "Amazon" Then
c.Offset(, 3) = c.Offset(, 3).Value * 1.2
End If
Next c
End With
Application.ScreenUpdating = True
In-Place Modification
All the solutions have one common issue: you can use them only once. If you need to change the values after adding new records (rows) you should consider adding another column with the initial values so the code could be written to identify what has already been changed and what not. But that's for another question.
Your Sub Solution
You actually had only one serious mistake in two-three places.
Instead of row in the If statements you should have used c.Row and you could have removed Dim row As Integer:
Sub Test_Almost_Fixed()
Application.ScreenUpdating = False
Dim startrow As Integer
Dim c As Range
Dim Lastrow As Long
Application.ScreenUpdating = False
Lastrow = Cells(Rows.Count, "D").End(xlUp).row
For Each c In Range("D2:D" & Lastrow)
If Cells(c.Row, 1) = "Bol" Then
c.Value = c.Value * 1.19
End If
If Cells(c.Row, 1) = "Amazon" Then
c.Value = c.Value * 1.2
End If
Next
Application.ScreenUpdating = True
End Sub
Additionally after getting rid of the extra Application.ScreenUpdating = False and the Dim startrow As Integer and some further cosmetics, you could have had something like this:
Sub Test_Fixed()
Dim c As Range
Dim Lastrow As Long
Lastrow = Cells(Rows.Count, "D").End(xlUp).row
Application.ScreenUpdating = False
For Each c In Range("D2:D" & Lastrow)
If Cells(c.Row, 1) = "Bol" Then
c.Value = c.Value * 1.19
End If
If Cells(c.Row, 1) = "Amazon" Then
c.Value = c.Value * 1.2
End If
Next
Application.ScreenUpdating = True
End Sub
A More Complex Sub Solution
Use the following for the ActiveSheet in a standard module (e.g. Module1). For a particular sheet you can place it in a sheet module (e.g. Sheet1) or create a button on the sheet.
Tip: When you have such a simple (short, fast) code and especially when you're using a Button to run it (in a 'one-time operation code'), it is good practice to use a MsgBox at the end of the code to actually know that the code has run and to prevent accidentally pressing the Button more than once.
Option Explicit
Sub Test()
Const Proc As String = "Test"
On Error GoTo cleanError
' Define Constants.
Const FirstRow As Long = 2
Const SourceColumn As Variant = 1 ' e.g. 1 or "A"
Const TargetColumn As Variant = 4 ' e.g. 4 or "D"
Dim Criteria As Variant ' Add more values.
Criteria = Array("Bol", "Amazon")
Dim Multiplier As Variant ' Add more values.
Multiplier = Array(1.19, 1.2)
' Check if Criteria and Multiplier Arrays have the same number
' of elements (columns).
Dim ubCM As Long: ubCM = UBound(Criteria)
If UBound(Multiplier) <> ubCM Then Exit Sub
' Write Source and Target Ranges to Source and Target Arrays.
Dim rng As Range
' Define Last Non-Empty Cell.
Set rng = Columns(TargetColumn).Find("*", , xlValues, , , xlPrevious)
' Check if Target Column is empty.
If rng Is Nothing Then Exit Sub
' Check if the row of Last Non-Empty Cell is above FirstRow.
If rng.Row < FirstRow Then Exit Sub
Dim Target As Variant
' Write Target Range to Target Array.
Target = Range(Cells(FirstRow, TargetColumn), rng).Value
Set rng = Nothing
Dim ubST As Long: ubST = UBound(Target)
Dim Source As Variant
' Write Source Range to Source Array.
Source = Cells(FirstRow, SourceColumn).Resize(ubST).Value
' Modify Target Array.
Dim i As Long, j As Long
' Loop through elements (rows) of Source and Target Arrays.
For i = 1 To ubST
' Loop through elements (columns) of Criteria and Multiplier Arrays.
For j = 0 To ubCM
' Check if the value in current element (row) of Source Array
' matches the value of current element (column) in Criteria Array.
If Source(i, 1) = Criteria(j) Then
' Modify value in current element (row) of Target Array
' by multiplying it with the value of current element (column)
' of Multiplier Array.
Target(i, 1) = Target(i, 1) * Multiplier(j)
' Since a match is found, there is no need to loop anymore.
Exit For
End If
Next j
Next i
Erase Source
' Write values of Target Array to Target Range.
Cells(FirstRow, TargetColumn).Resize(ubST).Value = Target
Erase Target
' Inform user.
MsgBox "Data copied.", vbInformation, "Success"
Exit Sub
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
End Sub
An Event Solution
To make it automatically change the values in column D for each change of a value in column A you can place the following code into the sheet module (e.g. Sheet1):
Option Explicit
Private Const SOURCE_COLUMN As Variant = 1 ' e.g. 1 or "A"
Private Const TARGET_COLUMN As Variant = 4 ' e.g. 4 or "D"
Private Sub sdfWorksheet_Change(ByVal Target As Range)
Const Proc As String = "Worksheet_Change"
On Error GoTo cleanError
If Intersect(Columns(SOURCE_COLUMN), Target) Is Nothing Then Exit Sub
Const FirstRow As Long = 2
Dim rng As Range
Set rng = Columns(TARGET_COLUMN).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.Row < FirstRow Then Exit Sub
Set rng = Cells(FirstRow, SOURCE_COLUMN).Resize(rng.row - FirstRow + 1)
If Intersect(rng, Target) Is Nothing Then Exit Sub
Dim cel As Range
Application.Calculation = xlCalculationManual ' -4135
For Each cel In Target.Cells
TestChange cel
Next cel
CleanExit:
Application.Calculation = xlCalculationAutomatic ' -4105
Exit Sub
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
On Error GoTo 0
Resume CleanExit
End Sub
Private Sub TestChange(SourceCell As Range)
Const Proc As String = "TestChange"
On Error GoTo cleanError
Dim Criteria As Variant
Criteria = Array("Bol", "Amazon")
Dim Multiplier As Variant
Multiplier = Array(1.19, 1.2)
Dim ubCM As Long: ubCM = UBound(Criteria)
If UBound(Multiplier) <> ubCM Then Exit Sub
Application.ScreenUpdating = False
Dim TargetCell As Range, j As Long
For j = 0 To ubCM
If SourceCell.Value = Criteria(j) Then
Set TargetCell = Cells(SourceCell.row, TARGET_COLUMN)
TargetCell.Value = TargetCell.Value * Multiplier(j)
Exit For
End If
Next j
CleanExit:
Application.ScreenUpdating = True
Exit Sub
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'." & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description _
, vbCritical, Proc & " Error"
On Error GoTo 0
Resume CleanExit
End Sub

Find list of words from a range if words exits multiple times

I have a list of words in Sheet1 I need to match one by one from Sheets("Sheet2").Range("A1:A7500") until the end of the Range. Whenever word is matched I need to do something with it in Sheet1. That word occurs multiple times in Sheets("Sheet2").Range("A1:A7500").
Following code is Finding word only once. I dont understand where it is going wrong.
Sub XMAX()
Dim lrow As Long
Dim cel As Range
Dim oRng As Range: Set oRng = Sheets("Sheet2").Range("A1:A7500")
Dim oFoundRng As Range, oLastRng As Range
lrow = Sheets("sheet1").Cells(Sheets("Sheet1").Rows.Count, "f").End(xlUp).Row
'''''''''''''''Sheet1'''''''''''''''
For Each cel In Range("f4:f" & lrow)
If IsEmpty(cel.Value) = False Then
Set oFoundRng = oRng.find(cel.Value)
Do While Not oFoundRng Is Nothing
If UCase(oFoundRng.Offset(0, 1).Value) = "ISAAC" Then
Range("X" & cel.Row).Value = "X"
ElseIf UCase(oFoundRng.Offset(0, 1).Value) = "YO" Then
Range("V" & cel.Row).Value = "X"
ElseIf UCase(oFoundRng.Offset(0, 1).Value) = "JAN" Then
Range("U" & cel.Row).Value = "X"
Else
MsgBox oFoundRng.Value
End If
Set oLastRng = oFoundRng
Set oFoundRng = oRng.FindNext(cel.Value) 'Getting Error(1004) here "unable to get findnext property of the range class"
If oLastRng >= oFoundRng Then
Exit Do
End If
Loop
Else
End If
Next
Change this line
Set oFoundRng = oRng.FindNext(oFoundRng)
to
Set oFoundRng = oRng.FindNext
You are not searching for the word but for the range you previously found. You actually don't need to pass a value to .FindNext at all.
You also have to change this line
If oLastRng >= oFoundRng Then
to
If oLastRng.Row >= oFoundRng.Row Then
since the first line compares the values (which is not what you want to do since it will always evaluate to True). You actually want to compare the row numbers.
On another note, the following code snippet does not work:
If UCase(oFoundRng.Offset(0, 1).Value) = "ISAAC" Then
Range("X" & cel.Row).Value = "X"
ElseIf UCase(oFoundRng.Offset(0, 1).Value) = "ISAAC" Then
Range("W" & cel.Row).Value = "X"
This ElseIf will never be triggered since the condition is the same as the initial If condition.
You also don't need both of these statements:
Set oFoundRng = Nothing
Exit Do
They both achieve the same thing (breaking the loop), Exit Do does it more efficiently.
you may be after this (explanations in comments):
Sub XMAX()
Dim cel As Range
Dim oRng As Range: Set oRng = Sheets("Sheet2").Range("A1:A7500")
Dim oFoundRng As Range
Dim firstAddress As String
With Sheets("sheet1") ' reference "Sheet1" sheet
With .Range("f4", .Cells(.Rows.Count, "f").End(xlUp)) ' reference referenced sheet column "F" range from row 4 down to last not empty one
If WorksheetFunction.CountA(.Cells) > 0 Then ' if there's at least one not empty cell
For Each cel In .SpecialCells(xlCellTypeConstants) ' loop through referenced range not empty cells
Set oFoundRng = oRng.Find(what:=cel.Value, LookIn:=xlValues, lookat:=xlWhole) ' always specify at least 'LookIn' and 'LookAt' parameters, or they will be set as per last 'Find()' usage (even from Excel UI!)
If Not oFoundRng Is Nothing Then ' if a match found
firstAddress = oFoundRng.Address ' store first matched cell address
Do
Select Case UCase(oFoundRng.Offset(0, 1).Value2)
Case "ISAAC"
.Range("X" & cel.Row).Value = "X"
Case "YO"
.Range("V" & cel.Row).Value = "X"
Case "JAN"
.Range("U" & cel.Row).Value = "X"
Case Else
MsgBox oFoundRng.Value
End Select
Set oFoundRng = oRng.FindNext(oFoundRng) ' search for next occurrence
Loop While oFoundRng.Address <> firstAddress ' exit do when hitting fisr found cell again
End If
Next
End If
End With
End With
End Sub

how to set a cell to 0 if its blank and another cell has data

so i have this code and what i want to do is the following:
if Range("aj61:aj432") is blank and Range("F61:F432") has text, then set the blank cells to 0
Here is what I tried but got a type mismatch
Sub Insert_0()
Dim rng As Range
Set rng = Range("AJ61:AJ432")
If IsEmpty(rng) And rng.Offset(-30, 0) <> "" Then rng.Value = 0
End Sub
Use SpecialCells to capture the rows from text values in column F intersecting with the blank values in column AJ.
Option Explicit
Sub Insert_0()
Dim rng As Range
On Error Resume Next
Set rng = Intersect(Range("F61:F432").SpecialCells(xlCellTypeConstants, xlTextValues).EntireRow, _
Range("AJ61:AJ432").SpecialCells(xlCellTypeBlanks))
On Error GoTo 0
If Not rng Is Nothing Then
rng = 0
Else
Debug.Print Err.Number & ": " & Err.Description
On Error GoTo -1
End If
End Sub
You need to loop through range:
For i = 61 To 432
If Cells("AJ" & i).Value = "" And Cells("F" & i).Value <> "" Then Cells("AJ" & i).Value = 0
Next
no loops
Sub Insert_0()
Intersect(Range("F61:F432").SpecialCells(xlCellTypeConstants).EntireRow, Range("AJ:AJ")).SpecialCells(xlCellTypeBlanks).Value = 0
End Sub
If you want to check if a range of multiple cells is blank, you need to use something like:
If WorksheetFunction.CountA(rng) = 0 Then
You would have to loop through the cells in the range. Something like:
dim cel as range
for each cel in rng.cells
If IsEmpty(cel) And cel.Offset(-30, 0) <> "" Then cel.Value = 0
next
to make it faster you could fill an array with the values of the range

Macro that only works if the cell range has a 1 in it

I have a macro that works perfectly but only if the range has a 1 in the first cell such as the following: Range("E1:E12"). If I want to change the range to Range("E2:E13") it doesn’t paste to the correct cell. The uploaded Excel sheet is the current macro that works but I need to change the range to different cells.
Sub Part()
Dim SearchRange As Range, _
DashPair As Variant, _
PairParts As Variant, _
SearchVal As Variant, _
FoundPos As Variant, _
NextCol As Long
Set SearchRange = Range("E1:E12")
For Each DashPair In Range("B30, F30, J30")
Err.Clear
NextCol = 1
If DashPair.Value <> "" Then
PairParts = Split(DashPair, "-")
If PairParts(1) = "15" Then
SearchVal = DashPair.Offset(RowOffset:=1).Value
On Error Resume Next
Set FoundPos = SearchRange.Find(SearchVal, LookAt:=xlWhole)
If Not FoundPos Is Nothing Then
FoundPos = FoundPos.Row
' find first empty column right of E
While SearchRange(FoundPos).Offset(ColumnOffset:=NextCol).Value <> ""
NextCol = NextCol + 1
Wend
PairParts(1) = PairParts(1) + 1
PairParts = Join(PairParts, "-")
With SearchRange(FoundPos).Offset(ColumnOffset:=NextCol)
.NumberFormat = "#"
.Value = "" & PairParts & ""
End With
DashPair.Resize(ColumnSize:=3).ClearContents
End If
End If '15 found
End If
Next DashPair
End Sub
excel image
Cleaned up the code a little: your issue is with the following: FoundPos = FoundPos.Row as SearchRange(FoundPos) will return the index cell not the cell in the same row
i.e. E2:E15 => E2 is row 2, but SearchRange(2) is E3
* Edit *
Altered next empty cell selection protocol; previous one didn't work as expected
Sub Part()
Dim ws As Worksheet: Set ws = ActiveSheet
Dim Cell As Range, Target As Range, arr As Variant
With ws
Dim SearchRange As Range: Set SearchRange = .Range("E1:E12")
For Each Cell In .Range("B30, F30, J30")
If Cell <> "" Then
arr = Split(Cell, "-")
If UBound(arr) > 0 And arr(1) = "15" Then
On Error Resume Next
Set Target = SearchRange.Find(Cell.Offset(1, 0), LookAt:=xlWhole)
On Error GoTo 0
If Not Target Is Nothing Then
Do While Target <> ""
Set Target = Target.Offset(0, 1)
Loop
With Target
arr(1) = "16"
.NumberFormat = "#"
.value = Join(arr, "-")
Debug.Print Join(arr, "-")
End With
.Range(Cell, Cell.Offset(0, 2)).ClearContents
End If
End If
End If
Next Cell
End With
End Sub

Adding value when certain condition applies

I'm interested in a macro that will add a value in column P (Pass, At Risk or Failed) if column A has a certain condition - see below example.
I wonder if below macro can be used as inspiration. It was created to color a row if certain condition is met.
I'd also like the new macro to assign certain cell color in column P for value: Green for Pass, Yellow for At Risk and Red for Failed (same colors as in below macro)
Option Explicit
Sub Stackoverflow()
Dim ws As Worksheet
Dim rows As Long, i As Long
Dim rngSearch As Range, rngColor As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
Set ws = ActiveSheet
rows = ws.UsedRange.rows.Count
For i = 1 To rows
Set rngSearch = ws.Cells(i, 1)
Set rngColor = ws.Range("A" & i, "O" & i)
If rngSearch = "Unexpected Status" Then
rngColor.Interior.Color = 13434828
End If
If rngSearch = "At Risk" Then
rngColor.Interior.Color = 8420607
End If
If rngSearch = "Requirements Definition" Then
rngColor.Interior.Color = 10092543
End If
Next i
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
This would make column P yellow, if rngSearch is "At Risk":
For i = 1 To rows
Set rngSearch = ws.Cells(i, 1)
Set rngColor = ws.Range("A" & i, "O" & i)
If rngSearch = "Unexpected Status" Then
rngColor.Interior.Color = 13434828
End If
If rngSearch = "At Risk" Then
Cells(rows, "P").Interior.Color = vbYellow
End If
If rngSearch = "Requirements Definition" Then
rngColor.Interior.Color = 10092543
End If
Next i
The others are to be made correspondingly.
Yes you can, simplified
Dim i As Long, lngColor as Long 'It is inadvisable to declare variables which could also be the name of built in functions and objects, in your case I would not declare "rows" as a variable as it is also a property of an object
Dim varVal as Variant
Dim ws As Worksheet
Set ws = Thisworkbook.Worksheets("Sheet1") 'As general advice, avoid active and select but used fixed values, this way no confusion can exist as to which sheet is used In my example it is Sheet1, but you have to set it to the actual name of your sheet
with ws
For i = 1 To .UsedRange.Rows.Count
Select Case .Cells(i, 1) 'Looks at the value of row i column A, and then below if it matches a case.
Case "Unexpected Status"
varVal = "Pass"
lngColor = 13434828
Case "At Risk"
varVal = "At Risk"
lngColor = 8420607
Case "Requirements Definition"
varVal = "Failed"
lngColor = 10092543
Case else
varVal = Empty
lngColor = 0
End Select
.Cells(i, 16) = varVal 'row i in column P is set to the value determined by the condition in the select case part
If Not lngColor = 0 Then 'This value of lngColor is only present if the select case did not match and if so, the color should not be changed
.Range(.Cells(i, 1), .Cells(i, 16)).Interior.Color = lngColor 'Set the range of row i column A to column P to the color specified by the case select.
End If
Next i
End With

Resources