My data in column A has comma-separated values (one/two digit numbers).
I need a way to count the number of repeats in two consecutive rows.
Example data:
DATA Expected Results
1,2,3,4,5 4
2,3,4,5 2
3,4 0
10,11,40,60,72,75 3
10,40,3,75
Note that each list doesn't have the same number of values. A1 has 5 values, A2 has 4, A3 has 2, etc.
I'd appreciate any help. Thanks!
Here is one option for B2:
=IFERROR(SUMPRODUCT(--(1*TRIM(MID(SUBSTITUTE(A2,",",REPT(" ",99)),(ROW(INDEX(AAA:AAA,1):INDEX(AAA:AAA,LEN(A2)-LEN(SUBSTITUTE(A2,",",""))+1))-1)*99+1,99))=(TRANSPOSE(1*TRIM(MID(SUBSTITUTE(A3,",",REPT(" ",99)),(ROW(INDEX(AAA:AAA,1):INDEX(AAA:AAA,LEN(A3)-LEN(SUBSTITUTE(A3,",",""))+1))-1)*99+1,99)))))),"")
Enter through CtrlShiftEnter
Drag down...
Picture shows dots as I couldn't use commas due to my version of Excel.
Borrowed some knowledge from here
as a VBA alternative
Public Function commonCount(aRng As Range, bRng As Range) As Integer
Dim bArr() As String, aArr() As String, a As Integer, b As Integer
aArr = Split(aRng.Value, ",")
bArr = Split(bRng.Value, ",")
For a = LBound(aArr) To UBound(aArr)
For b = LBound(bArr) To UBound(bArr)
If aArr(a) = bArr(b) Then
commonCount = commonCount + 1
GoTo nexta
End If
Next b
nexta:
Next a
End Function
In B2 commonCount(A2,A3)
Related
In excel, I need to count the number of rows based on criteria from values in individual columns, and from the sum of a set of multiple columns.
For example, with the attached image of data, I want to be able to count the number of rows which are "valid" (= when Column A = 1), are over 17 years old (= Column B = >17), and when the sum of columns C to G are equal to zero.
I am currently using countifs function, with individual criteria for columns C to G being zero. However, with my actual data there are many more columns than C to G so the formula becomes too large, they are taking a long time to write and very vulnerable to mistakes.
I have tried using sumproduct but this has the same problem with a long formula.
Formulas I have tried;
=COUNTIFS($A:$A, 1, $B:$B, ">17", $C:$C, 0, $D:$D,0, $E:$E,0, $F:$F,0, $G:$G,0)
=SUMPRODUCT(($A:$A=1)*($B:$B>17)*($C:$C=0)*($D:$D=0)*($E:$E=0)*($F:$F=0)*($G:$G=0))
I know I could create a new column with an If function for the sum of columns C-G first (=IF(SUM(C2:G2)=0, 1, 0)), and then include this as a criteria (new column = 1) within a countifs, but I would like to avoid creating new columns with this data.
I would like to do =COUNTIFS($A:$A, 1, $B:$B, ">17", C:G, SUM(C:G)=0), but sum within countifs is not possible.
Any ideas would be very much appreciated?
Image of data:
Sample data:
| Valid | Age | a | b | c | d | e |
|-------|-----|---|---|---|---|---|
| 1 | 18 | 0 | 0 | 0 | 0 | 0 |
| 0 | 8 | 1 | 0 | 0 | 0 | 1 |
| 0 | 48 | 0 | 1 | 0 | 0 | 1 |
| 1 | 22 | 0 | 0 | 0 | 0 | 0 |
You said that you're unhappy with your COUNTIFS formula, but here's an efficient way to still use COUNTIFS (shorter/easier than VBA) and maintain accuracy.
The formula with your example would be:
=COUNTIFS(A:A,1,B:B,">=18",C:C,,D:D,,E:E,,F:F,,G:G,)
This is likely similar what you were using, but note:
If the criteria is "=0" then no criteria need to be specified between the commas.
If the function applies to the entire column, there is no need to specify row numbers.
In fact, even if there's other values
above/below your data (like headings), they'll be ignored
(unless they
meet all the criteria in the formula, which would be unlikely.)
Want to avoid errors? Make Excel write the formula for you!
If you're concerned about making errors when adjusting the formula to your actual data, let Excel do the work for you with three steps. (First save your workbook.)
Select each column (or a cell from each column) that you want to include in your formula. (To select multiple areas, click the first one and then hold Ctrl while you click the rest.)
Copy the line below by highlighting it and hitting Ctrl+C:
?"=COUNTIFS(A:A,1,B:B,"">=18""";:For Each c In Selection.Columns:?","&Columns(c.Column).Address&",";:Next c:?")"
Hit Alt+F11 then Ctrl+GV then Enter (This immediately runs the VBA code from Step 2.)
The formula will appear on the next line. Just copy/paste into to where you want it!
Example output:
=COUNTIFS(A:A,1,B:B,">=18",$C:$C,,$F:$F,,$G:$G,,$P:$P,,$T:$T,,$AJ:$AJ,,$AC:$AC,)
Edit:
I'm not sure why you want/need to use INDIRECT but it's fine as long as you maintain the same syntax. A simplified example:
I have values in Columns A and B. I want to count rows where A=1 and B=1. My COUNTIFS formula (in D2) would be: =COUNTIFS(A:A,1,B:B,1)
The reason to use INDIRECT could be if, for example, I don't always want this to use Column B -- I want to be able to specify which column to use, in a different cell, maybe D5.
In D5 I enter the text: B:B. Then I change the formula is D2, replacing B:B with INDIRECT(D5).
Since E2 contains the text B:B, the formula is still indirectly referring to B:B, and the result of the formula does not change. If I specify a different column range in E2, the formula will look at the new range.
Important Note:
With SUMIFS, COUNTIFS and AVERAGEIFS, all ranges specified must have the same number of rows and columns as the criteria_range1 argument.
In this formula, that means they must be entire columns.
If you're just trying to refer to a column on a different worksheet, that's fine as long as you use correct syntax, such as: =COUNTIFS(A:A,1,Sheet1!D:D,1) to refer to column D on Sheet1.
If the name of the sheet is contained as text in a cell (D5), but you want the column (D:D) still hard-coded, then your INDIRECT section of the formula would be: INDIRECT(D5&"!D:D")
If the specified worksheet name has a SPACE in it, then you need to surround the name with ' apostophes, in the correct spot:
=COUNTIFS(A:A,1,INDIRECT("'" & D5&"'!D:D"),1)
...which is one of the many reasons spaces and other non-alphanumeric characters should be avoided when naming "anything".
This can easily be done with a custom function using VBA. A custom function is a self programmed function that can be used as a normal function in an Excel cell. the function is called countCorrectEntries and takes a Range as Parameter. So if your table(including header) is located in A1:G5 the function in your target cell would be =countCorrectEntries(A1:G5) What it essentialy does is, it initiallizes a variable countCorrect=0 which is going to count all rows that fullfill all conditions.
The loop:
For i = 2 To UBound(table, 1)
...
Next i
Goes through the rows and checks the conditions that look as follows:
If table(i, columnNumber) <> condition Then
conditionsMet = False
End If
It checks in row i (the iterator) if in a column e.g 1 for first does not meet a certain condition. E.g value is not equal to 1. If that is so, a boolean conditionsMet is set to False and it is not counted as correct.
For your sum problem, I propose the following condition:
'Check sum
tempSum = 0
For j = startColumn To EndColumn
tempSum = tempSum + table(i, j)
Next j
If tempSum > 0 Then
conditionsMet = False
End If
The loop within the loop goes over the columns between startColumn and endColumn e.g 3 and 7 for column C to G and sums the values in tempSum. Then it is checked if the sum is greater 0 and again the conditionsMet is set to False if so.
If after all the conditions are checked the conditionsMet is still True then CountCorrect is incremented by 1.
The following code should work for your problem. Just change the inner loop values for the correct columns and you are all set.
Cheers!
Function countCorrectEntries(Rng As Range)
Dim table As Variant
table = Rng
countCorrect = 0
For i = 2 To UBound(table, 1)
conditionsMet = True
If table(i, 1) <> 1 Then
conditionsMet = False
End If
If table(i, 2) < 18 Then
conditionsMet = False
End If
'Check sum
tempSum = 0
For j = 3 To 7
tempSum = tempSum + table(i, j)
Next j
If tempSum > 0 Then
conditionsMet = False
End If
If conditionsMet = True Then
countCorrect = countCorrect + 1
End If
Next i
countCorrectEntries = countCorrect
End Function
In a cell I have a multi value separated by semicolon like this:
Red;Blue;Green
I need to compare if each of those values exist on a list:
Black
Orange
Green
Blue
Red
I think it should be an array formula, but I have no idea how to set it.
Is it even possible?
Regards
MichaĆ
You've not mentioned what output you are looking for. Below are the two possible solution.
1. If you are looking for the count of words in a cell from the list use following formula:
=SUMPRODUCT(ISNUMBER(FIND($E$2:$E$6,$A2))*1)
2. If you want words in the cell that are in the list to be displayed in separate columns, use the following array formula
=IFERROR(INDEX($J$2:$J$6,SMALL(IF(ISNUMBER(FIND($J$2:$J$6,$A2)),ROW($J$2:$J$6)-ROW($J$1)),COLUMNS($A1:A1))),"")
Drag/copy above formula across and down as required.
Being an array formula you'll have to commit this formula by pressing Ctrl+Shift+Enter.
You can write this UDF and use it as a formula. Wasn't sure what output is required. This UDF gives number of items that match in the list.
Parameters:
myValue - the cell that contains multi value separated by semicolon
listRange - Range that has the list to check against. Should be a single column list
Function checkList(myValue As Range, listRange As Range) As Integer
Dim t As Variant
t = Split(myValue.Value, ";")
Dim c As Integer
c = 0
For i = LBound(t) To UBound(t)
For j = 1 To listRange.Rows.Count
If (t(i) = listRange(j, 1)) Then
c = c + 1
End If
Next j
Next i
checkList = c
End Function
Since you want to do this only with excel formulas, the input string has to be split to multiple cells before comparing it with the list.
If your input string is in A1, use the below formula and drag it right to split them based on the delimiter ;.
=TRIM(MID(SUBSTITUTE($A1,";",REPT(" ",999)),1+((COLUMN(A1)-1)*999),999))
Assuming your list is in column G, use the below formula which counts the strings Red, Blue and Green in your list and returns Found or Not found.
in C2,
=IF(COUNTIF($G:$G,C1),"Found","Not found")
Hope this helps.
I have a range of numbers and I need to identify if the first number of each cell is repeated anywhere in the corresponding row.
For example, in row 2 below, column 2 and column 3 both start with a 3. I know that if I do =LEFT(TRIM(cell)) to get just the first number but how do I find the rows that have repeated numbers in the row so row 1 isn't marked but row 2 is?
100|600|203|700| |
202|302|301|400|600|
Use a helper column with this as an array formula:
=SUMPRODUCT(--(COLUMN($A1:$E1)<>MATCH(INT($A1:$E1/100),INT($A1:$E1/100),0)))>0
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode. If done correctly then Excel will put {} around the formula.
Consider the following UDF():
Public Function AnyDups(rng As Range) As Boolean
Dim valu() As String
Dim i As Long, L As Long
L = rng.Count
ReDim valu(1 To L)
AnyDups = False
If L = 1 Then Exit Function
i = 1
For Each r In rng
valu(i) = Left(r.Value, 1)
i = i + 1
Next r
For i = 1 To L - 1
v = valu(i)
For j = i + 1 To L
If v = valu(j) Then AnyDups = True
Next j
Next i
End Function
For example:
The code just loops through the possible combinations of left-most characters in the cells.
It should work with either text or numeric data.
One way to do it would be to use this formula as a basis:
=IF(ISERROR(FIND(LEFT(TRIM(A1),1),B1)),FALSE,"Row "& ROW(A1))
Depending on how you want to check your row, you can adapt it. You could either have one formula to check one cell (Lock the A1 reference and drag right) - which would allow you to know where the match is but take more space on the sheet.
Or, if you don't have too many cells to check in each row, you could concatenate all cells in the same formula:
=IF(ISERROR(FIND(LEFT(TRIM(A1),1),B1&C1&D1&E1)),FALSE,"Row "& ROW(A1))
I'm sure Gary's Student will have a more elegant answer though!
I have a range of cells which I want to do some math on. But I also want those cells to contain some text.
For instance I want the sum of A1 and B1 where A1 contains the number 10 and "z001" and B1 contains the number 20 and "Z004".
Then I want the formula to ignore the text, and just come up with 30.
Is this possible?
For a quick solution, type "=Left(A1, 2) + Left(B1, 2)" into C1. Drag this equation down the rest of your range and you should get the results you want, provided the numbers you are adding are all 2 digits.
You can also use VBA if you need to run the same equation on multiple cells.
If you can get the same results by just removing the letters, try:
For i = 58 To 127
'Change out str with the variable name you have assigned to your cell value.
str = Replace(str, Chr(i), "")
Next i
58 and 127 represent the first and last positions in a range of characters on the Ascii table that are not numerals http://www.asciitable.com/
If you just want to include the first two numbers of each cell in your equation and ignore the "Z00#", you can try:
strLeft = Left(str, 2)
This will reduce your string down to the first two characters of each cell.
You can look here for other ways to remove characters you don't want.
http://www.globaliconnect.com/excel/index.php?option=com_content&view=article&id=269:excel-vba-string-functions-left-right-mid-len-replace-instr-instrrev&catid=79&Itemid=475
Here is in example of how you would implement something like this with simple addition.
Dim a as range
Dim b as range
Dim aLeft as integer
Dim bLeft as integer
Dim cleft as integer
a = Worksheets("WorksheetName").Cells(A1).Value
b = Worksheets("WorksheetName").Cells(B1).Value
aLeft = Left(a, 2)
bLeft = Left(b, 2)
cLeft = aLeft + bLeft
Worksheets("WorksheetName").Cells(C1).Value = cLeft
This would add the first two digits of cells A1 and B1 then display the result in C1.
As I see it, you have 2 options:
Search for the number within each cell and sum it up (see below).
Split the columns to have 1 column of numbers and one of codes (e.g.
"z001"). See on the "Data" tab on the ribbon and click "Text to
Columns" on the Data Tools group.
The first option would be the quickest and more straightforward. You need to make a third column where the sum will be and then use, for example, the function LEFT. This function allows you to retrieve characters from a cell. See example below:
To get "30" I have used the following formula on C2:
=LEFT(A2,2)+LEFT(B2,2)
Note this is not ideal since this formula is looking for 2 characters every time. If you have a scenario with the following code "5z005" it won't work because it will try to sum "5z" as if it was a number. In that case you're better off finding a pattern (code = "number" "z" "number") and splitting the columns as I said on option 2.
I have a column in Excel that consists of data in the following format: "NAME OF BAND Album Title". I'd like to split this cell into two--one for the all-caps band name and another for Album Title. Below are a few examples from the data:
Column A
ABSORBED Demo '98
ABSTRACT CELL THEORY Act
ABSTRACT SATAN Elite 7512
ABSTRACT SATAN Aryan Blitzkrieg Union
ABSTRACT SATAN Satanic Blood Circle
ABSTRACT SHADOWS Symphony of Hakel
Splitting by space doesn't work since bands have varying numbers of words in their name. Any help would be appreciated.
Here is a formula solution. No VBA required.
Assuming your list starts in cell A1, enter the following formula in cell B1:
=LEFT(A1,MATCH(,--(CODE(MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1))<96),)-3)
This is an array formula and must be confirmed with Ctrl+Shift+Enter.
And then in cell C1, enter this:
=MID(A1,MATCH(,--(CODE(MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1))<96),)-1,99)
This is an array formula and must be confirmed with Ctrl+Shift+Enter.
Now select the range B1:C1 and copy downward as far as needed.
.
Here is how they work. We'll discuss the first formula.
The MID function splits the value of cell A1 into individual characters. The CODE function returns the ASCII code number for each char. We test each code number to see if it is less than 96, which is "a" the first lower case char.
This gives us an array of Boolean values (TRUE or FALSE), one Booelan value for each char in cell A1.
We convert the Booleans to ONES and ZEROES by the double unary (--).
We search the array for the location of the first ZERO by using the MATCH function.
The end of the contiguous upper case letters is three char locations prior to the location returned by MATCH.
That's it.
What makes all of that possible is the array at the heart of the formula produced by the ROW/OFFSET combination. In conjunction with the LEN function, this combo produces a vector array that looks something like {1;2;3;4;5;6;7;8;9;10;11}. That array's last and largest number is equal to the length of the value in cell A1.
.
UPDATE
Here is a sample workbook showing these formulas work on the question's example data: http://www.excelhero.com/samples/torentino_excelhero.xlsx
Something like this might split off the band names from the albums.
Sub splt()
Dim rw As Long, p As Long, r As Long, sp As Long, v As Long
Dim bnd As String, ttl As String, tmp As Variant
With Worksheets("Sheet1")
For rw = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
p = 1
bnd = vbNullString
ttl = Trim(.Cells(rw, 1).Value2) & Chr(32)
tmp = Split(ttl)
For v = LBound(tmp) To UBound(tmp)
If UCase(tmp(v)) = tmp(v) Then
bnd = Join(Array(bnd, tmp(v)), Chr(32))
Else
Exit For
End If
Next v
.Cells(rw, 2) = bnd
.Cells(rw, 3) = Trim(Right(ttl, Len(ttl) - Len(bnd)))
Next rw
End With
End Sub