"--" converts TRUE/FALSE to 1/0. I have found that sometimes "--" is not needed . Math can be done directly on TRUE/FALSE. The following is an example:
=AGGREGATE(14,6,(LEFT(C5:C400,1)="T")*(LEN(C5:C400)=6)*RIGHT(C5:C400,5),1)
Both "(LEFT(C5:C400,1)="T")" and "(LEN(C5:C400)=6)" give an array of TRUE/FALSE. However, this array can be used directly in multiplication without first being converted to 1/0.
When it is not necessary to convert TRUE/FALSE to 1/0 and math would still work?
-- is the same as -1 * -1.
Any time Math is done against a string or boolean that can be converted to a number Excel will make the conversion to the number.
-- is just a shorter method when only one Boolean or number stored as a string is used.
VALUE() can be used in place, or + 0, or * 1 Any math will do it.
If multiple numbers stored as string or multiple Booleans are added or Multiplied or Subtracted or Divided, then the conversion is done and the -- is not needed.
Related
I have a column of numbers in Excel 2016. The numbers span many orders of magnitude, but are all positive. Some are less than zero. How can I return the first significant figure of each cell in a new column?
For example, for the number 1.9 the result should be 1. For the number 0.9 the result should be 9.
Things I've tried:
Using LEFT() to get the first character. This works for values greater than 1, but for numbers between 0 - 1 it returns 0 (that is, LEFT(0.3, 1) returns 0). I've tried using this with scientific notation formatting and it returns the same result.
I've searched Google and SO for solutions to this problem. There are many posts about rounding to significant figures, but I'm looking to truncate, not round.
Reading through Office's online docs regarding scientific notation.
You could use scientific notation:
=LEFT(TEXT(A1,"0.000000000000000E+00"))
Note: You can only have 15 digits of precision in Excel so this should be OK.
you can multiply the number by a factor of 10 significant enough to deal with any 0 not wanted:
=--LEFT(A1*10^LEN(A1),1)
Read the cell value as text, replace dots and zeros (. / 0) with nothing, return the leftmost "character"; multiply it by 1 to coerce it back into a number:
=LEFT(SUBSTITUTE(SUBSTITUTE(TEXT(A1,"#"),".",""),"0",""))*1
You can also create a custom UDF (User Defined Function) that uses Regular Expressions to accomplish this task. This would require copy/paste VBA knowledge, as well as you setting a reference to:
Microsoft VBScript Regular Expressions 5.5
(which can be done by going to the VBE (Alt+F11), Tools > References. Then check the box of the reference listed above)
Paste the following UDF into a standard code module within the VBE:
Public Function SigNum(ByVal InputNumber As Double) As Long
Dim s As SubMatches
With New RegExp
.Pattern = "\.0*([^0])|^([^0])"
If .test(InputNumber) Then
Set s = .Execute(InputNumber)(0).SubMatches
If s(0) > 0 Then ' This is before the period
SigNum = s(0)
Else
SigNum = s(1)
End If
End If
End With
End Function
On your worksheet, you would be able to use your newly created formula as such:
=SigNum(A1)
You can see what it matches in the example on regex101. When viewing this site, green highlighted numbers are what would be returned if the value is < 0, and red would be what is returned if the value > 0). If the value = 0, this will return 0.
Breaking Down the Pattern
Here's how the pattern \.0*([^0])|^([^0]) works. First, you can see that there is a |, which essentially acts like an Or statement, so we will split these into two sections.
First Section \.0*([^0])
\. will match a literal period. This ensures that we are looking at a value that is less than 0.
0* matches all zeros, 0 to unlimited * times. We use * (zero to unlimited) instead of + (1 to unlimited) because a zero is not required to be in front of the significant number - but the zero itself isn't significant.
[^0] This is a negated character class [^...]. This means it will match anything that is not in this class. Since our significant number should be a value other than zero, we do not want to match a zero. And because it's surrounded by a capturing group (...), this is what is returned back to the function.
Second Section ^([^0])
We've established that since the first section didn't match, then the value must be greater than 0.
^ this is an anchor point that matches the beginning of the string. On the first section we didn't require it because we essentially used the period \. as our anchor. Since our value is greater than 0, we need to ensure we are starting from the absolute left of the input number.
(...) Capturing Group. Anything within this group will be returned as a submatch and ultimately back to the function as it's return value.
[^0] Negated Character class. It will match anything except a 0.
I have some data which is badly formatted ( inherited) after some manipulation and some concatenation I have something resembling the following in a string
"SIGNAGE -- 11 Requires door signage. "
My table has to cross reference a some data from a VLOOKUP and then tries to get the first chars in a pattern after the --
My formula is this
=IF(VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)<>"",LEFT((RIGHT((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)), LEN((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)))-SEARCH("--", (VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)),1)-2)),2),"")
This successfully gives me the number 11.
My problem is that the number is being treated as a string and not as a numeric value.
What am I missing?
Use NUMBERVALUE() function to convert a string into a number.
I often use the trick when getting numbers out of text with LEFT(), MID() or RIGHT() to do a "*1" as the final step.
=mid(....) *1
for example,
So, yours would be :
=IF(VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)<>"",LEFT((RIGHT((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)), LEN((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)))-SEARCH("--", (VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)),1)-2)),2),"")*1
In excel, what's the best way to check if a list of strings in a column start or end with another list of strings?
Example:
First List:
Reddy
CodeRed
Zabby
KaBlueY
Second List: Red, Blue, Blop, Blurp
The solution should return:
Reddy - TRUE (because it contains 'red' from the second list in the start or end position)
CodeRed - TRUE (because it contains 'red' from the second list in the start or end position)
Zabby - FALSE (because it does not contain any strings from the second list in the start or end position.
KaBlueY - FALSE (because it does not contain any strings from the second list in the start or end position.
Edited Answer:
The question has been changed, and so should my answer to make it current:
If the second argument of SEARCH function is a range, you may use this formula.
Solution #4: Check if any of the strings in a range contain a substring
=OR(ISNUMBER(SEARCH("red",range)))*1
Result: 1
=OR(ISNUMBER(SEARCH("redX",range)))*1
Result: 0
Same explanation as Solution #1 below but instead of searching for a substring in a "parent" string, it searches multiple strings and is made possible by creating an array formula and can only be done by pressing CTRL+SHIFT+ENTER. Check for {} around your formula in the formula bar to make sure that you created an array formula.
Since there are multiple results in an array formula, wrap it with OR function to see if any of the strings in a range contain the string that you're looking for. Finally, simply multiply it by 1 to convert the resulting boolean values to its numerical values.
Hope it helps!
Original Answer:
There are number of ways to do this. You may use SEARCH or SUBSTITUTE function, to parse the string, in combination with other functions such as those that returns boolean values, to check the expected result against the return value of the former. Finally, to convert boolean values into its numerical values, simply multiply it by 1.
Here are some examples to get you started:
Solution #1
=ISNUMBER(SEARCH("red","reddy"))*1
Result: 1
=ISNUMBER(SEARCH("redX","reddy"))*1
Result: 0
If it is able to find the substring red within the "parent" string reddy, the SEARCH function returns a number—the position of the substring you're looking for. Otherwise, like in the case of redX, it returns #VALUE!. To hide the ugly #VALUE! error message as well as to show a more appropriate message than simply showing the position of the substring, wrap it with ISNUMBER function to return TRUE or FALSE. And if you'd like to convert it to its numerical values, multiply it by 1.
Solution #2
=IF(SUBSTITUTE("reddy","red","anyText")="reddy",FALSE,TRUE)*1
Result: 1
=IF(SUBSTITUTE("reddy","redX","anyText")="reddy",FALSE,TRUE)*1
Result: 0
Here, the resulting string from the SUBSTITUTE function is compared against the "parent" string by wrapping it with IF function, which in turn returns a boolean value that can be converted into a numerical value by multiplying it by 1.
Solution #3
=NOT(EXACT("reddy",SUBSTITUTE("reddy","red","anyText")))*1
Result: 1
=NOT(EXACT("reddy",SUBSTITUTE("reddy","redX","anyText")))*1
Result: 0
This is just a variation of the formula presented in Solution #2. It uses EXACT function to check if the resulting string from the SUBSTITUTE function is exactly the same as the old string (which I called the "parent string" in Solution #1). If it is exactly the same, it means nothing were substituted because it didn't find the string you're looking for. Since EXACT function returns TRUE if the two strings are an exact match, which means nothing has changed, which also means, it didn't find the string you're looking for, you need to reverse the result by wrapping it with NOT function. Again, if you'd like to convert it to its numerical form, simply multiply it by 1.
Hope it helps!
References:
SEARCH
ISNUMBER
OR
SUBSTITUTE
IF
EXACT
NOT
I have this excel formula that someone has created without documentation and I'm struggling to understand it.
=SUMPRODUCT(-MID(TEXT(MID(TEXT(F2,REPT(0,15)),ROW(INDIRECT("1:15")),1)*{2;1;2;1;2;1;2;1;2;1;2;1;2;1;2},"00"),{1,2},1))
it looks like it creates a "random" digit from another number.
There are few key things I'm stuggling with:
* why is there an array ({1,2}) given to a MID() function?
* since there is a SUMPRODUCT(), which needs an array, I'm assuming that the result of the -MID() function is some sort of an array, how do I see what it is?
* what does multplying by an array {2;1;2;1;2;1;2;1;2;1;2;1;2;1;2} does?
* the INDIRECT() functions seems to always return 1?
any help would be appriciated.
There is a function in EXCEL called Evaluate Formula, a good tool to check the formula step by step.
Assuming F2 is 123
REPT(0,15)
Generate a string with 15 "0", that is "000000000000000"
TEXT(F2,[1])
Convert F2 into a string with 15 char. Eg. 123 > "000000000000123"
ROW(INDIRECT("1:15"))
Return an array {1;2;3;4;5;6;7;8;9;10;11;12;13;14;15}
MID([2],[3],1)
Separate [2] into an array, each element is a char {"0";"0";"0";"0";"0";"0";"0";"0";"0";"0";"0";"0";"1";"2";"3"}
[4]*{2;1;2;1;2;1;2;1;2;1;2;1;2;1;2}
Since {A;B} * {C;D} = {A*C;B*D}
{"0";"0";"0";"0";"0";"0";"0";"0";"0";"0";"0";"0";"1";"2";"3"}*{2;1;2;1;2;1;2;1;2;1;2;1;2;1;2}
={0*2;0*1;0*2;....}={0;0;0;0;0;0;0;0;0;0;0;0;2;2;6}
TEXT([5],"00")
Converts the elements in the Array to two char by adding "0" in the front. The array goes to {"00";"00";"00";"00";"00";"00";"00";"00";"00";"00";"00";"00";"02";"02";"06"}
MID([6],{1,2},1)
Note that {A,B} and {A;B} are different. {A,B} is an array with 1 row and 2 columns; {A;B} is an array with 2 rows and 1 column.
In this formula, you can imagine doing MID twice, first time we use 1 as second parameter, second time we use 2 instead.
The result is a 2-D array:
{"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","0";"0","2";"0","2";"0","6"}
SUMPRODUCT(-[7])
The minus sign before [7] will force all elements in the array to convert to numbers with opposite sign.
In this example, it sums 0+0+0+...+(-2)+0+(-2)+0+(-6) = -10
Trying to decipher some Excel formulas and I see some stuff like SUMPRODUCT(--Left(...)...)
What is the -- doing? Naturally seems like decrementing to me but couldn't find any documentation on it.
The double-dash is known as a double unary operator.
Try this link: Why use -- in SUMPRODUCT formulae
Specifically:
SUMPRODUCT() ignores non-numeric entries. A comparison returns a boolean (TRUE/FALSE) value, which is non-numeric. XL automatically coerces boolean values to numeric values (1/0, respectively) in arithmetic operations (e.g., TRUE + 0 = 1).
The most efficient way to coerce the value is first to apply the unary minus operator, coercing TRUE/FALSE to -1/0, then applying it again to negate the value, e.g., +1/0.
A single unary operator (-) coerces true/false values into -1/0. By using the double unary operaor, we coerce the values again to 1/0.
The unary operator (-) is a shorthand method to convert a true/false statement into -1/0.
A single operator will convert -(true) into -1, so a double unary operator is used to convert that back into 1:
-(-(true)) = -(-(1)) = 1
-(-(false)) = -(-(0)) = 0
I've been using SUMPRODUCT for a while and have always used the * symbol instead of the --. I'm sure I asked the same question you've asked, but I can't remember the reason they gave me, but I was told that there wasn't really a need for --as sumproduct managed itself quite well without the it.
Anyway, =sumproduct(()*()*()*()) has always worked for me, and it's less confusing.
Boolean values TRUE and FALSE in excel are treated as 1 and 0, but we need to convert them. To convert them into numbers 1 or 0, do some mathematical operation. The Unary operator negates the boolean (math operation), hence, converts the boolean to number. Same works in TRUE * FALSE = 0