Attempting to Highlight Cells Based on String within Cell - string

Basically what I'm trying to do is the following:
First, determine if I'm in the correct row of cells based on the String value of the cell.
i.e If the current cell's string value contains the string AB1 or AB2, go through the entire row.
Once that has been determined, I would like to highlight the cells either green (if the cell holds a value greater than 5) or blue (if the cell holds a value between 4 and 5).
The above if block is not giving me trouble, it's the initial procedure.
What is stopping me from completing this is the run-time [error '91']: "Object variable or With block variable not set".
I have some programming experience, but no VBA experience. Any help would be greatly appreciated.
Sub ChangeCellColor()
Dim columnD As Range
Dim str1, str2 As String
Dim currCell As Range
Dim rightCell As Range
Dim i As Long
str1 = "AB1"
str2 = "AB2"
Columns(1).Font.Color = vbBlack
For i = 1 To Rows.Count
'If the current cell in the D column contains either the string AB1 or AB2, it will look into the values here.
If (currCell.Cells(i, 4).Value = str1) Or (currCell.Cells(i, 4).Value = str2) Then
'From the cell range of
For j = 1 To Range("E10").End(xlToRight)
If rightCell.Cells(j, 5) >= 5# Then
rightCell.Interior.Color = vbRed
ElseIf (rightCell.Cells(j, 5) >= 4 And rightCell.Cells(j, 5) <= 4.99) Then
cell.Interior.Color = vbYellow
End If
Next j
End If
Next i
End Sub

Try this: the following code looks at each cell in Column D, and checks the cell value to determine if cell.value = str1 or str2. Then, it loops through each cell in that row, beginning with column E, changing the color based on your parameters.
Also, try the Usedrange property of the Worksheet object to get the number of rows you need.
Sub ChangeCellColor()
Dim str1, str2 As String
Dim i As Integer
Dim j As Integer
Dim col As Integer
str1 = "AB1"
str2 = "AB2"
Columns(1).Font.Color = vbBlack
For i = 1 To ThisWorksheet.Usedrange.Rows.Count
With ThisWorksheet
'If the current cell in the D column contains either the string AB1 or AB2, it will look into the values here.
If .Cells(i, 4).Value = str1 Or .Cells(i, 4).Value = str2 Then
col = .Range("D" & i).End(xltoRight).Column
For j = 5 To col
If .Cells(i, j).Value >= 5 Then
.Cells(i,j).Interior.Color = vbRed
Else
If .Cells(i, j).Value >= 4 And .Cells(i, j).Value <= 4.99 Then
.Cells(i,j).Interior.Color = vbYellow
End If
End If
Next j
End If
End With
Next i
End Sub

There are a several issues...First, the error is because assigning to a Range variable requires the Set keyword, like so:
Set columnD = Range("D:D")
Second, in your For loop, you're comparing an integer to a range. If you want to loop through to the right-most column, you can do this:
For j = 1 to Range("E10").End(xlToRight).Column
Third, it looks like you've intended to use i for rows and j for columns? If so, you've got your js in the wrong place.
Assuming that is are rows and js are columns, I believe that as you're checking your cells for values, you should be referencing Cells(i, j,), (making both column and row selection dynamic) rather than hardcoding the value of 5.
Finally, you actually don't need those three range variables that you declared at the beginning at all. There's no need to position the cell inside an existing range (though you can if you wish). VBA assumes that you're dealing with the active sheet of the active workbook. As long as those two assumptions hold, then Cells(i,j) works just fine. If you want to add some specificity/protect from running on the wrong sheet, you can use Sheets("Sheet1").Cells(i,j).
PS--I assume that the '#' after the 5 is a typo?

You might want to either assign range value to currCell and rightCell or get rid of it.
Sub ChangeCellColor()
Dim columnD As Range
Dim str1, str2 As String
Dim currCell As Range
Dim rightCell As Range
Dim i As Long
str1 = "AB1"
str2 = "AB2"
Columns(1).Font.Color = vbBlack
For i = 1 To Rows.Count
'If the current cell in the D column contains either the string AB1 or AB2, it will look into the values here.
If (Cells(i, 4).Value = str1) Or (Cells(i, 4).Value = str2) Then
'From the cell range of
For j = 1 To Range("E10").End(xlToRight)
If Cells(j, 5) >= 5 Then
Cells(j, 5).Interior.Color = vbRed
ElseIf (Cells(j, 5) >= 4 And Cells(j, 5) <= 4.99) Then
Cells(j, 5).Interior.Color = vbYellow
End If
Next j
End If
Next i
End Sub

I think possible without VBA but with Conditional Formatting and, for green, a formula rule such as:
=AND(OR(NOT(ISERROR(FIND("AB1",$D1))),NOT(ISERROR(FIND("AB2",$D1)))),N(A1)>5)

Related

Excel VBA loop columns and rows color cell based on value

I would like to loop through the rows and columns (range B3:I16) of an excel worksheet. If the cell value matches my column p, I would like to color the background of the cell the color of the corresponding hex code (column O) or rgb codes (columns L:M).
I am seeing a compile error at the line "Next j" that says "Next without for" which I assume means there's an error in the previous line. I could not resolve that error.
Once I get the code to work, is there a more efficient way to check all the values in column P without a huge if else statement?
Sub format_quilt()
Dim i, j As Long
'psuedo code python style
'for i in range column number max
' for j in range row number max
' if (cell value == to index name in p4:p14) or (cell directly above == index name in p4:p14)
' color current cell using hex number
For i = 3 To Range("R2").Value
For j = 2 To Range("R1").Value
If (Cells(i, j).Value = Range("P4").Value) Or (Cells(i - 1, j).Value = Range("P4").Value) Then
Cells(i, j).Interior.Color = RGB(Range("L4").Value, Range("M4").Value, Range("n4").Value)
Next j
Next i
End Sub
You can use Match() to check your list in Col P.
For example (copying the fill color from the matched cell):
Option Explicit
Sub format_quilt()
Dim c As Range, ws As Worksheet, m, rngList As Range
Dim i As Long, j As Long
Set ws = ActiveSheet 'or some specific sheet
Set rngList = ws.Range("P4:P14") 'lookup range
For i = 3 To ws.Range("R2").Value
For j = 2 To ws.Range("R1").Value
Set c = ws.Cells(i, j)
m = Application.Match(c.Value, rngList, 0)
If Not IsError(m) Then 'got a match?
c.Interior.Color = rngList.Cells(m).Interior.Color
Else
c.Interior.ColorIndex = xlNone 'clear if no match
End If
Next j
Next i
End Sub

Split array and compare values to separate columns

Im trying to create a function which scans a column (job-trav-seq) and splits the values in each cell within a given range. It then compares these values to comparable cells in separate columns (so for instance job-trav-seq would have a cell 58546-05-10; this function would remove the dashes and compare the 58546 to job number, 05 to traveller ID and 07 to sequence No.
Basically, the function needs to first takes the A column (JobTravSeq) and breaks it apart into individual variables. (variable 1 should be compared with values in column B, values in variable 2 should be compared with column C and values in variable 3 should be compared with column D)
A loop should go up through the column cells as long as variable 1 = values in column B and variable 2 = values in column C (this is rowStart); this should be stored as a variable
A second loop should occur (rowEnd); which should loop down though the column cells as long as variable 1 = values in column B and variable 2 = values in column C; this should be stored as a variable
The code should then traverse between rowStart and rowEnd and check if variable 3 = values in column D, if it does then place an asterisk (or something similar) in front of the value to mark it as a current task
What im starting with: Sample Doc
What im trying to achieve: SampleDocOutput
any help would be most appreciated
heres my code for reference:
Sub SampleDocOrganise()
Dim i As Integer
Dim LastRow, rowCompare As Long
Dim variArr, rowStart, rowEnd, rangeID As Variant
Dim JobTravSeqRng As Range, jobNoRng As Range, TravellerRng As Range,
opSeqRng As Range, _
rng_JobTravSeq As Range, rng_JobNo As Range, rng_Traveller As Range,
rng_opSeq As Range
Set JobTravSeqRng = Range("A:A")
Set jobNoRng = Range("B:B")
Set TravellerRng = Range("C:C")
Set opSeqRng = Range("D:D")
For Each JobTravSeq In Selection
Str_Array = Split(JobTravSeq, "-")
For h = 0 To UBound(Str_Array)
Range("A:A").Find (Str_Array)
Range.Offset(, h + 1) = Str_Array(h)
For rowStart = 4 To Rows.Count
If Worksheets("Sheet1").Cells(Str_Array, 1).Value = jobNoRng.Value Then
If Cells(Str_Array, 2).Value = jobNoRng.Value Then
Cells.Value = rowStart
End If
End If
Next rowStart
For rowEnd = LastRow To 4 Step -1
If Cells(Str_Array, 1).Value = Range("B:B").Value Then
If Cells(Str_Array, 2).Value = Range("C:C").Value Then
Cells.Value = rowEnd
End If
End If
Next rowEnd
For rowCompare = rowStart To rowEnd
For Each opSeqArr In Str_Array
If Cells(Str_Array, 3).Value = Range("D:D").Value Then
If Cells(Str_Array, 1).Value = Range("B:B") Then
ActiveCell.Characters(0, 0).Insert (" P ")
With ActiveCell.Characters(0, Len(" P ")).Font
.Name = "OpSeq_Equals"
.Bold = True
.Color = -16776961
End With
MsgBox cell.Value = "*" & ""
' if cell changes then go to next loop
Else
' if cell changes then go to next loop
End If
End If
Next
Next
Next h
Next
End Sub
Sub MsgboxTasks() 'should display all rows that contain an asterisk in opSeq (current tasks)
End Sub

Create a header by determining when two cells do not match and pasting header from another sheet

I'm looking for something that is able to start searching in row 9 of column C for cells that do not equal cells 2 rows below. E.g. C9 <> C11, C10 <> C12, etc. Then Copy a cell from another sheet and paste it into Column A in the same row where there was the first discrepancy. E.G. if C9 <> C11, then paste from Sheet2 into A11. The purpose is to insert a new header after already formatting and sorting the data, below is one of the many variations I have tried, receiving only errors or blank inputs.
Any help would be greatly appreciated.
Dim iRow2 As Integer, iCol2 As Integer, iRow3 As Integer, iCol3 As Integer
Dim oRng2 As Range
Dim oRng3 As Range
Dim qqq As Range
Set oRng2 = Range("C9:C80")
Set oRng3 = Range("A9:A80")
iCol2 = oRng2.Column
iCol3 = oRng3.Column
For Each qqq In oRng2
Do
If qqq.Cells(oRng2, 3) <> qqq.Cells(oRng2 + 2, 3) Then
ThisWorkbook.Worksheets("Sheet1").Range("N1").Copy Destination = Sheets("Sheet2").Range(oRng2 + 2, 1)
End If
Loop While Not Cells(iRow2, iCol2).Text = ""
Next
I suggest you work with column numbers if you can. Then you will probably see that you need far less indices than your current code does, and you don't forget to update the indices (like currently iRow2 and iCol2) so easily.
Dim dataSheet As Worksheet
Dim headerSheet As Worksheet
Set dataSheet = ActiveWorkbook.Sheets(2)
Set headerSheet = ActiveWorkbook.Sheets(1)
Dim r As Integer
For r = 9 To 80
If dataSheet.Cells(r, 3).Value <> dataSheet.Cells(r + 2, 3).Value Then
dataSheet.Cells(r, 1).Value = headerSheet.Cells(1, 14).Value
End If
Next r
This should give you a good start. I don't know that exactly the inner loop is meant to check, because you're never touching iRow2 and iCol2 it will try to check the cell at R0C0 which is an invalid address. If you want to make sure the row you compare with isn't empty, check that first within the For loop:
...
For r = 9 To 90
If dataSheet.Cells(r + 2, 3).Value = "" Then
Exit For
ElseIf dataSheet.Cells(r, 3).Value <> dataSheet.Cells(r + 2, 3).Value Then
dataSheet.Cells(r, 1).Value = headerSheet.Cells(1, 14).Value
End If
Next r

Hide rows according to range of cells

Good day, I would love to ask you a question.
I have two colls with numbers and I need to compare first coll (longer) with second coll (shorter) and if there is a match, hide the row where the match occurs.
I have this so far:
Sub RowHide()
Dim cell As Range
Dim CompareCells As Range
Set CompareCells = Range("I2:I18")
For Each cell In Range("A2:A200")
If cell.Value = CompareCells Then
cell.EntireRow.Hidden = True
End If
Next
End Sub
My problem is that I don't know how to set value of CompareCells to start comparing. I'll appreciate every advice.
You have to set 2 separate ranges and compare them. If you want every cell compared with the one on the same line (A1 with B1, A2 with B2, etc) then consider using:
for i = 1 to something
set cell1 = range("A" & i)
set cell2 = range("B" & i)
if cell1.value = cell2.value then
'Do this, and do that!
cell1.entirerow.hidden = true
end if
next i
try this:
Sub RowHide()
Dim Longer As Range
Dim i As Double
i = 2 'Initial row
For Each Longer In Range("A2:A200")
If Longer.Value = Cells(i,2).Value Then
Longer.EntireRow.Hidden = True
End If
i = i + 1
Next
End Sub
PS:
Cells(RowIndex, ColumnIndex).Value: returns the value of the Row And Column.
ColumnIndex => Column A = 1, Column B = 2, an so on...
I looked into both of yours ideas and converted them into one and I finally get it working.
Here is my final code:
Sub RowHide()
Dim i As Integer
Dim j As Integer
For i = 2 To 197
Set FirstRange = Range("A" & i)
For j = 2 To 18
If FirstRange.Value = Cells(j, 8).Value Then
FirstRange.EntireRow.Hidden = True
End If
Next j
Next i
End Sub
Only modification if someone wants to use it is that you have to change numbers in for cycles according to number of rows in columns.
Thanks to both of you for your advices.

Parse strings, and add a number to the value

I have an Excel table in which sometimes an entire cell has the following content:
pos=51;70;112;111;132;153
Note the whole content in in a single cell, that is to say the value 51;70;112... are strings clumped together in a single cell and not in their own cells.
Can I write a macro that in all cells that contain the keyphrase "pos=", add 2 to each value, so that the end result is:
pos=53;72;114;113;134;155
Here is a code that will do it (tested on a sample on my Excel 2003):
Sub t()
Dim rCells As Range, c As Range
Dim arr As Variant, i As Integer
'Define the range to apply the code
Set rCells = Range("A1")
For Each c In rCells
'check if the cell desserves to be changed (could be adapted though to another check)
If Left(c.Value, 4) = "pos=" Then
'split all the values after the "pos=" into an array
arr = Split(Mid(c.Value, 5, Len(c.Value)), ";")
'add +2 to every value of the array (we convert the value to be sure, probably unneeded)
For i = 0 To UBound(arr)
arr(i) = CLng(arr(i)) + 2
Next i
'set back the value to the worksheet
c.Value = "pos=" & Join(arr, ";")
End If
Next c
End Sub
Note that I didn't add the error checking part if your values aren't well formated.
You know that you can easily split data without using macros, right? Just use the TextToColumns function on the Data tab
But if you really want a macro, you can do something like the following:
Sub AddNumber()
Dim numberToAdd As Integer
numberToAdd = 2
Set myRange = Range("A1:A5")
For Each myCell In myRange
If Left(myCell.Value, 4) = "pos=" Then
arEquality = Split(myCell, "=")
arElements = Split(arEquality(1), ";")
For i = 0 To UBound(arElements)
arElements(i) = arElements(i) + numberToAdd
Next
myCell.Offset(0, 1).Value = arEquality(0) + "=" + Join(arElements, ";")
End If
Next
End Sub

Resources