Search again if not found - vba

So I have a part in my macro that I want to add what I assume needs to be an "Else" portion, but I am not that good with macros and am asking for help.
Range("Z1").Copy
Dim FindString As String
Dim Rng As Range
FindString = Sheets("Pull").Range("Y1").Value
If Trim(FindString) <> "" Then
With Sheets("HourTracker").Range("A:A")
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, True
Else
MsgBox "Nothing found"
End If
End With
ActiveCell.Offset(0, 1).Activate
Selection.PasteSpecial xlPasteValues
Application.DisplayAlerts = True
End If
End Sub
So what I want this to do, is instead of "MsgBox "Nothing Found"", I want it to essentially perform the same thing as above, but copy cell Z2, and search for the value of Y2 in the same sheet "HourTracker" then paste the value. I have no idea on how to accomplish this, and all my attempts have failed. Any help would be much appreciated. Let me know if you need more clarification, thank you in advance!!!

Sounds to me like you're looking for a loop.
Sub findStuff()
Application.DisplayAlerts = False
' The item you want to paste
Dim PasteString As String
' The item you're looking for
Dim FindString As String
' The range that may containing FindString
Dim Rng As Range
' The variable used to loop through your range
Dim iCounter as Long
' loop through the first cell in column Y to the last used cell
For iCounter = 1 To Sheets("Pull").Cells(Rows.Count, 25).End(xlUp).Row
' PasteString = the current cell in column Z
PasteString = Sheets("Pull").Cells(iCounter, 26).Value
' FindString = the current cell in column Y
FindString = Sheets("Pull").Cells(iCounter, 25).Value
If Trim(FindString) <> "" Then
With Sheets("HourTracker").Range("A:A")
' Find the cell containing FindString
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
' There's no need to activate/ select the cell.
' You can directly set the value with .Value
Rng.Offset(0, 1).Value = PasteString
Else
' Do nothing
End If
End With
Else
' Do nothing
End If
Next
Application.DisplayAlerts = True
End Sub
Every time the compiler hits Next it will start again at For but raise the value of iCounter by 1. We can use Cells to accomplish this since Cells takes the row and column arguments as numbers, not strings (like Range). The syntax is simply Cells(Row #, Column #). Therefore, every time the For . . . Next loops around again, iCounter will go up by one and you'll search in the next row.
Instead of using .Paste, you can set the value of a cell directly with .Value. Pasting is pretty slow and using .Value is much faster.
Cells().End(xlUp).Row is a method used to find the last used cell in a range. See Error in finding last used cell in VBA for a much better explanation than I can give here.

Related

How can I split delimited strings into specific individual cells?

I have the following nodes:
Expected output:
My current steps to get this are:
Delimit by "/"
Sort
Conditionally format some cells. I'm trying to make the cells blank by doing A2=A1 and setting the font color to white. However this is not working.
How can I do that using VBA? I am told that this would probably require VBA.
The trick is keeping only one of the parent nodes per line.
Try with formulas (in new sheet or column) like
X2 =IF(A2=A1,"",A2)
X3 =IF(A3=A2,"",A3)
X4 =IF(A4=A3,"",A4)
etc..
For column A
Quick and dirty, but it gets the job done. This will loop through columns A-F rows 1-12 and select the value for each cell find that occurrence and delete the second occurrence not the first. This should do the trick.
Sub findItemInColumns()
With ThisWorkbook.Worksheets("Sheet1")
For r = 1 To 12
For c = 1 To 6
RemoveDups .Cells(r, c).Value
Next
Next
End With
End Sub
Sub RemoveDups(ByVal somevalueToFindAndRemove As String)
Dim FindString As String
Dim Rng As Range
listOfValues = Array(somevalueToFindAndRemove)
If Trim(somevalueToFindAndRemove) <> "" Then
With Sheets("Sheet1").Range("A:AK")
For i = LBound(listOfValues) To UBound(listOfValues)
Set Rng = .Find(What:=listOfValues(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
Application.Goto Rng, True
If Rng.Address <> FirstAddress Then Rng.Value = ""
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next i
End With
End If
End Sub

VBA - Find next empty row

Good day, I am newbie in VBA programming. need some help from experts :)
After i enter the date and click the generate button the code will find the date on the excel, but im done with this problem and here are my codes..
Dim Rng As Range
Dim FindDate As Date
FindDate = txtDate.Value
If Trim(FindDate) <> "" Then
With Sheets("Sheet2").Range("B:B")
Set Rng = .Find(What:=FindDate, After:=.Cells(.Cells.Count), LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox "Nothing found"
End If
End With
End If
My next problem is, i need to select the empty cell next to the date.. Here is a screen shot
To answer your specific question, the simplest way would be:
Rng.Offset(, 1).Select
However, you ought to be aware that the Find() function when using dates can be a little unreliable. See this post for more info and links: VBA, goto cell with a certain value (type: date). Your case is particularly exposed to risk as the date is entered via a TextBox.
I have to say your code looks awfully similar to the OP's of that post. You really ought to credit code sources if you didn't write it yourself.
If I were you, I'd convert your textbox value to a Long and then search the cell values (using the .Value2 property which provides date values as Longs) for the matching Long. Code isn't much longer and could look like this:
Dim src As Range
Dim findDate As Date
Dim findVal As Long
Dim cell As Range
'Define the source data range
With Sheet2
Set src = .Range(.Cells(1, "B"), .Cells(.Rows.Count, "B").End(xlUp))
End With
'Acquire search date and convert to long
findDate = CDate(UserForm1.txtDate.Value)
findVal = CLng(findDate)
'Search for date
For Each cell In src.Cells
If cell.Value2 = findVal Then
Application.Goto cell, True
'Select the next cell to the right
cell.Offset(, 1).Select
End If
Next
you could
use a Function to try returning the wanted range
Function SetRange(FindDate As Date) As Range
If Trim(FindDate) <> "" And IsDate(FindDate) Then
With Sheets("Sheet2") '<--| reference wanted sheet
With .Range("B1", .cells(.Rows.Count, 2).End(xlUp)) '<--| reference its column "B" range from row 1 down to last not empty row
On Error Resume Next '<--| if subsequent 'Find()' avoid possible subsequent statement error to stop the Function
Set SetRange = .Find(What:=FindDate, After:=.cells(.cells.Count), LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=True).Offset(, 1) '<--| try finding the passed 'FindDate' in referenced range and offset 1 column to the right
End With
End With
End If
End Function
and have your "Main" sub check it against Nothing before using it:
Option Explicit
Sub Main()
Dim Rng As Range
Set Rng = SetRange(txtDate.Text)
If Not Rng Is Nothing Then Rng.Select
End Sub

What is wrong with my math in Excel VBA?

Hopefully this my last question on this project of mine. I asked this question over at yahoo so I don't ask too many questions here, but no one has gotten back.
In Excel VBA code I am trying to add the values in Column H after doing a search in Column B for same date and highlight color. I have the code to loop to search and find the matching cells and perform the math operations that I want. The math operations is to get the value of Column H of the same Row of the Column B found with the search criteria. When I run the macro, it takes the value of Column H of the active row, and the result is multiplied by the number of cells found, not adding each value to get the sum.
For Example, the sum that I am looking for is 85, but the answer from the macro is 15 because the value of Column H in the active row is 3 and there are 5 cells that match the search criteria.
I know this for when I didn't incude the starting cell, the answer was 12, because there were 4 cells.
Example of what I am looking for: I select the last green highlighted cell with the date of "7/22/2016" (cell B15) I want to get the value of Column H of that same row (this would be H15) and add only the Column H values that have a green highlighted date "7/22/2016" (cells; H15+H7+H3+H2+H1) which should equal 85
What am I doing wrong with my math in my code? And how can I fix it? I have the search function working. I just need to get the selected row value and add the other search matching Column H values.
With the help of user [tag:Thomas Inzina], I was able to come up with this code:
Sub FindMatchingValue()
Const AllUsedCellsColumnB = False
Dim rFound As Range, SearchRange As Range
Dim cellValue As Variant, totalValue As Variant
' Get the H value of active row and set it to totalValue
cellValue = Range("H" & ActiveCell.Row)
totalValue = cellValue
' set search range
If AllUsedCellsColumnB Then
Set SearchRange = Range("B1", Range("B" & Rows.Count).End(xlUp))
Else
Set SearchRange = Range("B1:B30")
End If
' If there is no search range, show Msg
If Intersect(SearchRange, ActiveCell) Is Nothing Then
SearchRange.Select
MsgBox "You must select a cell in the highlighted area before continuing", vbInformation, "Action Cancelled"
Exit Sub
End If
' Get search criteria & set it to rFound
Set rFound = SearchRange.Find(What:=ActiveCell.Value, _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
SearchFormat:=False)
' If rFound is not Nothing, then do math. If rFound is Nothing, then findnext
If Not rFound Is Nothing Then
Do
If rFound.Style.Name = "Good" Then
totalValue = totalValue + cellValue
End If
Set rFound = SearchRange.FindNext(rFound)
' Loop till all matching cells are found
Loop While Not rFound Is Nothing And rFound.Address <> ActiveCell.Address
End If
Range("D1") = totalValue ' Show value in test cell to see if math works
End Sub
Here is a picture of the spreadsheet
Edit 1: below is the code that the user [tag:Thomas Inzina] help me come up with.
Sub FindMatchingValue()
Const AllUsedCellsColumnB = False
Dim rFound As Range, SearchRange As Range
' DOES NOT HAVE "cellValue" or "totaValue"
If AllUsedCellsColumnB Then
Set SearchRange = Range("B1", Range("B" & Rows.Count).End(xlUp))
Else
Set SearchRange = Range("B1:B30")
End If
If Intersect(SearchRange, ActiveCell) Is Nothing Then
SearchRange.Select
MsgBox "You must select a cell in the highlighted area before continuing", vbInformation, "Action Cancelled"
Exit Sub
End If
Set rFound = SearchRange.Find(What:=ActiveCell.Value, _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
SearchFormat:=False)
If Not rFound Is Nothing Then
Do
If rFound.Style.Name = "Good" Then
Range("H" & rFound.Row).Interior.Color = vbRed 'THIS IS THE MAIN CHANGE
End If
Set rFound = SearchRange.FindNext(rFound)
Loop While Not rFound Is Nothing And rFound.Address <> ActiveCell.Address
End If
End Sub
And this is a picture of what the code does.
What I want is instead of highlighting the red, is to find the sum of these red cells and the cell that is not highlighted but is original search source (cell H15), then take the sum of these and assign it to a variable such as ' totalValue'
Use the following as the section doing the math. It will add the value from the line where the find occurs (rather than the initial value) and it will also avoid counting the initial value twice if it is the only match.
' If rFound is not Nothing, then do math. If rFound is Nothing, then findnext
If Not rFound Is Nothing Then
If rFound.Address <> ActiveCell.Address Then
Do
If rFound.Style.Name = "Good" Then
totalValue = totalValue + rFound.Offset(0, 6).Value
End If
Set rFound = SearchRange.FindNext(rFound)
' Loop till all matching cells are found
Loop While Not rFound Is Nothing And rFound.Address <> ActiveCell.Address
End If
End If

VBA, goto cell with a certain value (type: date)

I have code as follow:
Sub Find_First()
Dim FindString As String
Dim Rng As Range
FindString = Range("A1")
If Trim(FindString) <> "" Then
With Sheets("Kalendarz").Range("A5:LY5")
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, True
Else
MsgBox "Nothing found"
End If
End With
End If
End Sub
but it doesn't work with date format, any suggestion?
More details: In A1 cell I will enter a date, In 5. row I have a list of every day in 2016. I want to (after run macro) go to cell with date from cell A1.
Using the Find function to locate a date is notoriously tricky in Excel VBA. The function relies on your search date being formatted in the same way as Excel's default setting. In addition, you need to ensure that the search string is converted to a date within the Find function, using CDate. Ozgrid has a good article on it: http://www.ozgrid.com/VBA/find-dates.htm
I have amended your code below to accommodate those requirements and added an extra With Sheets... statement to ensure the FindString uses the Range from your target sheet.
However, because of the unpredictability of users' adjusting date formats, I prefer a VBA loop, using Value2 which is Excel's numerical representation of the date, so cannot be fiddled with. The Ozgrid article prefers not to use VBA loops when a Find function is so much faster, but I guess it's a matter of personal preference and I feel a bespoke loop is more reliable.
Up to you which one you want to go with.
The Find method:
Sub Find_First()
Dim FindString As String
Dim Rng As Range
With Sheets("Kalendarz")
FindString = .Range("A1")
If Trim(FindString) <> "" Then
With .Range("A5:LY5")
Set Rng = .Find(What:=CDate(FindString), _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox "Nothing found"
End If
End With
End If
End With
End Sub
The VBA loop method:
Sub Find_First_VBA_Loop()
Dim dateVal As Long
Dim cell As Range
With Sheets("Kalendarz")
dateVal = .Range("A1").Value2
For Each cell In .Range("A5:LY5").Cells
If dateVal = cell.Value2 Then
Application.Goto cell, True
Exit For
End If
Next
End With
End Sub

VBA for searching string in a column and copy entire rows depending on the presence of certain string at adjacent cell

I am completely new for VBA.
I have excel data sheet containing numbers and strings. I want to search for certain string say 'CYP' in column I then look for a cell of its row at column C and copy entire rows containing the string of cell C. I want to paste in sheet 2 of the same workbook and loop it again to look for remaining CYPs in column.
Would you help me on this please?
After the suggestion from pnuts, here is my macro code
Sub Macro1()
'
' Macro1 Macro
'
'
Columns("I:I").Select
Range("I729").Activate
Selection.Find(What:="cyp", After:=ActiveCell, LookIn:=xlValues, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveWindow.SmallScroll Down:=5
Range("C749").Select
Selection.Copy
Columns("C:C").Select
Range("C734").Activate
Selection.Find(What:="EPT001TT0601C000151", After:=ActiveCell, LookIn:= _
xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext _
, MatchCase:=False, SearchFormat:=False).Activate
Rows("746:750").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet2").Select
ActiveSheet.Paste
End Sub
In this code the CYP was found in I749, cell C749 was copied as string and first row in column C containing the same string was searched followed by copying of the entire row and 4 more followed by it then pasting in sheet2 of the same workbook.
What I wanted was to loop this action again and again upto the end of column I and repeat the same action.
Thank you!
I managed to solve the problem with the help of Trebor76 at Excelforum. Here I am giving solution in that way it might be helpful for some newbies like myself with similar problem.
Option Explicit
Sub Macro1()
'Written and assisted by Trebor76
'Copy an entire row from Sheet1 to Sheet2 for each unique matching item in Col. C if the text in Col. I contains the text 'CYP' (case sensitive)
'http://www.excelforum.com/excel-programming-vba-macros/962511-vba-for-searching-string-in-a-column-and-copy-rows-depending-on-string-in-adjacent-cell.html
Dim rngCell As Range
Dim objMyUniqueArray As Object
Dim lngMyArrayCounter As Long
Dim lngMyRow As Long
Dim varMyItem As Variant
Application.ScreenUpdating = False
Set objMyUniqueArray = CreateObject("Scripting.Dictionary")
For Each rngCell In Sheets("Sheet1").Range("I1:I" & Sheets("Sheet1").Range("I" & Rows.Count).End(xlUp).Row)
If InStr(rngCell, "CYP") > 0 Then
If Not objMyUniqueArray.Exists(Trim(Cells(rngCell.Row, "C"))) Then
lngMyArrayCounter = lngMyArrayCounter + 1
objMyUniqueArray.Add (Trim(Cells(rngCell.Row, "C"))), lngMyArrayCounter
varMyItem = Sheets("Sheet1").Cells(rngCell.Row, "C")
For lngMyRow = 1 To Sheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row
If Sheets("Sheet1").Cells(lngMyRow, "C") = varMyItem Then
Rows(lngMyRow).Copy Destination:=Sheets("Sheet2").Range("A" & Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1)
End If
Next lngMyRow
End If
End If
Next rngCell
Set objMyUniqueArray = Nothing
Application.ScreenUpdating = True
MsgBox "All applicable rows have been copied.", vbInformation
End Sub
Cheers!