Excel VBA Search Button - vba

I am trying to use a text box and command button to search my entire workbook for a specific word or value. For example, "3132" or "Work Instructions". So far I am able to search the sheet that I am on but I cannot search the rest of the workbook. Plus, some of the worksheets are hidden. Any insight to this would be beneficial and help me out a ton! I have listed my currect program below:
Private Sub CommandButton6_Click()
Dim strFindWhat As String
strFindWhat = TextBox1.Text
On Error GoTo ErrorMessage
Cells.Find(What:=strFindWhat, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False).Select
Exit Sub
ErrorMessage:
MsgBox ("The data you are searching for does not exist")
End Sub
Have a good one!

Try something like this, which uses FindNext method while looping over the Sheets in the Workbook.
Sub FindLoopSheets()
Dim srchString$
Dim w As Integer
Dim wsName As String
Dim rng As Range
Dim fndRange As Range
Dim nxtRange As Range
srchString = Application.InputBox("Enter the value to search for", "Search Query")
If srchString = vbNullString Then
MsgBox "No value entered.", vbInformation
Exit Sub
End If
For w = 1 To Sheets.Count
With Sheets(w)
wsName = .Name
Debug.Print "Beginning search on " & wsName
Set rng = .Cells.Find(What:=srchString, After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False)
If Not rng Is Nothing Then
Set fndRange = rng
Do
Set nxtRange = .Cells.FindNext(After:=fndRange)
Debug.Print Sheets(w).Name & "!" & nxtRange.Address
Set fndRange = nxtRange
Loop Until fndRange.Address = rng.Address
Else:
Debug.Print srchString & " was not found on " & wsName
End If
End With
Next w
End Sub

You need to loop through the array of worksheet objects in the workbook.worksheets collection.

Related

Transfer macro to UDF

I want the macro below transferred to a UDF but I do not know how.
I want a udf where I select the Findstring and return it in the cell where is place the udf.
Can someone help me?
Sub Find_pipe()
Dim Findstring As String
Dim Location As String
Dim Rng As Range
Sub Find_First()
Dim Findstring As String
Dim Rng As Range
Findstring = InputBox("vul naam van leiding in")
If Trim(Findstring) <> "" Then
With Sheets("scenario 1V2").Range("A1:BP150")
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.Offset(1), True
Application.Goto ThisWorkbook.Worksheets("D en L berekening").Range("A1"), True
ThisWorkbook.Worksheets("D en L berekening").Range("U10").Value = Rng.Offset(1).Value
Else
MsgBox "Nothing found"
End If
End With
End If
End Sub
Try this:
Function FindPipe(Findstring As String)
Application.Volatile 'You need this if your UDF needs to update after changes in
' the search range
Dim f As Range
If Trim(Findstring) <> "" Then
With ThisWorkbook.Sheets("scenario 1V2").Range("A1:BP150")
Set f = .Find(What:=Findstring, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
End With
If Not f Is Nothing Then
FindPipe = f.Offset(1).Value
Else
FindPipe = "Not found"
End If
Else
FindPipe = ""
End If
End Function
Note the range to be searched is hard-coded in the UDF, so Excel doesn't know to recalculate your UDF if the search range is updated. I added Application.Volatile to take care of that but it may slow your workbook if you have a lot of formulas pointing to that UDF.

VBA delete spaces within a string

I want to be able to delete all of the spaces from a group of cells so that the cell contents result in just being a string of information that I want. I have come up with a code but it doesn't work and I can't figure out whether I have to use a replace function or not
My code is:
Sub Tester()
Dim SearchString As String
Dim cell As Range
Dim LastRowSource As Long
Dim ws1 As Worksheet
Set ws1 = ActiveWorkbook.ActiveSheet
SearchString = " " 'look for strings containing ( )
With ws1
LastRowSource = .Cells.Find(" ", [B2], , , xlByRows, xlPrevious).Row
For Each cell In .Range("B2:B" & LastRowSource)
If InStr(cell.Value, SearchString) > 0 Then
cell.Value = Replace(" ", "")
End If
Next cell
End Sub
If you need to do this programmatically then, recording a Macro using the Replace dialog generates this code:
Sub Macro1()
Selection.Replace What:=" ", Replacement:="", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End Sub
Substitute your range for Selection. You do not need to iterate each cell.
You don't need to loop:
With ws1
.Range("B2", .Cells(.rows.count, "B").End(xlUp)).Replace " ", vbnullstring, xlpart
End With
Try like this:
LastRowSource = 10000.
If it works, then the problem is the way you are setting the last row. Thus, add the LastRow() function to your code, it should work:
LastRowSource = LastRow ws1
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
Function from here - https://www.rondebruin.nl/win/s9/win005.htm

How to select a date with a set cell color in Excel?

I am trying to create a macro in excel VBA, that searches the Range (B1:B30) of the value of the ActiveCell in Column “B” by a loop. Along with the search of Column, I also want to check if the date’s cell is colored with a particular color. If the date's cell equals the set color "Good", then I want it to change the color of the cell in Column H of the same row as selected to red.
When I run the code, I get an error message of “Run-time error ‘424’: Object required.” When I go to debug the problem, it highlights the .Find function I have and points to the last line of the search which is “SearchFormat:=False).Activate” What should I do to fix this problem?
Any improvement with my overall code will be very much appreciated.
Sub Find()
Dim FirstAddress As String
Dim MySearch As Variant
Dim Rng As Range
Dim I As Long
MySearch = Array(ActiveCell)
With Sheets("Sheet1").Range("B1:B30")
For I = LBound(MySearch) To UBound(MySearch)
Set Rng = .Find(What:=MySearch(I), _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
SearchFormat:=False).Activate
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
If ActiveCell.Style.Name = "Good" Then
Rng("H" & ActiveCell.Row).Select
Rng.Interior.ColorIndex = xlColorIndexRed
End If
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
End Sub
Showing the Debug mode of the run-time error.
Screenshot of the Spreadsheet for reference
Code Review:
You have several problems here.
MySearch = Array(ActiveCell) will always be a single value. So why bother looping through it
You cannot set a range to equal range.activate. Searching Sheets("Sheet1").Range("B1:B30") implies that you are searching a worksheet other that the ActiveSheet. If this is the case than .Find(After:=Activecell) suggests that you are looking for a value after the ActiveCell of another worksheet.
Set Rng = .Find(What:=MySearch(I), _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
SearchFormat:=False).Activate
Rng("H" & ActiveCell.Row) Rng is a Range object. It doesn't work like Range. You cannot pass it a cell address. You can do this Rng(1,"H") which is really shorthand for Rng.cells(1,"H") bit that is misleading because Rng is in column 2 Rng(1,"H") will reference the value in column I.
Sub Find()
Dim FirstAddress As String
Dim MySearch As Variant
Dim Rng As Range
Dim I As Long
MySearch = ActiveCell 'This is the ActiveCell of the ActiveSheet not necessarily Sheets("Sheet1")
With Sheets("Sheet1").Range("B1:B30")
Set Rng = .Find(What:=MySearch, _
After:=.Range("B1"), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
SearchFormat:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
If Rng.Style.Name = "Good" Then
.Range("H" & Rng.Row).Interior.ColorIndex = xlColorIndexRed
End If
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
End With
End Sub
UPDATE:
Here is the actual answer to your question:
Sub FindMatchingValue()
Const AllUsedCellsColumnB = False
Dim rFound As Range, SearchRange As Range
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
End If
Set rFound = SearchRange.FindNext(rFound)
Loop While Not rFound Is Nothing And rFound.Address <> ActiveCell.Address
End If
End Sub
You can't put Activate at the end of the findthe way you are trying to do.
Try this as you find statement.
Set Rng = .Find(What:=MySearch(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
Rng.Activate
Then if you want to Activate the range, do that. But, it is best to stay away from Select, Activate etc in VBA code. I strongly suggest not using that last line of code and adjust you code to not rely on Select and Activate.
you may want to consider an Autofilter approach so as to loop only through relevant cells, as follows:
Option Explicit
Sub Find()
Dim cell As Range
With Sheets("Sheet1").Range("B1:B30")
.Rows(1).Insert '<--| insert a dummy header cell to exploit Autofilter. it'll be removed by the end
With .Offset(-1).Resize(.Rows.Count + 1) '<--| consider the range expanded up to the dummy header cell
.Rows(1) = "header" '<--| give the dummy header cell a dummy name
.AutoFilter field:=1, Criteria1:=ActiveCell '<--| filter range on the wanted criteria
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if any cell other than "header" one has been filtered...
For Each cell In .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) '<--| ... loop through filtered cells only
If cell.Style.Name = "Good" Then cell.Offset(, 6).Interior.ColorIndex = 3 '<--| ... and color only properly styled cells
Next cell
End If
.AutoFilter '<--| .. show all rows back...
End With
.Offset(-1).Resize(1).Delete '<--|delete dummy header cell
End With
End Sub

Using VBA to assign a criterion for average.ifs()

I use the following formula in excel
=AVERAGEIFS(B4:B440;A4:A440;"<"&A441;A4:A440;">"&EDATE(A441;-6))
to get the average of a range of values, based on the values in an adjacent column. However I need to apply this formula for more than a thousand dates (column A contains dates). I have a macro, which asks the user to specify sheet name and date (using dialog boxes). So I would like to add some code, that takes the date specified by the user and replaces cell A441 from the above formula with it. Then copy the average, so that I can paste it where desired. Here is what I tried coding so far, with no success:
Sub Find()
Dim FindString As Date
Dim Sumact As Range
Dim Analyst As Double
Dim shname As String
Do Until WorksheetExists(shname)
shname = InputBox("Enter sheet name")
If Not WorksheetExists(shname) Then MsgBox shname & " doesn't exist!", vbExclamation
Loop
Sheets(shname).Select
FindString = InputBox("Enter a Search value")
If Trim(FindString) <> "" Then
With Sheets(shname).Range("A:A")
Set Sumact = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Sumact Is Nothing Then
Application.Goto Sumact, True
Else
MsgBox "Nothing found"
End If
End With
End If
Set Analyst = Application.AverageIf(Range(("B:B"), ("A:A")), "<Sumact")
Selection.Copy
End Sub
You do not Set a variable unless you are setting an object like the cell returned by the Range.Find method. Assigning a double to a var should be simply equal (e.g. =).
Sub Make_AVERAGEIFS()
Dim FindString As Date
Dim Sumact As Range
Dim Analyst As Double
Dim shname As String
Dim d As Integer, m As Integer, y As Integer
Do Until WorksheetExists(shname)
shname = InputBox("Enter sheet name")
If Not WorksheetExists(shname) Then MsgBox shname & " doesn't exist!", vbExclamation
Loop
With worksSheets(shname)
.Activate
FindString = InputBox("Enter a Search value")
If Trim(FindString) <> "" Then
With .Range("A:A")
Set Sumact = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Sumact Is Nothing Then
Application.Goto Sumact, True
Else
MsgBox "Nothing found"
End If
End With
End If
If IsDate(Sumact) Then
d = Day(Sumact): m = Month(Sumact): y = Year(Sumact)
Analyst = Application.AverageIfs(.Columns(2), _
.Columns(1), "<" & DateSerial(y, m, d), _
.Columns(1), ">" & DateSerial(y, m - 6, d))
End If
End With
Selection.Copy
End Sub
I suppose that searching for the date in column A is one way to check that the user has input a valid date but there must be other, less complicated methods. The IsDate Function that I have used above is one.

How can i find a value in another sheet in Excel and in the active sheet using a form?

Well, here is my problem so far, i have a form in VB in this form the user put a number what i want to do is that excel search in Sheet2 If i get this number (if is buyed), and in the active sheet "Data" if is already captured, finally put it in the last empty A row in Sheet1.
I have this so far.
Private Sub CommandButton1_Click()
Me.TextBox1.Text = ""
Me.TextBox2.Text = ""
End Sub
Private Sub CommandButton2_Click()
Dim lastrow As Double
Dim frange As Range
lastrow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count
If TextBox1.Text = TextBox2.Text Then
Sheets("Sheet2").Activate
ActiveSheet.Range("A2").Select
If Range("A2:A200").Find(What:=TextBox2.Value _
, After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False).Activate Then
Sheets("Datos").Activate
If Range("A3:A200").Find(What:=TextBox2.Value _
, After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False).Activate Then
MsgBox ("This number is already registred")
Else
Cells(lastrow + 1, 1) = TextBox2.Value
End If
Else
MsgBox ("The number has not been buyed")
End If
Else
MsgBox ("The number are not the same")
End If
End Sub
I really hope someone you can help me because i am stuck and i do not see the answer.
Thanks
Sorry for my english
UNTESTED
Please see if this is what you are trying?
Private Sub CommandButton1_Click()
Me.TextBox1.Text = "": Me.TextBox2.Text = ""
End Sub
Private Sub CommandButton2_Click()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim aCell As Range, bCell As Range
Dim lrow As Long
Set ws1 = Sheets("Datos"): Set ws2 = Sheets("Sheet2")
If TextBox1.Text = TextBox2.Text Then
Set aCell = ws2.Columns(1).Find(What:=TextBox2.Value _
, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not aCell Is Nothing Then
Set bCell = ws1.Columns(1).Find(What:=TextBox2.Value _
, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not bCell Is Nothing Then
MsgBox ("This number is already registred")
Else
'~~> This will write to sheet "Datos". if you want to
'~~> write to sheet Sheet2 then change ws1 to ws2 below
With ws1
lrow = ws1.Range("A" & .Rows.Count).End(xlUp).Row + 1
.Cells(lrow, 1) = TextBox2.Value
End With
End If
Else
MsgBox ("The number has not been buyed")
End If
Else
MsgBox ("The number are not the same")
End If
End Sub