Find a string from Cell, and delete 4-5 rows attached to it and then move to next cell - excel

What I'm looking for is, I need to find out if a cell contains ".L" in it, if yes, the entire row along with 4 more rows needs to be deleted and this series goes on until last set of data.
For example:
There would be hundreds of dataset like shown below, out of which "RIC" contains ".L".
TID: xxx, Symbol=xxx, Date=xxx, RIC=EPWN.L , CUSIP=xxx, SEDOL=xxx
DataStream: xxxx
Bloomberg.: xxxx
Market....: xxxx
TID: xxx, Symbol=xxx, Date=xxx, RIC=BAR.BR , CUSIP=xxx, SEDOL=xxx
DataStream: xxx
Bloomberg.: xxx
Market....: xxx
Need to delete the entire set if any RIC is having ".L". So in the end, what should I get is dataset without ".L"
Please help
Below is the vba but it is not working:
Range("b2:b2000").ClearContents
Dim rng As Range
Dim cell As Range
Dim serchstring As String
Set rng = ActiveSheet.UsedRange
searchstring = ".l"
On Error Resume Next
For Each cell In rng
If UCase(cell.Value) Like "*" & UCase(searchstring) Then
cell.Offset(0, 1).Value = "NA"
cell.Offset(1, 1).Value = "NA"
cell.Offset(2, 1).Value = "NA"
cell.Offset(3, 1).Value = "NA"
cell.Font.Bold = True
cell.Interior.Color = vbYellow
End If
Next cell
Cells.Select
With ActiveSheet
.AutoFilterMode = False
.Range("A:B").AutoFilter
.Range("A:B").AutoFilter field:=2, Criteria1:="NA"
Intersect(.UsedRange, .UsedRange.Offset(1)).SpecialCells(xlCellTypeVisible).EntireRow.Delete
.AutoFilterMode = False
End With
With ActiveSheet
.AutoFilterMode = False
.Range("A:B").AutoFilter field:=1, Criteria1:=""
Intersect(.UsedRange, .UsedRange.Offset(1)).SpecialCells(xlCellTypeVisible).EntireRow.Delete
.AutoFilterMode = False
End With

If your program is not erasing the row, I think the issue lies with these lines:
cell.Offset(0, 1).Value = "NA"
cell.Offset(1, 1).Value = "NA"
cell.Offset(2, 1).Value = "NA"
cell.Offset(3, 1).Value = "NA"
Offset is returning a single cell so you are only erasing a single cell. But your post says you want to erase the whole row. To reference the row, I suggest:
cell.Offset(0, 1).EntireRow.ClearContents
cell.Offset(1, 1).EntireRow.ClearContents
cell.Offset(2, 1).EntireRow.ClearContents
cell.Offset(3, 1).EntireRow.ClearContents
Which can be reduced to a single line like:
cell.Offset(0).Resize(4).EntireRow.ClearContents
Or if you don't want to leave blank rows behind you can directly delete the rows like:
cell.Offset(0).Resize(4).EntireRow.Delete
But if you do repetitive deleting, you'll notice that Excel stutters and the execution is slow. So I suggest saving the rows to be deleted into a range variable and then deleting them all at once at the end. Use Union() to add ranges together.
If rToBeDeleted Is Nothing Then
Set rToBeDeleted = cell.Offset(0).Resize(4).EntireRow
Else
Set rToBeDeleted = Union(rToBeDeleted, cell.Offset(0).Resize(4).EntireRow)
End If
'And then at the end
rToBeDeleted.Delete
And if you do it this way, you don't need to do any of that autofilter deleting.
Edit:
For clarity, here is how I suggest your code be structured after applying my suggestions:
Range("b2:b2000").ClearContents
Dim rng As Range
Dim cell As Range
Dim rToBeDeleted As Range
Dim serchstring As String
Set rng = ActiveSheet.UsedRange
searchstring = "*.L"
On Error Resume Next
For Each cell In rng
If UCase(cell.Value) Like searchstring Then
If rToBeDeleted Is Nothing Then
Set rToBeDeleted = cell.Offset(0).Resize(4).EntireRow
Else
Set rToBeDeleted = Union(rToBeDeleted, cell.Offset(0).Resize(4).EntireRow)
End If
End If
Next cell
rToBeDeleted.Delete

Related

in Excel VBA why does my code not work with SpecialCells type visible and work without it?

In columns Bk and CB they both contain formula's that will result in a code. Now CB will also contain four codes and a remove statement which if they match with the cell in column BK in the same row then take the value from CB and paste over hence overriding the value in BK with that code and then paste it red.
the above should be done only on a filtered range though.
The ignore #N/A are in there as the overide column will error out on almost everyline except for when there is a code to overide.
This macro works perfectly without the visible cells statement at the end of my with range line but as soon as the visible cells statement is added the loop only goes up to #N/A and disregards the rest of the ElseIF statement.
Here is my code below:
Option Explicit
Sub Override()
Dim x As Workbook: Set x = ThisWorkbook
Dim rRange As Variant, fltrdRng As Range, aCell As Range, rngToCopy As Range
Dim ws As Worksheet
Dim LR As Long
Dim LR2 As Long
Dim SrchRng As Range, cel As Range
Dim mRow
mRow = 2
Set ws = x.Worksheets("Data")
LR = ws.Range("CB" & ws.Rows.Count).End(xlUp).Row
LR2 = ws.Range("BK" & ws.Rows.Count).End(xlUp).Row
'clears any filters on the sheet
ws.AutoFilterMode = False
' turns formula's to manual
Application.Calculation = xlManual
'copies down the formula in Column BK ignoring the last two rows as they have already been pasted over.
ws.Range("BK2:BK4 ").AutoFill Destination:=ws.Range("BK2:BK" & LR2 - 2)
'filters on N/A's and 10 as these are the codes we are interested in overiding
ws.Range("$A$1:$CB$1").AutoFilter Field:=19, Criteria1:=Array( _
"10", "N/A"), Operator:= _
xlFilterValues
' will loop through all cells in specified range and ignore any error's and #N/A's and will paste over the code overided in CB column to the BK column if conditions are met.
On Error Resume Next
While IsEmpty(ws.Range("CB" & mRow)) = False
With ws.Range("CB" & mRow).SpecialCells(xlCellTypeVisible)
If .Value = "#N/A" Then
ElseIf .Value = "1234" Then
.Offset(0, -17).Value = "1234"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "1235" Then
.Offset(0, -17).Value = "1235"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "1236" Then
.Offset(0, -17).Value = "1236"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "Remove" Then
.Offset(0, -17).Value = "Remove"
.Offset(0, -17).Interior.Color = vbRed
ElseIf .Value = "1237" Then
.Offset(0, -17).Value = "1237"
.Offset(0, -17).Interior.Color = vbRed
End If
End With
mRow = mRow + 1
Wend
'turn Formula 's back to automatic
Application.Calculation = xlAutomatic
End Sub
With ws.Range("CB" & mRow).SpecialCells(xlCellTypeVisible)
Using SpecialCells on just one cell is problematic.
Instead, use it on the entire filtered column, like this, which will replace your entire While...Wend loop (by the way, While...Wend is obsolete):
On Error Resume Next
Dim visibleCells As Range
Set visibleCells = ws.Range("CB2:CB" & LR).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If visibleCells Is Nothing Then Exit Sub
Dim cell As Range
For Each cell In visibleCells
If Not IsError(cell.Value) Then
Select Case cell.Value
Case "1234", "1235", "1236", "1237", "Remove"
cell.Offset(0, -17).Value = cell.Value
cell.Offset(0, -17).Interior.Color = vbRed
End Select
End If
Next

Copy and paste if one cell is blank and the other is not

So data gets pasted in to column B as the code keeps running it'll do a condition check to see there's any values in column B and paste a value in to the adjacent column A. I need to make it so it does two condition checks:
If there's values in column b, but then to check if there's values in column A before pasting so it doesn't overwrite different data that's been pasted already.
For Each Cell In y.Sheets("Compiled").Range("A:B")
If Range("B:B").Value <> "" And Range("A:A").Value = "" Then
Cell.Offset(0, -1).PasteSpecial xlPasteValues
End If
Next
You were close, don't try to loop over a multiple column range:
Sub Test()
For Each Cell In y.Sheets("Compiled").Range("B:B")
If Cell.Value <> "" And Cell.Offset(0, -1).Value = "" Then
Cell.Offset(0, -1).Value = Cell.Value
End If
Next
End Sub
NOTE: You are looping through every cell in Range("B:B") which is probably unnecessary. It'd be better if you use a lastrow value, or a static range like Range("B2:B1000"). Or you could use a criteria to exit your loop like If Cell.Value = "" Then Exit For.
Here's a version of the code that implements the lastrow value that dwirony mentioned in their answer. This also throws everything in arrays, so it might go a bit faster if you have a really large dataset.
Option Explicit
Sub test()
Dim ACol As Variant
Dim BCol As Variant
Dim lastrow As Long
Dim i As Long
lastrow = Range("B:B").Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).row
BCol = Range("B1:B" & lastrow).Value
ACol = Range("A1:A" & lastrow).Value
For i = LBound(BCol) To UBound(BCol)
If IsEmpty(ACol(i, 1)) And Not IsEmpty(BCol(i, 1)) Then
ACol(i, 1) = BCol(i, 1)
End If
Next i
Range("A1:A" & lastrow).Value = ACol
End Sub

Hiding row if cell equals next visible cell

I am trying to write a macro that hides the row if the cell value equals the next visible cell in that column and loops through the whole column. I have read that SpecialCells(xlCellTypeVisible) only works up to 8192 cells and my spreadsheet has 15,000 rows.
I have tried something like this but want to restrict it to only visible cells
Sub Test()
For i = 7 To 15258
If Range("P" & i).Value = Range("P" & i + 1).Value Then
Rows(i).Hidden = True
End If
Next i
End Sub
I have tried to search for a solution but haven't been able to find one yet.
Thanks!
I'd be surprised if this couldn't be optimized just a little bit, but it will work for what you are needing.
You can follow the comments within the code itself to kind of get a sense of what it's doing, but in a nutshell, you are using a For...Next statement to loop through your visible cells. For each visible cell, you will search for the next visible cell and then check to see if that matches. If it does, you add that cell to a special range that tracks all the rows to hide at the end of the code, then hide it.
Sub Test()
Dim ws As Worksheet, lookupRng As Range, rng As Range, lstRow As Long
Set ws = ThisWorkbook.Worksheets(1)
lstRow = 15258
Set lookupRng = ws.Range("P7:P" & lstRow)
Dim rngToHide As Range, i As Long
For Each rng In lookupRng.SpecialCells(xlCellTypeVisible)
Application.StatusBar = "Checking row " & rng.Row & " for matches."
For i = rng.Row + 1 To lstRow 'Loop through rows after rng
If Not ws.Rows(i).Hidden Then 'Check if row is hidden
If rng.Value = ws.Cells(i, "P") Then 'check if the non-hidden row matches
If rngToHide Is Nothing Then 'Add to special range to hide cells
Set rngToHide = ws.Cells(i, "P")
Else
Set rngToHide = Union(rngToHide, ws.Cells(i, "P"))
End If
End If
Exit For 'Exit the second For statement
End If
Next i
Next rng
Application.StatusBar = "Hiding duplicate rows"
If Not rngToHide Is Nothing Then rngToHide.EntireRow.Hidden = True
Application.StatusBar = False
End Sub

Find duplicate macro not working

The following code works on worksheets labeled Walk INs
Sub Find_Duplicatel()
Dim wrkSht As Worksheet 'The worksheet that you're lookin for duplicates in.
Dim rng As Range 'The range containing the duplicates.
Dim Col As Long 'The last column containing data +1
Set wrkSht = ThisWorkbook.Worksheets("Walk INs")
With wrkSht
'Reference to whole data range.
Set rng = .Range("A5:L2003")
'If the sheet is blank an error will be thrown when trying to find the last column.
'This code looks for the last column - you could just set Col to equal the last column number + 1.
On Error Resume Next
Col = 12
Err.Clear
On Error GoTo 0
If Col = 0 Then Col = 0
'Place a COUNTIF formula in the last column.
rng.Offset(, Col).Columns(1).FormulaR1C1 = "=COUNTIF(" & rng.Columns(1).Address(ReferenceStyle:=xlR1C1) & ",RC" & rng.Column & ") & "" duplicates."""
With rng
'Add conditional formatting to first column in range: If the COUNTIF formula is showing >1 then highlight cell.
With .Columns(1)
'This formula is =VALUE(LEFT($M5,FIND(" ",$M5)-1))>1.
'It returns only the number from the duplicate count and checks it is higher than 1.
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=VALUE(LEFT(" & rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ",FIND("" ""," & _
rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ")-1))>1"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(0, 100, 255)
End With
'Apply filter to your range.
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End With
End With
End Sub`
However when I changed Walk INs to VOC_ASST It hangs up on .AutoFilter I am not certain why. Could you inform me what happened & how to fix it. Other than the sheet titles every thing is identical.
You can add some code it to check if there is an AutoFilter already.
If .AutoFilterMode = False Then
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End If
I found the following code on the ENCODEDNA website & after modifying it for my worksheet, it works exactly as I expected.
Sub FIND_DUPLICATE()
`Option Explicit
Dim myDataRng As Range
Dim cell As Range
' WE WILL SET THE RANGE (FIRST COLUMN).
Set myDataRng = Range("A1:A" & Cells(Rows.Count, "B").End(xlUp).Row)
For Each cell In myDataRng
cell.Offset(0, 0).Font.Color = vbBlack ' DEFAULT COLOR.
' LOCATE DUPLICATE VALUE(S) IN THE SPECIFIED RANGE OF DATA.
If Application.Evaluate("COUNTIF(" & myDataRng.Address & "," &
cell.Address & ")") > 1 Then
cell.Offset(0, 0).Font.Color = vbRed ' CHANGE FORE COLOR TO
RED.
End If
Next cell
Set myDataRng = Nothing
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub`
Thank you to the people that have assisted me.

How to change the number of digits based on previous column?

This builds off of this question Using Left without Copy & Paste
I need to conditionally format these columns depending on the company in the column before. Here is the coding that works:
Sub keep12()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim rng As Range
Set rng = wks.Range("C3:C" & wks.Range("C" & wks.Cells.Rows.Count).End(xlUp).Row)
'set column C as Number (if this step is skipped it can go to Scientific and that doesn't work)
Columns("C:C").Select
Application.CutCopyMode = False
Selection.NumberFormat = "0.00"
Selection.NumberFormat = "0"
For Each Cell In rng
Cell.Value = Left(Cell.Text, 12)
Next Cell
End Sub
basically I want to go one step further and if Column B (company codes) are ABC, DEF, or GHI, then format the cell next to it in C as 10 digits, for any other info in column B (JKL, MNO, etc) then set it as 12. I'm guessing I could use a For Each, Select Case sort of thing? But I'm not entirely sure how to do this. Any help would be greatly appreciated.
Sub keep12()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim rng As Range
Set rng = wks.Range("C3:C" & wks.Range("C" & wks.Cells.Rows.Count).End(xlUp).Row)
'set column C as Number (if this step is skipped it can go to Scientific and that doesn't work)
Columns("C:C").Select
Application.CutCopyMode = False
Selection.NumberFormat = "0.00"
Selection.NumberFormat = "0"
For Each cell In rng
Select Case cell.Offset(0, -1)
Case "ABC", "DEF", "GHI"
cell.Value = Left(cell.Text, 10)
Case Else
cell.Value = Left(cell.Text, 12)
End Select
Next cell
End Sub

Resources