counting blocks and histogram of text data - excel-formula

I have the following challenge. I need to count how many blocks of info are in the column and what the size of each block, using Excel 2013.
Example (data in columns A... actual size of the columns 40.000 entries)
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
7Z7Z
7Z7Z
7Z7Z
B4B4
B4B4
Z2Z2
7Z7Z
7Z7Z
7Z7Z
7Z7Z
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
B4B4
D8D8
7Z7Z
B4B4
B4B4
In this example we have
B4B4 has 4 blocks (1 size 12, 1 size 10, 2 size 2)
7Z7Z has 3 blocks (1 size 4, 1 size 3, 1 size 1)
D8D8 has 1 block size 1
Z2Z2 has 1 block size 1
If possible not using VBA, because I'm not familiar with it.

You could also use a combination of Excel formulae and a pivot table to do it.
Set up a counter in column B which starts at one for each new block:-
IF(A2=A1,B1+1,1)
Set up a label in column C which shows a "Yes" for the end of each block:-
=IF(A3=A2,"No","Yes")
Insert a pivot table which uses the "Data" column for row labels, the "Count" column for column labels, a count field for the Sigma field, and the "Label" column as a filter:-
The pivot table appears like this:-

Here's some VBA code that will do what you want (if I understand correctly)
Sub test()
Dim x As Integer
x = 1
Dim allStrings() As String
ReDim allStrings(0) 'array starts at 1, 0 will be null
Dim datablocks() As Integer
ReDim datablocks(0, 0)
Dim uniqueflag As Boolean
uniqueflag = True
Dim blockcount As Integer
blockcount = 1
Dim Blocks As Integer
Blocks = 1
Dim strReport As String
Do While Cells(x, 1) <> ""
'get unique strings
For y = 0 To UBound(allStrings)
If Cells(x, 1).Value = allStrings(y) Then
uniqueflag = False
End If
Next y
If uniqueflag = True Then
'add unique string to array
ReDim Preserve allStrings(UBound(allStrings) + 1)
allStrings(UBound(allStrings)) = Cells(x, 1).Value
Else
uniqueflag = True 'reset flag
End If
x = x + 1
Loop
ReDim datablocks(UBound(allStrings), 0)
For z = 1 To x - 1
If z > 1 And newblock = flase Then
If Cells(z, 1).Value = Cells(z - 1, 1).Value Then
'current cell is same value as the last
blockcount = blockcount + 1
Else
For w = 1 To UBound(allStrings)
'new block starts, record previous
If Cells(z - 1, 1).Value = allStrings(w) Then 'determine which string the block
ReDim Preserve datablocks(UBound(allStrings), Blocks) 'expand array
datablocks(w, Blocks) = blockcount
Blocks = Blocks + 1
End If
Next w
If z = x - 1 Then
'last item is a block of 1
For w = 1 To UBound(allStrings)
If Cells(z, 1).Value = allStrings(w) Then 'determine which string the block
ReDim Preserve datablocks(UBound(allStrings), Blocks) 'expand array
datablocks(w, Blocks) = 1
Blocks = Blocks + 1
End If
Next w
End If
blockcount = 1
End If
End If
Next z
Dim uniqueblocksizes() As Integer
ReDim uniqueblocksizes(0)
Dim sizeexists As Boolean
sizeexists = False
For w = 1 To UBound(allStrings)
For r = 1 To Blocks - 1
If datablocks(w, r) <> 0 Then
For q = 0 To UBound(uniqueblocksizes)
If uniqueblocksizes(q) = datablocks(w, r) Then
sizeexists = True
End If
Next q
If sizeexists = False Then
ReDim Preserve uniqueblocksizes(UBound(uniqueblocksizes) + 1)
uniqueblocksizes(UBound(uniqueblocksizes)) = datablocks(w, r)
End If
sizeexists = False
End If
Next r
Next w
Dim tally As Integer
Dim summary() As String
ReDim summary(UBound(allStrings))
For w = 1 To UBound(allStrings) 'for strings
summary(w) = "'" & allStrings(w) & "' Has blocks ("
Next w
tally = 0
For q = 1 To UBound(uniqueblocksizes) 'for occurences of blocks
For w = 1 To UBound(allStrings) 'for strings
For r = 1 To Blocks - 1 'for blocks datablocks(w, r)
If uniqueblocksizes(q) = datablocks(w, r) Then
tally = tally + 1
End If
Next r
'MsgBox (tally & " sets of '" & allStrings(w) & "' size " & uniqueblocksizes(q))
If tally <> 0 Then
summary(w) = summary(w) & " " & tally & " of size " & uniqueblocksizes(q) & ", "
End If
tally = 0
Next w
Next q
For w = 1 To UBound(allStrings) 'for strings
summary(w) = summary(w) & ")"
summary(w) = Replace(summary(w), ", )", ")")
MsgBox (summary(w))
Next w
End Sub
Edited to write to data to sheet 3
Sub test()
Dim x As Integer
x = 1
Dim allStrings() As String
ReDim allStrings(0) 'array starts at 1, 0 will be null
Dim datablocks() As Integer
ReDim datablocks(0, 0)
Dim uniqueflag As Boolean
uniqueflag = True
Dim blockcount As Integer
blockcount = 1
Dim Blocks As Integer
Blocks = 1
Dim strReport As String
Sheets(1).Activate
Do While Cells(x, 1) <> ""
'get unique strings
For y = 0 To UBound(allStrings)
If Cells(x, 1).Value = allStrings(y) Then
uniqueflag = False
End If
Next y
If uniqueflag = True Then
'add unique string to array
ReDim Preserve allStrings(UBound(allStrings) + 1)
allStrings(UBound(allStrings)) = Cells(x, 1).Value
Else
uniqueflag = True 'reset flag
End If
x = x + 1
Loop
ReDim datablocks(UBound(allStrings), 0)
For z = 1 To x - 1
If z > 1 And newblock = flase Then
If Cells(z, 1).Value = Cells(z - 1, 1).Value Then
'current cell is same value as the last
blockcount = blockcount + 1
Else
For w = 1 To UBound(allStrings)
'new block starts, record previous
If Cells(z - 1, 1).Value = allStrings(w) Then 'determine which string the block
ReDim Preserve datablocks(UBound(allStrings), Blocks) 'expand array
datablocks(w, Blocks) = blockcount
Blocks = Blocks + 1
End If
Next w
If z = x - 1 Then
'last item is a block of 1
For w = 1 To UBound(allStrings)
If Cells(z, 1).Value = allStrings(w) Then 'determine which string the block
ReDim Preserve datablocks(UBound(allStrings), Blocks) 'expand array
datablocks(w, Blocks) = 1
Blocks = Blocks + 1
End If
Next w
End If
blockcount = 1
End If
End If
Next z
Dim uniqueblocksizes() As Integer
ReDim uniqueblocksizes(0)
Dim sizeexists As Boolean
sizeexists = False
For w = 1 To UBound(allStrings)
For r = 1 To Blocks - 1
If datablocks(w, r) <> 0 Then
For q = 0 To UBound(uniqueblocksizes)
If uniqueblocksizes(q) = datablocks(w, r) Then
sizeexists = True
End If
Next q
If sizeexists = False Then
ReDim Preserve uniqueblocksizes(UBound(uniqueblocksizes) + 1)
uniqueblocksizes(UBound(uniqueblocksizes)) = datablocks(w, r)
End If
sizeexists = False
End If
Next r
Next w
Dim tally As Integer
'Dim summary() As String
'ReDim summary(UBound(allStrings))
'For w = 1 To UBound(allStrings) 'for strings
'summary(w) = "'" & allStrings(w) & "' Has blocks ("
' Next w
Dim tablerows As Integer
tablerows = 2
tally = 0
Sheets(3).Cells(1, 1).Value = "Block Value"
Sheets(3).Cells(1, 2).Value = "Block Size"
Sheets(3).Cells(1, 3).Value = "Occurences"
For q = 1 To UBound(uniqueblocksizes) 'for occurences of blocks
For w = 1 To UBound(allStrings) 'for strings
For r = 1 To Blocks - 1 'for blocks datablocks(w, r)
If uniqueblocksizes(q) = datablocks(w, r) Then
tally = tally + 1
End If
Next r
If tally <> 0 Then
Sheets(3).Cells(tablerows, 1).Value = allStrings(w)
Sheets(3).Cells(tablerows, 2).Value = uniqueblocksizes(q)
Sheets(3).Cells(tablerows, 3).Value = tally
tablerows = tablerows + 1
'summary(w) = summary(w) & " " & tally & " of size " & uniqueblocksizes(q) & ", "
End If
tally = 0
Next w
Next q
'reorder data
'For w = 1 To UBound(allStrings) 'for strings
' summary(w) = summary(w) & ")"
' summary(w) = Replace(summary(w), ", )", ")")
' MsgBox (summary(w))
'Next w
End Sub

Related

Problem with finding similar numbers in 2 columns in vba

i have problem with my code in vba. I have to find how much similar numbers are in column 1 and 2, but for example Column 1 (6,6,34,21,23,40) and column2 (49,34,6,9,6,20) should write 3 cause there are pairs 6-6, 6-6 and 34-34. I know its messy explenation but i hope its understandable. My code so far is:
Sub totolotek()
Dim i As Integer
Dim x As Integer
Dim j As Integer
Dim liczba As Integer
Dim suma As Integer
Dim ileLosowan As Integer
Range("B2:C7").Interior.Color = RGB(135, 134, 125)
Range("B2:B7").Font.ColorIndex = 3
Range("C2:C7").Font.ColorIndex = 5
ileLosowan = 7
Randomize
For i = 2 To ileLosowan
x = Int(Rnd * (49) + 1)
Range("c" & i) = x
Next i
For i = 2 To 7
liczba = Range("c" & i)
For j = 2 To 7
liczbe = Range("b" & j)
If liczbe = liczba Then
Range("c" & i).Interior.Color = RGB(255, 255, 0)
Range("b" & j).Interior.Color = RGB(255, 255, 0)
suma = suma + 1
End If
Next j
Next i
Range("c" & 9) = suma
End Sub
Try this. I invested some time and I added some lines of code. The macro find all the number pairs.
Example (6,6,3,4,2) (2,3,6,9,0) --> results 3: (6-6, 3-3, 2-2)
Sub totolotek()
Dim i As Integer
Dim x As Integer
Dim j As Integer
Dim liczba As Integer
Dim suma As Integer
Dim ileLosowan As Integer
Dim str_B As String, str_C As String, str_BC As String
Dim max_rand As Long
ileLosowan = 20 ' you can change the number of element in the column
max_rand = 49 ' max randum number
start_row = 2 'start_row
str_BC = "B2:C" & ileLosowan
str_B = "B2:B" & ileLosowan
str_C = "C2:C" & ileLosowan
Range(str_BC).Interior.Color = RGB(135, 134, 125)
Range(str_B).Font.ColorIndex = 5
Range(str_C).Font.ColorIndex = 5
Randomize
For i = start_row To ileLosowan
x = Int(Rnd * (max_rand) + 1)
Range("C" & i) = x
Next i
For i = start_row To ileLosowan
x = Int(Rnd * (max_rand) + 1)
Range("B" & i) = x
Next i
liczba_array = Range("B" & start_row & ":B" & ileLosowan).Value2
liczbe_array = Range("C" & start_row & ":C" & ileLosowan).Value2
ReDim ID_array(1 To 1)
ID_array(1) = max_rand + 1
Count = 1
For i = 1 To UBound(liczba_array, 1)
For j = 1 To UBound(liczbe_array, 1)
For k = 1 To UBound(ID_array, 1)
If ID_array(k) = j Then
GoTo out
End If
Next k
If liczba_array(i, 1) = liczbe_array(j, 1) Then
Range("B" & (start_row + i - 1)).Interior.Color = RGB(150 + Count * 20, 0, 0)
Range("C" & (start_row + j - 1)).Interior.Color = RGB(150 + Count * 20, 0, 0)
suma = suma + 1
ID_array(Count) = j
Count = Count + 1
ReDim Preserve ID_array(1 To Count)
Exit For
End If
Next j
out:
Next i
Range("C" & ileLosowan + 2) = suma
End Sub
Something like this will do what you're after. Just incorporate it into you're code cause I don't really know what's going on there.
Dim i As Long, j As Long, arr As Variant, Total As Integer
For i = 2 To 7 'Rows to loop through in the column
Total = 0
arr = Split(Range("A" & i), ",") 'Split column A using the comma
For j = 0 To UBound(arr) 'Loop through the split values
If InStr(Range("B" & i), arr(j)) > 0 Then 'Find if value is within other column
Total = Total + 1 'If it is, add 1 to total
End If
Next j
Range("C" & i) = Total 'Write total to another column on same row
Next i
Or if you want a basic function for it that you can use in your sheet you can use this:
Public Function CountMatches(Cell As String, Rng As Range, Optional Delim As String)
Dim i As Long, j As Long, arr As Variant, Total As Integer
If Delim = "" Then Delim = ","
If Rng.Count > 1 Then
CountMatches = "Please choose 1 cell to compare to."
Exit Function
End If
Total = 0
arr = Split(Cell, Delim) 'Split column A using the comma
For j = 0 To UBound(arr) 'Loop through the split values
If InStr(Rng, arr(j)) > 0 Then 'Find if value is within other column
Total = Total + 1 'If it is, add 1 to total
End If
Next j
CountMatches = Total
End Function
Use it like =CountMatches(A1,B1,",")

How can I add looping per 250 cells and offset the array?

I have this code that looks at column A and loops through to create an array to paste to another destination, but I want to manipulate it to loop through sets of 250 cells and create a concatenated array and print it to cells B1. After that set of 250, I go cells a251-a501, and so forth until I reach the end of the list and have each set of 250 concatenated ID's (separated by a ";") to print to the next destination row (B1>B2>B3, etc..)
Sub JC_Fill()
Dim varArray() As Variant
Dim x As Long, i As Long
i = 0
x = 1
With ThisWorkbook.Worksheets("Sheet1").UsedRange.Rows.Count
ReDim varArray(1) 'resize array
Do Until Cells(x, 1).Value = ""
If Cells(x, 1) <> "" Then
varArray(i) = Cells(x, 1).Value
i = i + 1
ReDim Preserve varArray(i)
End If
x = x + 1
Loop
ReDim Preserve varArray(i - 1)
End With
ThisWorkbook.Worksheets("Sheet1").Range("B1").Value = varArray
End Sub
How could I edit my Do While/Loop to repeat the process every 250 cells and then concatenate the array to one cell separated by ; and then offset the next batch until I have no more ID's to cycle through?
Try changing your code this way:
Sub JC_Fill()
Dim OutString
Dim x As Long, i As Long
Dim out_row As Long
i = 0
x = 1
out_row = 1
With ThisWorkbook.Worksheets("Sheet1").UsedRange.Rows.Count
OutString = ""
Do Until Cells(x, 1).Value = ""
If Cells(x, 1) <> "" Then
If (x > 1) Then OutString = OutString & ";"
OutString = OutString & Cells(x, 1).Value
End If
If (x Mod 250) = 0 Then
ThisWorkbook.Worksheets("Sheet1").Range("B" & out_row).Value = OutString
OutString = ""
out_row = out_row + 1
End If
x = x + 1
Loop
End With
ThisWorkbook.Worksheets("Sheet1").Range("B" & out_row).Value = OutString
End Sub
For interest, you can do this without looping each of the 250 cells.
Sub x()
Dim n As Long, v As Variant, r As Range, n2 As Long
n = 5 '250 for you
n2 = Range("A" & Rows.Count).End(xlUp).Row
Set r = Range("A1").Resize(n)
Do While Len(r(1)) > 0
If n2 - r(1).Row < n Then Set r = r.Resize(n2 - r(1).Row + 1)
If r.Count = 1 Then
v = r.Value
Else
v = Join(Application.Transpose(r), ";")
End If
Range("B" & Rows.Count).End(xlUp)(2).Value = v
Set r = r.Offset(n)
Loop
End Sub

VBA: sorted collection

The code below extracts & format values from the range B6:E6, and then stores them in the variable. Afterwards, the routine sorts the collection of 4 variables in the ascending order. When sorted they're being put into the range L31:O31.
The problem is that if there are less than 4 variables selected, say 3, the routine will skip L31 cell, and put the rest to M31:O31. Whilst it should be input as L31:N31, and O31 - blank.
How can the code be modified to make it fulfill the data starting from L31 if less than 4 variables are in the collection?
Function ExtractKey(s As Variant) As Long
Dim v As Variant, n As Long
v = Trim(s) 'remove spaces leave only spaces between words
If v Like "*(*)" Then 'if it's SOPXX (YYYY) then
n = Len(v) 'find number of the characters
If n = 11 Then
v = Mid(v, n - 7, 7) 'find the number of SOP + year in bracket
ElseIf n = 12 Then
v = Mid(v, n - 8, 8)
End If
v = Replace(v, "(", "") 'replace the brackets with nothing
v = Replace(v, " ", "")
'SOP10 (2015) doesn't have to go first before SOP12 (2014); switch figures
If n = 11 Then
v = Right(v, 4) + Left(v, 1)
ElseIf n = 12 Then
v = Right(v, 4) + Left(v, 2)
End If
ExtractKey = CLng(v)
Else
ExtractKey = 0
End If
End Function
Sub Worksheet_Delta_Update()
Dim SourceRange As Range, TargetRange As Range
Dim i As Long, j As Long, minKey As Long, minAt As Long
Dim v As Variant
Dim C As New Collection
Set SourceRange = Worksheets("t").Range("B6:E6")
Set TargetRange = Worksheets("x").Range("L31:O31")
For i = 1 To 4
v = SourceRange.Cells(1, i).Value
C.Add Array(ExtractKey(v), v)
Next i
'transfer data
For i = 1 To 4
minAt = -1
For j = 1 To C.Count
If minAt = -1 Or C(j)(0) < minKey Then
minKey = C(j)(0)
minAt = j
End If
Next j
TargetRange.Cells(1, i).Value = C(minAt)(1)
C.Remove minAt
Next i
End Sub
You could add one variable e.g. col which will be used instead of variable i when the value is inserted into TargetRange. This variable will work the same way as the i works but it will be incremented only when the value which is inserted is not empty. HTH
'transfer data
Dim col As Integer
col = 1
For i = 1 To 4
minAt = -1
For j = 1 To C.Count
If minAt = -1 Or C(j)(0) < minKey Then
minKey = C(j)(0)
minAt = j
End If
Next j
If (C(minAt)(1) <> "") Then
TargetRange.Cells(1, col).Value = C(minAt)(1)
col = col + 1
End If
C.Remove minAt
Next i

How can I set the range for the Sheet3 lots of columns called(attribute value1,attribute value2..N)

I want this code to search the column name called((attribute value1,attribute value2..N)
If that column contains fraction values, it should convert it to decimal. I'm using this macros(VBA).
The code is working but it is converting only one column(attribute value1).
It will take more time because I have multiple columns(attribute value2...N) that have fraction values.
Please help me out I am struck here.
Sub deci()
Dim LR As Long
Dim Dash As Long
Dim Whole As Double
Dim lngDataColumn As Long
Dim pi
lngDataColumn = 4
Sheets("Sheet3").Select
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
For r = 2 To LR
s = Cells(r, lngDataColumn)
arr = Split(s, ",")
For i = LBound(arr) To UBound(arr)
Whole = 0
P = InStr(arr(i), " IN")
If P > 0 Then
Worksheet = (Left((arr(i)), P - 1))
Else
Worksheet = arr(i)
End If
Dash = InStr(Worksheet, "-")
If Dash > 0 Then
Whole = Frac(Left(Worksheet, Dash - 1))
Worksheet = Mid(Worksheet, Dash + 1)
End If
af = Right(arr(i), Len(arr(i)) - P + 1)
evfrac = Whole + Left(CStr(Evaluate(Worksheet)), 5)
' evfrac = Whole + Format(Evaluate(frac), "0.###")
ss = ss & evfrac & af & ", "
Next i
Cells(r, lngDataColumn) = Left(ss, Len(ss) - 2)
ss = ""
Next r
End Sub
Function Frac(ByVal X As String) As Double
Dim P As Integer, N As Double, Num As Double, Den As Double
X = Trim$(X)
P = InStr(X, "/")
If P = 0 Then
N = Val(X)
Else
Den = Val(Mid$(X, P + 1))
If Den = 0 Then Err.Raise 11 ' Divide by zero
X = Trim$(Left$(X, P - 1))
P = InStr(X, " ")
If P = 0 Then
Num = Val(X)
Else
Num = Val(Mid$(X, P + 1))
N = Val(Left$(X, P - 1))
End If
End If
If Den <> 0 Then
N = N + Num / Den
End If
Frac = N
End Function
The reason it's only doing one column is because that's exactly what your telling it to do with this section of the code:
lngDataColumn = 4
Sheets("Sheet3").Select
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
Because your setting lngDataColumn as a fixed figure, your code is only executed on column 4. If you want to do more columns as a loop, you need to increment this value in the same maner you are incrementing r in your for loop.
For example:
lngDataColumn = 10
Sheets("Sheet3").Select
For 4 To lngDataColumn
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
'Rest of code
Next lngDataColumn

Counting numbers after certain letters have occured down a column (with VBA in excel)

I have data which goes down a column (A:A) (see example).
The only possible values [in this case] are: 1,2,3,4,5,s,f and p,o,a,b,c, (which aren't needed in this case and can be deleted)
1-
2-
s
1
2
3
2
f
s
f
1
s
4
5
3
4
2
s
f
1
2
3
4
I need some code that will count the frequencies of numbers after certain letters have occured. In this case, i want the code to count the numbers after S or F. I have put in bold the numbers after S and in italics the numbers after F. The two numbers at the start can be ignored since no letter precedes them.
I would then need 10 different output variables
After S:
Frequency of 1:## Frequency of 2:## Frequency of 3:## Frequency of 4:## Frequency of 5:##
After F:
Frequency of 1:## Frequency of 2:## Frequency of 3:## Frequency of 4:## Frequency of 5:##
Im assuming the .countif would come in handy, have no idea to make this work though.
Is this what you are looking for? There are other ways to accomplish this as well. Let me know if you have any questions about what I did.
Private Sub CommandButton1_Click()
Dim sOne As Integer
Dim sTwo As Integer
Dim sThree As Integer
Dim sFour As Integer
Dim sFive As Integer
Dim fOne As Integer
Dim fTwo As Integer
Dim fThree As Integer
Dim fFour As Integer
Dim fFive As Integer
Dim lastRow As Integer
lastRow = ThisWorkbook.Sheets(1).Range("A1").End(xlDown).Row
For rows1 = 1 To lastRow
If ThisWorkbook.Sheets(1).Range("A" & rows1) = "s" Then
Do While WorksheetFunction.IsNumber(ThisWorkbook.Sheets(1).Range("A" & rows1 + 1))
If ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 1 Then
sOne = sOne + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 2 Then
sTwo = sTwo + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 3 Then
sThree = sThree + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 4 Then
sFour = sFour + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 5 Then
sFive = sFive + 1
End If
rows1 = rows1 + 1
Loop
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1) = "f" Then
Do While WorksheetFunction.IsNumber(ThisWorkbook.Sheets(1).Range("A" & rows1 + 1))
If ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 1 Then
fOne = fOne + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 2 Then
fTwo = fTwo + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 3 Then
fThree = fThree + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 4 Then
fFour = fFour + 1
ElseIf ThisWorkbook.Sheets(1).Range("A" & rows1 + 1) = 5 Then
fFive = fFive + 1
End If
rows1 = rows1 + 1
Loop
End If
Next rows1
ThisWorkbook.Sheets(1).Range("H2") = sOne
ThisWorkbook.Sheets(1).Range("H3") = sTwo
ThisWorkbook.Sheets(1).Range("H4") = sThree
ThisWorkbook.Sheets(1).Range("H5") = sFour
ThisWorkbook.Sheets(1).Range("H6") = sFive
ThisWorkbook.Sheets(1).Range("J2") = fOne
ThisWorkbook.Sheets(1).Range("J3") = fTwo
ThisWorkbook.Sheets(1).Range("J4") = fThree
ThisWorkbook.Sheets(1).Range("J5") = fFour
ThisWorkbook.Sheets(1).Range("J6") = fFive
End Sub
You don't need VBA code to do this. If your values in column A only consist of the values 1,2,3,4,5,s and f then you can use a helper column as shown in the picture, below.
The formula in cell B2 is
=IF(ISNUMBER(A2),B1,A2)
and this is copied down the remaining cells of column B. After the first s or f is encountered in A, B contains either s or f dependent on which occurred in 'most recently'.
The formula for cell E4 can be seen from the picture and copying this to range E4:I5 provides your results table.
Here's a fairly flexible approach:
Sub Tester()
Dim d As Object, x As Long, k
Dim arrL, arr, L As String, c As Range, tmp
arrL = Array("s", "f")
Set d = CreateObject("scripting.dictionary")
For x = LBound(arrL) To UBound(arrL)
d.Add arrL(x), Array(0, 0, 0, 0, 0)
Next x
Set c = ActiveSheet.Range("A1")
L = ""
Do While Len(c.Value) > 0
tmp = c.Value
If d.exists(tmp) Then
L = tmp 'save the "current" letter
Else
If IsNumeric(tmp) Then
'assuming whole numbers...
If tmp >= 1 And tmp <= 5 Then
If d.exists(L) Then
'can't modify an array stored in a dictionary: copy out
arr = d(L)
arr(tmp - 1) = arr(tmp - 1) + 1
d(L) = arr 'store back in dict
End If
End If
End If
End If
Set c = c.Offset(1, 0)
Loop
'output the letters and counts
For Each k In d.keys
Debug.Print k, Join(d(k), ", ")
Next k
End Sub

Resources