I would like to know if anyone can help me on this one.
I have a workbook with several tabs and a main page.
On the main page i have a top 20 of issues that are populated automatically.
What i want to do is to automatically create hyperlinks on the "number" row, and when i click them to search that number in the workbook and go to as well. Similar to the CTRL+F.
Number - Problem - Status
IM123
IM124
IM145
ETC..
can someone help me?
Thanks
In the Worksheet_SelectionChange event, you can use something like this to search for the data
If Not Intersect(Target, Range("A1:A4")) Is Nothing Then
If Target.Count = 1 Then
Cells.Find(What:=Target.Value, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
After:=ActiveCell, SearchFormat:=False).Activate
End If
End If
this moves to the next cell containing the same data as the cell you have clicked in, as long as you are in the specified range (A1:A4) and you have only selected one cell (Target.Count=1)
The following will search for whatever number is in the cell you have selected.
In addition to finding the first result, it will ask if you want to continue searching for the next result. That way, if you have multiple instances of an issue, you can "loop" through all of the results that are found in the worksheet. It will also ignore search results found on your MainWorksheet containing your top 20 issues. Cells.Find by itself will simply return the first result found, even if it is in the same worksheet.
It will also tell you whether or not the issue number was found in each sheet, and when all of the worksheets have been checked (in case no more results are found). If you respond that you don't want to continue searching, it will go to the first instance of the issue number that was found in the most recent worksheet that was checked.
In order to simulate a hyperlink, you need to use a worksheet event such as Intersect (described in Sean's answer) or FollowHyperlink. Personally, I prefer to use alternatives to worksheet events where possible, as they will always trigger when the condition is met, even if unintentionally. For example, you could create a shape or macro button and assign the macro to it. That way, the code will only run when the user clicks on the button.
Also, please let us know if there is more that you really want to do once you've identified the issue. For example, you could automatically make changes to related cells, or create a list of all of the instances of that issue (or all issues) that were found.
Good luck!
'Create a string variable to store the problem status
Dim StringProblemStatus As String
'Create a string variable to store the worksheet name of the main page containing the problem status
Dim StringMainWorksheet
'Create a range variable to store the results of the Find method
Dim RangeFindResults As Range
'Create an integer variable to store the current worksheet number
Dim IntegerSheetCount As Integer
'Set the variable to the problem status stored in the current cell
StringProblemStatus = Selection.Value
'Set the variable to the worksheet name containing the problem status
StringMainWorksheet = ActiveSheet.Name
'Create a For/Next loop so that the following code will evaluate all worksheets in the workbook
For IntegerSheetCount = 1 To ActiveWorkbook.Sheets.Count
Sheets(IntegerSheetCount).Activate
'Search for the problem number within the worksheet
'Check that the sheet being searched is not the MainWorksheet
If ActiveSheet.Name <> StringMainWorksheet Then
'Searches for exact matches
Set RangeFindResults = _
Cells.Find( _
What:=StringProblemStatus, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Returns a message to the user if the status is not found
If RangeFindResults Is Nothing Then
MsgBox "Problem Status " & StringProblemStatus & " was not found in worksheet " & Sheets(IntegerSheetCount).Name
Else
'Returns a message to the user if the status is found
If MsgBox("Problem Status " & RangeFindResults & " found in worksheet " & _
Sheets(IntegerSheetCount).Name & " in cell " & " " & RangeFindResults.Address & _
". Continue searching?", vbYesNo) = vbNo Then
RangeFindResults.Activate
Exit Sub
End If
End If
End If
'Move to the next worksheet
Next IntegerSheetCount
'Notify the user that all worksheets have been searched
MsgBox "All worksheets searched"
End Sub
Related
I have a working Excel sheet that when opened the user is asked to enter a product type. This is done by VBA code InputBox and places the input in cell A6 of the active sheet. I have a hidden sheet that lists all the possible types in cells A2:A160. I would like to have a way to check that what the user entered is valid and if not to try again.
This macro will search the hidden worksheet(Change Sheet2 to the hidden worksheet name). and a MsgBox. You should change ActiveSheet to the actual worksheet.
Sub FindInHiddenSht()
Dim findVal As Variant
With Sheet2 'Your hidden worksheet
Set findVal = .Cells.Find(What:=ActiveSheet.Range("A6").Value, After:=.Cells(1), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False)
End With
If findVal Is Nothing Then
MsgBox "Not Found"
Else
MsgBox "Found at " & findVal.Address
End If
End Sub
I have a tab in excel where managers can input their forecast of Holidays, Sickness, Training and other lost time for the next 4 months.
To make this smoother I've made it so they select their own name and their team shows in the table and they can input the lost days for the team.
What I'm having issues with is the code that then takes this information and copies it to another tab, and puts it in against the right employee. This data tab has every employee so it needs to search down column B for the matching name and copy the data into the corresponding columns. I've tried a few different ways but none quite do what i'm looking for
First image is the screen the manager sees to enter their forecast of lost days
second image is the screen that the data needs to be copied into the archive it for it to be used elsewhere
Hopefully this coveres my query, any help would be wonderful
Closest code I could get working below, only copies 1 value and for only 1 employee however
Sub Find_First()
Dim FindString As String
Dim Rng As Range
FindString = Sheets("Calc").Range("G7").Value
If Trim(FindString) <> "" Then
With Sheets("DATA Build").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
Sheets("Calc").Range("I31").Copy Sheets("DATA Build").Cells(Rng.Row, "BD")
Else
MsgBox "Nothing found"
End If
End With
End If
End Sub
I'm working on a database for my workplace, which is the Outreach department of a large science center. We have a lot of schools that violate our (pretty specific) contract, so we're looking to track and reduce these violations.
To cut down on misspellings that would make searching the database later more difficult, I want the user (when entering a new school) to pull up the Userform, enter the name of their school, then click a search button to populate a listbox with the names of schools that match what they entered. If they click on a school in that list, the form uses that as the school name. If not, it prompts them to enter a new school name.
My code is pretty basic right now. I'm trying to use a Find & FindNext procedure to pull up all instances of a school name, but I'm getting a Type Mismatch error (#13) with the code I have currently and I can't find where that might come from. I've checked that no variables or Userform objects are misspelled.
I want the Find function to return only the Range of the first cell, so that I can turn it into .Address or .Value as needed.
Option Explicit
Private Sub cbtnSearchSchool_Click()
Dim lrow As Long
Dim schoolmatch As Range
'defines "lrow" as the last completely empty row in the table
lrow = Cells.find(What:="", _
After:=Range("A1"), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False).Row
Range("A1").Activate
'defines "schoolmatch" variable as the first school in the list that
'matches what was entered in the text box.
Set schoolmatch = Range("SchoolName").find(What:=txtbSchoolName.Value, _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'returns value of first found cell to check for accuracy
MsgBox schoolmatch.Value
This is a photo of the Userform if anybody would like to see it.
Edit: Sorry, I actually dimensioned schoolmatch as a Range originally and just changed it to Object while I was debugging - I got the same error before and after changing it.
It shows me the line I'm getting the error on - it's the Set schoolmatch = Range.Find operation, but I can't figure out anywhere that I would be mixing up data types. I have a SchoolName range that I've double-checked, and I've checked all of the other variable names for misspellings.
Over time there will be thousands of schools on this list, so this search function is necessary to filter some results before users select a school on the form.
It looks like the use of Object may be causing the error. Also, with a slight tweak to how lRow is assigned, this should run better:
Option Explicit
Private Sub cbtnSearchSchool_Click()
Dim lrow As Long
Dim schoolmatch As Range
'defines "lrow" as the last completely empty row in the table
lrow = Range("A1").End(xlDown).Row
'defines "schoolmatch" variable as the first school in the list that
'matches what was entered in the text box.
Set schoolmatch = Range("SchoolName").find(What:=txtbSchoolName.Value, _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'returns value of first found cell to check for accuracy
MsgBox schoolmatch.Value
A note with lRow, if say cell A100 is empty but B100 isn't, it will improperly assign that row (row 100) as the last row.
If you really need to make sure this doesn't happen (same with your OP), you could loop through all rows until a blank. Like this perhaps:
lRow = 1
Do While WorksheetFunction.CountA(Rows(lRow)) <> 0
lRow = lRow + 1
Loop
Debug.print "Last row is: " & lRow
I have searched to find the answers to get to where I am but am now stuck! I am a relative beginner with VBA.
I have a Workbook that lists a few hundred orders that we are producing for our customer.
The order details are on the first sheet called "In Progress" and on the 3rd sheet called "StyleData" are more details about each product such as its composition, design reference, SKU etc...
At present my code searches column A on the Data sheet based on the 6 digit style code in the active cell on the In Progress Sheet, then goes to that cell. I have put a MsgBox in purely to put a pause in the code so I know where it has got to.
What I want it to do after finding the style code on the data sheet is return a value on the same row from column H, preferable in a format that the use can select and copy, then it will return to the original cell at the start of the macro.
Code as follows:
Sub get_composition()
Dim item_no As String
Dim data_sheet As Worksheet
Dim found_item As Range
Set Rng = ActiveCell
item_no = ActiveCell.Value
Set data_sheet = Sheets("StyleData")
If Trim(item_no) <> "" Then
With Sheets("StyleData").Range("A:A")
Set found_item = .Find(What:=item_no, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not found_item Is Nothing Then
Application.Goto found_item, True
Else
MsgBox "Nothing found"
End If
End With
End If
MsgBox "Return to Original Cell"
Application.Goto Rng
End Sub
if I understand what you want :
you arrive at cell "found_item" and want to return a value from the same row.
If it's so, you can use method Offset on "found_item"
found_item.Offset() allow you to navigate from the current range
https://msdn.microsoft.com/en-us/library/office/ff840060.aspx
If you are on column A, found_item.Offset(, 1) will return the range on the same line but column B
I have a table created in excel (named WaterTable) and have a userform which allows data to be entered into it. The columns are: YEAR, QUARTER, SOURCE, VOLUME.
Looking around on here and other locations I have managed to get sorted with code that allows users to enter data into the boxes on the form and submit - with the code adding a new row and entering their data.
However, where I am struggling is that at the moment a user could put in:
YEAR - QUARTER - SOURCE - VOLUME
2013 - 4 - MAINS - 50
And that's no problem - BUT if they enter a wrong number and want to re-enter it will just create a new line, but retain the original entry. This causes problems for presenting the data (multiple entries) and also means errors cannot be corrected. I have managed to look around and put the following code in:
Set sheet = ThisWorkbook.Worksheets("Raw Data")
Set table = sheet.ListObjects.Item("WaterTable")
Set EvalRange = table.DataBodyRange
If WorksheetFunction.CountIf(EvalRange, YearBox.Text) > 1 And WorksheetFunction.CountIf(EvalRange, QuarterBox.Text) > 1 And WorksheetFunction.CountIf(EvalRange, SourceBox.Text) > 1 Then
MsgBox "Data Entry Already Present"
Application.EnableEvents = False
Else
Call AddDataRow
End If
Which partially solves my problem - as now you can only enter one 'volume' data point for a particular year, quarter and source. Which works to an extent - but what I really want is for the message box to give option to either replace the current data OR close. So that wrongly entered data can be corrected. Unfortunately I've come across a brick wall on that one and can't think what to use!
Hope that makes sense!
AS ADDITION FOLLOWING COMMENT MADE BELOW:
I've changed to using 'find' command, and come up with the following code to start me off:
SearchString = YearBox.Value
On Error Resume Next
Set bCell = oRange.Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Offset(0, 3)
If Not bCell Is Nothing Then
MsgBox "Checking data Validity"
ReplaceData = bCell.Address
End If
Set aCell = oRange.Find(What:=SearchString, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
FoundAt = aCell.Address
Select Case MsgBox("The entered exists: " & FoundAt & " " & ReplaceData & " Replace?", vbYesNo)
Case vbNo
MsgBox "data entry cancelled"
Case vbYes
Select Case MsgBox("This will replace data: Are You Sure?", vbYesNo)
Case vbYes
bCell = VolBox.Value
Case vbNo
Call CommandButton1_Click
End Select
End Select
Else
MsgBox "Unique Data Entry Confirmed - submit data?", vbOKCancel
Call AddDataRow
End If
Not terribly elegant unfortunately (and I don't know why the first 'find' for bCell fails if the entry is not found - although the aCell which seems to be virtually the same works fine?? Hence the resume on error).
This however will only check one data point (in this case year) so I can find out if the year column matches and then make a change to the volume data if the user wants to or stop if they don't. What I can't do is use multiple criteria. I don't see a way to have 'AND' with this?
Think I might have solved it (albeit in a slightly clumsy way!)
I've added a hidden column to my table generated from data entry by:
lastRow.Cells(1, 1) = YearBox.Text & "-" & QuarterBox.Text & "-" & SourceBox.Text
This creates a row which includes the data from all three variables.
I've then modified my search string in the 'find' code I posted in my question to be the same as the above:
SearchString = YearBox.Text & "-" & QuarterBox.Text & "-" & SourceBox.Text
That way it is only searching one box, but checks all three criteria.
Thanks for the help Siddharth.