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
Related
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 have a data of 10 x 2 dimension. The data looks like below -
year rate
05-06 10%
06-07 20.222%
07-08 13.17%
.
.
.
I want to print this data as a string within a text box present over the chart object and the format of the first column must be a text and the format of the second column must be truncated to one decimal place with a percent symbol. I have concatenated the data as string and pasted it to the text box object over the chart by mapping the cell containing the formula calling the function below.
The string format should look like below -
05-06 : 10.0% ; 06-07 : 20.2% ; 07-08 : 13.2% ...
I have stored this data as a named range rateCurrent and I have used the below code to generate the string of visible rows.
= ConcatenateVisible(rateCurrent, ":", ";")
For time being, assume I have pasted the data starting at column 3, row 8.
Function ConcatenateVisible(rng As Variant, seperator As String, separator1 As String)
For Each cll In rng
If cll.EntireRow.Hidden = False And rng.Column = 3 Then
Debug.Print rng.Row
ConcatenateVisible = ConcatenateVisible & Format(cll.Value, "#") & seperator
Debug.Print cll.Value
Else
Debug.Print rng.Row
ConcatenateVisible = ConcatenateVisible & Format(cll.Value, "0.0%") & seperator1
End If
Next
ConcatenateVisible = Left(ConcatenateVisible, Len(ConcatenateVisible) - Len(seperator))
End Function
For some reason, the second loop is not working and I am receiving the output like below -
05-06 : 10.00000000000 : 06-07 : 20.2222222222 : 07-08 : 13.1765433333 ....
I tried the below function as well which, when added the if loop for format breaks -
Public Function MakeList(ByVal myRange As Range) As String
On Error GoTo Errhand:
Dim c As Range
Dim MyDict As Object: Set MyDict = CreateObject("Scripting.Dictionary")
For i = 1 To myRange.Cells.Count
For Each c In myRange
If Not Rows(c.Row).Hidden Then
If Not MyDict.exists(c.Value2) Then MyDict.Add c.Value2, 1
End If
Next
Debug.Print c, MyDict.keys
If i Mod 2 = 0 Then
MakeList = Join(MyDict.keys, ": ")
Else
MakeList = Join(MyDict.keys, "; ")
End If
Next
cleanExit:
Set MyDict = Nothing
Set c = Nothing
Exit Function
Errhand:
Debug.Print Err.Number, Err.Description
GoTo cleanExit
End Function
Any hints or help or suggestions are much appreciated. TIA.
Try this:
Option Explicit
Function concatenateVisible(rng As Range, Optional separator As String = " : ", _
Optional separator1 As String = " ; ") As String
Dim rw As Range
Dim str As String
str = ""
For Each rw In rng.Rows
If rw.Hidden = False And Len(rw.Cells(1, 1)) > 0 Then
str = str & separator1 & _
rw.Cells(1, 1) & separator & Format(rw.Cells(1, 2), "0.0%")
End If
Next rw
concatenateVisible = Mid(str, Len(separator1))
End Function
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
I have a string which is in A1 of Sheet1 and it refreshes regularly.
it looks like this -
{"rows":[{"advances":637,"declines":836,"unchanged":76,"total":1549}],"success":"true","results":1}
I want to extract numeric values 637 and 836 and 76 and store it in separate columns. The values keeps on changing, like 637 can be sometimes 1200.
I want a VBA code, not an user defined function to automatically extract the numeric data and store it.
I am using this code, but I am not getting anything. What is wrong?
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" Then
Dim s As String
Dim fieldNames As Variant
Dim iField As Long
Dim nFields As Long
Dim v As Variant
' specify what you want
fieldNames = Array("advances", "declines", "unchanged")
nFields = UBound(fieldNames) - LBound(fieldNames) + 1
s = [a1].Value ' read in the string
' parse it, put values in a Variant array
ReDim v(1 To 1, 1 To nFields)
For iField = 1 To nFields
s = Mid(s, InStr(s, """" & fieldNames(iField - 1) & """:") _
+ Len(fieldNames(iField - 1)) + 3)
v(1, iField) = Left(s, InStr(s, ",") - 1)
Next iField
' write array to sheet
[b1].Resize(1, nFields).Value = v
End If
Range("=Sheet1!$E$1:$G$1").Copy Destination:=Sheets("Updated").Range("B" & Rows.Count).End(xlUp).Offset(1)
Sheets("Updated").Range("A" & Rows.Count).End(xlUp).Offset(1).Value = Now
End Sub
While I would be tempted to use standard functions for this you could run a VBA UDF like so
to get the first match from A1 (as a number)
=RegexMatches(A1,1)
the second match
=RegexMatches(A1,2)
and so on
The UDF returns "No Match" where no matches are found, or a message "Less than X matches" if you try to extract a match from a position that doesb't exist
Function RegexMatches(strIn As String, LngPos As Long)
Dim objRegex
Dim objRegexMC
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.Global = True
.Pattern = ":(\d+),"
If .test(strIn) Then
Set objRegexMC = .Execute(strIn)
If objRegexMC.Count >= LngPos Then
RegexMatches = CLng(objRegexMC(LngPos - 1).submatches(0))
Else
RegexMatches = "Less than " & LngPos & " matches"
End If
Else
RegexMatches = "No Match"
End If
End With
End Function
[Update: added sheet event code]
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
Set rng1 = Sheets("Updated").Range("B" & Rows.Count).End(xlUp).Offset(1, 0)
'set row1 as first row if it is blank
If rng1.Row = 2 And rng1.Offset(-1, 0) = vbNullString Then Set rng1 = rng1.Offset(-1, 0)
rng1.Resize(1, 3).Value = Range("B1:D1").Value
rng1.Offset(0, -1).Value = Now
End Sub
You can use an instance of the windows script control to parse the text for you:
Sub Tester()
Dim JSON As String
Dim sc As Object
JSON = "{""rows"":[{""advances"":637,""declines"":836," & _
"""unchanged"":76,""total"":1549}]" & _
",""success"":""true"",""results"":1}"
'JSON = ActiveSheet.Range("A1").Value
Set sc = CreateObject("ScriptControl")
sc.Language = "JScript"
sc.Eval "var o = eval(" & JSON & ")" 'evaluate to an object
Debug.Print "success", sc.Eval("o.success")
Debug.Print "#results", sc.Eval("o.results")
Debug.Print " advances", sc.Eval("o.rows[0].advances")
Debug.Print " declines", sc.Eval("o.rows[0].declines")
Debug.Print " unchanged", sc.Eval("o.rows[0].unchanged")
End Sub
I needed something similar and developed the following code. I have no doubts that it could be made more sophisticated but it provided me with the required result.
Dim cr_ref As String ' Original reference - alpha and numer
Dim new_ref As String ' Resultant numeirc only reference
Dim iAsciiCode As Integer
Dim sCount As Integer ' Length of reference
cr_ref = Trim(Cells(4, 19).Value) ' Get reference from source
sCount = Len(cr_ref)
new_ref = "" ' Start with empty result
For i = 0 To sCount - 1 ' Strip out all except digits
iAsciiCode = Asc(Mid(cr_ref, i + 1, 1)) ' Give me Ascii code
If iAsciiCode >= 48 And iAsciiCode <= 57 Then ' I only want 0-9
new_ref = new_ref & Mid(cr_ref, i + 1, 1) ' Append numeric digit
End If
Next i
' Result is in new_ref
This works:
Dim s As String
Dim fieldNames As Variant
Dim iField As Long
Dim nFields As Long
Dim v As Variant
' specify what you want
fieldNames = Array("advances", "declines", "unchanged")
nFields = UBound(fieldNames) - LBound(fieldNames) + 1
s = [a1].Value ' read in the string
' parse it, put values in a Variant array
ReDim v(1 To 1, 1 To nFields)
For iField = 1 To nFields
s = Mid(s, InStr(s, """" & fieldNames(iField - 1) & """:") _
+ Len(fieldNames(iField - 1)) + 3)
v(1, iField) = Left(s, InStr(s, ",") - 1)
Next iField
' write array to sheet
[b1].Resize(1, nFields).Value = v