I found a problem when I'm running one macro that I wrote. I am not able to find the root.
I am looking for all values in a column containing the word RCS with my sub "FindMultipleOccurrences". The sub is working well in case I don't call another sub called "RCS" where I am also doing a find for some empty values.
But if RCS sub is call the sub "FindMultipleOccurrences" does not look any more for RCS entries but for empty values.
How can I avoid that problem?
My macros (please notice both macros unfinished yet):
Sub FindMultipleOccurrences()
Dim rngSearch As Range, rngLast As Range, rngFound As Range
Dim strFirstAddress As String
Worksheets("RCS").Range("B5:J1000").Delete
Set rngSearch = Worksheets("Ongoing").Range("B:B")
Set rngLast = rngSearch.Cells(rngSearch.Cells.Count)
Set rngFound = rngSearch.Find(What:="RCS", After:=rngLast, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False) 'buscando RCS
If Not rngFound Is Nothing Then
strFirstAddress = rngFound.Address
Do
Set rngFound = rngSearch.FindNext(rngFound)
MsgBox rngFound.Address
' Call RCS(rngFound)
Loop Until rngFound.Address = strFirstAddress
End If
MsgBox "done"
End Sub
Makro 2:
Sub RCS(rngo As Range)
Set Row1 = Range(rngo.Address).Offset(7, -1).Resize(, 13).Find("", LookIn:=xlValues, LookAt:=xlWhole)
If Row1 Is Nothing Then
Set row2 = Range(rngo.Address).Offset(8, -1).Resize(, 13).Find("", LookIn:=xlValues, LookAt:=xlWhole)
If row2 Is Nothing Then
Set rower = Range(rngo.Address).Offset(9, -1).Resize(, 13).Find("", LookIn:=xlValues, LookAt:=xlWhole)
Else
Set rower = row2
End If
Else
Set rower = Row1
End If
End Sub
When you call a second .Find command you are essentially cancelling the first and subsequent .FindNext commands will not carry on from the original .Find.
Use alternate methods to achieve your offset blank cell location.
If CBool(Application.CountBlank(Range(rngo.Address).Offset(7, -1).Resize(, 13))) Then
Set Rower = Range(rngo.Address).Offset(7, -1).Resize(, 13).SpecialCells(xlCellTypeBlanks).Cells(1, 1)
It is unclear to me what the successive operations are intended to achieve. If you are looking in a column for blanks and cannot find anything then moving the range down one cell and searching again shouldn't find anything.
Related
I've got the below to copy data based on two variables to the appropriate row in another sheet. It works (HOORAY!). However what I'm struggling to get my head around is the if logic I have used. I understand as it saying "If we find both cells, we redefine the Found to be nothing in order to end the loop". However as I now have set Found to Nothing, how is the code then able to find the address previously stored in Found and paste the data to it?
Sub copy_transpose()
Dim rng_source As Range
Dim Found As Range, Firstfound As String
Dim rngSearch As Range
Dim Criteria As Variant
Set rng_source = ThisWorkbook.Sheets("KPI").Range("H6:H100")
Set rngSearch = Sheets("Table").Range("A:A")
Criteria = Sheets("KPI").Range("C2:D2").Value
Set Found = rngSearch.Find(What:=Criteria(1, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Found Is Nothing Then
Firstfound = Found.Address
Do
If Found.EntireRow.Range("B2").Value = Criteria(1, 2) Then Exit Do 'Match found
Set Found = rngSearch.FindNext(After:=Found)
If Found.Address = Firstfound Then Set Found = Nothing
Loop Until Found Is Nothing
End If
If Not Found Is Nothing Then
Application.Goto Found
rng_source.Copy
Sheets("Table").Range(found.Offset(0, 1), found.Offset(0, 7)).PasteSpecial Transpose:=True
Else
MsgBox ("Error")
End If
End Sub
I have the following code I use to go through a sheet and parse the information onto separate sheets based on the string [Start].
Private Sub CommandButton7_Click()
Application.ScreenUpdating = False
Dim i As Long, rFind As Range, rFind1 As Range, rFind2 As Range, rFind3 As Range, rFind4 As Range, ws As Worksheet, s As String, s1 As String, s2 As String
s = "[Start]"
With Sheets("Full History File").Columns(1)
Set rFind3 = .Find(What:="[HistoryEnd]", LookAt:=xlPart, MatchCase:=False, SearchFormat:=False)
Set rFind = .Cells(Rows.Count, 1)
For i = 1 To WorksheetFunction.CountIf(.Cells, "*" & s & "*")
Set rFind = .Find(What:=s, After:=rFind, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not rFind Is Nothing Then
Set rFind1 = .Find(What:=s, After:=rFind)
Set ws = Worksheets.Add(After:=Sheets(Sheets.Count))
ws.Name = "Blasted " & i
If i = WorksheetFunction.CountIf(.Cells, "*" & s & "*") Then
Set rFind1 = rFind2.Offset(1)
End If
Range(rFind, rFind1.Offset(-1)).Copy ws.Range("A1")
End If
Next i
End With
Sheets("Blast Summary Sheet").Select
SheetNames
CommandButton6.Visible = True
Application.ScreenUpdating = True
End Sub
My problem is that the information I am working through has changed and I need to adapt the code to do the following:
Search for the string [TrainingModeChanged]
If not found search for the string [TrainingMode]
If not found search for the string [Start]
Once any of the strings are found create the new sheet Blasted with the number and copy the information between the found string up until the next found string which could be either one of the 3 above.
All help in modify the code to do this would be helpfull thanks
I am not entirely sure what you are after, but you could write a function that returns your required string instead of hardcoding it. Function below:
Option Explicit
Function getString() As String
'we will use On Error Resume Next to by pass the expected error if cannot find the string
On Error Resume Next
Dim searchRng As Range
Dim mySheet As Worksheet
Set mySheet = ThisWorkbook.Sheets("Full History File")
'search for first range
Set searchRng = mySheet.Columns(1).Find(What:="[TrainingModeChanged]", LookIn:=xlValues, LookAt:=xlWhole)
If Not searchRng Is Nothing Then
'this means search range was found
getString = searchRng.Value
'reset error handling
On Error GoTo 0
Exit Function
End If
'implicit to say if program runs here first search was unsuccessful
Set searchRng = mySheet.Columns(1).Find(What:="[TrainingMode]", LookIn:=xlValues, LookAt:=xlWhole)
If Not searchRng Is Nothing Then
'this means search range was found
getString = searchRng.Value
On Error GoTo 0
Exit Function
End If
'implicit to say if program runs here second search was unsuccessful
Set searchRng = mySheet.Columns(1).Find(What:="[Start]", LookIn:=xlValues, LookAt:=xlWhole)
If Not searchRng Is Nothing Then
'this means search range was found
getString = searchRng.Value
On Error GoTo 0
Exit Function
End If
End Function
And you call in your routine as:
s = getString()
And then continue on with your code..
I have two spreadsheets. Each spreadsheet contains rows with various bits of information on them, including a unique identifier number (an ISBN in this case).
I am trying to make a script that determines a record is present on the working sheet (obtaining ISBN from column A – working sheet is called ePubWorking), and marks a column (V) on the master sheet (ePubMaster) in the row that contains the same ISBN as found on the previous sheet (the ISBN on the new sheet is also kept in column A). It needs to do this for each record found on the ePubWorking sheet.
I’ve tried a few variants of code I’ve found on here, but I can’t seem to get anything to work. This is what I’m currently working with (which doesn’t appear to be doing anything):
Dim rCell As Range
Dim rFind As Range
Dim iColumn As Integer
For Each rCell In Sheets("ePubWorking").Range("A2", Sheets("ePubWorking").Cells(Rows.Count, "A").End(xlUp))
Set rFind = Sheets("ePubMaster").Rows(1).Find(What:=Trim(rCell.Value), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
rCell.Offset(0, 2).Value = "Sent"
If Not rFind Is Nothing Then
rFind.Offset(0, 21).Value = "Sent"
End If
Next rCell
Nothing is happening using the above (or any of my other variants). I can't even get the "Sent" part to appear on the secondary sheet.
Can anyone point me in the right direction please?
Ok so thanks for the guidance, obviously I'd been banging my head on frankenstein attempts for too long and got blinded to what I was doing. As Zac pointed I was looking along the wrong axis on the ePubMaster sheet.
Working code:
Dim wb As Workbook: Set wb = ThisWorkbook
Dim workingSheet As Worksheet: Set workingSheet = wb.Sheets("ePubWorking")
Dim masterSheet As Worksheet: Set masterSheet = wb.Sheets("ePubMaster")
Dim workingRange As Range: Set workingRange = Range(workingSheet.Range("A2"), workingSheet.Cells(workingSheet.Rows.Count, "A").End(xlUp))
Dim rCell As Range
Dim rFind As Range
For Each rCell In workingRange
If Not rCell.Value = vbNullString Then
Set rFind = masterSheet.Rows.Find(What:=Trim(rCell.Value), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
rCell.Offset(0, 2).Value = "Sent"
If Not rFind Is Nothing Then
rFind.Offset(0, 21).Value = "Sent"
End If
End If
Next rCell
All. I am new to VBA and MS EXCEl 2010. I just started to play with the macro module in EXCEL yesterday, almost zero experience.
What I was trying to do is described as follows. First search for value records in a range in sheet1, then for each cell I found, I locate that row and pull out another cell value at that row. Using this value to do another search in a range in sheet2. I'll point out the problem I am having after my code. Here is the pesudcode.
Dim Found As Range
With RangeInSheet1
Set Found = .Find(value1)
If Not Found Is Nothing Then
firstAddress = Found.Address
Do
With RangeInSheet2
ColumnIndex = .Find(value2).Column
End With
Set Found = .FindNext(Found)
Loop While Not Found Is Nothing And Found.Address <> firstAddress
End If
End With
value1 is the key I used to search in RangeSheet1, and value2 in RangeSheet2. The above code goes through every record I found for value1 in sheet 1 and do another search in Sheet2.
Now let's Say value1 = 1, value2 =2007, and there are 5 records that contains value1 in sheet 1. The problem arises from this line of code "ColumnIndex = .Find(value2).Column".
Supposedly, for all the five found records, value of Found should always be 1 after "Set Found = .FindNext(Found)" is executed . But, after I added this ColumnIndex code, value of Found is set to 2007, which is so weird to me. Anyone knows what the problem is? Any help will be appreciate. I really need to keep the Found behaves "normal" as I want.
If anything is unclear, please let me know
.Find/.Findnext remembers the last setting. And hence it is always advisable to completely Specify the parameters. specially After:= parameter. It will also remember what was your last search term i.e What:=
Here is a demonstration on how to work with .Find/.Findnext
Also do not use Value2 as a variable. It is a reserved word. Instead of using Value1 and Value2, I am using sSearch1 and sSearch2 in the below code
Let's say your sheets look like this
Now Try this code
Sub Sample()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim rngWs1 As Range, rngWs2 As Range
Dim aCell As Range, bCell As Range, cCell As Range, dCell As Range, eCell As Range, cl As Range
Dim sSearch1, sSearch2
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set rngWs1 = ws1.Range("A1:A10")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
Set rngWs2 = ws2.Cells
With ws1
For i = 1 To 10
sSearch1 = .Range("A" & i).Value
Set aCell = .Range("A" & i)
If Len(Trim(sSearch1)) <> 0 Then
Set aCell = rngWs1.Find(What:=sSearch1, After:=aCell, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
sSearch2 = aCell.Offset(, 1).Value
With ws2
Set bCell = rngWs2.Find(What:=sSearch2, After:=.Range("A1"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not bCell Is Nothing Then
Debug.Print "For " & sSearch1 & ", " & sSearch2 & " Found in " & bCell.Address
Set cCell = bCell
Do
Set bCell = rngWs2.FindNext(After:=bCell)
If Not bCell Is Nothing Then
If bCell.Address = cCell.Address Then Exit Do
Debug.Print "For " & sSearch1 & ", " & sSearch2 & " Found in " & bCell.Address
Else
Exit Do
End If
Loop
End If
End With
End If
End If
Next
End With
End Sub
This is the result that we get.
I am trying to use .Find and .FindNext to search through a single column of data. I first need to find the first cell containing the value "Total". The cell I'm trying to get to is the third cell AFTER the "Total" cell to contain the value "Tech". It is known for certain that the Cells(1, 1) does not contain "Tech" or "Total".
Dim FirstTotal As Range
Dim SearchRng As Range
Dim ResultRng As Range
Set SearchRng = Range("A:A")
Set FirstTotal = SearchRng.Find(What:="Total", After:=Cells(1, 1), SearchDirection:=xlNext)
Set ResultRng = SearchRng.Find(What:="Tech", After:=FirstTotal, SearchDirection:=xlNext)
SearchRng.FindNext().Activate
SearchRng.FindNext().Activate
About 50% of the times I've run this code, I've been stopped by a type mismatch error on the line beginning with Set ResultRng =. The rest of the time, the code has run all the way through, but the results look as though the final two lines of code were ignored completely.
I suspect that the answer here is pretty elementary, but I'm pretty new to excel vba and no resources I've found so far have answered this. Please help!
Would this help?
Sub Sample()
Dim oRange As Range, aCell As Range, bCell As Range
Dim ws As Worksheet
Dim SearchString As String, FoundAt As String
On Error GoTo Err
Set ws = Worksheets("Sheet3")
Set oRange = ws.Columns(1)
SearchString = "2"
Set aCell = oRange.Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bCell = aCell
FoundAt = aCell.Address
Do
Set aCell = oRange.FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bCell.Address Then Exit Do
FoundAt = FoundAt & ", " & aCell.Address
Else
Exit Do
End If
Loop
Else
MsgBox SearchString & " not Found"
End If
MsgBox "The Search String has been found at these locations: " & FoundAt
Exit Sub
Err:
MsgBox Err.Description
End Sub
If "Total" isn't found, then FirstTotal will be Nothing, which will result in a Type Mismatch when you try to use FirstTotal for the "After" argument in the ResultRange Find (the 2nd line). This will prevent that error:
Set FirstTotal = SearchRng.Find(What:="Total", After:=Cells(1, 1), SearchDirection:=xlNext)
If Not FirstTotal is Nothing Then
Set ResultRng = SearchRng.Find(What:="Tech", After:=FirstTotal, SearchDirection:=xlNext)
End If
Generally speaking any dependent Finds need to be treated this way.
Clearly, some kind of Else statement is required here, but I don't know what that would be.
I have observed the FindNext method fail to find the next occurrence of the searched item when applied in a function with parameters, which is invoked from a cell. The Find method (to search the first occurrence) does work as expected.