For each loop does not operate as expected - excel

I have two sheets in excel, one is a board with several cells with numbers inside, and the other is references (that have the numbers in previous board) and i need to write in same line of the references where are the cells located.
image of the first board where are the references
image of the excel sheet that i have to write the location of each reference
my vba code
Example:
The arm8.png is the board and local.png is where i write de localizations of the cells
Option Explicit
Sub ciclo()
Dim FindString As String
Dim Rng As Range
Dim matrixVal As Range
Set matrixVal = Sheets("Localizações").Range("B1")
FindString = matrixVal
For Each Rng In matrixVal
If Trim(FindString) <> "" Then
With Sheets("Arm8").Range("A1:J10")
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
'Application.Goto Rng, False
'MsgBox Rng.Column & " - " & Rng.Row
Else
MsgBox "Nothing found"
End If
End With
With Sheets("Localizações")
.Range("C1:C9").Value = Rng.Column
.Range("D1:D9").Value = Rng.Row
End With
End If
Next Rng
End Sub
I expected the output in local.png to be column C and D
2 - 9
2 - 7
2 - 8
2 - 4
5 - 4
7 - 4
5 - 9
9 - 7
9 - 0

Firstly, as I said in my comment, this:
Set matrixVal = Sheets("Localizações").Range("B1")
sets matrixVal as one single cell (B1 to be precise), so your For-Each loop doesn't have any cells to loop through apart from this single cell, so it will only run once.
Second, the FindString needs to be updated inside the loop, otherwise you'll be searching for the same value over and over.
Finally, you shouldn't update the Rng variable inside the loop because you are already using it to loop through a range. You need a second variable of type Range.
Your code should look like:
Sub ciclo()
Dim FindString As String
Dim Rng As Range
Dim cell As Range
Dim matrixVal As Range
Set matrixVal = ThisWorkbook.Worksheets("Localizacoes").Range("B1:B9")
For Each cell In matrixVal
FindString = cell.Value
If Trim(FindString) <> "" Then
With ThisWorkbook.Worksheets("Arm8").Range("A1:J10")
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
With ThisWorkbook.Worksheets("Localizacoes")
.Cells(cell.Row, "C").Value = Rng.Column
.Cells(cell.Row, "D").Value = Rng.Row
End With
Else
MsgBox "Nothing found"
End If
End With
End If
Next cell
End Sub

Related

Find specific text or dates inside a range and mark line with a specific colour

I have report were I use a VBA Macro to get a list from a large amount of Raw Data.
I have a very specific need, I hope someone can help me with.
My range is from A5:I500, each line from A:I has information to a specific need.
If a cell in the "H" Column has a specific text (in my case "Unconfirmed"), I would like The entire line (for instance A5:I5 or A26:I26), to be marked in a specific color.
If "H" Column has a date which is later than the date of "today", I would like the line (for instance A5:I5 or A26:I26), to be marked in a specific color.
If "H" Column has a date which is before the date of "today", I would like the line (for instance A5:I5 or A26:I26), to be marked in a specific color.
I want to end up like this
I found code which turns just the specific cell in the color I want.
How do I change this code to fill the entire Line from A:I on every line which contains "unconfirmed"?
Sub test1()
Dim FirstAddress As String
Dim MySearch As Variant
Dim myColor As Variant
Dim Rng As Range
Dim I As Long
MySearch = Array("Unconfirmed")
myColor = Array("3")
With Sheets("Ronnie").Range("A5:I1000")
For I = LBound(MySearch) To UBound(MySearch)
Set Rng = .Find(What:=MySearch(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rng.Interior.ColorIndex = myColor(I)
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
End Sub
This code will use if statements to check the data, and assign colour to the range of cells on that row.
Sub ColourRng()
Dim RNum As Integer
RNum = 1
For I = 1 To 500
If Sheets("Ronnie").Range("H" & RNum) = "Unconfirmed" Then
Sheets("Ronnie").Range("A" & RNum & ":I" & RNum).Interior.ColorIndex = 6
Else
If Sheets("Ronnie").Range("H" & RNum) >= Date Then
Sheets("Ronnie").Range("A" & RNum & ":I" & RNum).Interior.ColorIndex = 4
Else
If Sheets("Ronnie").Range("H" & RNum) < Date Then
Sheets("Ronnie").Range("A" & RNum & ":I" & RNum).Interior.ColorIndex = 3
End If
End If
End If
RNum = RNum + 1
Next I
End Sub

Search for last information in a range to copy and paste

I have a code that searches for a value in another shett, after searching i want to copy what the original sheet has bellow in another cells, but i want to oly copy what has information. Then return to the value found and paste bellow last cell with information.
In the sample code the partida.value was found in sheets("bancos") cell = H6
I want to copy the info in Sheets("Bu") B7:C19 and its supposed to get pasted bellow sheets("bancos") G13:h13
Private Sub C1_Click()
Dim Partida As String
Dim Rng As Range
Partida = Worksheets("BU").Range("c3").Value
If Trim(Partida) <> "" Then
With Sheets("Bancos").Rows("6:6")
Set Rng = .Find(What:=Partida, after:=.Cells(.Cells.Count), LookIn:=xlValues, lookat:=xlWhole, searchorder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
If Not Rng Is Nothing Then
Worksheets("Bu").Activate
ActiveSheet.Range("b7:c19").Select
'i want to copy only the filled cells in the range (b7:c19); the filled cells in b and c
Selection.Copy
Application.Goto Rng, True
'I want to paste in the last cells with information within the right and below cells from the "rng" found in cells G and H
Else
MsgBox "Not found"
End If
End With
End If
End Sub
No error msg tho
Can you try this. It's untested, but should get you close at least.
Private Sub C1_Click()
Dim Partida As String
Dim Rng As Range, r1 As Range, r As Long, c As Long
Partida = Worksheets("BU").Range("c3").Value
If Trim(Partida) <> "" Then
With Sheets("Bancos").Rows("6:6")
Set Rng = .Find(What:=Partida, after:=.Cells(.Cells.Count), LookIn:=xlValues, lookat:=xlWhole, searchorder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
If Not Rng Is Nothing Then
r = Rng.Row + 4
c = Rng.Column - 1
For Each r1 In Worksheets("Bu").Range("b7:c19")
If Len(r1) > 0 Then
.Cells(r, c + r1.Column - 2).Value = r1.Value
r = r + 1
End If
Next r1
Else
MsgBox "Not found"
End If
End With
End If
End Sub

Find a value from a range of cells in column over many sheets and return a "X" in next empty column

I'm trying to put a "X" or what ever in a the next empty column that I later can use INDEX and INDERECT (since the sheets are named the same as the range in column A in my main sheet) to look up for my main sheet. The "X" needs to be added in each of the sheets where the value is found.
The column in the sheets where the numbers I need to find the value is always in column A. In my main sheet the values are listed from B2:B23. The range varies in each sheet (from 400 to 5000 rows).
Is there a clever way of doing this that I haven't found still?
atm there are 80 sheets and the one main sheet
Code:
Sub Mark_cells_in_column()
Dim FirstAddress As String
Dim MyArr As Variant
Dim Rng As Range
Dim I As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Search for a Value Or Values in a range
MyArr = Array("34-2472", "36-437", "36-4351", "36-4879", "36-4982", "36-4981" _
, "36-5715", "36-4983", "36-4984", "36-5125", "36-5126", "36-5257", "36-6139" _
, "38-7079-1", "38-7079-2", "44-1276", "31-8589", "31-8589-1", "31-8647", "36-6149" _
, "36-5770", "31-8590")
'Search Column or range
With Sheets("3").Range("A:A") 'cant get my head around how to get this to apply so it loops through every sheet except main sheet
'clear the cells in the column to the right
.Offset(0, 13).ClearContents
For I = LBound(MyArr) To UBound(MyArr)
'If you want to find a part of the rng.value then use xlPart
'if you use LookIn:=xlValues it will also work with a
'formula cell that evaluates to "values listed"
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
'mark the cell in the column to the right if "Values listed" is found
Rng.Offset(0, 13).Value = "X"
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Here you go:
Sub Mark_cells_in_column()
Dim FirstAddress As String
Dim MyArr As Variant
Dim Rng As Range
Dim I As Long
Dim mainWS As Worksheet, ws As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set mainWS = Sheets("Main") ' Change this to whatever the name of your Main WS is, that you DON'T want to run the macro on
'Search for a Value Or Values in a range
MyArr = Array("34-2472", "36-437", "36-4351", "36-4879", "36-4982", "36-4981" _
, "36-5715", "36-4983", "36-4984", "36-5125", "36-5126", "36-5257", "36-6139" _
, "38-7079-1", "38-7079-2", "44-1276", "31-8589", "31-8589-1", "31-8647", "36-6149" _
, "36-5770", "31-8590")
' Loop through Sheets
For Each ws In Worksheets
If ws.Name <> mainWS.Name Then
With ws
'Search Column or range
With .Range("A:A")
'clear the cells in the column to the right 13 columns (aka column N)
.Offset(0, 13).ClearContents
For I = LBound(MyArr) To UBound(MyArr)
'If you want to find a part of the rng.value then use xlPart
'if you use LookIn:=xlValues it will also work with a
'formula cell that evaluates to "values listed"
Set Rng = .Cells.Find(What:=MyArr(I), _
After:=.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
'mark the cell in the column to the right if "Values listed" is found
Rng.Offset(0, 13).Value = "X" ' This marks it in 13 columns to the right where the value is found
Set Rng = .Columns("A:A").FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With ' Ends the .Range("A:A")
End With ' ends the `with WS`
End If
Next ws
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
The main thing seemed to be you were using the very last cell (After:=.Cells(.Cells.Count)) with SearchDirection:=xlNext. ...there's no next cell, if you're at the end! So, I changed that to After:=.Cells(1,1).
Secondly, I added a loop to check the worksheets, and if it's "Main", skip it. Edit as required.

Find and FindNext in VBA

I am working on Excel macro. What i need when getting data from another excel sheet, code should first check if there is any other row with the same FundName and if found then conditions apply.
I am just giving the sample of Excel Sheet from which the FundId is to be checked :
S.No Funds
1 A
2 B
3 C
4 D
5 A
Code is given below:
Set shtData = wbraw.Sheets(1) ' this line is correct
Set CCell = shtData.Cells.Find("Funds", LookIn:=xlValues, LookAt:=xlWhole).Offset(1, 0)
Set DCell = CCell.End(xlDown)
Dim SearchString as String
SearchString = "A"
Set FindRow = shtData.Range(CCell, DCell).Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
Set NextRow = shtData.Range(CCell, DCell).FindNext(After:=FindRow)
Above two lines in code not working as i want it should be. Let say if SearchString is set to "A" then FindRow and NextRow both should have the value. And if SearchString is set to "B" then as per given excel sheet FindRow should have the value but NextRow returns Nothing so that I can apply my conditions.
Please if anyone can help me.
Find will use the first cell of Range for the After parameter, if it is not specified, therefore the search is started after B2, and thus the first cell it finds is B6.
If the order is important for you then call Find with the last cell provided as After:
Dim counter As Integer
counter = 0
With shtData.Range(CCell, DCell)
Set c = .Find(SearchString, LookIn:=xlValues, LookAt:=xlWhole, After:=DCell)
If Not c Is Nothing Then
firstAddress = c.Address
Do
counter = counter + 1
Debug.Print "The next match #" & counter & " is " & c.Address
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With
Replace this:
Set FindRow = shtData.Range(CCell, DCell).Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
Set NextRow = shtData.Range(CCell, DCell).FindNext(After:=FindRow)
With:
If WorksheetFunction.CountIf(CCell.EntireColumn, SearchString) > 1 Then
'Duplicate found, do something here
Else
'Unique string, do something here
End If
Or
If Evaluate("COUNTIF(" & CCell.EntireColumn.Address & "," & SearchString & ")") > 1 Then
'Duplicate found, do something here
Else
'Unique string, do something here
End If

Excel unique value query

I'm not very experienced with excel -- I'm much more of a c# guy -- was hoping some of the excel gurus could help me out here!
Basically I have a spreadsheet that has only one column of text data (column a). I need to query this list of data.
I will be needing to basically copy in some more text data into another column (let's say column b), and then filter out the records in column b that are already present somewhere in column a, leaving me with only the unique records that are in column b, but not column a.
I've tried using the advanced filter but can't seem to get it to work. Any tips or advice on how I can do this would be great.
Thanks
You can filter your data dynamically, say into column C with formulas like
=IF(ISNA(VLOOKUP(B1,A:A,1,FALSE)),B1,"")
And then filter non-empty cells in column C
Otherwise this simple macro will clear the duplicates in place
Sub FilterDuplicates()
Dim r As Range
For Each r In ActiveSheet.Columns("B").Cells
If r.Value <> "" Then
On Error Resume Next
WorksheetFunction.VLookup r, ActiveSheet.Columns("A"), 1, False
If Err.Number = 0 Then r.ClearContents
On Error GoTo 0
End If
Next r
End Sub
This should do what you need. It looks for each value in column B in column A and deletes the cell if it finds a match. Run the code after you've pasted your data into column B. Note that it doesn't remove duplicates from column B, it just removes any values from column B that are in column A. To remove dupes from column B, select the column and choose Remove Duplicates from the Data tab.
You'll need to add a module to the workbook and insert the following code in the module:
code:
Option Explicit
Sub RemoveMatchesFromColumn()
On Error Resume Next
Dim LastRow As Long
Dim SearchText As String
Dim MatchFound As String
LastRow = Range("b" & ActiveSheet.Rows.Count).End(xlUp).Row
SearchText = Range("b" & LastRow).Value
Do Until LastRow = 0
MatchFound = Find_Range(SearchText, Columns("A")).Value
If SearchText = MatchFound Then
Range("b" & LastRow).Delete Shift:=xlUp
End If
LastRow = LastRow - 1
SearchText = Range("b" & LastRow).Value
Loop
End Sub
Function Find_Range(Find_Item As Variant, _
Search_Range As Range, _
Optional LookIn As Variant, _
Optional LookAt As Variant, _
Optional MatchCase As Boolean) As Range
' Function written by Aaron Blood
' http://www.ozgrid.com/forum/showthread.php?t=27240
Dim c As Range
Dim firstAddress As Variant
If IsMissing(LookIn) Then LookIn = xlValues 'xlFormulas
If IsMissing(LookAt) Then LookAt = xlPart 'xlWhole
If IsMissing(MatchCase) Then MatchCase = False
With Search_Range
Set c = .Find( _
What:=Find_Item, _
LookIn:=LookIn, _
LookAt:=LookAt, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=MatchCase, _
SearchFormat:=False)
If Not c Is Nothing Then
Set Find_Range = c
firstAddress = c.Address
Do
Set Find_Range = Union(Find_Range, c)
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With
End Function
Run the sub RemoveMatchesFromColumn. You can step into it to see what it's doing F8 or run it with F5.
NON VBA METHOD
Put this formula in Cell C1
=IF(VLOOKUP(B1,A:A,1,0)=B1,"DELETE ME","")
Drag it till the end. and then filter the data on Col C for DELETE ME And then delete the duplicate data.
VBA METHOD
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long
Dim delRange As Range, aCell As Range
Set ws = Sheets("Sheet1")
With ws
lRow = .Range("B" & Rows.Count).End(xlUp).Row
For i = 1 To lRow
Set aCell = .Columns(1).Find(What:=.Range("B" & i).Value, _
LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
If delRange Is Nothing Then
Set delRange = .Range("B" & i)
Else
Set delRange = Union(delRange, .Range("B" & i))
End If
End If
Next i
If Not delRange Is Nothing Then delRange.Delete shift:=xlUp
End With
End Sub

Resources