I'm trying to compare two cells in Excel to retrieve a numeric value, for example:
Trial type Duration Letters shown Distracters Laterality Response Full
6 80 XZHTEJ 0 Bilateral TEHZ
In that line I would like to compare the letters shown with the response, and return a number for how many are correct. I would like it to have the number 4, as there are four letters typed that match the letters shown.
VBA might be more suitable but you have not tagged as such and a formula should work:
=IFERROR(FIND(MID(C1,1,1),F1)>0,0)+IFERROR(FIND(MID(C1,2,1),F1)>0,0)+IFERROR(FIND(MID(C1,3,1),F1)>0,0)+IFERROR(FIND(MID(C1,4,1),F1)>0,0)++IFERROR(FIND(MID(C1,5,1),F1)>0,0)+IFERROR(FIND(MID(C1,6,1),F1)>0,0)
#pnuts' answer works if Letters Shown (in C1) is always 6 or fewer characters.
The following will work if Response (in F1) is always 4 or fewer characters:
=LEN(C1)-
LEN(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(
C1,MID(F1,1,1),""),MID(F1,2,1),""),MID(F1,3,1),""),MID(F1,4,1),"")
)
Either method can easily be expanded as needed.
Just FYI, here is a solution for any length of response. It also has the advantage of being shorter than the other given solutions (I think)
{=SUM(IF(ISERROR(MATCH(MID(F1,ROW(INDIRECT("B1:B"&LEN(F1))),1),MID(C1,ROW(INDIRECT("A1:A"&LEN(C1))),1),0)),0,1))}
It's an array formula so leave out the curly braces and enter the formula using Ctrl+Shift+Enter
The solution creates two arrays like below
Shown Inputted
X T
Z E
H H
T Z
E
J
And then loops through each of the Inputted characters looking for a match in the Shown array and returning a 1 if there is a match, otherwise a 0. Finally the SUM adds all of the 1's (matches) to give the required result.
Related
In xls I have a single cell with multiple arguments in text format like this:
a;c;d;b
I want a formula which tells me the order, so for Input
a it should return 3
c it should return 2
d it should return 1
b it should return 0
the substrings "a", "b" etc. have multiple letters.
First of all take the string value of the cell, then split it based on the semicolons. After that you have an array (or a list) of strings.
Then sort this list as you need.
I cannot figure out your sort order - it looks like you made it up.
So maybe you just need to assemble the strings from the list in your order, but that is what string concatenation should solve.
You can try the following on cell D2:
=LET(split, TEXTSPLIT($A$1,";"), cols, COLUMNS(split),
pos, SEQUENCE(1, cols, cols-1,-1), XLOOKUP(C2:C5, split, pos))
Here is the output:
where the Lookup column have the input values for testing purpose. If you enter a letter that doesn't exist in cell A1, it returns #N/A.
Explanation
LET function is used to avoid repetitions of the same calculations in the formula.
From your requirement it seems you want to return the position in reverse order starting from the number of letters minus 1 and ending in 0.
split variable TEXTSPLIT($A$1,";") generates the following output (column wise):
a c d b
The cols variable COLUMNS(split) calculates the number of columns of the split array. In our case 4.
The pos variable represents the array positions and the output we are looking for, SEQUENCE(1, cols, cols-1,-1) would generate the following output:
3 2 1 0
and XLOOKUP(C2:C5, split, pos) generates the final result.
Notes
If you don't have TEXTSPLIT available in your excel version, you can try instead:
=FILTERXML("<t><s>"&SUBSTITUTE(A1,";","</s><s>")&"</s></t>","//s")
Remember FILTERXML has also some constraints: it is not available in Excel for the web and Excel for Mac. Since the solution generates column-wise arrays, you need to transpose the output of FILTERXML, i.e. TRANSPOSE(FILTERXML(...)).
An alternative if you can't use FILTERXML is the following one. Adapted the response of the question: Split a string (cell) in Excel without VBA (e.g. for array formula) provided by: #Carble:
=LET(txt,A1,del, ";",length, LEN(txt)+1,
items, length-LEN(SUBSTITUTE(txt,";","")),
seq, SEQUENCE(items,,0), findSpaces, FIND(" ",SUBSTITUTE(txt,del," ",seq)),
startTxt, IFERROR(findSpaces+1,1),startDel1, IFERROR(findSpaces,0),
startDel2, IFERROR(FIND(" ",SUBSTITUTE(txt,del," ",seq+1)), length),
MID(txt,startTxt,startDel2-startDel1-1)
)
If your version doesn't allow to use LET, then just replace the value of the variable defined in the formula. It will require SEQUENCE (available from O365 2021). Not having even SEQUENCE will make it very hard. A helper columns will be required to generate the sequences.
Within Excel, is there an array formula or something else that could shorten the formula below? This is only an example going through 12 rows. The actual formula would have thousands of rows, which is why I'd like to find a way to write this formula much shorter. I've considered and tried SUMIF and SUMPRODUCT in addition to what's below, but I haven't found a way for it to check for a specified value in multiple columns, and then doing that for many rows, like a FOR loop would do. The below formula is in Cell J3. I have attached an image of the spreadsheet example.
=SUM(
IF(ISNUMBER(MATCH($I$3,$B3:$E3,0)),$F3,0),
IF(ISNUMBER(MATCH($I$3,$B4:$E4,0)),$F4,0),
IF(ISNUMBER(MATCH($I$3,$B5:$E5,0)),$F5,0),
IF(ISNUMBER(MATCH($I$3,$B6:$E6,0)),$F6,0),
IF(ISNUMBER(MATCH($I$3,$B7:$E7,0)),$F7,0),
IF(ISNUMBER(MATCH($I$3,$B8:$E8,0)),$F8,0),
IF(ISNUMBER(MATCH($I$3,$B9:$E9,0)),$F9,0),
IF(ISNUMBER(MATCH($I$3,$B10:$E10,0)),$F10,0),
IF(ISNUMBER(MATCH($I$3,$B11:$E11,0)),$F11,0),
IF(ISNUMBER(MATCH($I$3,$B12:$E12,0)),$F12,0),
IF(ISNUMBER(MATCH($I$3,$B13:$E13,0)),$F13,0),
IF(ISNUMBER(MATCH($I$3,$B14:$E14,0)),$F14,0))
Use SUMPRODUCT like this:
=SUMPRODUCT($F$3:$F$14*(MMULT(N($B$3:$E$14=I3),TRANSPOSE(COLUMN($B$3:$E$14)^0))>0))
This is an array formula and it needs to be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode.
Improved solution
=SUMPRODUCT($F$3:$F$14,CEILING(((($B$3:$B$14=$I3)+($C$3:$C$14=$I3)+($D$3:$D$14=$I3)+($E$3:$E$14=$I3))/4),1))
Idea : 4 is the number of rows/week. Use ceiling() to normalize value instead of int() n sqrt().
Expansion note : just add another row condition & adjust 4 to the number of rows.
Past solution (for reference)
=SUMPRODUCT($F$3:$F$14,INT(SQRT(INT(SQRT(($B$3:$B$14=$I3)+($C$3:$C$14=$I3)+($D$3:$D$14=$I3)))+($E$3:$E$14=$I3))))
should do.
idea : while $B$3:$B$14=$I3 part is creating an array of 0 n 1, the INT() n SQRT() function 'force' the '+' sum to become 1 even if there is more than 1 match in the same month.
please share if it works/not. (:
p/s : (note for expansion) Upon dissecting the int() and sqrt() function, you can see that sqrt(3)=1.73205 , sqrt(2)1.414213, sqrt(1)=1 and its int() results the same value (1) . So let say you want to add more rows, just use 'bundle' 3 rows together in one int(sqrt(__)) function, recursively.
I have personal ID's in reports I have to find in one cell. Too bad the string in the cell which hides this ID can be anything, the ID can be at the beginning, the end, anywhere, but it is there.
The only thing I know is the pattern "space,letter,letter,number,number,number,number,number,number,space". Jike DB544345
I was looking for the correct word for this "mask", but couldn't find an answer. Thank you for your help.
As the comments are numerous I have created a minimal example that might represent what the OP is dealing with:
A1: 123456789 DB544345 asdfg asdfghjk
A2: creating dummy data is a DB544345 pain
A3: DB5443456 and soething else
parsed a copy of that in ColumnB with Text To Columns (with space as the delimiter) then applied:
=IFERROR(IF(AND(LEN(B1)=8,CODE(LEFT(B1))>64,CODE(LEFT(B1))<91,CODE(MID(B1,2,1))>64,CODE(MID(B1,2,1))<91,ISNUMBER(RIGHT(B1,6)*1),RIGHT(B1,6)*1>99999),B1,""),"")
to K1, copied this across to P1 and then K1:P1 down.
A concise "built-in function only" solution to a problem such as this requires a bit of tinkering as many attempts will dead-end or need workarounds due to deficiencies and quirks in the built-in Excel formulas. I much prefer single cell formulas because they minimally affect the general spreadsheet structure. However, due to the limitations listed above, complex single cell solutions often come at the cost of being rather long and cumbersome (this answer is somehow still only two lines on my formula bar in Excel). I came back to your question and cobbled together a formula that can (as far as I have tested) extract the first occurrence of this pattern with a single cell formula. This is an array formula (Ctrl+Shift+Enter instead of Enter) that assumes your data is in A2. This rough formula returns the first 8 characters if no match is found and throws #REF if the string is shorter than 10 characters.
=MID(A2,MIN(IF(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9))),1)=" ",IF(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+9,1)=" ",IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))>64,IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))<91,IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))>64,IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))<91,IF(IFERROR(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+3,6)*1>99999,FALSE),ROW(INDIRECT("A1:A"&(LEN(A2)-9)))))))))))+1,8)
Let me try to break this down at least on a high level. We are splitting the main text into every possible ten character chunk so that we can test each one using the suggestion of #pnuts to verify the Unicode values of the first two characters and run an ISNUMBER check on the rest of the string. This first block recurs throughout my formula. It generates a list of numbers from 1 to n-9 where n is the length of our main text string.
ROW(INDIRECT("A1:A"&(LEN(A2)-9)))
Let's assume our string is 40 characters long and replace the above formula with {1...31}. Using this number sequence generation we can check if characters 1 to 31 are spaces:
IF(MID(A2,{1...31},1)=" "
Then we can check if characters 10 to 40 are spaces:
IF(MID(A2,{1...31}+9,1)=" "
Then we can check if characters 2 to 32 are capital letters:
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))>64,
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+1,1))<91
Then we can check if characters 3 to 33 are capital letters:
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))>64,
IF(CODE(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+2,1))<91
Then we can check if the strings of characters 4 to 9, 5 to 10, ..., 33 to 38, 34 to 39 are six-digit numbers:
IF(IFERROR(MID(A2,ROW(INDIRECT("A1:A"&(LEN(A2)-9)))+3,6)*1>99999,FALSE)
If all conditions are TRUE, that 10 digit chunk test will return the index of its first character in the string via another instance of the original array {1...31}. Otherwise it returns nothing. We take the Min of all return indexes and then use the Mid function to grab the 8 digit string determined by the aforementioned minimum index:
=MID(A2,MIN(matching index list)+1,8)
I think this will work, if we assume that the SPACE at the beginning and end are merely to differentiate the ID from the rest of the string; hence would not be present if the ID were at the beginning or end of the string. This formula is case insensitive. If case sensitivity is required, we could do character code comparisons.
=LOOKUP(2,1/((LEFT(myArr,2)>="AA")*(LEFT(myArr,2)<="ZZ")*(LEN(myArr)=8)*ISNUMBER(-RIGHT(myArr,6))),myArr)
Where myArr refers to:
=TRIM(MID(SUBSTITUTE(TRIM(Sheet2!A1)," ",REPT(" ",99)),(ROW(INDIRECT("1:10"))-1)*99+1,99))
If myArr is initially defined with the cursor in B1, referring to A1 as shown, it will adjust to refer to the cell one column to the left of the cell in which the Name appears.
The 10 in 1:10 is the maximum number of words in the string -- can be adjusted if required.
I'm using Excel 2010 and I'm looking for a way to return the first negative number of a column. For instance, I have the following numbers distributed in a column:
1
4
6
-3
4
-1
-10
8
Which function could I use to return -3?
Thanks!
This could be interpreted two ways... If all the numbers are in a single cell (one column) as a string, the MID function can be used. If the numbers are in A1, a formula that could work is this:
=VALUE(MID(A1,SEARCH("-",A1),SEARCH(" ",A1,SEARCH("-",A1))-SEARCH("-",A1)))
If the numbers are each in their own columns (in my example, A3:H3), a different technique must be used:
{=INDEX(A3:H3,1,MATCH(TRUE,A3:H3<0,0))}
Don't type the { } - enter the equation using CTRL+SHIFT+ENTER.
In each case, the formula will return the number -3, which is the first negative number in the series.
Another possibility, avoiding the array formula (which are a big source of performance issues):
=LOOKUP(1;1/(M2:M15<0);M2:M15)
(I assume your numbers are in the M2:M15 range).
This will return the first number matching the "<0" condition. You may use any other condition, including text comparisons.
You may also extract the value of another array corresponding to the matching cell:
=LOOKUP(1;1/(M2:M15<>"OK");T2:T15)
In this example, the first cell containing another string than "OK" will be searched for in the m2:m15 array and the corresponding value in array t2:t15 will be returned.
Please note that the usage of the lookup function should be avoided whenever possible (but in this case, it's very handy !)
(I got the original inspiration for this answer from this post)
I am have a string with 6 spaces, e.g. 000000. Each space can hold one of three digits - 0, 1, or 2. I know that I can get a total of 120 permutations using the Permut function in Excel, i.e. =PERMUT(6,3) = 120. But I would actually like to have each individual permutation in a cell, e.g. 000001, 000010, etc.. Ideally, the end result would be 120 rows of unique 6-digit IDs.
Please help if you know a faster way of accomplishing this without entering the figures manually.
Thanks!
There is a VBA functionin the last post on this page. Copy it into a VBA module, then in Excel, create a column of integers from 0 to n where n = the number of IDs you want. In the next column, call the VBA function with the value from the first column as the first argument, and 3 as the second argument. Something like
Column A Column b
0 =baseconv(A1, 3)
1 =baseconv(A2, 3)
2 =baseconv(A3, 3)
... etc.
Your IDs are really just incremental values using a base 3 counting system. You can format the output to get leading zeros with a custom format of '000000'.
Incidentally, with 6 positions and 3 available values, you can get 3 ^ 6, or 729 unique IDs
First, I don't think you're using PERMUT correctly here. What PERMUT(6,3) gives you is the total number of ways to arrange three things picked out of a set of six things. So the result is 120 because you could have 6*5*4 possible permutations. In your case you have 3^6 = 729 possible strings, because each position has one of three possible characters.
Others have posted perfectly fine VBA-based solutions, but this isn't that hard to do in the worksheet. Here is an array formula that will return an array of the last six digits of the ternary (base-3) representation of a number:
=FLOOR(MOD(<the number>,3^({5,4,3,2,1,0}+1))/(3^{5,4,3,2,1,0}),1)
(As WarrenG points out, just getting a bunch of base-3 numbers is one way to solve your problem.)
You would drag out the numbers 0 through 728 in a column somewhere, say $A$1:$A$729. Then in $B$1:$G$1, put the formula:
=FLOOR(MOD(A1,3^({5,4,3,2,1,0}+1))/(3^{5,4,3,2,1,0}),1)
remembering to enter it as an array formula with Ctrl-Shift-Enter. Then drag that down through $B$729:$G$729.
Finally in cell $H$1, put the formula:
=CONCATENATE(B1,C1,D1,E1,F1,G1)
and drag that down through $H$729. You're done!