I found the following great udf for fuzzy match a string but it doesnt work with Array formula, I am very basic in VBA and cant make it work (from reading different post it may have something to do with adding Lbound somewhere but cant figure it out).
Could I get some help ?
what I would like to do is something like
{=searchChars("yellow",if(list_of_product="productA",list_of_colors))}
.
'Name function and arguments
Function SearchChars(lookup_value As String, tbl_array As Variant) As String
'Declare variables and types
Dim i As Integer, str As String, Value As String
Dim a As Integer, b As Integer, cell As Variant
'Iterste through each cell
For Each cell In tbl_array
'Save cell value to variable
str = cell
'Iterate through characters
For i = 1 To Len(lookup_value)
'Same character?
If InStr(cell, Mid(lookup_value, i, 1)) > 0 Then
'Add 1 to number in array
a = a + 1
'Remove evaluated character from cell and contine with remaning characters
cell = Mid(cell, 1, InStr(cell, Mid(lookup_value, i, 1)) - 1) & Mid(cell, InStr(cell, Mid(lookup_value, i, 1)) + 1, 9999)
End If
'Next character
Next i
a = a - Len(cell)
'Save value if there are more matching characters than before
If a > b Then
b = a
Value = str
End If
a = 0
Next cell
'Return value with the most matching characters
SearchChars = Value
End Function
Option Explicit
Working OK for me - does not need to be entered as an array formula:
A few "improvements":
Function SearchChars(lookup_value As String, tbl_array As Variant) As String
Dim i As Long, str As String, Value As String, c As String
Dim a As Long, b As Long, cell As Variant
For Each cell In tbl_array
If Len(cell) > 0 Then 'skip empty values
str = cell
a = 0
For i = 1 To Len(lookup_value)
c = Mid(lookup_value, i, 1) '<< do this once
If InStr(cell, c) > 0 Then
a = a + 1
cell = Replace(cell, c, "", Count:=1) '<< simpler
If Len(cell) = 0 Then Exit For '<< nothing left...
End If
Next i
a = a - Len(cell)
'Debug.Print str, a
If a > b Then
b = a
Value = str
End If
End If
Next cell
SearchChars = Value
End Function
Related
I'm trying to write a VBA code that will take values from a selection and concatenate the cell values with a line seperator. I also wish to not include and duplicates.
Ex. as follows:
Say I have a data set like the below. I would like to type =ConcatenateUnique(A1:B2,",") and have it return One,Two,Three
Column A
Column B
One
Two
Three
One
I tried the below, although I'm aware if it did work it would only return Two,Three
Function CONCATENATEUNIQUE(Ref As Range, Separator As String) As String
Dim Cell As Range
Dim Result As String
For Each Cell In Ref
If WorksheetFunction.CountIf(Ref, Cell.Value) <= 1 Then
Result = Result & Cell.Value & Separator
End If
Next Cell
CONCATENATEMULTIPLE = Left(Result, Len(Result) - 1)
End Function
For this type of task a Scripting Dictionary is useful (but note this won't work on a Mac):
Function UniqueList(rng As Range, Optional sep As String = ",")
Dim arr, r As Long, c As Long, v, dict As Object
If rng.Count = 1 Then 'handle single-cell case
UniqueList = rng.Value
Exit Function
End If
arr = rng.Value 'get values into an array
Set dict = CreateObject("Scripting.Dictionary")
For r = 1 To UBound(arr, 1)
For c = 1 To UBound(arr, 2)
v = arr(r, c)
If Not IsError(v) Then
If Len(v) > 0 Then dict(v) = True
End If
Next c
Next r
UniqueList = Join(Application.Transpose( _
Application.Transpose(dict.Keys)), sep)
End Function
Example
In Cell "A2" I have 2,4,5,7-9
How do I count them by using formula or coding with vba
and count them as 2 4 5 7 8 9 which sum up value to 6
and return value in Cell "B2"
Please, try the next function. It builds a virtual discontinuous range and count its cells:
Function countNumb(strNo As String) As Long
Dim arr, i As Long
arr = Split(Replace(Replace(strNo, " ", ""), "-", ":"), ",")
For i = 0 To UBound(arr)
If Not InStr(arr(i), ":") > 0 Then
arr(i) = arr(i) & ":" & arr(i)
End If
Next
countNumb = Intersect(Range(Join(arr, ",")), Range("A:A")).cells.count
Debug.Print Range(Join(arr, ",")).Address 'only to visually see the built range before intersection address...
End Function
It can also process a string as "2, 4,5,7 - 9"...
It can be tested using the next code:
Sub testCountNumbers()
Dim x As String: x = "2,4,5,7-9"
Debug.Print countNumb(x)
End Sub
With VBA,
Function AddNumbers(rngTarget As Range) As Long
Dim arrValues() As String
Dim lngValue As Long
Dim strValue As String
Dim lngMinimum As Long
Dim lngMaximum As Long
arrValues = Split(rngTarget.Text, ",")
For lngValue = LBound(arrValues) To UBound(arrValues)
strValue = arrValues(lngValue)
If InStr(strValue, "-") > 0 Then
lngMinimum = CLng(Left(strValue, InStr(strValue, "-") - 1))
lngMaximum = CLng(Replace(strValue, lngMinimum & "-", vbNullString))
AddNumbers = AddNumbers + ((lngMaximum - lngMinimum) + 1)
Else
AddNumbers = AddNumbers + 1
End If
Next lngValue
End Function
Assuming column XFD in the active sheet is empty, and that no integer within the string will ever exceed 2^20:
=SUM(COUNTIF(INDIRECT("XFD"&SUBSTITUTE(TEXTSPLIT(A2,","),"-",":XFD")),""))
For those without TEXTSPLIT:
=SUM(COUNTIF(INDIRECT(SUBSTITUTE(FILTERXML("<a><b>XFD"&SUBSTITUTE(A2,",","</b><b>XFD")&"</b></a>","//b"),"-",":XFD")),""))
Using a Macro or Formula, is there a way to achieve the result of the following formula of Office 365?
=FILTER(B:B,A:A = "x")
What it does is get all the values from Column B if Column A on the same row has a value of x.
My PC has office 365 but the one I'm working with only has Office Pro Plus 2019. I had to use my pc when I needed the function and I'm getting tired of it, maybe it can be done on Office Pro Plus 2019 too using a formula or a macro?
Use:
=IFERROR(INDEX($B$1:$B$100,AGGREGATE(15,7,ROW($A$1:$A$100)/($A$1:$A$100="x"),ROW($ZZ1))),"")
Note the use of a set range and not full columns. That is done on purpose, This being an array formula it will do a lot of calculations each cell it is placed. Limiting the range to the data set will speed it up.
Put this in the first cell of the output and copy down till blanks are returned.
I had some spare time and I am recently interested in User defined functions so I decided to make my own version of what I imagine this would be. I'm prefacing this by saying its not good and is excessively long but it works!
Function JOINIF(ByRef IfRange As Range, ByVal Criteria As String, Optional JoinRange As Range, Optional Delimeter As String = ",") As String
'IfRange is the range that will be evaluated by the Criteria
'Criteria is a logical test that can be applied to a cell value.
'Examples of Criteria: "=Steve", ">100", "<>Toronto", "<=-1"
'JoinRange is the range of values that will be concatenated if the corresponding -
'IfRange cell meets the criteria. JoinRange can be left blank if the values to be -
'concatenated are the IfRange values.
'Delimeter is the string that will seperate the concatenated values.
'Default delimeter is a comma.
Dim IfArr() As Variant, JoinArr() As Variant, OutputArr() As String
Dim IfArrDim As Integer, JoinArrDim As Integer
Dim JCount As Long, LoopEnd(1 To 2) As Long
Dim MeetsCriteria As Boolean, Expression As String
Dim i As Long, j As Long
'PARSING THE CRITERIA
Dim Regex As Object
Set Regex = CreateObject("VBScript.RegExp")
Regex.Pattern = "[=<>]+"
'Looking for comparison operators
Dim Matches As Object
Set Matches = Regex.Execute(Criteria)
If Matches.Count = 0 Then
'If no operators found, assume default "Equal to"
If Not IsNumeric(Criteria) Then
'Add quotation marks to allow string comparisons
Criteria = "=""" & Criteria & """"
End If
Else
If Not IsNumeric(Replace(Criteria, Matches(0), "")) Then
Criteria = Matches(0) & """" & Replace(Criteria, Matches(0), "") & """"
End If
'Add quotation marks to allow string comparisons
End If
'Trim IfRange to UsedRange
Set IfRange = Intersect(IfRange, IfRange.Parent.UsedRange)
'Default option for optional JoinRange input
If JoinRange Is Nothing Then
Set JoinRange = IfRange
Else
Set JoinRange = Intersect(JoinRange, JoinRange.Parent.UsedRange)
End If
'DIMENSIONS
'Filling the arrays
If IfRange.Cells.Count > 1 Then
IfArr = IfRange.Value
IfArrDim = Dimensions(IfArr)
Else
ReDim IfArr(1 To 1)
IfArr(1) = IfRange.Value
IfArrDim = 1
End If
If JoinRange.Cells.Count > 1 Then
JoinArr = JoinRange.Value
JoinArrDim = Dimensions(JoinArr)
Else
ReDim JoinArr(1 To 1)
JoinArr(1) = JoinRange.Value
JoinArrDim = 1
End If
'Initialize the Output array to the smaller of the two input arrays.
ReDim OutputArr(IIf(IfRange.Cells.Count < JoinRange.Cells.Count, IfRange.Cells.Count - 1, JoinRange.Cells.Count - 1))
'DEFINING THE LOOP PARAMETERS
'Loop ends on the smaller of the two arrays
If UBound(IfArr) > UBound(JoinArr) Then
LoopEnd(1) = UBound(JoinArr)
Else
LoopEnd(1) = UBound(IfArr)
End If
If IfArrDim = 2 Or JoinArrDim = 2 Then
If Not (IfArrDim = 2 And JoinArrDim = 2) Then
'mismatched dimensions
LoopEnd(2) = 1
ElseIf UBound(IfArr, 2) > UBound(JoinArr, 2) Then
LoopEnd(2) = UBound(JoinArr, 2)
Else
LoopEnd(2) = UBound(IfArr, 2)
End If
End If
'START LOOP
If IfArrDim = 1 Then
For i = 1 To LoopEnd(1)
If IsNumeric(IfArr(i)) And IfArr(i) <> "" Then
Expression = IfArr(i) & Criteria
Else
'Add quotation marks to allow string comparisons
Expression = """" & IfArr(i) & """" & Criteria
End If
MeetsCriteria = Application.Evaluate(Expression)
If MeetsCriteria Then
If JoinArrDim = 1 Then
OutputArr(JCount) = CStr(JoinArr(i))
Else
OutputArr(JCount) = CStr(JoinArr(i, 1))
End If
JCount = JCount + 1
End If
Next i
Else
For i = 1 To LoopEnd(1)
For j = 1 To LoopEnd(2)
If IsNumeric(IfArr(i, j)) And IfArr(i, j) <> "" Then
Expression = IfArr(i, j) & Criteria
Else
'Add quotation marks to allow string comparisons
Expression = """" & IfArr(i, j) & """" & Criteria
End If
MeetsCriteria = Application.Evaluate(Expression)
If MeetsCriteria Then
If JoinArrDim = 1 Then
OutputArr(JCount) = CStr(JoinArr(i))
Else
OutputArr(JCount) = CStr(JoinArr(i, j))
End If
JCount = JCount + 1
End If
Next j
Next i
End If
'END LOOP
ReDim Preserve OutputArr(JCount + 1 * (JCount > 0))
JOINIF = Join(OutputArr, Delimeter)
End Function
Private Function Dimensions(var As Variant) As Long
'Credit goes to the great Chip Pearson, chip#cpearson.com, www.cpearson.com
On Error GoTo Err
Dim i As Long, tmp As Long
While True
i = i + 1
tmp = UBound(var, i)
Wend
Err:
Dimensions = i - 1
End Function
Examples of it in use:
Seperate IfRange and JoinRange
IfRange as the JoinRange
You might try the following udf (example call: FILTER2(A1:A100,B1:B100)) consisting of the following tricky steps:
a) Evaluate the general condition (=If(A1:A100="x",Row(A1:A100),"?") as tabular Excel formula and assign all valid row numbers to array x (marking the rest by "?" strings),
b) Filter out all "?" elements
c) Apply x upon the data column benefitting from the advanced restructuring features of Application.Index()
Public Function Filter2(rng1 As Range, rng2 As Variant, Optional ByVal FilterID As String = "x")
Dim a As String: a = rng1.Address(False, False, External:=True)
'a) get all valid row numbers (rng1)
Dim myformula As String: myformula = "if(" & a & "=""" & FilterID & """,row(" & a & "),""?"")"
Dim x: x = Application.Transpose(Evaluate(myformula))
'b) filter out invalid "?" elements
x = VBA.Filter(x, "?", False)
'c) apply x upon data column (rng2)
If UBound(x) > -1 Then Filter2 = Application.Index(rng2, Application.Transpose(x), 1)
End Function
Note that function calls before versions 2019/MS 365 need to be entered as array formula (Ctrl+Shift+Enter).
The function assumes one-column (range) arguments.
Edit due to comment as of 2022-06-08
The whole example is based on the actual row numbers starting in the first row (OP ranges refer to A:A,B:B. If you want to allow ranges to start at any row, you'd need to change the myFormula definition in section a) by correcting the row indices by subtracting possible offsets (row number + 1 - first row):
Dim myFormula As String
myFormula = "if(" & a & "=""" & FilterID & """,row(" & a & ")+1 -" & rng1.Row & ",""?"")"
Try this UDF for the Filter Function:
Function FILTER_HA(Where, Criteria, Optional If_Empty) As Variant
Dim Data, Result
Dim i As Long, j As Long, k As Long
'Create space for the output (same size as input cells)
With Application.Caller
i = .Rows.Count
j = .Columns.Count
End With
'Clear
ReDim Result(1 To i, 1 To j)
For i = 1 To UBound(Result)
For j = 1 To UBound(Result, 2)
Result(i, j) = ""
Next
Next
'Count the rows to show
For i = 1 To UBound(Criteria)
If Criteria(i, 1) Then j = j + 1
Next
'Empty?
If j < 1 Then
If IsMissing(If_Empty) Then
Result(1, 1) = CVErr(xlErrNull)
Else
Result(1, 1) = If_Empty
End If
GoTo ExitPoint
End If
'Get all data
Data = Where.Value
'Copy the rows to show
For i = 1 To UBound(Data)
If Criteria(i, 1) Then
k = k + 1
For j = 1 To UBound(Data, 2)
Result(k, j) = Data(i, j)
Next
End If
Next
'Return the result
ExitPoint:
FILTER_HA = Result
End Function
I am trying to quickly calculate a long lists unique values given several filters.
Rwave2 generates a range that starts past the end of Rwave, somehow taking values from the original "Export" range.
The first value of s = 44928 and e = 85991 and second value s = 1 and e = 2388. However the second range starts at 89855 of the original "Export" cell Range and 2388 values after. Not 1-2388 of the Rwave range.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("B4")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
Dim wave As String
wave = CStr(Range("B4").Value)
Dim Rwave As Range
Dim s, e As Long
'Separate by Wave
s = Search_Start(Sheets("Export").Range("A:A"), "A", wave)
e = Search_End(Sheets("Export").Range("A:A"), "A", wave, s)
Set Rwave = Sheets("Export").Range(Sheets("Export").Cells(s, "A"), Sheets("Export").Cells(e, "G"))
Sheets("TestSheet1").UsedRange.ClearContents
Rwave.Copy Sheets("TestSheet1").Range("A1")
For i = 6 To 56
'Separate by Zone
Dim Rwave2 As Range
s = Search_Start(Rwave, "B", CStr(Sheets("Sheet1").Cells(i, "B")))
e = Search_End(Rwave, "B", CStr(Sheets("Sheet1").Cells(i, "B")), s)
Set Rwave2 = Rwave.Range(Rwave.Cells(s, "A"), Rwave.Cells(e, "G"))
Sheets("TestSheet2").UsedRange.ClearContents
Rwave2.Copy Sheets("TestSheet2").Range("A1")
'Create an array of only the unique locations
Dim tmp, cell As String
Dim arr() As String
tmp = "|"
For j = 1 To Rwave2.Rows.Count
'Only count the locations on the right level
If Rwave2.Cells(j, "C") = Sheets("Sheet1").Cells(i, "C") Then
cell = Rwave2.Cells(j, "D")
If (cell <> "") And (InStr(tmp, cell) = 0) Then
tmp = tmp & cell & "|"
End If
End If
Next j
If Len(tmp) > 0 Then tmp = Left(tmp, Len(tmp) - 1)
arr = Split(tmp, "|")
Cells(i, "M") = UBound(arr) - LBound(arr)
Next i
End If
End Sub
Function Search_Start(r As Range, c As String, y As String) As Double
For i = 1 To r.Rows.Count
If InStr(r.Cells(i, c), y) <> 0 Then
Search_Start = i
Exit Function
End If
Next i
Search_Start = 1
End Function
Function Search_End(r As Range, c As String, y As String, s As Variant) As Double
For i = s To r.Rows.Count
If InStr(r.Cells(i, c), y) = 0 Then
Search_End = i - 1
Exit Function
End If
Next i
Search_End = r.Rows.Count
End Function
Think I see what's going on now.
The code below will search column C of the range B5:D10.
Because the searched range starts on column B - then column C is the third column, which is column D when looking at the whole worksheet.
Similarly you're counting rows within your range. If worksheet cell D7 contains the word Yellow then it will return i=3 as that's the third row in your range.
Sub Test()
Debug.Print Search_Start(Sheet3.Range("B5:D10"), "C", "Yellow")
End Sub
Function Search_Start(r As Range, c As String, y As String) As Double
Dim i As Long
For i = 1 To r.Rows.Count
Debug.Print r.Cells(i, c).Address
If InStr(r.Cells(i, c), y) <> 0 Then
Search_Start = i
Exit Function
End If
Next i
Search_Start = 1
End Function
To return the correct number use Search_Start = r.Cells(i, c).Row.
I have a file with 200 rows which have values like this:
ANTWERPEN 3 ABDIJ Abdijstraat 71-73 2020 9:00 18:00 9:00 18:00 9:00 18:00 9:00 18:00 9:00 19:00 9:00 19:00 which I want to have splitted into separate columns.
I want to have 1 column for the part which is in Capitals entirely. In this specific case, that would be:
ANTWERPEN 3 ABDIJ.
And another column for the part that comes after it, until the 4 numeric characters. In this case: Abdijstraat 71-73
I am happy the row values have this distinction to separate the addresses, but I do not know how to do this.
I have had a similar situation for splitting cells at the first numeric character:
text to columns: split at the first number in the value
But now I am looking for a two-fold solution to have in the first column the first part which is entirely in capitals, which represents the city and in the 2nd column I need to have the string which starts with a capital but is then followed by non-capital characters and ends before a 4 characters string of numeric characters.
I would be happy if I could create a vba or excel code/formula which could do this for me, but unfortunately, I can not :-(
So I hope someone can.
edit:
finding some other routines and modifying and testing it, helped me to create this:
Sub doitall()
Dim cell As Range, j As Integer, i As Integer, x As String
Dim str As String
Dim strlen As Integer
Dim k As Integer
Dim l As Integer
Dim y As Integer
' Dim v As Integer
'
'
' For j = 1 To Cells(Rows.Count, 1).End(xlUp).Row
' For Each cell In ActiveSheet.Range(Cells(1, 1), Cells(j, 1))
' For i = 1 To Len(cell)
' x = Mid(cell, i, 1)
' If x = ":" Then Exit For
' Next i
' cell.Offset(0, 1) = Left(cell, i - 8)
' Next cell
' Next j
'geparkeerd
' If l >= 65 And l <= 90 Then
' If v > 1 Then
' m = v - 1
' l = Asc(Mid(Cells(j, 2), m, 1))
' Else
' l = 0
' End If
For j = 1 To Cells(Rows.Count, 2).End(xlUp).Row
For Each cell In ActiveSheet.Range(Cells(1, 2), Cells(j, 2))
For v = 1 To Len(cell)
k = Asc(Mid(cell, v, 1))
If k >= 97 And k <= 122 Then
If v < 1 Then
Exit For
Else: m = v - 1
End If
l = Asc(Mid(cell, m, 1))
If l >= 65 And l <= 90 Then
y = Len(cell) - (v - 1)
cell.Offset(0, 1) = Mid(cell, m, y + 1)
Else
End If
End If
Next v
Next cell
Next j
End Sub
the first part finds the ":" in the cell value and uses all characters on the left from ":" minus 8 as the cell value for the cell in the column next to it.
The second part has to use this 'new' value to separate the city name from the street name. Fortunately, the street name always starts with a capital and is followed by a non-capital.
And fortunately, the city name is completely in capitals which makes it easier to split the value based on Capital followed by non capital.
I focus on the second part now.
what the second part does is check for each cell and each position in the cell if it is non-capital. If it is, it checks if the position before is capital. If it does, it have to use the all characters from the capital as a new value in the cell in the next column.
This works.
But not for this value:
BELLE- ILE "Belle-Ile" Shop 22 -Quai des Vennes 1
the result from that value is only Vennes 1.
but why? v loops from 1 to the length of the cell. But starts at 1 so position 1 is at the left of the cell value. From this routine, the result should actually be Belle-Ile" Shop 22 -Quai des Vennes 1.
Anyone have the explanation for this?
I will adjust it by hand now, but I am just curious to find out why it returns this values.
Solution: v has to check from len(cell) to 1 step -1. After I changed that, It works almost perfectly.
But I still do not understand why. How I read it, is that v starts testing at the last position works towards the first position of the cell value. Like this, in my opinion, the routine would not work I believe. But somehow it does. The key is understanding why v has to be len(cell) to 1 step -1 instead of 1 to len(cell).
I hope someone can explain this to me.
(I will also try the regex solution after I have got to learn something about it).
I am new to regex, but the following works with the input line given above. No doubt a more elegant solution exists, but this might get you going in the right direction. StackOverflow links I found useful in building the regex patterns:
How to match "anything up until this sequence of characters" in a regular expression?
Regex to match mixed case words
Regex to match only uppercase "words" with some exceptions
How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops
Function Part1(Myrange As Range) As String
Dim regEx As New RegExp
Dim strPattern As String
Dim strInput As String
strPattern = ".+?(?=[A-Z][a-z]+)"
If strPattern <> "" Then
strInput = Myrange.Value
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern
End With
If regEx.test(strInput) Then
Set matches = regEx.Execute(strInput)
For Each Match In matches
Part1 = Part1 & Match.Value
Next
Else
Part1 = "Not matched"
End If
End If
End Function
Function Part2(Myrange As Range) As String
Dim regEx As New RegExp
Dim strPattern As String
Dim strInput As String
Dim strReplace As String
strPattern = ".+?(?=[A-Z][a-z]+)"
If strPattern <> "" Then
strInput = Myrange.Value
strReplace = ""
With regEx
.Global = True
.MultiLine = True
.IgnoreCase = False
.Pattern = strPattern
End With
If regEx.test(strInput) Then
Part2 = regEx.Replace(strInput, strReplace)
regEx.Pattern = ".+?(?=[0-9]{4})"
Set matches = regEx.Execute(Part2)
For Each Match In matches
Part2 = Match.Value
Next
Else
Part2 = "Not matched"
End If
End If
End Function
This is what I have and what satisfies my 'need':
Sub doitall()
Dim cell As Range, j As Integer, i As Integer, x As String
Dim str As String
Dim strlen As Integer
Dim k As Integer
Dim l As Integer
Dim y As Integer
Dim v As Integer
For j = 1 To Cells(Rows.Count, 1).End(xlUp).Row
For Each cell In ActiveSheet.Range(Cells(1, 1), Cells(j, 1))
For i = 1 To Len(cell)
x = Mid(cell, i, 1)
If x = ":" Then Exit For
Next i
cell.Offset(0, 1) = Left(cell, i - 8)
Next cell
Next j
For j = 1 To Cells(Rows.Count, 2).End(xlUp).Row
For Each cell In ActiveSheet.Range(Cells(1, 2), Cells(j, 2))
For v = Len(cell) To 1 Step -1
k = Asc(Mid(cell, v, 1))
If k >= 97 And k <= 122 Then
If v < 1 Then
Exit For
Else: m = v - 1
End If
l = Asc(Mid(cell, m, 1))
If l >= 65 And l <= 90 Then
y = Len(cell) - (v - 1)
cell.Offset(0, 1) = Mid(cell, m, y + 1)
cell.Offset(0, 2) = Left(cell, (m - 1))
Else
End If
End If
Next v
Next cell
Next j
End Sub
It works almost perfectly. except for some cells that have some other characters in the string which are not covered by this routine.
But I believe that could also be added (check op spaces, double quotes etc.)