VBA search in two ranges - vba

I'm more than new at this, and I'm having trouble sorting out For...Next loops.
I want to track to two text variables in two columns, so that when both variables are found in a row text is added to that row in a different column.
This is what I have so far:
Sub AB()
Dim Rng1 As Range
Dim Rng2 As Range
Set Rng1 = Range("B1:B100")
Set Rng2 = Range("A1:A100")
For Each cel In Rng1
If InStr(1, cel.Value, "A") > 0 Then
For Each cel In Rng2
If InStr(1, cel.Value, "B") > 0 Then
cel.Offset(0, 5).Value = "AB"
End If
Next
End If
Next cel
End Sub

You might even be able to just do this?
Sub AB()
With ActiveSheet
For I = 1 To 100
If InStr(1, .Cells(I, 2), "A") > 0 And InStr(1, .Cells(I, 1), "B") > 0 Then
.Cells(I, 6).Value = "AB" 'i think offset 5 is column F?
End If
Next
End With
End Sub

Appreciate you have an answer now, but here's a different method using Find. Always good to know several ways to do something.
Sub AB()
Dim rng As Range
Dim itemaddress As String
With Columns(1)
Set rng = .Find("A", searchorder:=xlByRows, lookat:=xlWhole)
If Not rng Is Nothing Then
itemaddress = rng.Address
Do
If rng.Offset(0, 1) = "B" Then
rng.Offset(0, 2).Value = "AB"
End If
Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And itemaddress <> rng.Address
End If
End With
End Sub

You're using `cel' to step through each loop - the inner loop will get confused.
Along the vein of #findwindow answer (appeared as I was typing this). Loop just once and when a match is found check the cell next to it.
Sub AB()
Dim Rng1 As Range
Dim Rng2 As Range
Dim cel1 As Range
'Be specific about which sheet your ranges are on.
With ThisWorkbook.Worksheets("Sheet1")
Set Rng1 = .Range("B1:B100")
Set Rng2 = .Range("A1:A100")
End With
For Each cel1 In Rng1
'Check each value in column B.
If InStr(1, cel1.Value, "A") > 0 Then
'If a match is found, check the value next to it.
If InStr(1, cel1.Offset(, -1), "B") > 0 Then
cel1.Offset(, 4).Value = "AB"
End If
End If
Next cel1
End Sub

Related

Creating a named range in adjacent cells based on criteria in other cells

I have the following code... It should go through my table, picking out where column B has the value 'OSI' and column C has the value 'Notifications'. There are three rows which match this criteria.
From this I want to create a named range called 'Notif' that spans the corresponding columns from D to F for those rows, not including the B and C items.
Set NotifRng = sht.Range(sht.Range("B1"), sht.Range("C" & sht.Rows.Count).End(xlUp))
counter = 0
For Each cell In NotifRng 'loop through the range of features
If cell.Value = "Notifications" And cell.Vaue = "OSI" Then
counter = counter + 1
If counter = 1 Then
Set rng = sht.Range(cell.Offset(0, 1), cell.Offset(0, 3))
Else
Set rng = Union(rng, sht.Range(cell.Offset(0, 1), cell.Offset(0, 3))) 'build the range
End If
End If
Next cell
Debug.Print rng.Address
ThisWorkbook.Names.Add "Notif", rng
When I run the above code, only the first row returns, not all three. What am I doing wrong? I am not getting any error messages...
Any help would be very very very much appreciated!
The problem is in If cell.Value = "Notifications" And cell.Vaue = "OSI" Then, because the cell.Value cannot be both "Notifications" and "OSI".
Furthermore, you only need to loop through the first column of the range, thus: For Each cell In notifRng.Columns(1).Cells
The counter variable is not needed, if you check whether rng is assigned or not. At the end it is a good idea to check the rng again, before printing its address - If Not rng Is Nothing Then Debug.Print rng.Address
If this is the input:
Then running this code:
Sub TestMe()
Dim sht As Worksheet
Set sht = Worksheets(1)
Dim notifRng As Range
Set notifRng = sht.Range(sht.Range("B1"), sht.Range("C" & sht.Rows.Count).End(xlUp))
Dim rng As Range
Dim cell As Range
For Each cell In notifRng.Columns(1).Cells
If cell.Value = "OSI" And cell.Offset(columnoffset:=1).Value = "Notifications" Then
If rng Is Nothing Then
Set rng = sht.Range(cell.Offset(0, 1), cell.Offset(0, 3))
Else
Set rng = Union(rng, sht.Range(cell.Offset(0, 1), cell.Offset(0, 3)))
End If
End If
Next cell
If Not rng Is Nothing Then Debug.Print rng.Address
End Sub
Would deliver this:
$C$3:$E$3,$C$5:$E$5,$C$9:$E$9
This may work for you. It does away with the counter to see if a range has passed and checks the status of the Rng variable instead.
Sub Test()
Dim sht As Worksheet
Dim NotifRng As Range
Dim cell As Range
Dim Rng As Range
Set sht = ThisWorkbook.Worksheets("Sheet1")
With sht
Set NotifRng = .Range(.Cells(1, 2), .Cells(.Rows.Count, 2).End(xlUp))
End With
For Each cell In NotifRng 'loop through column B.
If cell.Value = "Notifications" And cell.Offset(, 1) = "OSI" Then 'Check value in column B & C.
If Rng Is Nothing Then 'If Rng doesn't contain a range then set one (columns C & E)
Set Rng = sht.Range(cell.Offset(0, 1), cell.Offset(0, 3))
Else 'If Rng already contains a range(s) then add to it.
Set Rng = Union(Rng, sht.Range(cell.Offset(0, 1), cell.Offset(0, 3))) 'build the range
End If
End If
Next cell
ThisWorkbook.Names.Add "Notif", Rng
End Sub
Hmmm - trying to delete my answer as #Vityata explains better, but it's not letting me.

insert entire same row beneath when condition was met

I am working on the below code to insert same entire row below/beneath original one. I had a hard time fulfilling the requirement because I am just new to making macros.
I already tried searching but not able to code correctly. It is working to insert an empty row. But what I need is to insert the row that met the condition. Below is the screenshot/code for my macro.
Private Sub CommandButton1_Click()
Dim rFound As Range, c As Range
Dim myVals
Dim i As Long
myVals = Array("LB") '<- starts with 51, VE etc
Application.ScreenUpdating = False
With Range("F1", Range("F" & Rows.Count).End(xlUp))
For i = 0 To UBound(myVals)
.AutoFilter field:=1, Criteria1:=myVals(i)
On Error Resume Next
Set rFound = .Offset(2).Resize(.Rows.Count - 1) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
.AutoFilter
If Not rFound Is Nothing Then
For Each c In rFound
Rows(c.Row + 1).Insert
c.Offset(1, -1).Value = ActiveCell.Value
Next c
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
Sub Test()
Dim rng As Range
Dim rngData As Range
Dim rngArea As Range
Dim rngFiltered As Range
Dim cell As Range
Set rng = Range("A1").CurrentRegion
'Exclude header
With rng
Set rngData = .Offset(1).Resize(.Rows.Count - 1)
End With
rng.AutoFilter Field:=6, Criteria1:="LB"
Set rngFiltered = rngData.Columns("F:F").SpecialCells(xlCellTypeVisible)
rng.AutoFilter Field:=6
For Each rngArea In rngFiltered.Areas
For Each cell In rngArea
'// When inserting a row,
'// iteration variable "cell" is adjusted accordingly.
Rows(cell.Row + 1).Insert
Rows(cell.Row).Copy Rows(cell.Row + 1)
Next
Next
End Sub
Below is the code I just used . Thank you!
Private Sub CommandButton2_Click()
Dim x As Long
For x = ActiveSheet.UsedRange.Rows.CountLarge To 1 Step -1
If Cells(x, "F") = "LB" Then
Cells(x, "F") = "ComP"
Cells(x + 1, "F").EntireRow.Insert
Cells(x, "F").EntireRow.Copy Cells(x + 1, "F").EntireRow
End if
Next x
End Sub

How to delete empty cells in excel using vba

This is just a sample I am testing the code in this data. I have three columns in sheet2. I have to delete the empty cells. This is the updated code which is working for column B only. You can check the snapshot
Sub delete()
Dim counter As Integer, i As Integer
counter = 0
For i = 1 To 10
If Cells(i, 1).Value <> "" Then
Cells(counter + 1, 2).Value = Cells(i, 1).Value
counter = counter + 1
End If
Next i
End Sub
Sample screenshot
If all you want is to delete the empty cells, give this a try...
Sub DeleteBlankCells()
Dim rng As Range
On Error Resume Next
Set rng = Intersect(ActiveSheet.UsedRange, Range("A:C"))
rng.SpecialCells(xlCellTypeBlanks).Delete shift:=xlUp
End Sub
Not the most elegant solution but it works.
Option Explicit
Sub delete()
Dim rCells As Range, rCell As Range, sFixCell As String
Set rCells = Range("A1:A13")
For Each rCell In rCells
If rCell = "" Then
sFixCell = rCell.Address
Do While rCell.Value = ""
rCell.delete Shift:=xlUp
Set rCell = Range(sFixCell)
Loop
End If
Next rCell
End Sub

Using a For/Each Loop but Jumping Active Cell VBA

So I am trying to write a For Each loop to look through an entire row. If it finds the word "Specialty" Copy it over to the next three cells.
It does this part fine, but then when it loops around, of course the next cell has "Specialty" in it bc it just copied it over. I need to figure out how to say, if you've found "Specialty" and copied it over, jump 4 cells over and begin searching again..... Tried Offsetting the active cell but didn't work.
Any ideas?
Thanks!
Sub CopySpecialtyOver()
Dim rngRow As Range
Dim Cell As Range
Set rngRow = Range("A8:BA8")
For Each Cell In rngRow
If InStr(1, Cell.Value, "Specialty") Then
Cell.Offset(0, 1).Value = Cell.Value
Cell.Offset(0, 2).Value = Cell.Value
Cell.Offset(0, 3).Value = Cell.Value
End If
Next Cell
End Sub
Here's how to loop backwards given your current code:
Sub CopySpecialtyOver()
Dim rngRow As Range
Dim Cell As Range
Dim cIndex As Long
Set rngRow = Range("A8:BA8")
For cIndex = rngRow.Columns.Count To rngRow.Column Step -1
Set Cell = Cells(rngRow.Row, cIndex)
If InStr(1, Cell.Value, "Specialty", vbTextCompare) Then
Cell.Offset(, 1).Resize(, 3).Value = Cell.Value
End If
Next cIndex
End Sub
You could replace 'For each' by a an integer iterable:
Sub CopySpecialtyOver()
Dim i As Integer
Dim rngRow As Range
Dim Cell As Range
Set rngRow = Range("A8:BA8")
For i = 1 To rngRow.Cells.Count
Set Cell = rngRow(1, i)
If InStr(1, Cell.Value, "Specialty") Then
Cell.Offset(0, 1).Value = Cell.Value
Cell.Offset(0, 2).Value = Cell.Value
Cell.Offset(0, 3).Value = Cell.Value
i = i + 3
End If
Next i
End Sub
Thank you so much! I ended up solving it like this:
Sub CopySpecialtyOver()
Dim rngRow As Range
Dim Cell As Range
Set rngRow = Range("A8:BA8")
For Each Cell In rngRow
If InStr(1, Cell.Value, "Specialty") Then
If InStr(1, Cell.Offset(0, -1).Value, "Specialty") Then
Else
Cell.Offset(0, 1).Value = Cell.Value
Cell.Offset(0, 2).Value = Cell.Value
Cell.Offset(0, 3).Value = Cell.Value
End If
End If
Next Cell
End Sub
For Each - as pointed out by other responses - may not be the best strategy. Nevertheless - as you asked for it - here comes a piece of code using some in-loop control to overcome the deficites of For Each in this use case:
Sub CopySpecialtyOver()
Dim rngRow As Range
Dim Cell As Range
Dim Found As Boolean
Dim Cnt As Integer
Set rngRow = Range("A8:BA8")
Found = False
Cnt = 0
For Each Cell In rngRow.Cells
If InStr(1, Cell.Value, "Specialty") And Not Found Then
' capture start of sequence - otherwise do nothing
Found = True
Cnt = 0
Else
If Found Then
'if in Found mode increment counter
Cnt = Cnt + 1
' expand using negative offset
If Cnt <= 3 Then
Cell = Cell.Offset(0, -Cnt).Value
End If
' break after 3rd
If Cnt = 3 Then
Found = False
Cnt = 0
End If
End If
End If
Next Cell
End Sub
This seemingly more complex code will have its advantage when run vertically (instead horizontally) over much more than just a handfull of cells, as For/Each performs much better than regular For/Next

VBA: Cells Starting with "=" Causing Problems in my Move Macro

I currently have some code that finds cells not in the first column and moves them over. I'm facing a problem with cells that start with "=". Can you guys think of any work-arounds to solve this problem. Thanks in Advance.
Sub Move()
Dim cel As Range, rng As Range
Dim wk As Worksheet
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
If cel.Value <> "" And cel.Column <> 1 Then
wk.Cells(cel.Row, 1) = cel.Value
cel.Value = ""
End If
Next cel
End Sub
Either every time in your For each loop
If Cstr(cel.Value) <> "" And ... 'you need to do that for every cel.Value occurencies
Or declare a variable at the beginning
Dim StringInCell as String
For Each cel In rng
StringInCell=Cstr(cel.Value)
If StringInCell...
You may try .Text property as well (though I haven't had luck using that ever, I rather to use CStr).
This may work as well if the parsed data is throwing an error exception or something:
...
wk.Cells(cel.Row, 1).NumberFormat = "#"
wk.Cells(cel.Row, 1) = Cstr(cel.Value) 'related to the option chosen from above
Try this
Sub Move()
Dim cel As Range, rng As Range
Dim wk As Worksheet
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
If cel.HasFormula Then
wk.Cells(cel.Row, 1).Formula = cel.Formula
cel.ClearContents
Else
If cel.Value <> "" And cel.Column <> 1 Then
With wk.Cells(cel.Row, 1)
.NumberFormat = "#" '<<edit: added formatting
.Value = cel.Value
End with
cel.Value = ""
End If
End If
Next cel
End Sub
If you have cells that begin with =, but are not to be treated as formulas, but rather as Text, then using Sgdva's alternative suggestion:
Sub Move()
Dim cel As Range, rng As Range
Dim wk As Worksheet
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
If cel.Text <> "" And cel.Column <> 1 Then
wk.Cells(cel.Row, 1) = cel.Text
cel.Value = ""
End If
Next cel
End Sub
EDIT#1:
This version should "de-formularise" a cell before moving it to column 1:
Sub Move2()
Dim cel As Range, rng As Range
Dim wk As Worksheet, s As String
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
s = cel.Text
If s <> "" And cel.Column <> 1 Then
wk.Cells(cel.Row, 1).Value = s
cel.Value = ""
End If
Next cel
End Sub