Why is this Google Sheets Concatenate Formula giving me weird results? - google-sheets

I'm trying to use Google Sheets to concatenate a bit of data. It works 90% of the time, however on certain numbers, I get an odd result. I have to copy the result of this data and paste it into a financial program in a specific format and am using the concatenate formula to do this. The format the program requires is that each field be separated by one period, even if it is a dollar amount as the program will automatically move the decimal point two places to the left while it is evaluating the information. The issue is that on some numbers the formula adds two periods between the fields, which stops the evaluation of the data in our financial program.
Here is a screenshot including the formula
You can see that it works with most numbers in the amount column, but with two of the amounts and several others, it adds two periods after the amount.
Would you please take a look at this and see if you can help me find the issue?
Thank you!!!!

Looks like it's an existing floating point calculation error in Google Sheets, the multiplication by 100 did not return exact value for certain numbers but with extra very small decimal. That's why there's an additional period on the result.
As a workaround, use ROUND() upon multiplying by 100 to "snap" it to an integer.
Sample:
References:
Floating Point Calculation Error

use just:
=B2&"."&ROUND(C2*100)&"."&D2

Related

How to generate random Double numbers in Google Sheets within range?

I am looking to generate a list of 50 numbers between -.15 to +.15 in Google Sheets
Both rand(), randarray() seem to offer positive numbers only. I hacked my way around n via a conditional =if(F5>=0.5,1,-1), but this seems grossly inelegant.
Is there a better, cleaner way to create a list of positive and negative numbers within a given range? Wish =RANDBETWEEN(-0.15,0.15) would work
Any ideas?
May be
=RAND()*0.3-0.15
so that you will have numbers between -0.15 and +0.15. Or to avoid decimals after .01
=round(RAND()*0.3-0.15,2)

Google Sheets - Split Data

I have these data in Google Sheets
$71,675_x000d_
$80,356_x000d_
$107,361_x000d_
$123,393_x000d_
$116,878
I want them to be split into different columns.
However, when I do so using Data > Split Data into Different Columns, it separates $71 and 675_x000d_ but I need the $71,275 and remove the xoood
Please note that the last number doesn't have those extra characters.
Please help.
Your post says you want to "remove the x000d (that is, extract only the dollar amounts). That said, let's say your raw data starts in A2 (i.e., the data is in A2:A). Place the following formula into the first cell of another otherwise empty column (e.g., B1):
=ArrayFormula({"Extracted";IF(A2:A="",,REGEXEXTRACT(SUBSTITUTE(A2:A&"_",",",""),"\d+"))})
How It Works:
ArrayFormula(...) signifies that we'll be processing an entire range and not just one cell.
The outer curly brackets {...} signify that a virtual array will be formed from non-like or non-contiguous pieces.
The first piece of the virtual array is the header. Here, that is "Extracted"; but you can change it as you like.
The semicolon means "place the next information below the previous part."
IF(A2:A="",, ...) is a standard check that basically says "Don't try to process any blank cells in Column A"; or alternatively worded, "If any cell in A2:A is blank/null, do nothing."
Skipping the REGEXEXTRACT for now, A2:A&"_" appends an underscore to every entry in A2:A. This allows entries in A2:A that are just a dollar amount (e.g., from the post, $116,878) to have a consistent symbol following them if not already there. (And adding the underscore to anything that already has an underscore won't matter, because we won't be extracting that far out.)
Now that we've got the new strings, we SUBSTITUTE every comma for a null (i.e., delete all commas).
Finally, REGEXEXTRACT will take all of the virtually modified strings and extract \d+, which means only digits (\d) in an unbroken sequence of any length greater than 0 (+). Note that REGEXEXTRACT will only return the first such match it encounters as written, so 000 will not be extracted.
An IFERROR wrap is placed around the REGEXEXTRACT, just in case you have any situations in real life that don't have any sequence of numbers at all. In these cases, nothing will be returned (whereas, without the IFERROR, an error would have been returned).
Once the extraction is done, you can apply Format > Number > Currency (rounded) to the entire column.
Addendum:
After an additional comment (below), it appears that the raw data is in Column T, that all five entries are in one cell and that the OP would like all five amounts extracted across each row. That being the case, assuming that Columns U:Y are empty to start, place the following in cell U1 (not U2):
=ArrayFormula({"Va11","Val2","Val3","Val4","Val5";IF(T2:T="",,IFERROR(REGEXEXTRACT(SUBSTITUTE(T2:T&"_",",",""),REPT("\$(\d+)[^\$]*",5))))})
This works much the same way as the previous formula. The differences:
There are five headers now.
You'll see REPT(...,5) here. This is an easy way to repeat the same extraction five times.
That repeated extraction is now the following:
\$(\d+)[^\$]*
The backslash in front of the dollar signs means to treat those symbols as literals instead of as their usual meaning (i.e., end-of-string). So the extraction reads as follows:
\$ anything that starts with a dollar sign
(\d+) extract what is between the ( ), which is any group of digits [^$]*` followed by any number (including 0) characters that are not dollar signs
As I said, the REPT will repeat this five times; so five groups matching this pattern will be extracted.
Understand that if you have any groups that don't follow the pattern exactly, resulting in five matching extractions, nothing will be returned.
Be sure to format U:Y as currency rounded, or you will wind up with some of those numbers translating as raw dates and therefore being completely off.
Please use the following formula and format cells to your needs.
=ArrayFormula(IFERROR(SPLIT(REGEXREPLACE(A2:A,"\n|_x000d_","√"),"√")))
The big advantage of the above formula compared to others is that it works for any number of lines included within a single cell (as shown in the image below).
Functions used:
ArrayFormula
IFERROR
SPLIT
REGEXREPLACE
You can use SPLIT function:
=ArrayFormula(IF(LEN(A:A),SPLIT(A:A,"_x000d_",FALSE),""))

Google sheets - Subtraction giving unexpected results

I have the following sheet:
Why does the difference of two cells with the same value (J7 & J8) not equal zero?
Here is an example spreadsheet.
Switching to Format/Number/Scientific on that cell, you can see the leftover value:
These rounding errors are clearly a regular thing. You can use a formula such as =E3-round(E3,2) to see them for any cell:
Clearly, allowing for a small value in the conditional formatting would avoid the problem:
To add to #df778899's answer, this is not just a "regular thing". It is an unavoidable consequence of floating-point arithmetics.
The surprising thing is that Google apparently represents numbers internally in the floating-point format. For the same numbers, Excel gives the correct result in the equality comparison, which suggests that unlike Google, Excel's representation is fixed-point.
EDIT: upon double-checking, one can find examples of floating point errors in Excel too, so this paragraph is not correct.
Students in computer science are taught to always use approximated and not exact comparison for FP numbers. I think it's unreasonable to expect this from spreadsheets users, though.
In practical terms, when comparing fractionals to other fractionals, avoid using
=if(j7=j8, ...)
or EQ(). Instead, use
=if(abs(J7-J8)<0.0001, ...)
(with appropriate arbitrary precision)

Find a time in some text, allowing for multiple formats

I have the following formula.
=INDEX(Lookups!$L$1:$L$726,MAX(IF(ISERROR(FIND(Lookups!$L$1:$L$726,$A1)),-1,1)*(ROW(Lookups!$L$1:$L$726)-ROW(Lookups!$L$1)+1)))
The idea is to pick up the time for a certain item from an email (already parsed into google sheets). The emails come in various formats so I'm unable to specify the location in the the text string to look at specifically.
The times are not always written in a conventional time format either so as you can see from the formula there are 726 possibilities that I work with. For example, sometimes the time could be written as 13:15 and others as 1:15 or even 1.15 or 1-15 etc etc.
The issue I have is that the above formula seems to start with the smallest string possible and work 'upwards', therefore picking up 3:15 from the email string rather than the full time string which is 13:15. Is there a way I can amend the formula to search for the longest string first, in that example looking for 13:15 and then only searching for 3:15 if the prior is not found.
Hope that makes sense. Thanks in advance for any assistance.
One way is to reorder those 726 possibilities so that you have the longer ones first. You can do it by creating another column with =len(L1), copying that formula down, and sorting the range by this new column in descending order.
But it would be easier to use regexextract instead, because regular expressions are designed to solve the problem you are facing. For example,
=regexextract(L1, "\b\d{1,2}[:.-]\d{1,2}\b")
picks up all of the variants 1:15, 13:15, 1-15 or 13.15. (It looks for the following sequence: word boundary, 1-2 digits, one of characters :, ., -, then 1-2 digits, and another word boundary.) The match is greedy, so it will find 13:15 when it's there, not just 3:15.
A more complex form
=regexextract(L1, "(?i)\b\d{1,2}[:.-]\d{1,2} ?(?:am|pm)?\b")
also supports "am" or "pm" after the time, case-insensitive and possibly separated by a space from the digits.
This can be refined further, for example the hours part would be more precisely stated as [0-2]?\d instead of \d{1,2}, and the minutes part as [0-6]?\d.

How to format cells as weight in grams but removing insignificant decimal point and places?

I have a sheet with values that I want to format in grams. The values range from high to low and I wish to format them with a comma as a thousand-separator, and rounded to two decimal places, but trimming both the decimal point and places where the number is a whole number. The following examples should explain better:
1000 to be presented as 1,000g
0.75 to be presented as 0.75g
0.2 to be presented as 0.2g
0.1234 to be presented as 0.12g
I've tried using a custom number format of #,##0.##g but this does not satisfy my first requirement (a) where the numbers are whole numbers and leaves an insignificant decimal point (i.e. 1,000.g), although does very well at formatting the remaining three requirements (b, c and d).
Is there a way of overcoming this?
#,##0.00_ g;(#,##0.00 g)
I'm a bit late to this article but I found the above format works for me.
Assuming your numbers are in column A with a header. You could try putting this in B2 then hide column A:
=arrayformula(if(arrayformula(TRUNC(A2:A,2)&"g")="0g","",arrayformula(TRUNC(A2:A,2)&"g")))
The best I could do with format was [=0]0;.## It gets rid of the period in 1000 but does not truncate 0.1234 and doesn't add the g. Maybe you could work with that if you must use format. I really don't think format can do it.

Resources