Trying to fill blanks with alpha characters based on number above - excel

I have this.
3
3.1
3.2
3.3
3.4
4
4.1
NULL
NULL
NULL
NULL
5
I would like this.
3
3.1
3.2
3.3
3.4
4
4.1
4.A
4.B
4.C
4.D
5
I have about 22k rows to fill in. How can I do it? I put together the code below, bu tit doesn't do what I want. I need to start over with prior number + 'A' whenever a new blank cell is found.
This is what I have so far, but it doesn't work.
Sub AlphaFill()
Dim Cell, CellChars
Dim Default, Prompt, Title
Dim rangeSelected As Range
Dim UpperCase As Boolean
On Error Resume Next
Set rangeSelected = Range("F1:F21400")
For Each Cell In rangeSelected
If Cell.Value <> "" Then
i = 1
End If
If Cell.Value = "" Then
CellChars = Chr(64 + i)
If Not UpperCase Then CellChars = UCase(CellChars)
Cell.Value = Cell.Value & CellChars
i = i + 1
End If
Debug.Print Cell.Value
Next
End Sub
The problem is, I can't seem to preserve the prior cell, for instance, the 4.A, 4.B, 4.C, and 4.D

If I understand correctly then you need to store the last whole number you see then use that on the next blank cell, resetting the counter between gaps:
Sub AlphaFill()
Dim Cell As Range
Dim UpperCase As Boolean
Dim LastWholeNumber As String
Dim LastLetter As Long
Dim CurrentNumber As String
UpperCase = True
For Each Cell In Range("F1:F21400")
CurrentNumber = Cell.Value
If CurrentNumber = "" Then
LastLetter = LastLetter + 1
Cell.Value = LastWholeNumber & "." & ChrW$(LastLetter)
ElseIf InStr(CurrentNumber, ".") = 0 Then
'// whole number - store it & reset to A/a
LastLetter = IIf(UpperCase, 64, 97)
LastWholeNumber = CurrentNumber
End If
Next
End Sub

Oh, I got it. This works!!
Sub AlphaFill()
Dim Cell, CellChars
Dim Default, Prompt, Title
Dim rangeSelected As Range
Dim UpperCase As Boolean
On Error Resume Next
Set rangeSelected = Range("F1:F21400")
For Each Cell In rangeSelected
If Cell.Value <> "" Then
KeepValue = Cell.Value
i = 1
End If
If Cell.Value = "" Then
CellChars = Chr(64 + i)
If Not UpperCase Then CellChars = UCase(CellChars)
Cell.Value = KeepValue & CellChars
i = i + 1
End If
Next
End Sub

Assuming your data is as
Try this
Sub AlphaFill()
Dim Cell, CellChars
Dim Default, Prompt, Title
Dim rangeSelected As Range
Dim UpperCase As Boolean
Dim charIndex As Long
On Error Resume Next
Set rangeSelected = Range("F1:F21400")
UpperCase = True
charIndex = 65
For Each Cell In rangeSelected
If Cell.Value = "" Then
If InStr(Cell.Offset(-1, 0), ".") > 0 Then 'check if value contains "."
Cell.Value = Left(Cell.Offset(-1, 0), WorksheetFunction.Find(".", Cell.Offset(-1, 0))) & Chr(charIndex) 'extract the string till "."
Else
Cell.Value = Cell.Offset(-1, 0) & "." & Chr(charIndex) 'get the number and add "."
End If
charIndex = charIndex + 1
Else
If charIndex <> 65 Then charIndex = 65 'if cell is not blank set charIndex to 65
End If
Next
End Sub
This will give result as

Related

Group number sequence inside a range

I am new to VBA and learning myself...
I am facing a similar problem with this post: Excel Vba - Group number sequence inside a string
which the difference is that my item no. is in horizontal like below:
ColA(ID) ColB ColC ColD ColE ColF ColG
A 101 102 103
B 201 202 203 501 502
Sometimes for an ID, there will only have 3 item no., sometimes with 5, they can be upto 30 sometimes...
What I think the function could look like this: Cell G1 = lookupsequence(A1:A30), since that lookup function is no need in this situtation
Then G1 -> 101-103
Then G2 -> 201-203, 501-502
Below is the code I have based on that post, but just generating G1: 101, 102, 103
Lookupsequence(Return_val_col As Range)
Dim i As Long
Dim result As String
Dim initial As String
Dim separator As String
Dim preValue As Integer
Dim value As Integer
preValue = -1
separator = ""
For i = 1 To 30
value = CInt(Return_val_col.Cells(1, i).value)
If value - 1 = preValue Then
result = initial & "-" & value
Else
result = result & separator & value
initial = result
separator = ","
End If
Next
Lookupsequence = Trim(result)
End Function
I tried to add something like but not succeed
Dim lastcol As Long
lastcol = Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To lastcol
Thank you
Assuming a max of 30 numbers within the limits of rownumbers of Excel, try:
Function GetSequence(rng1 As Range) As String
Dim rng2 As Range
For Each cl In rng1.SpecialCells(2, 1)
If rng2 Is Nothing Then
Set rng2 = Cells(cl.Value, 1)
Else
Set rng2 = Union(rng2, Cells(cl.Value, 1))
End If
Next
GetSequence = Replace(Replace(rng2.Address(False, False), "A", ""), ":", "-")
End Function
Invoke through: =GetSequence(B1:D1) or whichever range holding the numbers.
If numbers get too large and too many for the above function, try:
Function GetSequence(rng As Range) As String
Dim arr As Variant: arr = rng.Value
With CreateObject("System.Collections.ArrayList")
For Each el In arr
If IsNumeric(el) And el <> "" Then .Add el
Next
.Sort
For i = .Count - 1 To 0 Step -1
If i = .Count - 1 Then
GetSequence = .Item(i) & "|"
Else
If Val(GetSequence) = .Item(i) + 1 Then
If Mid(GetSequence, Len(.Item(i)) + 1, 1) = "-" Then
GetSequence = .Item(i) & Mid(GetSequence, Len(CStr(Val(GetSequence))) + 1)
Else
GetSequence = .Item(i) & "-" & GetSequence
End If
Else
GetSequence = .Item(i) & "," & GetSequence
End If
End If
Next
End With
GetSequence = Replace(GetSequence, "|", "")
End Function
It's abit verbose but this way can even insert empty or unsorted arrays of numbers:
I tested this code and it worked correctly for me. I returned to the page and saw the solution from JvdV; so I thought I'd post my solution too.
Option Explicit
Private Sub Test()
Dim result$
Dim WS As Worksheet
Set WS = ThisWorkbook.Sheets("Sheet3")
result$ = Lookupsequence(WS.Range("B1:AE1"))
result$ = Lookupsequence(WS.Range("B2:AE2"))
result$ = Lookupsequence(WS.Range("B3:AE3"))
End Sub
Private Function Lookupsequence(Return_val_col As Range) As String
Dim preValue%, value%
Dim i&
Dim result$, separator$
preValue = -1
result = ""
separator = ", "
For i = 1 To Return_val_col.count
value = CInt(Return_val_col.Cells(1, i).value)
If value = 0 Then
Exit For
ElseIf result = "" Then
result = value
ElseIf value - 1 <> preValue Then
result = result & "-" & preValue & separator & value
End If
preValue = value
Next
If value = 0 Then
value = preValue
End If
result = result & "-" & value
Lookupsequence = Trim(result)
End Function
My test data in two images from columns A to AE to test the possibility of 30 item numbers

Instr function only on specific font

I´m trying to find a way to use Instr to work only with words that have a specific font.
I´m currently using a code that allows me to find differences between two paragraphs and show the changes on another column by chainging the words that are the same to the color green.
The problem is that when using Instr it only finds the first occurence of a word. But with the paragraphs I´m using, the words appear multiple times:
myLastRow = Cells(Rows.Count, "G").End(xlUp).Row
For I = 3 To myLastRow
strTemp = " "
WordsA = Split(Range("F" & I).Text, " ")
Debug.Print WordsA
WordsB = Split(Range("H" & I).Text, " ")
Debug.Print WordsB
For ndxB = LBound(WordsB) To UBound(WordsB)
For ndxA = LBound(WordsA) To UBound(WordsA)
If StrComp(WordsA(ndxA), WordsB(ndxB), vbTextCompare) = 0 Then
FindText = WordsA(ndxA)
Debug.Print FindText
Set TextRange = Range("H" & I)
fontColor = 4
'FindText.Font.ColorIndex = fontColor
For Each part In TextRange
lenOfpart22 = InStr(1, TextRange, FindText, 1)
lenPart = Len(FindText)
part.Characters(Start:=lenOfpart22, Length:=lenPart).Font.ColorIndex = fontColor
Next part
Exit For
End If
Next ndxA
Next ndxB
Next I
What I need is for the Instr to only search the word if its fond is 0 (black).
TextRange is the paragraph. Usually more than 500 caracters long
FindText is the word that I´m searching
This is an example of the problem I´m having:
In this paragraph you can see how some words appear in green. These are the words that are the same on the two paragraphs that I´m comparing (columns F and G). There are some words such as: aeqqw, SAWR, SIGMEL... that are different. The problem is that Instr only finds the first occurrence of a word. That´s why I want a condition were if the word is green, it won´t be considered in the instr and will move on to find the next word.
In the picture you can see that the first "El" is in green, but the rest aren´t. This is because when it searches for the second, thrid, fourth... "el" it comes back to the first "el".
Please, use the next function to do what (I understood) you need (playing with arrays...):
Sub WordsComp(cell1 As Range, cell2 As Range) 'punctuation characters eliminated
Dim arr1() As String, arr2() As String, arrMtch() As String, mtch, El
Dim strArr As String, i As Long, cleanWord As String, endPlus As Long
arr1 = Split(cell1.value): arr2 = Split(cell2.value) 'split the two cells content by words
For Each El In arr1 'iterate between the first cell words
For i = 0 To UBound(arr2)
cleanWord = EndingCharsOut(CStr(El))
endPlus = Len(cleanWord) - Len(El)
If EndingCharsOut(CStr(arr2(i))) = cleanWord Then 'when a match has been found:
arrMtch = Split(cell2, , i + 1, vbTextCompare) 'split the range only up to the searched word (plus the rest of the string)
'eliminate the last element of the array:
arrMtch(UBound(arrMtch)) = "##$%": arrMtch = filter(arrMtch, "##$%", False)
strArr = Join(arrMtch, "|") 'join the array elements to obtain the necessary start, before the word to be colored
cell2.Characters(start:=Len(strArr) + 2, length:=Len(El) + endPlus).Font.Color = vbGreen '+ 2 because of the 1D zero based array and a space
End If
Next i
Next
End Sub
Private Function EndingCharsOut(strMatch As String) As String 'eliminates ending punctuation characters (,.?:;)
With CreateObject("Vbscript.RegExp")
.Pattern = "[.,/?:;]$"
If .test(strMatch) Then
EndingCharsOut = (.Replace(strMatch, ""))
Else
EndingCharsOut = strMatch
End If
End With
End Function
The above Sub should be called by the next one:
Sub testWordsCompare()
Dim ws As Worksheet, rng As Range, lastR As Long, i As Long
Set ws = ActiveSheet
lastR = ws.Range("F" & ws.rows.count).End(xlUp).row
Set rng = ws.Range("F2:G" & lastR)
rng.Columns(2).Font.Color = 0 'make the font color black (default)
Application.EnableEvents = False: Application.ScreenUpdating = False
For i = 1 To rng.rows.count
WordsComp rng.rows(i).cells(1, 1), rng.rows(i).cells(1, 2)
Next i
Application.EnableEvents = True: Application.ScreenUpdating = True
MsgBox "Ready..."
End Sub
The function compares words even containing punctuation (comma, dot, question mark, ":", ";") at the end...
A faster solution but not so compact and easy to be understood, would be the next classic one:
Sub compWdClassic(cell1 As Range, cell2 As Range)
Dim iStart1 As Long, iEnd1 As Long, iStart2 As Long, oldStart As Long, strWd As String
Dim boolEnd As Boolean, boolOut As Boolean, i As Long, frstW As Boolean, midleW As Boolean
iStart1 = 1 'initialize starting position for Cell1 string
Do While Not boolEnd
iEnd1 = InStr(iStart1, cell1, " ", vbBinaryCompare) 'determine the ending of the word to be returned
strWd = Mid(cell1, iStart1, IIf(iEnd1 > 0, iEnd1 - iStart1, Len(cell1) - iStart1 + 1)) ' extraxting the word to be checked
If iEnd1 > 0 Then iStart1 = iEnd1 + 1 Else: boolEnd = True 'determine if is it about the last word (or not)...
strWd = EndingCharsOut(strWd) 'clean the word ending
midleW = False: boolOut = False: iStart2 = 1 'initialize the necessary variables
Do While Not boolOut 'loop in cell2 value string
If Not frstW And iStart2 = 1 Then 'if not a first word has been found:
iStart2 = InStr(IIf(iStart2 = 0, 1, iStart2), cell2, strWd & " ", vbBinaryCompare) 'check against a word without a space in front
If iStart2 > 0 Then frstW = True 'first word in the sentence. If such a word found, make the boolean variable True
Else
oldStart = iStart2 'memorize the previous value of iStart2
iStart2 = InStr(iStart2 + 1, cell2, " " & strWd & " ", vbBinaryCompare) 'search if a word with spaces at both sides
If iStart2 > 0 Then midleW = True 'if founded, make the boolean variable True
If oldStart > 0 And midleW Then 'if nothing found before, but a pevious word with spaces of both sides has been found:
If iStart2 = 0 Then iStart2 = InStr(oldStart, cell2, " " & strWd, vbBinaryCompare): _
If iStart2 > 0 And iStart2 + Len(strWd) = Len(cell2) Then boolOut = True Else: iStart2 = 0: boolOut = True: 'if the last word or only part of a word
ElseIf oldStart = 0 And Not midleW Then
If iStart2 = 0 Then iStart2 = InStr(oldStart + 1, cell2, " " & strWd, vbBinaryCompare):
If iStart2 > 0 Then boolOut = True: ' last word and loop must be exited
End If
End If
If iStart2 > 0 Then
cell2.Characters(iStart2 + IIf(boolOut, 1, IIf(frstW And Not midleW, 0, 1)), Len(strWd)).Font.Color = vbRed 'do the job
iStart2 = iStart2 + Len(strWd) + 1 'increment the variable for the next search
Else
If (frstW And Not boolOut) Or (Not frstW And Not midleW And Not boolOut) Then Exit Do 'exiting loop if conditions are met
End If
Loop
Loop
End Sub
It uses the same EndingCharsOut function to clear punctuation characters. You only must call this Sub instead of previous. I mean, replace:
WordsComp rng.rows(i).cells(1, 1), rng.rows(i).cells(1, 2)
in testWordsCompare sub with:
compWdClassic rng.rows(i).cells(1, 1), rng.rows(i).cells(1, 2)
Please, send some feedback after testing them...

extract specific set of digits from random strings in EXCEL VBA

Disclaimer- my case is specific, and in my case my code works because I know the pattern.
I was looking for an answer everywhere, and the codes I tried were not quite what I was looking for, this is my solution if you are looking for a set of numbers.
In my case, I was looking for 7 digits, starting with digit 1 in a a column with random strings, some string had the number some others didn't.
The number will appear in these three scenarios "1XXXXXX", "PXXXXXXXX", "PXXXXXXXXX"(this has more digits because there is a slash).
Here are the examples of strings:
9797 P/O1743061 465347 Hermann Schatte Earl Lowe
9797 Po 1743071 404440 Claude Gaudette Jose Luis Lopez
9817 1822037 463889 Jean Caron Mickelly Blaise
My Code
Sub getnum()
'i don't use explicit so i didn't declare everything
Dim stlen As String
Dim i As Integer
Dim arra() As String
Dim arran() As String
Orig.AutoFilterMode = False
Call BeginMacro
LastRow = Orig.Cells(Rows.Count, 1).End(xlUp).Row
Orig.Range("J2:J" & LastRow).Clear
'loop though column
For n = 2 To LastRow
celref = Orig.Cells(n, 4).Value
'split string on white spaces
arra() = Split(celref, " ")
'turn string to multiple strings
For counter = LBound(arra) To UBound(arra)
strin = arra(counter)
'remove white spaces from string
storage = Trim(strin)
lenof = Len(storage)
'if string has 9 characthers, check for conditions
If lenof = 9 Then
'position of first and last charachter
somstr = Mid(storage, 1, 1)
somot = Mid(storage, 9, 1)
If somstr = "P" Or somstr = "p" And IsNumeric(somot) = True Then
'removes Po or PO and keeps only 7 digits
storage = Right(storage, 7)
'stores in column J
Orig.Cells(n, 10).Value = storage
End If
ElseIf lenof = 10 Then
somstr = Mid(storage, 1, 1)
somot = Mid(storage, 10, 1)
'other conditions
If somstr = "P" Or somstr = "p" And IsNumeric(somot) = True Then
'removes Po or PO and keeps only 7 digits
storage = Right(storage, 7)
'stores in column J
Orig.Cells(n, 10).Value = storage
End If
End If
'eliminate comma within
arran() = Split(storage, ",")
If Orig.Cells(n, 10).Value <> storage Then
For counter2 = LBound(arran) To UBound(arran)
strin2 = arran(counter2)
storage2 = Trim(strin2)
'final condition if is 7 digits and starts with 1
If IsNumeric(storage2) = True And Len(storage2) = 7 Then
car = Mid(storage2, 1, 1)
If car = 1 Then
'stores in columns J at specific position
Orig.Cells(n, 10).Value = storage2
End If
Else
If isnumeric(orig.cells(n,10).value) =true and _
len(orig.cells(n,10).value = 7 then
orig.cells(n,10).value = orig.cells(n,10).value
else
Orig.Cells(n, 10).Value = "no po# in D"
End If
Next counter2
End If
Next counter
Next n
Call EndMacro
End Sub
you may try this
Option Explicit
Sub getnum()
Dim position As Variant
Dim cell As Range
With Worksheets("Orig") ' change it to your actual sheet name
With Intersect(.UsedRange, Columns("J"))
.Replace what:="P/O", replacement:="P/O ", lookat:=xlPart
For Each cell In .Cells
position = InStr(cell.Text, " 1")
If position > 0 Then cell.Value = Mid(cell.Value, position + 1, 7)
Next
End With
End With
End Sub
This code paste two formulas one in column G and one in column J). The first formula checks for a "P" in the first character of the cell in column 2 and if there is a "P" it extracts the last 7 characters in the string and puts them in column G. The second formula checks if there is not a "P" and if not extracts the last 7 characters in the string and puts them in column J.
Sub Extract()
Dim ws As Worksheet
Dim lRow As Long
Set ws = ThisWorkbook.Sheets("Sheet3")
lRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
ws.Range("G2:G" & lRow).Formula = "=IF(LEFT(B2)=""P"",(RIGHT(B2,7)),"""")"
ws.Range("J2:J" & lRow).Formula = "=IF(LEFT(B2)<>""P"",(RIGHT(B2, 7)),"""")"
End Sub
You may use the RegEx to extract the number in desired format.
Please give this a try...
Function Get10DigitNumber(ByVal Str As String) As String
Dim RE As Object
Set RE = CreateObject("VBScript.RegExp")
With RE
.Global = False
.Pattern = "1\d{6}"
End With
If RE.test(Str) Then
Get10DigitNumber = RE.Execute(Str)(0)
End If
End Function
Then if you want to use this function on the worksheet itself, assuming your string is in A2, try this...
=Get10DigitNumber(A2)
OR
You may use this function in another sub routine/macro like this...
Debug.Print Get10DigitNumber(<pass your string variable here>)
Edited Function:
Function Get10DigitNumber(ByVal Str As String) As String
Dim RE As Object, Matches As Object
Set RE = CreateObject("VBScript.RegExp")
With RE
.Global = False
.Pattern = "[Pp]?\/?[Oo]?(1\d{6})\b"
End With
If RE.test(Str) Then
Set Matches = RE.Execute(Str)
Get10DigitNumber = Matches(0).SubMatches(0)
End If
End Function
And use if as already described above.
After understanding what you were doing, I think this will work. Any feedback would be appreciated.
Dim cell As Range, LRow As Long
LRow = ActiveSheet.Cells(Rows.Count, 4).End(xlUp).Row
For Each cell In Range("D2:D" & LRow)
If cell.Value Like "*Po *" Then
cell.Offset(0, 6).Value = Split(cell.Value, " ")(2)
Else: cell.Offset(0, 6).Value = Split(cell.Value, " ")(1)
End If
Next cell
For Each cell In Range("J2:J" & LRow)
If Len(cell.Value) > 7 Then
cell.Value = Right(cell.Value, 7)
End If
Next

Excel VBA Cell Auto Advance Sub Splitting Words

I currently have a VBA sub routine in an Excel sheet that prompts the user with an input box, inserts the data into a cell, and automatically advances to the cell below if the entire string will not fit into a single cell. It works, but the code will advance to the next line even if it has to split a word to do it. I do not want this, and I would appreciate some suggestions on how to improve my code so that Excel not only advances cells, but advances cells with words that don't get cut off.
Sub AutoCellAdvance()
If bolEditMode = True Then
Exit Sub
End If
Dim str As String, x As Integer, y As Integer
intPlaceholder = Sheet1.Range("AE1").Value
If IsEmpty(ActiveCell) Then
str = InputBox("Enter Description of Activities (Max 192 characters)", "Incidents, Messages, Orders, Etc.")
y = 0
For x = 1 To Len(str) Step 64
ActiveCell.Offset(y, 0) = "" & Mid(str, x, 64)
If Len(str) > 64 And Len(str) <= 128 And intPlaceholder = 6 Then
ActiveCell.Offset(1, -4).Resize(1, 4).Value = Chr(151) & Chr(151)
End If
If Len(str) > 128 And Len(str) < 192 And intPlaceholder = 6 Then
ActiveCell.Offset(1, -4).Resize(2, 4).Value = Chr(151) & Chr(151)
End If
If Len(str) >= 192 And intPlaceholder = 6 Then
ActiveCell.Offset(1, -4).Resize(3, 4).Value = Chr(151) & Chr(151)
End If
y = y + 1
Next
Else
Exit Sub
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal target As Range)
'Incident, Messages, Orders, Etc. Input
Dim rng As Range
Set rng = Intersect(target, Range("N12,N13,N14,N15,N16,N17,N18,N19,N20,N21,N22,N23,N24,N25,N26,N27,N28,N29,N30,N31,N32,N33,N34,N35,N36,N37,N38,N39,N40,N41,N42,N43,N44"))
If rng Is Nothing Then
Exit Sub
ElseIf target.Count > 14 Then
Exit Sub
Else
Dim cl As Range
For Each cl In rng
AutoCellAdvance
Next cl
End If
Selection.Font.Name = "arial"
Selection.Font.Size = 10
End Sub
Try this. The code below splits the input string, into an array of strings based on the delimiter " ". It then loops through the string array. Whenever it reaches a size of 64 it goes to the next line.
Sub AutoCellAdvance()
Dim strTemp As String
Dim arrStrings() As String
Dim i As Integer
Dim strNew As String
Range("A1").Activate
strTemp = InputBox("Enter Description of Activities (Max 192 characters)", "Incidents, Messages, Orders, Etc.")
'splits the string based on the delimeter space
arrStrings = Split(strTemp, " ")
strNew = ""
'loops through the strings
For i = LBound(arrStrings) To UBound(arrStrings)
If Len(strNew + arrStrings(i)) < 64 Then
'as long as its smaller than 64 its adds the string to the rest of the strings
strNew = strNew + arrStrings(i) + " "
Else
'if its larger than 64 then it prints the value in the active cell and goes down a row
ActiveCell = strNew
strNew = arrStrings(i)
Range(Cells(ActiveCell.Row + 1, ActiveCell.Column), Cells(ActiveCell.Row + 1, ActiveCell.Column)).Activate
End If
Next i
ActiveCell = strNew
End Sub
Also here's an article I've written about string processing on my blog. It also talks about splitting strings. String Processing

How to read e & é as the same thing using search macro in excel

I'm not entirely sure how to word this but, I have an Excel macro that enables a search functionality within my workbook. My issue is that I need the search to understand 'é' as 'e'. So that if I search for 'Belem', my result would come back with 'Belém'. How would I go about this? Thanks for any time and consideration.
Sub city()
If ActiveSheet.Name <> "City" Then Exit Sub
LastRow = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row
Sheets("Results").Range("3:10000").Delete
SearchTerm = Application.InputBox("What are you looking for?")
Application.ScreenUpdating = False
Range("W1") = SearchTerm
Range("W2:W" & LastRow).FormulaR1C1 = _
"=IF(ISERR(SEARCH(R1C23,RC[-22]&RC[-21]&RC[-20]&RC[-19]&RC[-18]&RC[-17]&RC[-16]&RC[-15]&RC[-15]&RC[-14]&RC[-13]&RC[-12]&RC[-11]&RC[-10]&RC[-9]&RC[-8]&RC[-7]&RC[-6]&RC[-5]&RC[-4]&RC[-3]&RC[-2]&RC[-1])),0,1)"
If WorksheetFunction.CountIf(Columns(23), 1) = 0 Then
Columns(23).Delete
Application.ScreenUpdating = True
MsgBox "None found."
Else
For Each Cell In Range("A2:A" & LastRow)
If Cell.Offset(, 22) = 1 Then
Cell.Resize(, 51).Copy Sheets("Results").Range("A" & Rows.Count).End(xlUp).Offset(1)
x = x + 1
End If
Next Cell
Columns(22).Delete
Application.ScreenUpdating = True
If x = 1 Then
MsgBox "1 matching record was copied to Search Results tab."
Else
MsgBox x & " matching records were copied to Search Results tab."
End If
End If
End Sub
You can modify the search parameter and then use the like operator as follows:
Sub city()
Dim rngResult As Range
Dim searchTerm As String, counter As Integer
Dim values As Variant, value As Variant
If ActiveSheet.Name <> "City" Then Exit Sub
'First Cell with the results
Set rngResult = <First cell of the result Range>
'Uses a variant array to get all values from the range. This speeds up the routine
values = <Area of Search>.Value
'Converts to lowercase to do a case insensitive search (e.g. Belem = belem)
searchTerm = LCase(Application.InputBox("What are you looking for?"))
If searchTerm = "" Then Exit Sub
' "§" is just a placeholder
searchTerm = Replace(searchTerm, "e", "§")
searchTerm = Replace(searchTerm, "é", "§")
searchTerm = Replace(searchTerm, "§", "[eé]")
Application.ScreenUpdating = False
counter = 0
For Each value In values
If LCase(value) Like searchTerm Then
rngResult = value
Set rngResult = rngResult.Offset(1, 0) 'Moves to the next line
counter = counter + 1
End If
Next value
If counter = 0 Then
MsgBox "None found."
Else
MsgBox "Found " & counter & " results"
'Do what you need to do with the results
End If
Application.ScreenUpdating = True
End Sub
All the results will be at the column of rngResult.
The code works by replacing "e" and "é" by "§" and then replacing "§" by "[eé]", (e.g. "bélem" -> "bél§m" -> "b§l§m" -> "b[eé]l[eé]m").
The like will match either "e" or "é" on that position. You can learn more about it here or in the help files. Here is a Example:
bélem Like "b[eé]l[eé]m" ' true
belem like "b[eé]l[eé]m" ' true
recife like "b[eé]l[eé]m" ' false
You can search more graphs by adding other criteria like:
'Like will match "a","á", "à" and "ã"
searchTerm = Replace(searchTerm, "a", "§")
searchTerm = Replace(searchTerm, "á", "§")
searchTerm = Replace(searchTerm, "à", "§")
searchTerm = Replace(searchTerm, "ã", "§")
searchTerm = Replace(searchTerm, "§", "[aáàã]")
This method has the advantage that you only need one "translation" in order to do comparisons. This can improve the performance if you have a large dataset
You can keep an array of all the characters you want to replace and what you want to replace them with. It's easier if you "search" your data a little differently that using that formula. Here's how I would do it.
Sub FindCity()
Dim shResults As Worksheet
Dim vaData As Variant
Dim i As Long, j As Long
Dim sSearchTerm As String
Dim sData As String
Dim rNext As Range
'Put all the data into an array
vaData = ActiveSheet.UsedRange.Value
'Get the search therm
sSearchTerm = Application.InputBox("What are you looking for?")
'Define and clear the results sheet
Set shResults = ActiveWorkbook.Worksheets("Results")
shResults.Range("A3").Resize(shResults.UsedRange.Rows.Count, 1).EntireRow.Delete
'Loop through the data
For i = LBound(vaData, 1) To UBound(vaData, 1)
For j = LBound(vaData, 2) To UBound(vaData, 2)
'Get rid of diacritial characters
sData = LCase(Anglicize(vaData(i, j)))
'Look for a match
If InStr(1, sData, LCase(Anglicize(sSearchTerm))) > 0 Then
'Write the row to the next available row on Results
Set rNext = shResults.Cells(shResults.Rows.Count, 1).End(xlUp).Offset(1, 0)
rNext.Resize(1, UBound(vaData, 2)).Value = Application.Index(vaData, i, 0)
'Stop looking in that row after one match
Exit For
End If
Next j
Next i
End Sub
Public Function Anglicize(ByVal sInput As String) As String
Dim vaGood As Variant
Dim vaBad As Variant
Dim i As Long
Dim sReturn As String
'Replace any 'bad' characters with 'good' characters
vaGood = Split("S,Z,s,z,Y,A,A,A,A,A,A,C,E,E,E,E,I,I,I,I,D,N,O,O,O,O,O,U,U,U,U,Y,a,a,a,a,a,a,c,e,e,e,e,i,i,i,i,d,n,o,o,o,o,o,u,u,u,u,y,y", ",")
vaBad = Split("Š,Ž,š,ž,Ÿ,À,Á,Â,Ã,Ä,Å,Ç,È,É,Ê,Ë,Ì,Í,Î,Ï,Ð,Ñ,Ò,Ó,Ô,Õ,Ö,Ù,Ú,Û,Ü,Ý,à,á,â,ã,ä,å,ç,è,é,ê,ë,ì,í,î,ï,ð,ñ,ò,ó,ô,õ,ö,ù,ú,û,ü,ý,ÿ", ",")
sReturn = sInput
For i = LBound(vaBad) To UBound(vaBad)
sReturn = Replace$(sReturn, vaBad(i), vaGood(i))
Next i
Anglicize = sReturn
End Function
List of characters from Excel 2007 VBA Converting Accented Characters to Regular

Resources