Loop through code and highlight row. Return only first two finds - vba

I've written code to loop through a range for a specific value. If the value equals "123" then highlight the entire row green. However, I only want it to highlight the very first two matches it finds and stop there. Many thanks.
Sub Macro3()
Sheets("XYZ").Select
Dim rng As Range
Sheets("XYZ").Select
Set rng = Range("L2:L10000")
For Each cell In rng
If cell.Value = "123" Then
cell.EntireRow.Interior.ColorIndex = 4
End If
Next
End Sub

It's better if you avoid using Select and other relatives, instead use referenced Objects, Sheets and Ranges.
Also, you can search for the last row with data in Column L instead of just looping through row 10000.
Option Explicit
Sub Macro3()
Dim Rng As Range, cell As Range
Dim counter As Integer, LastRow As Long
With Sheets("XYZ")
' find last row at Column "L"
LastRow = .Cells(.Rows.Count, "L").End(xlUp).Row
Set Rng = .Range("L2:L" & LastRow)
For Each cell In Rng
If cell.Value = "123" Then
cell.EntireRow.Interior.ColorIndex = 4
counter = counter + 1
End If
If counter >= 2 Then Exit For
Next
End With
End Sub

Sub Macro3()
Sheets("XYZ").Select
Dim rng As Range
dim count as integer
'Set the range in column D to loop through
Sheets("XYZ").Select
Set rng = Range("L2:L10000")
For Each cell In rng
If cell.Value = "123" Then
cell.EntireRow.Interior.ColorIndex = 4
count = count + 1
End If
if count >= 2 Then exit For
Next
End Sub

Filtering lets you avoid looping through cells
Assuming row 1 has header, you can try:
Dim cell As Range
Dim counter As Integer
With Sheets("XYZ")
With .Range("L1", .Cells(.Rows.Count, "L").End(xlUp)) '<--| reference its column "L" cells from row 1 (header) down to last not empty row
.AutoFilter field:=1, Criteria1:="123" '<--| filter referenced range on its first (and only) column with "123"
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if any cell gets filtered
For Each cell In .Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible) '<--| loop through filtered cells, skipping header
cell.EntireRow.Interior.ColorIndex = 4
counter = counter + 1 '<--| update counter
If counter = 2 Then Exit For '<--| exit at 2nd iteration
Next cell
End If
End With
.AutoFilterMode = False
End With

Here's your code with some addition:
Sub Macro3()
Sheets("XYZ").Select
Dim rng As Range
greenrows = 0
Sheets("XYZ").Select
Set rng = Range("b2:b10000")
For Each cell In rng
If cell.Value = "123" Then
If greenrows = 2 Then Exit Sub
cell.EntireRow.Interior.ColorIndex = 4
greenrows = greenrows + 1
End If
Next
End Sub

Related

need vba macro to delete cells except first and last row in each column

I have a excel which has multiple rows and columns and range of column values differ for each row.
Need a macro which will delete all cells in a row except first and last in each row and paste the last value next to first value.
Tried the below script:
Sub test()
Dim sh As Worksheet
Dim IDS As range
Dim ID As range
Set sh = ThisWorkbook.Sheets("Sheet1")
Set IDS = ActiveSheet.range("A2", range("A1").End(xlDown))
For Each ID In IDS
Dim b As Integer
Dim k As Integer
k = sh.range("ID", sh.range("ID").End(xlToRight)).Columns.Count
b = k - 1
range(ID.Offset(0, 0), ID.Offset(0, "b")).Select
Selection.ClearContents
Next ID
End Sub
This is a little different approach but should help.
Also, it is generally not best to declare variables in a loop as you do with b & k just fyi
Sub test()
Dim sh As Worksheet
Dim row As Integer
Dim lastCol As Integer
Set sh = ThisWorkbook.Sheets("Sheet1")
For row = 2 To sh.Cells(Sheets(1).Rows.Count, "A").End(xlUp).row
lastCol = sh.Cells(row, Columns.Count).End(xlToLeft).Column
sh.Range("B" & row).Value = sh.Cells(row, lastCol).Value
sh.Range(sh.Cells(row, 3), sh.Cells(row, lastCol)).ClearContents
Next
End Sub
Best of luck
I'd go as follows:
Sub test()
Dim cell As Range
With ThisWorkbook.Sheets("Sheet1") ' reference relevant sheet
For Each cell In .Range("A2", .Cells(.Rows.Count, "A").End(xlUp)) ' loop through referenced sheet column A cells from row 2 down to last not empty one
With .Range(cell, .Cells(cell.Row, .Columns.Count).End(xlToLeft)) ' reference referenced sheet range spanning from current cell to last not empty one in the same row
If .Count > 2 Then ' if referenced range has more then 2 cells
cell.Offset(, 1).Value = .Cells(1, .Count).Value ' store last cell value next to the current one
.Offset(, 2).Resize(, .Columns.Count - 1).ClearContents 'clear all cells right of current one
End If
End With
Next
End With
End Sub
You can use Range.Delete Method (Excel)
range(ID.Offset(0, 0), ID.Offset(0, b)).Delete Shift:=xlToLeft

VBA - if cell is empty then skip the sub

I have code, which put formula into area and it works fine:
Private Sub Jeeves_account2_C()
Dim lastrow As Long
Dim rng As Range, C As Range
With Worksheets("Crd_Headers") ' <-- here should be the Sheet's name
lastrow = .Cells(.Rows.Count, "C").End(xlUp).Row ' last row in column B
Set rng = .Range("C2:C" & lastrow) ' set the dynamic range to be searched
' loop through all cells in column B
For Each C In rng
If Not IsEmpty(C.Value) Then
C.Offset(, -1).Formula = "=IFERROR(VLOOKUP(RC[2],Jeeves_Cust_list!C[-1]:C[1],3,0),RC[2])" ' use offset to put the formula in column "P"
End If
Next C
End With
End Sub
But I would like to add condition, if cell C2 on the sheet Crd_Headers is empty, then skip the whole sub:
If Worksheets("Crd_Headers").Cells("C2") = "" Then
Exit Sub
End If
So the code looks like:
Private Sub Jeeves_account2_C()
If Worksheets("Crd_Headers").Cells("C2") = "" Then
Exit Sub
End If
Dim lastrow As Long
Dim rng As Range, C As Range
With Worksheets("Crd_Headers") ' <-- here should be the Sheet's name
lastrow = .Cells(.Rows.Count, "C").End(xlUp).Row ' last row in column B
Set rng = .Range("C2:C" & lastrow) ' set the dynamic range to be searched
' loop through all cells in column B
For Each C In rng
If Not IsEmpty(C.Value) Then
C.Offset(, -1).Formula = "=IFERROR(VLOOKUP(RC[2],Jeeves_Cust_list!C[-1]:C[1],3,0),RC[2])" ' use offset to put the formula in column "P"
End If
Next C
End With
End Sub
But it gives me error message invalid procedure call or argument
Could you advise me, what do I do wrong?
Thank you!
You simply mixed up Cells and Range object references.
To refer single cell you have two solutions:
If Worksheets("Crd_Headers").Range("C2") = "" Then
or
If Worksheets("Crd_Headers").Cells(2, "C") = "" Then

Loop through list and hide blanks

I have a list called "District List" on one tab and a Template that is driven by putting the name of a district into Cell C3. Each District has a wildly varying number of branches (between 1 & 500+ branches depending on the District) so the report template has a lot of blank space in some cases. I came up with this to loop through the District List, copy the Template tab, rename it the District Name, insert the name of the district into Cell C3, and then I have another loop to hide the blank rows.
It works, but it takes forever, like 5 minutes per tab, then after about four tabs, I get an object error at the first like of Sub CreateTabsFromList.
Is there a problem with the code, or is this just a really inefficient way to do this? If so can anyone help with a better method?
Sub HideRows()
Dim r As Range, c As Range
Set r = Range("a1:a1000") 'Sets range well beyond the last possible row with data
Application.ScreenUpdating = False
For Each c In r
If Len(c.Text) = 0 Then
c.EntireRow.Hidden = True 'Hide the row if the cell in A is blank
Else
c.EntireRow.Hidden = False
End If
Next c
Application.ScreenUpdating = True
End Sub
Sub CreateSheetsFromAList()
Dim MyCell As Range, MyRange As Range
Set MyRange = Sheets("District List").Range("A1")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
For Each MyCell In MyRange
Sheets("Template").Copy After:=Sheets(Sheets.Count) 'creates a new worksheet
Range("C3").Value = MyCell.Value 'Pastes value in C3
Sheets(Sheets.Count).Name = MyCell.Value 'renames worksheet
HideRows 'Hides rows where cell in column A is ""
Next MyCell
End Sub
Deleting/Hiding rows, 1 by 1 is the slowest method. Always club them in one range and delete/hide them in one go, also looping through cells is slower than looping array.
Sub HideRows()
Dim lCtr As Long
Dim rngDel As Range
Dim r As Range
Dim arr
Set r = Range("a1:a1000") 'Sets range well beyond the last possible row with data
Application.ScreenUpdating = False
arr = r
For lCtr = LBound(arr) To UBound(arr)
If arr(lCtr, 1) = "" Then
If rngDel Is Nothing Then
Set rngDel = Cells(lCtr, 1) 'harcoded 1 as you are using column A
Else
Set rngDel = Union(rngDel, Cells(lCtr, 1))
End If
End If
Next
If Not rngDel Is Nothing Then
rngDel.EntireRow.Hidden=True
End If
Application.ScreenUpdating = True
End Sub
takes fraction of a second for 1000 rows.

Autofill the same number from column A in column B

I need to create output like the following:
Column A | Column B
1. 1 1
2. 1
3. 2 2
4. 2
5. 2
So far, I have written the following code:
Sub ItemNum()
Dim rng As Range
Dim i As Long
Dim cell
Set rng = Range("A1:A99")
i = 1
For Each cell In rng
If (...) Then
cell.Offset(0, 1).Value = i
End If
Next
End Sub
I have already obtained the number sequence in column A. I need to add the same value in column B down to the column.
I would like to know how to add to increment statement.
Thanks
If what you are wanting to do is place a value from column A into every cell in column B until you come to another value in Column A, then the following should work:
Sub ItemNum()
Dim rng As Range
Dim i As Variant
Dim cell
Set rng = Range("A1:A99")
i = "Unknown"
For Each cell In rng
If Not IsEmpty(cell) Then
i = cell.value
End If
cell.Offset(0, 1).Value = i
Next
End Sub
You can do this without loops (quicker code):
Sub FastUpdate()
Dim rng1 As Range
Set rng1 = Range([a2], Cells(Rows.Count, "a").End(xlUp))
'add two rows
Set rng1 = rng1.Resize(rng1.Rows.Count + 2, 1)
'add first row
[b1].Value = [a1].Value
With rng1
.Offset(0, 1).FormulaR1C1 = "=IF(RC[-1]<>"""",RC[-1],R[-1]C)"
.Offset(0, 1).Value = .Offset(0, 1).Value
End With
End Sub
If you use a For...Next loop instead of For...Each loop then you can use the counter variable to address the cells in column B:
Option Explicit
Sub ItemNum()
Dim rng As Range
Dim lngCounter As Long
Dim strCellValue As String
Set rng = Range("A1:A99")
strCellValue = 0
For lngCounter = 1 To rng.Cells.Count
If rng(lngCounter, 1).Value <> "" Then
strCellValue = rng(lngCounter, 1).Value
End If
rng(lngCounter, 2).Value = strCellValue
Next
End Sub
E.g.
If i understand correctly, below is the answer for you.
Assuming your data starts with A2 then Apply the below formula in B2 and drag down up to the last
=IF(A2<>"",A2,B1)
Note: A column data may be Number or anything.
Proof

macro that highlights rows that do not exist in an other worksheet

I have one file with two worksheets, both are full of names and addresses. I need a macro that will highlight rows in the first sheet if the cell A of that row does not match any rows from column A of the second sheet.
So if the first cell in a row has no matching data in any of the data in column A of sheet2 then that row is highlighted red.
Also I might want to expand this in the future so could I also specify that Sheet1 can be the active sheet, but sheet2 is called by the sheet name?
Try below code :
Sub Sample()
Dim lastRow As Integer
Dim rng As Range
lastRow = Sheets("Sheet1").Range("A65000").End(xlUp).Row
For i = 1 To lastRow
Set rng = Sheets("sheet2").Range("A:A").Find(Sheets("Sheet1").Cells(i, 1))
If rng Is Nothing Then
Sheets("Sheet1").Cells(i, 1).EntireRow.Interior.Color = vbRed
End If
Next
End Sub
Here's an ugly brute-force approach:
Dim r As Range
Dim s As Range
For Each r In ActiveSheet.UsedRange.Rows
For Each s In Sheets("Sheet2").UsedRange.Rows
If r.Cells(1, 1).Value = s.Cells(1, 1).Value Then
r.Interior.ColorIndex = 3
End If
Next s
Next r
Here's a slicker way:
Dim r As Range
Dim s As Range
Set s = Sheets("Sheet2").Columns(1)
For Each r In ActiveSheet.UsedRange.Rows
If Not (s.Find(r.Cells(1, 1).Value) Is Nothing) Then
r.Interior.ColorIndex = 3
End If
Next r
how about this:
Sub CondFormatting()
Range("D1:D" & Range("A1").End(xlDown).Row).Formula = "=IF(ISERROR(VLOOKUP(A:A,Sheet2!A:A,1,FALSE)),""NOT FOUND"",VLOOKUP(A:A,Sheet2!A:A,1,FALSE))"
With Columns("D:D")
.FormatConditions.Delete
.FormatConditions.Add Type:=xlCellValue, Operator:=xlEqual, Formula1:="=""NOT FOUND"""
.FormatConditions(1).Interior.ColorIndex = 3
End With
Range("I16").Select
End Sub
here is an approach using a Worksheet formula:
=IF(ISERROR(VLOOKUP(A:A,Sheet2!A:A,1,FALSE)),"NOT FOUND",VLOOKUP(A:A,Sheet2!A:A,1,FALSE))
then you would use Conditional formatting to turn the cells red if column A doesn't find a match!
HTH
Philip