Macro search in a range of cells - vba

Want to write a Macro that would search for a particular word in a range of cells (or after a cell), let's say "hello" in our case. Suppose my spreadsheet looks like this:
Hello user
Hello Nancy
Hello count 2
The content of the spread sheet change daily, so that I may have different number of 'Hello's everyday. I want to copy the number (2) beside the last 'Hello' to another cell. If the word count of hello doesn't exits, it will put 0 in that cell(Note that even if the word count is 0, there might still be 'hello' in this spread sheet). The location of the last Hello will always be after Cell A17.
I was thinking about setting the parameter After to cell A17, and change SearchOrder to xlByColumns, but When the search reaches the end of the search range, it wraps around to the beginning of the range.
How should I stop the search when this wraparound occurs?
I also try to use the Find method within With to search within range A17 to B22:
With Sheets("Data").Range("A17:B22")
Set hello = Cells.Find(What:="hello", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
End With
If Not hello Is Nothing Then
With Sheets("Data").Range("A17:B22")
Cells.Find(What:="Hello", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Offset(0, 1).Range("A1").Select
Application.CutCopyMode = False
Selection.Copy
Range("B17").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End With
Else
Range("B17").Select
ActiveCell.FormulaR1C1 = "0"
End If
But it will still locate the search to the first 'Hello' in the spreadsheet.

Try This:
Function GetLastNumber(TheRange As Range, TheWord As String) As Variant
Dim Finder
'You can add LookAt:=xlWhole if you want entire word only
Set Finder = TheRange.Find(TheWord, SearchDirection:=xlPrevious)
If Finder Is Nothing Then
GetLastNumber = CVErr(xlErrNA)
Else
'Return the value of the cell one column to the right of our search word
GetLastNumber = Finder.Offset(0, 1).Value
End If
End Function
You can use it like this:
Sub Test()
Range("D1") = GetLastNumber(Range("A1:A11"), "Hello")
End Sub
You can also use it as a formula:
=GetLastNumber(A1:A11,"Hello")
Results:

Related

Excel macro paste same value in ctrl+f box although different cell value

New to forum and vba but want to learn more.
Got two tables of large data and want to look for a cell value equal to the cell value to the left of my active cell in table 1 and then find that value in the 2nd table. When value is found I want to return the cell value found in the 5th column to the right of column A in the 2nd table.
The macro I have created works well - if it hadn't been that it always looks for the same value "10.136.32.10" i.e. this value does not change as the active cell moves down table 1. I would like the value to change depending on what is actually copied from the cell to the left. Is there a way to do this? I use Ctrl+f function and then paste in the cell value copied from table 1
Have the following macro:
Sub Makro2()
'
' Makro2 Makro
'
'
ActiveCell.Offset(0, -1).Range("A1").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("SKF-NOV-6-2017").Select
Cells.Find(What:="10.136.32.10", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Selection.End(xlToLeft).Select
ActiveCell.Offset(0, 4).Range("A1").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("All Equipment").Select
ActiveCell.Offset(0, 1).Range("A1").Select
ActiveSheet.Paste
ActiveCell.Offset(1, 0).Range("A1").Select
End Sub
Here is the code by which you can do your job. This macro searches immediately on all rows. If you only need to search for an active cell, then you need to remove the loop.
Sub macro2()
Dim lr As Long, r As Long, c As Long
Dim str As String
lr = Cells(Rows.Count, 1).End(xlUp).Row
For r = 1 To lr
str = Cells(r, c).Offset(0, -1)
Sheets("SKF-NOV-6-2017").Select
Cells.Find(What:=str, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Selection.End(xlToLeft).Select
ActiveCell.Offset(0, 4).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("All Equipment").Select
Cells(r, c + 1).past
Next r
End Sub

VBA: Pasting clipboard data into the "Find" feature

I'm an IT noob and have been tasked with creating an Excel macro that will cross-reference an employee number from one sheet to another. After finding a matching employee number it needs to copy the info from that employee (Name,etc) and finally take it to the result page and paste the info.
This is my first time making a VBA macro, or programming in general so bear with me.
Sub Macro2()
'
' Macro2 Macro
' 1st attempt
'
Dim DataObj As New MSForms.DataObject
Dim S As String
DataObj.GetFromClipboard
S = DataObj.GetText
For x = 1 To 10
Sheets("ad").Select
Cells(11 + x, 7).Select
Selection.Copy
Sheets("sp").Select
Cells.Find(What:=S, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveCell.Offset(0, -1).Range("Table_GetJobs4[#Headers]").Select
ActiveCell.Offset(0, 1).Range("Table_GetJobs4[[#Headers],[Company_Code]]"). _
Activate
Application.CutCopyMode = False
Selection.Copy
Sheets("adtospresult").Select
ActiveCell.Offset(0, -2).Range("A1").Select
Cells.Find(What:="33620", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveCell.Offset(0 + x, -9).Range("A1").Select
ActiveSheet.Paste
ActiveCell.Offset(0, 2).Range("A1").Select
Next x
End Sub
Quite simply, I haven't been able to get the clipboard to find function to work. Any help/directions would be much appreciated, thanks.
Instead of trying to pass the clipboard information to s you could just pass the value of the range to S like this:
s = Cells(11 + x, 7).Value
and when you copy it to the other worksheet reverse it.
some_range = s
Also you don't need to select any worksheets or cells this would be completely valid:
Sheets("sp").found_range = Sheets("ad").Cells(11 + x, 7).Value
Found range would be the range in the other sheet that you want to paste the first sheet's value.
FYI, http://www.techrepublic.com/blog/software-engineer/train-users-to-follow-best-practices-when-writing-vba-code/ This would be helpful to read over to learn best practices for writing code. It'll save you in the future when you have to go back and try to decipher what you were doing in you code later down the road.

Need to copy one worksheet to another based on header info that includes blank cells

I'm trying to copy specific columns from one worksheet to another worksheet to make it uniform so I can easily sort and slice the data in other worksheets. I'm having trouble with some columns copying the entire column including blanks. I am searching the header for specific phrases, selecting the entire column (except the header), and copy/pasting to the other worksheet. The problem arises when I get to a column that has blanks - the xlDown feature stops at the blank cell, but if I use xlCellTypeLastCell it selects all of the columns to the right of the column that I want to copy, so I end up overwriting other cells in my other worksheet. Here is a sample of the code I'm using:
' Copy Potential Name
Cells.Find(What:="Potential* Name", After:=ActiveCell, LookIn:=xlFormulas _
, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Range(Selection.Offset(1, 0), Cells.SpecialCells(xlCellTypeLastCell)).Select
Selection.Copy
Sheets("Formatted Sheet").Select
Range("B2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Sheet5").Select
Application.CutCopyMode = False
If I try using a LastRow function; e.g.
LastRow = Sheets("Sheet5").UsedRange.Rows.Count
I can't get it to select the column - it returns an error when I use
Range(Selection.Offset(1, 0), LastRow).Select
Please help!
Thanks in advance
Safer to use End(xlUp) from the bottom of the sheet:
Dim f As Range, rng As Range
Set f = Cells.Find(What:="Potential* Name", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not f Is Nothing Then
With f.Parent
Set rng = .Range(f.Offset(1, 0), .Cells(.Rows.Count, f.Column).End(xlUp))
End With
rng.Copy
Sheets("Formatted Sheet").Range("B2").PasteSpecial Paste:=xlPasteValues, _
Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Else
MsgBox "header not found!"
End If
Sheets("Sheet5").Select
Application.CutCopyMode = False

Excel VBA with multiple search criteria and loop until all distinct results are found

I'm very new to VBA and have an extremely short deadline, so I apologize if I'm not following all forum guidelines. I'd be greatful for any help you can provide!
Goal:
Search Sheet1 for keywords (Activity:, Site Address:, Description:, Owner:, Valuation:, Sub Type: and DATE_B:)
Once keyword is found, offset (0,1)
Copy value
On Sheet2, label columns as such: Permit_Type, Permit_Date, Permit_Address, Permit_Desc, Owner and Permit_Val)
Paste copied value from Sheet1 to the appropriate columns
Repeat script until all keywords are no longer found Sheet1. In other words, continue throughout Sheet1.
What works:
Creates column names on Sheet2
Script copies and pastes the first values found
What doesn't work:
Script stops after first values are found
Known issue:
I originally had the values copied/pasted on the same Sheet1 in Range O2:U2. I'm having a hard time removing this command since I just need these values to paste on Sheet2
Data looks like this, about 100 records
Most Keywords are in Column A, then the rest in Column E - sorry I couldn't provide a better respresentation!
'Column A Column B Column C Column D Column E Column F Column G G
'Activity: B13-0217 Type: BUILD-M Sub Type: Porch Status: ISSUED
'
'Parcel: DATE_B: 09/13/2013 Sq Feet:
'Site Address: 123 Main St
'Description: Patio cover 150 sqft
'Applicant: ABC Contracting Phone: 123-456-7890
'Owner: Jane Smith Phone: 123-456-7890
'Contractor: ABC Contracting Phone: 123-456-7890
'Occupancy: Use: Class: Insp Area:
'Valuation: $3,200.00 Fees Req: $256.90 Fees Col: $256.90 Bal Due: $0.00
'Activity: B13-0224 Type: BUILD-M Sub Type: Deck Status: ISSUED
'Parcel: DATE_B: 09/27/2013 Sq Feet:
'Site Address: 234 South St
'Description: Install a 682 sqft deck on the east side of the building
'Applicant: BCA Contracting Phone: 234-567-1234
'Owner: Joe Smith Phone: 234-567-1234
'Contractor: BCA Contracting Phone: 234-567-1234
'Occupancy: Use: Class: Insp Area:
'Valuation: $28,000.00 Fees Req: $1,408.60 Fees Col: $1,408.60 Bal Due: $0.00
Below is the script I pieced together. Any help would be greatly appreciated!
Sub Lafayette_Permit_arrangement_macro()
' This Macro is intended to arrange the monthly Lafayette Permit
' data so that specific data is extracted and organized in a more
' usable format for mass import.
'Permit Number
Cells.Find(What:="Activity:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("O2").Select
ActiveSheet.Paste
'Permit Type
Cells.Find(What:="Sub Type:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("P2").Select
ActiveSheet.Paste
'Permit Issue Date
Cells.Find(What:="DATE_B:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("Q2").Select
ActiveSheet.Paste
'Permit Address
Cells.Find(What:="Site Address:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("R2").Select
ActiveSheet.Paste
'Permit Description
Cells.Find(What:="Description:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("S2").Select
ActiveSheet.Paste
'Permit Owner
Cells.Find(What:="Owner:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("T2").Select
ActiveSheet.Paste
'Permit Value
Cells.Find(What:="Valuation:", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 1).Select
Selection.Copy
Range("U2").Select
ActiveSheet.Paste
Range("O2:U2").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet2").Select
Range("A2").Select
ActiveSheet.Paste
Sheets("Sheet2").Select
Range("A1").Select
Application.CutCopyMode = False
'Add PermitNo column to Sheet2
ActiveCell.FormulaR1C1 = "Permit_No"
Range("A1").Select
'Add PermitType column to Sheet2
ActiveCell.FormulaR1C1 = "Permit_Type"
Range("B1").Select
'Add PermitDate column to Sheet2
ActiveCell.FormulaR1C1 = "Permit_Date"
Range("C1").Select
'Add PermitAdd column to Sheet2
ActiveCell.FormulaR1C1 = "Permit_Address"
Range("D1").Select
'Add PermitDesc column to Sheet2
ActiveCell.FormulaR1C1 = "Permit_Desc"
Range("E1").Select
'Add PermitOwner column to Sheet2
ActiveCell.FormulaR1C1 = "Owner"
Range("F1").Select
'Add PermitVal column to Sheet2
ActiveCell.FormulaR1C1 = "Permit_Val"
Range("G1").Select
End Sub
First off, you should almost always avoid using select; storing values in variables or setting them directly is much faster (and cleaner at times).
Secondly, Find will only return the first instance of a searched parameter. You will need to utilize a combination of FindNext and a loop to find all instance of a parameter in a given range. Given these two facts, I would update the code with the following.
Dim searchResult As Range
Dim x As Integer
x = 2
' Search for "Activity" and store in Range
Set searchResult = Cells.Find(What:="Activity:", _
LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
' Store the address of the first occurrence of this word
firstAddress = searchResult.Address
Do
' Set the value in the O column, using the row number and column number
Cells(x, 15) = searchResult.Offset(0, 1).Value
' Increase the counter to go to the next row
x = x + 1
' Find the next occurence of "Activity"
Set searchResult = Cells.FindNext(searchResult)
' Check if a value was found and that it is not the first value found
Loop While Not searchResult Is Nothing And firstAddress <> searchResult.Address
After the search is complete for "Activity", for example, you would then reset x to 2 and repeat the same steps for all your other search parameters.
As #user2140261 commented, you can take further steps to make the above into a function and then either use the function within your vba code, or directly in the spreadsheet via a formula.
UPDATE
Given your data (which you just posted), the code I shared can be made more efficient by only searching Column A, since it seems to where you are looking for the word "Activity". In VBA, you should also try to limit your declared ranges to the source of the data (in this case, Column A, A:A, or even better, A1:A5000, or however many rows of data exist)
Therefore, instead of using Cells.Find, you should use range and indicate the area to be searched, e.g. Range("A1:A5000")

vba function to copy certain value from one workbook to another

I have 2 workbooks. I need copy the row in one workbook only if it contains a certain value from another workbook. Here's my code, it works for the first i=21 and i=22 but tells me there's an error in Cells.Find when I reach i=23.
For i = 21 To 35
Windows("Run Report.xlsm").Activate
Dim strL3 As String
strL3 = Sheets("Summary").Range("A" & i).Value
Workbooks("Ace Survey - Level 1 and level 3 Trending (w Resolution) v3").Activate
Range("A1").Activate
Cells.Find(What:=strL3, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
If strL3 = "Call Disconnected" Or strL3 = "Caller Not Present" Then
ActiveCell.Offset(2, 2).Select
Else
ActiveCell.Offset(1, 2).Select
End If
Application.CutCopyMode = False
ActiveCell.Copy
Windows("Run Report.xlsm").Activate
Sheets("Summary").Select
Range("G" & i).Select
ActiveSheet.Paste
Next i
Find returns a Range object if something is found, but Nothing otherwise. You are attempting to Activate the result of using Find, even if it is Nothing - which will generate an error.
You need to store the result of your Find attempt in a Range variable, and check for Nothing.
Dim rngFound As Range
Set rngFound = Range("A1").Find(...)
If Not rngFound Is Nothing Then
' we found something!
Else
' Nothing
End If
But, as advised, you should be supplying more details for your question.