Counting the number of numbers in a range of cells - excel

I am trying to find a formula in an Excel VBA that will count the number of numbers in a range of cells. I have tried a formula but it only counts the number of numbers within a single cell. Can anyone help me with this?
=IF(A1="",0,LEN(A1)-LEN(SUBSTITUTE(A1," ",""))+1)

Paste this code in a module
Function GetNumbCount(Rng As Range) As Long
Dim aCell As Range
Dim MYAr As Variant
Dim n As Long, i As Long
For Each aCell In Rng
If InStr(1, aCell.Value, " ") Then
MYAr = Split(aCell.Value, " ")
For i = LBound(MYAr) To UBound(MYAr)
If IsNumeric(Trim(MYAr(i))) Then n = n + 1
Next i
Else
If IsNumeric(Trim(aCell.Value)) Then n = n + 1
End If
Next
GetNumbCount = n
End Function
And then use it in a worksheet
Syntax
GetNumbCount(Range)
ScreenShot

Cannot understand what is needed and why, but to sum the results of the given formula in the range A1:B2, you could use an array formula like this:
{=SUM(IF(A1:B2="",0,LEN(A1:B2)-LEN(SUBSTITUTE(A1:B2," ",""))+1))}
Use Ctrl+Shift+Enter to enter the formula as an array one

Related

Max of substring in column

Given that I have a column of values in the format
01.2020
12.2021
3.2019
02.2020
etc.
over a million rows or so, I want a VBA function to find the maximum value of the digits to the left of the period.
Something like
Option Explicit
Sub test()
Dim r As Range, c As Range
Dim max As Long, current As Long
Dim s As String
With År_2020
Set r = .Range(.Range("D2"), .Range("D" & .Rows.Count).End(xlUp))
End With
For Each c In r
current = CLng(Left(c, InStr(1, c, ".", vbBinaryCompare) - 1))
If current > max Then max = current
Next c
Debug.Print max
End Sub
works, but I feel like there ought to be a simpler solution.
Can someone please give some input on whether they can find a simpler solution?
Formula solution
formula in B1: =VALUE(LEFT(A1,FIND(".",A1)-1))
in C1: =MAX(B:B)
VBA solution
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim LastRow As Long 'find last used row
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim ValuesToConvert() As Variant 'read data into array
ValuesToConvert = ws.Range("A1", "A" & LastRow).Value 'will throw an error if there is only data in A1 but no data below, make sure to cover that case
Dim iVal As Variant
For iVal = LBound(ValuesToConvert) To UBound(ValuesToConvert)
'truncate after period (might need some error tests if period does not exist or cell is empty)
ValuesToConvert(iVal, 1) = CLng(Left(ValuesToConvert(iVal, 1), InStr(1, ValuesToConvert(iVal, 1), ".") - 1))
Next iVal
'get maximum of array values
Debug.Print Application.WorksheetFunction.Max(ValuesToConvert)
Seems to work. And it is short.
Sub test()
Dim max As Long
max = [MAX(TRUNC(D:D))]
Debug.Print max
End Sub
I always like to propose a naive solution. On the face of it you could do this:
=TRUNC(MAX(--D:D))
(leave the truncation till the end because the part of the number after the decimal point doesn't affect the result)
As pointed out below, this only works correctly for those locales that use a decimal point (period) not a decimal comma.

Conditional Concatenation in Excel

As you can see in the image, there are some 1 and 0s rearranged in 3 rows and one English Alphabet for each column. What I need to do is concatenate the English Alphabets for each row when the respective column value is 0. How can I do it?
Here is a VBA solution that can handle any number of columns (assuming that the letter associated with each column is the standard column label):
Function ZeroColumns(R As Range) As String
Dim n As Long
Dim count As Long
Dim cols As Variant
Dim cell As Range
n = R.Cells.count
ReDim cols(1 To n)
For Each cell In R.Cells
If cell.Value = 0 Then
count = count + 1
cols(count) = Split(cell.Address, "$")(1)
End If
Next cell
ReDim Preserve cols(1 To count)
ZeroColumns = Join(cols, "")
End Function
The code shouldn't be too hard to tweak if the stated assumption doesn't hold.
Conditionally Concatenate Row (UDF)
Arguments
SourceRowRange: The range containing the values that will be
written toCCROW e.g. A, B, C ... Required.
CriteriaRowRange: The range that will be checked for
CriteriaValue. Required.
CriteriaValue: The value that the cells in CriteriaRowRange will
be checked against. Default is 0. Optional.
JoinString: The value that will be put between the values that will
be written to CCROW. Default is "". Optional.
' Copy the following code to a standard module i.e. in VBE go to Insert>Module.
The Code
Function CCROW(ByVal SourceRowRange As Range, ByVal CriteriaRowRange As Range, _
Optional ByVal CriteriaValue As Variant = 0, _
Optional ByVal JoinString As String) As String
Dim vntS As Variant ' Source Array
Dim vntC As Variant ' Criteria Array
Dim NoC As Long ' Number of Columns
Dim j As Long ' Arrays Column Counter
Dim strB As String ' String Builder
Dim strC As String ' Criteria String
' Calculate number of columns of the narrower Range.
NoC = WorksheetFunction.Min(SourceRowRange.Columns.count, _
CriteriaRowRange.Columns.count)
' Copy resized (adjust them to same size) Ranges to Arrays.
vntS = SourceRowRange.Resize(1, NoC)
vntC = CriteriaRowRange.Resize(1, NoC)
' Loop through columns of either Array.
For j = 1 To NoC
' Write current value of Criteria Array to Criteria String.
strC = vntC(1, j)
' Check if Criteria String is NOT empty.
If strC <> "" Then
' Check if Criteria String is equal to Criteria Value.
If strC = CriteriaValue Then
' Check if String Builder is NOT empty.
If strB <> "" Then ' NOT empty.
strB = strB & JoinString & vntS(1, j)
Else ' IS empty (only once).
strB = vntS(1, j)
End If
End If
End If
Next
' Write String Builder to Conditionally Concatenate Row.
CCROW = strB
End Function
Usage in Excel
=CCROW(A$1:I$1,A3:I3) ' Result: ADG
=CCROW(A$1:I$1,A4:I4) ' Result: CFI
=CCROW(A$1:I$1,A5:I5) ' Result: DG
If you add JoinString:
=CCROW(A$1:I$1,A3:I3,,",") ' Result: A,D,G
=CCROW(A$1:I$1,A3:I3,0,",") ' Result: A,D,G
=CCROW(A$1:I$1,A3:I3,0,", ") ' Result: A, D, G
IF you change CriteriaValue:
=CCROW(A$1:I$1,A3:I3,1) ' Result: BCEFHI
=CCROW(A$1:I$1,A4:I4,1) ' Result: ABDEGH
=CCROW(A$1:I$1,A5:I5,1) ' Result: ABCEFHI
Remarks
Lock ($) the row of SourceRowRange to keep it the same when the formula is copied down.
You can do it all in one formula if you like:
=CONCATENATE(IF($A1=0,'A',''),IF($B1=0,'B',''), ...)
Or put the intermediate strings in a separate row and then concatenate them (to save wear and tear on your fingers).
Are you going to this to many more columns, or just the ones you've mentioned? As long as the number of columns is relatively small, as in your picture, you can concatenate IF functions to achieve your result.
Here's what I did:
Using that formula will get you a result like the one you have:
Assuming also that you have the values in a worksheet like mine, just paste the formula =IF(B3=1,"",B$1)&IF(C3=1,"",C$1)&IF(D3=1,"",D$1)&IF(E3=1,"",E$1)&IF(F3=1,"",F$1)&IF(G3=1,"",G$1)&IF(H3=1,"",H$1)&IF(I3=1,"",I$1)&IF(J3=1,"",J$1)
in B7 and then drag to B8 and B9 to get the rest of the results.
Of course, if you are going to do this for many more columns, it's maybe best to use VBA.
Here, add this function to a module.
You can then call it directly via excel. Nice one.
Function conc(ref As Range, Optional Separator As String) As String
Dim Cell As Range
Dim Result As String
For Each Cell In ref
If Cell.Value = 0 Then
Result = Result & chr(64 + Cell.Column) & Separator
End If
Next Cell
If Separator <> "" Then conc = Left(Result, Len(Result) - 1) Else: conc = Result
End Function
The following array formula will do the job (enter it with Ctrl+Shift+Enter):
=CONCAT(IF($A1:$I1=0,UNICHAR(64+COLUMN($A1:$I1)),""))
For older Excel versions, use the legacy functions CONCATENATE() and CHAR() in place of these functions.

Excel duplicate words in row

How do I count only as "2" if the word "apple" show in the same row like row3 and row4 ? The code i need is in Microsoft excel 2010 not vba
Expected Output:
Got very close to figuring out a formula but I'm afraid I bailed and created a UDF instead after getting fed up.
Paste the following into a module in the vba editor (will have to save the file as a .xlsm now as well). This will work for all 2D ranges (i.e. where the count of rows and the count of columns are both greater than 1) a 1D range you can use COUNTIF as stated in the comments above.
Public Function CountStringOccurence(count_text As String, within_range As Range) As Long
Dim arr As Variant
Dim i As Long
' Create array of 1's and 0's (Numerical trues and falses)
arr = Application.Evaluate("--(" & within_range.Parent.Name & "!" & within_range.Address & "=""" & count_text & """)")
' Loop through each row array
For i = LBound(arr, 1) To UBound(arr, 1)
' Get max value in each row and sum (i.e. if there is a True present add it to the total count)
CountStringOccurence = CountStringOccurence + Application.Max(Application.Index(arr, i, 0))
Next i
End Function
and call it using CountStringOccurence(B7,A3:G4)
In the function it first populates an array from the range with 1 if the value in the range matches the string wanted and 0 if it doesn't. It then loops through each row in the array summing the maximum value in the row (i.e. 1 if the value exists and 0 if it doesn't). It then feeds the answer back to the Excel cell
If someone can come up with a formula for it though I'd love to see it.
If you can add an extra column to sheet you can also achieve this doing:
Last column in sheet enter =MAX(--(A3:G3=$B$7)) for each row and then sum this column to get your answer
It may not be the most simple way to do it but here you go:
Public Sub getRowCountOfStringOccurance()
Dim thisRange As Range
Set thisRange = Selection
MsgBox (countStringOccurancesInRows("apple", thisRange))
End Sub
Public Function countStringOccurancesInRows(stringToFind As String, searchRange As Range) As Integer
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim ws As Worksheet
Set ws = wb.ActiveSheet
Dim firstRow As Integer
Dim lastRow As Integer
Dim firstColumn As Integer
Dim lastColumn As Integer
Dim rowOccurances As Integer
rowOccurances = 0
Dim occurances As Integer
occurances = 0
firstRow = searchRange.Rows(1).Row
lastRow = searchRange.Rows.Count + firstRow - 1
firstColumn = searchRange.Columns(1).Column
lastColumn = searchRange.Columns.Count + firstColumn - 1
For thisRow = firstRow To lastRow
For thisColumn = firstColumn To lastColumn
If (ws.Cells(thisRow, thisColumn) = stringToFind) Then
rowOccurances = rowOccurances + 1
End If
Next
If (rowOccurances > 0) Then
occurances = occurances + 1
End If
Next
countStringOccurancesInRows = occurances
End Function
Be aware that I've entered the string for the moment and the range to be searched through has to be selected in the sheet. It will then give a messagebox with the result. While testing I had no issues.

How do I count cells with in a range in excel with specific value that has a comment using vba or formula?

I need help on this. I'm doing a report and inserting comments on cells. How do I count cells with in a range in excel with specific value that has a comment using vba or formula?
Here is one way. It loops through each cell you pass in the range and checks if there is a comment. If so, it adds it to a counter. This is probably going to be pretty expensive if used on large range, but it should at least get you started:
Add to a regular module:
Function CommentCounter(rng As Range) As Integer
Dim cell As Range
Dim counter As Integer
Dim currentComment As String
For Each cell In rng
On Error Resume Next
currentComment = cell.Comment.Text
If Len(currentComment) > 0 Then counter = counter + 1
currentComment = ""
Next cell
CommentCounter = counter
End Function
Just saw the part about having a specific value AND a comment. This should get you going:
Function CommentCounter(rng As Range) As Integer
Dim cell As Range
Dim counter As Integer
Dim currentComment As String
Dim specificValue As String
specificValue = "Something Specific"
For Each cell In rng
On Error Resume Next
currentComment = cell.Comment.Text
If cell.Value = specificValue And Len(currentComment) > 0 Then counter = counter + 1
currentComment = ""
Next cell
CommentCounter = counter
End Function
=COUNTIF(A:A;"comment")
Where A:A specifies that you want to examine the whole column of A. Instead of A:A, you could also use A1:A3, which means examine A1, A2 and A3.
EDIT:
If you want to count the cells with comments (not with the word "comment"), I would suggest to do the following:
=COUNT(A1:A3) - COUNTBLANK(A1:A3)

use more than 30 arguments in sum function in excel

I want to use more than 30 arguments in sum formula for excel, I am using below formula:-
=SUM(IF(AND(ISNUMBER($F$73),ISNUMBER($J$73)),PRODUCT($F$73,$J$73/100),0),IF(AND(ISNUMBER($G$74),ISNUMBER($J$74)),PRODUCT($G$74,$J$74),0))
Above formula will work fine for 30 argumnets, but for more than 30 argumemts excel will return error(#VALUE)
You could batch smaller groups into sub-SUMs like this:
=SUM(SUM(1,2), SUM(3,4),...).
This version will be shorter, you can add as many as you want, only limit will be maximum formula length
=(COUNT(F73,J73)=2)*(F73*J73/100)+(COUNT(G74,J74)=2)*(G74*J74/100)
Perhaps you could save further characters in your formula like this:
=(N(F73)*N(J73)+N(G74)*N(J74))/100
which could be extended much further, but for clarity, I'd suggest writing a custom UDF:
=SPRange((F73,G74),(J73,J74))%
SPRange would work like SUMPRODUCT but operates on multiple ranges:
Function SPRange(Range1 As Range, Range2 As Range) As Double
Dim i As Long, n As Long, rng As Range, Arr() As Double
n = Range1.Count
ReDim Arr(1 To n) As Double
i = 1
For Each rng In Range1
If IsNumeric(rng.Value2) Then Arr(i) = rng.Value2
i = i + 1
Next rng
i = 1
SPRange = 0
For Each rng In Range2
If IsNumeric(rng.Value2) Then SPRange = SPRange + Arr(i) * rng.Value2
i = i + 1
Next rng
End Function
If you want to extend to many ranges you can define names through code:
names.Add "Range1",Range("f73,g74")
names.Add "Range2",Range("j73,j74")
which allows for over 1000 cells in my tests. Then just enter the formula as:
=SPRange(Range1,Range2)%

Resources