I currently use this code to search for a specific value entered by the user. However, I'd like it to test for the value if it's located within the string, for example, if the user typed "Jon" the search results could be "Jon, Jonathan, Jones" etc. I'm thinking I need to utilize the InStr function somehow, but I'm not sure how to set it up... Any help would be appreciated.
Private Sub CommandButton1_Click()
ActiveSheet.Range("H1").Select
Dim MyValue As String
MyValue = TextBox1.Value
If MyValue = "" Then
MsgBox "Please enter a sales managers name!"
TextBox1.SetFocus
Else
Application.EnableEvents = False
Worksheets("Sheet2").Activate
Range("A3:I200").Select
Selection.ClearContents
Worksheets("Sheet1").Activate
Me.Hide
Set i = Sheets("Sheet1")
Set E = Sheets("Sheet2")
Dim d
Dim j
d = 2
j = 2
Do Until IsEmpty(i.Range("A" & j))
If i.Range("A" & j) = MyValue Then
d = d + 1
E.Rows(d).Value = i.Rows(j).Value
End If
j = j + 1
Loop
Application.EnableEvents = True
Worksheets("Sheet2").Activate
ActiveSheet.Range("H1").Select
If Range("A3").Value = "" Then
MsgBox "No results were found."
Else
MsgBox "Results were found!"
End If
End If
Unload Me
End Sub
I'd use AutoFilter(), and make some little refactoring as follows:
Private Sub CommandButton1_Click()
Dim MyValue As String
MyValue = Me.TextBox1.Value
If MyValue = "" Then
MsgBox "Please enter a sales managers name!"
Me.TextBox1.SetFocus
Else
With Worksheets("Sheet1")
With .Range("A1", .Cells(.Rows.count, 1).End(xlUp))
.AutoFilter field:=1, Criteria1:=MyValue & "*"
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then
Worksheets("Sheet2").UsedRange.ClearContents
Intersect(.Parent.UsedRange, .Resize(.Rows.count - 1).Offset(1).SpecialCells(xlCellTypeVisible).EntireRow).Copy Worksheets("Sheet2").Range("A3")
MsgBox "Results were found."
Else
MsgBox "No results were found."
End If
End With
.AutoFilterMode = False
End With
Me.Hide '<--| hide the userform and move 'Unload UserformName' command to the sub that's calling the Userform
End If
End Sub
You can do this pretty easily with a regular expression in the form of something like:
(^Jon\s)|(\sJon\s)|(\sJon$)
I'd wrap it in a function to allow building the pattern dynamically from user input. This is just an example - you'd either need to do some more escaping beyond just the . or (probably better) add input restrictions on the TextBox.
'Add reference to Microsoft VBScript Regular Expressions
Private Function ContainsWord(target As String, search As String) As Boolean
Const template As String = "(^<word>\s)|(\s<word>\s)|(\s<word>$)"
Dim expression As String
expression = Replace$(template, "<word>", Replace$(search, ".", "\."))
With New RegExp
.Pattern = expression
ContainsWord = .Test(target)
End With
End Function
Sample usage:
Public Sub Example()
Debug.Print ContainsWord("foo bar baz", "bar") 'True
Debug.Print ContainsWord("foo barbaz", "bar") 'False
Debug.Print ContainsWord("foobar baz", "bar") 'False
Debug.Print ContainsWord("bar foo baz", "bar") 'True
Debug.Print ContainsWord("foo baz bar", "bar") 'True
End Sub
In your code, you'd just replace the line...
If i.Range("A" & j) = MyValue Then
...with:
If ContainsWord(i.Range("A" & j).Value, MyValue) Then
Note that since you are calling it in a loop, you'd probably want to cache the RegExp in your case though to avoid repeatedly creating it if you have a ton of cells to check.
Related
I am trying to filter my movie list. Unfortunately it doesn't work out so well yet. I found a very fast way, but this one is missing a few options.
If I read the entire column into an array and search for the individual words, it takes a relatively long time for over 2000 movies.
What I miss:
In column A I can only filter by the first word. So it only goes from the beginning of the title. For example, "F" finds all "Film*" titles.
In column B and C I would like to be able to sort "from to". So all movies after 2012 and for example all with a rating better than 7.
In column G and H I have again the problem that I can only sort from the front. So if the genre Action is in second place, I can't find it. Additional i want to find 2 genres for example:"* Crime * Action*"
What works well is that I can now already combine.
The Excel Sheet:
https://mega.nz/file/RsUXRKgD#4ba95fkQOYiteWCH8WST8AuSKZi0k6YCtkuJkOK8tQc
My Code:
'filter in row2
Private Sub Worksheet_Change(ByVal Target As Range)
Dim LR As Long
If Not Application.Intersect(Range("A2:G2"), Range(Target.Address)) Is Nothing Then
If Cells(2, 1).Value = "" And Cells(2, 2).Value = "" And Cells(2, 3).Value = "" And Cells(2, 4).Value = "" And Cells(2, 5).Value = "" And Cells(2, 6).Value = "" And Cells(2, 7).Value = "" Then
On Error Resume Next
ActiveSheet.ShowAllData
ActiveSheet.Rows.Hidden = False
Else
LR = UsedRange.Rows.Count 'includes hidden rows
Range("A1:G" & LR).AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=Range("A1:G3")
End If
End If
End Sub
Private Sub ToggleButton1_Click()
Dim Reihe As String
Reihe = "A"
If ToggleButton1.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Private Sub ToggleButton2_Click()
Dim Reihe As String
Reihe = "B"
If ToggleButton2.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Private Sub ToggleButton3_Click()
Dim Reihe As String
Reihe = "C"
If ToggleButton3.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Private Sub ToggleButton4_Click()
Dim Reihe As String
Reihe = "D"
If ToggleButton4.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Private Sub ToggleButton5_Click()
Dim Reihe As String
Reihe = "E"
If ToggleButton5.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Private Sub ToggleButton6_Click()
Dim Reihe As String
Reihe = "F"
If ToggleButton6.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Private Sub ToggleButton7_Click()
Dim Reihe As String
Reihe = "G"
If ToggleButton7.Value = False Then
Call orderXA(Reihe)
Else
Call orderXD(Reihe)
End If
End Sub
Sub orderXA(Reihe As String)
LR = UsedRange.Rows.Count 'zählt uf versteckte mit
Range("A3:H" & LR).Sort Key1:=Range(Reihe & "4"), order1:=xlAscending, Header:=xlYes
End Sub
Sub orderXD(Reihe As String)
LR = UsedRange.Rows.Count 'zählt uf versteckte mit
Range("A3:H" & LR).Sort Key1:=Range(Reihe & "4"), order1:=xlDescending, Header:=xlYes
End Sub
Why so complicated? Just put on Autofilter. You don't even need VBA for that.
Sorry for the german screenshot.
Hi I have a search form which shows a listbox of results. It starts out empty and when I conduct a search then rows are created but no data is visible. I have checked a few obvious things like color and all seem normal black font etc. If I have the worksheet with the sourcedata in view the data in the list is visible, but in everyday practice that would not be the case. I think it is conducting the search on the correct results but then displaying the equivalent rows from another worksheet. I'm just not sure how to edit the code to avoid this.
My userform code is this, I assume the problem is where it is calling the Results range but I have tried adding a worksheet reference of the source data to the start of Range.Records and that doesn't seem to help:
Option Explicit
' Display All Matches from Search in Userform ListBox
'
Dim FormEvents As Boolean
Private Sub ClearForm(Except As String)
' Clears the list box and text boxes EXCEPT the text box
' currently having data entered into it
Select Case Except
Case "srchStCat"
FormEvents = False
srchStID.Value = ""
srchStSurname.Value = ""
Results.Clear
FormEvents = True
Case "srchStID"
FormEvents = False
srchStCat.Value = ""
srchStSurname.Value = ""
Results.Clear
FormEvents = True
Case "srchStSurname"
FormEvents = False
srchStID.Value = ""
srchStCat.Value = ""
Results.Clear
FormEvents = True
Case Else
FormEvents = False
srchStCat.Value = ""
srchStID.Value = ""
srchStSurname.Value = ""
Results.Clear
FormEvents = True
End Select
End Sub
Private Sub CmdClear_Click()
ClearForm ("")
End Sub
Private Sub CmdClose_Click()
Me.Hide
End Sub
Private Sub srchStCat_Change()
If FormEvents Then ClearForm ("srchStCat")
End Sub
Private Sub srchStID_Change()
If FormEvents Then ClearForm ("srchStID")
End Sub
Private Sub srchStSurname_Change()
If FormEvents Then ClearForm ("srchStSurname")
End Sub
Private Sub CmdSearch_Click()
Dim SearchTerm As String
Dim SearchColumn As String
Dim RecordRange As Range
Dim FirstAddress As String
Dim FirstCell As Range
Dim RowCount As Integer
' Display an error if no search term is entered
If srchStCat.Value = "" And srchStID.Value = "" And srchStSurname.Value = "" Then
MsgBox "No search term specified", vbCritical + vbOKOnly
Exit Sub
End If
' Work out what is being searched for
If srchStCat.Value <> "" Then
SearchTerm = srchStCat.Value
SearchColumn = "Current Role"
End If
If srchStID.Value <> "" Then
SearchTerm = srchStID.Value
SearchColumn = "ID Token"
End If
If srchStSurname.Value <> "" Then
SearchTerm = srchStSurname.Value
SearchColumn = "Surname"
End If
Results.Clear
' Only search in the relevant table column i.e. if somone is searching srchStSurname
' only search in the srchStSurname column
With Worksheets("Staff").Range("StaffFullData[" & SearchColumn & "]")
' Find the first match
Set RecordRange = .Find(SearchTerm, LookIn:=xlValues)
' If a match has been found
If Not RecordRange Is Nothing Then
FirstAddress = RecordRange.Address
RowCount = 0
Do
' Set the first cell in the row of the matching value
Set FirstCell = Range("A" & RecordRange.Row)
' Add matching record to List Box
Results.AddItem
Results.List(RowCount, 0) = FirstCell(1, 2)
Results.List(RowCount, 1) = FirstCell(1, 7)
Results.List(RowCount, 2) = FirstCell(1, 5)
Results.List(RowCount, 3) = FirstCell(1, 18)
RowCount = RowCount + 1
' Look for next match
Set RecordRange = .FindNext(RecordRange)
' When no further matches are found, exit the sub
If RecordRange Is Nothing Then
Exit Sub
End If
' Keep looking while unique matches are found
Loop While RecordRange.Address <> FirstAddress
Else
' If you get here, no matches were found
Results.AddItem
Results.List(RowCount, 0) = "Nothing Found"
End If
End With
End Sub
Private Sub UserForm_Initialize()
FormEvents = True
End Sub
Private Sub Results_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim i As Long
With Me.Results
For i = 0 To .ListCount - 1
If .Selected(i) Then
Me.TextBoxGetStaffFName.Value = .List(i, 1)
Me.TextBoxGetStaffSurname.Value = .List(i, 2)
Me.TextBoxGetStaffID.Value = .List(i, 0)
Exit For
End If
Next
End With
End Sub
Ok just figured out I need to specify the sheet in two places not just one. I needed to edit this section where asterixed
*With Sheet11.Range("StaffFullData[" & SearchColumn & "]")*
' Find the first match
Set RecordRange = .Find(SearchTerm, LookIn:=xlValues)
' If a match has been found
If Not RecordRange Is Nothing Then
*FirstAddress = Sheet11.RecordRange.Address*
Got the solution:
Use
Range.Address(,,,1) to get the full address
I have a Userform with a listbox for which I am using conditional logic to determine output values to the sheet of selected or non-selected items in the listbox. The issue is that when the Textbox (Tbl_AliasName) is blank, the code executes this:
ElseIf .Selected(k) = True And Tbl_AliasName = vbNullString Then
lstbxRow = lstbxRow + 1
Worksheets("New TRAX").Cells(lstbxRow, 3) = Trim(Cells(2, 1).Value2) & "." & .Column(1, k)
But if Tbl_AliasName is not blank then the code does nothing, but it is supposed to do this:
ElseIf .Selected(k) = True And Tbl_AliasName <> vbNullString Then
lstbxRow = lstbxRow + 1
Worksheets("New TRAX").Cells(lstbxRow, 3) = Tbl_AliasName & "." & .Column(1, k)
I have used several variations of If statements, and non of which have worked.
Below is My Code:
Option Explicit
Public Tbl_AliasName As String
Tbl_AliasName = Trim(UserForm_Finder.txtConcat.Value)
Private Sub BtnConcat_Click()
Dim k As Long, lstbxRow As Long, LR As Long
lstbxRow = 1
'****************
'This if statement works perfectly
If (Cells(2, 1).Value2 = vbNullString Or Cells(2, 2).Value2 = vbNullString) _
And Tbl_AliasName = vbNullString Then
MsgBox "You must Search for a Table or Column first.", _
vbExclamation, "Error Encountered"
Exit Sub
ElseIf (UserForm_Finder.ListBx_TblsCols.ListCount = 0 And Tbl_AliasName <> vbNullString) Then
MsgBox "You must Search for a Table or Column first.", _
vbExclamation, "Error Encountered"
'(Cells(2, 1).Value2 = vbNullString Or Cells(2, 2).Value2 = vbNullString) And _
Exit Sub
End If
With UserForm_Finder.ListBx_TblsCols
For k = 0 To .ListCount - 1
'****************
This is where the problems begin
If .Selected(k) = False Then
MsgBox "You must Select 1 or more items from the list box.", _
vbExclamation, "Error Encountered"
Exit Sub
ElseIf .Selected(k) = True And Tbl_AliasName <> vbNullString Then
lstbxRow = lstbxRow + 1
Worksheets("New TRAX").Cells(lstbxRow, 3) = Tbl_AliasName & "." & .Column(1, k)
ElseIf .Selected(k) = True And Tbl_AliasName = vbNullString Then
lstbxRow = lstbxRow + 1
Worksheets("New TRAX").Cells(lstbxRow, 3) = Trim(Cells(2, 1).Value2) & "." & .Column(1, k)
End If
Next k
End With
End Sub
My goal is to do the following:
If a Textbox (Tbl_AliasName) is not blank and the user has selected one or more items in the listbox (ListBx_TbleCols) then concatenate the Tbl_AliasName to the selected items in the listbox
If Tbl_AliasName is blank, then use the value in Cells(2,1) to concatenate to the selected Items in the list box.
I have tried the following additions:
Dim LstBxItemSelected As Boolean
'This was placed in the for loop
LstBxItemSelected = True
'this was placed outside the for loop
If LstBxItemSelected = False Then
MsgBox "You must Select 1 or more items from the list box.", _
vbExclamation, "Error Encountered"
Exit Sub
End If
Is there a better way to tell if items are selected, because I feel that the way I have it structured in my loop, the code will throw the error if everything isn't selected? Thank you in advance for any ideas, answers, or suggestions!
Note: The Listbox is populated by the click of another button on the userform which calls the following sub:
Sub FillLstBxCols()
Dim ListBx_Target As MSForms.ListBox
Dim rngSource As Range
Dim LR As Long
If Cells(2, 1).Value2 <> vbNullString Then
LR = Worksheets("New TRAX").Cells(Rows.Count, 2).End(xlUp).Row
'Set reference to the range of data to be filled
Set rngSource = Worksheets("New Trax").Range("A" & 2 & ":" & "B" & LR)
'Fill the listbox
Set ListBx_Target = UserForm_Finder.ListBx_TblsCols
With ListBx_Target
.RowSource = rngSource.Address
End With
End If
End Sub
Hard to say without sample data and expected results, but I think this is what you're looking for:
Private Sub btnConcat_Click()
Dim ws As Worksheet
Dim bSelected As Boolean
Dim sConcat As String
Dim i As Long, lRowIndex As Long
Set ws = ActiveWorkbook.Sheets("New TRAX")
lRowIndex = 1
bSelected = False
sConcat = Trim(Me.txtConcat.Text)
If Len(sConcat) = 0 Then sConcat = Trim(ws.Cells(2, "A").Value)
If Len(sConcat) = 0 Then
MsgBox "You must Search for a Table or Column first.", vbExclamation, "Error Encountered"
Exit Sub
End If
For i = 0 To Me.ListBx_TblsCols.ListCount - 1
If Me.ListBx_TblsCols.Selected(i) Then
If bSelected = False Then
bSelected = True
ws.Range("C2", ws.Cells(ws.Rows.Count, "C")).Clear 'clear previous concat results (delete this line if not needed)
End If
lRowIndex = lRowIndex + 1
ws.Cells(lRowIndex, "C").Value = sConcat & "." & Me.ListBx_TblsCols.List(i)
End If
Next i
If bSelected = False Then MsgBox "Must select at least one item from the list"
End Sub
I have tried this code which works fine for a cell that only contain number:
Sub IncreaseCellValue()
'Add 1 to the existing cell value
Range("A1").Value = Range("A1") + 1
End Sub
How can I do something similar if the cell has text and a number. For example, I have "Apple 1" and I want to "increase" the cell text to "Apple 2" and next time I run the macro I want "Apple 3".
Here's another way you could solve this problem:
Sub IncreaseCellValue()
Dim value As Variant
'Add 1 to the existing cell value
If IsNumeric(Range("A1").value) Then
Range("A1").value = Range("A1") + 1
Else
value = Split(Range("A1").value, " ")
Range("A1").value = value(0) & " " & (CInt(value(1)) + 1)
End If
End Sub
It will cover the 2 cases you presented in your question but not every scenario you could throw at it.
Try using the following function
Sub IncreaseCellValue()
'Add 1 to the existing cell value
Range("A1").Value = Replace(Range("A1").Value2, CleanString(Range("A1")), vbNullString) & CInt(CleanString(Range("A1").Value2)) + 1
End Sub
Function CleanString(strIn As String) As String
Dim objRegex
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.Global = True
.Pattern = "[^\d]+"
CleanString = .Replace(strIn, vbNullString)
End With
End Function
please check:
Option Explicit
Sub IncreaseCellValue()
'Add 1 to the existing cell value
Dim rg As Range
Set rg = Cells(Rows.Count, "A").End(xlUp)
Range("A1" & ":" & rg.Address).AutoFill Destination:=Range("A1" & ":" & rg.Offset(1, 0).Address), Type:=xlFillDefault
End Sub
Or you may try something like this...
Function GetNumber(ByVal rng As Range) As Long
Dim i As Long
For i = Len(rng.Value) To 1 Step -1
If IsNumeric(Mid(rng.Value, i, 1)) Then
GetNumber = GetNumber & Mid(rng.Value, i, 1)
Else
Exit For
End If
Next i
End Function
Sub IncrementNumber()
Dim num As Long
num = GetNumber(Range("A1"))
Range("A1").Value = Replace(Range("A1").Value, num, num + 1)
End Sub
I have a macro which is searching 3 worksheets for an invoice number that a user might enter (in total over 2.6 million records).
The numbers come in a single cell which also has a look up reference in it. form: invoicenumber, reference_letter.
Originally, that was fine because invoice numbers were 10 digits. Now they can be anything, but there is always a comma at the end, before single char reference.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address <> "$A$5" Then Exit Sub
If Target.Value = "" Then Exit Sub
Application.EnableEvents = False
Range("B5") = ""
For Each sh In Sheets
If sh.Name = ActiveSheet.Name Then GoTo 111
sh.Range("B1").FormulaArray = "=IFERROR(MATCH(Main!A5,LEFT(A:A,10),0),"""")"
If sh.Range("B1") <> "" Then
x = sh.Range("B1")
Range("B5") = Right(sh.Range("A" & x), 1)
Exit For
End If
111
Next sh
Application.EnableEvents = True
If x = "" Then MsgBox "Not Found!"
End Sub
I know that this 10 char restriction is in line 8, and I tried replacing with a FIND, but I don't think I had it right (on the basis that I couldn't get it to work!).
I'd be grateful for help in getting this sorted.
I have a further vLookup which is taking that last character and returning text from a separate sheet.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
Dim InvLen As Integer
If Target.Address <> "$A$5" Then Exit Sub
If Target.Value = "" Then Exit Sub
Application.EnableEvents = False
Range("B5") = ""
For Each sh In Sheets
If sh.Name = ActiveSheet.Name Then GoTo 111
InvLen = Len(Worksheets("Main").Range("A5").value)
sh.Range("B1").FormulaArray = "=IFERROR(MATCH(Main!A5,LEFT(A:A," & InvLen & "),0),"""")"
If sh.Range("B1") <> "" Then
x = sh.Range("B1")
Range("B5") = Right(sh.Range("A" & x), 1)
Exit For
End If
111
Next sh
Application.EnableEvents = True
If x = "" Then MsgBox "Not Found!"
End Sub