How to convert time values from Xh XXm to decimal - google-sheets

I want to batch convert duration values in google sheets to decimal format.
The format of data that I'm getting is 2h 30m or 1h 6m which AFAIK is not very standard.
Expected results:
Source
Result
2h 30m
2.5
1h 6m
1.1
I've been trying using formatting options, as well as INDEX and SPLIT formulas but did not managed to achieve expected results

If you have source values in range A2:A10, then try the following formula in cell B2:
=arrayformula(query(regexextract(A2:A10,"(\d+)h (\d+)m")*1,"select Col1+(Col2/60) label Col1+(Col2/60) ''"))
Look at the following screenshot:

You are asking how to get "digital hours." It would be better to get actual durations, like this:
=value( regexreplace(A2:10, "(\d+)h (\d+)m", "$1:$2") )
...or, with an array formula that evaluates multiple cells:
=arrayformula( iferror( 1 / value( regexreplace(A2:10, "(\d+)h (\d+)m", "$1:$2") ) ^ -1 ) )
Format the result cells as Format > Number > Duration. See this answer for an explanation of how date and time values work in spreadsheets.

Related

Google sheets sumif with odd data

I have sales data that gives me dates in a bad format. Every new sale gets automatically added to the sheet. Looks like this:
Column A
Column B
Column C
Order 1
2022-12-02T02:09:37Z
$1025.19
Order 2
2022-12-02T01:25:15Z
$873.65
This will continue on for all sales. Now the date format is UTC for whatever reason and I can't adjust that, so within this formula I have to subtract 6 hours to get it to central time. I'm trying to create an auto-updating chart that shows an average day for 7 days, so I'm trying to do a sumif formula.
Here's what I have on Sheet2:
=sumif(Sheet1!C:C,index(split((index(split(Sheet1!B:B,"T"),1)+index(split(left(Sheet1!B:B,19),"T"),2))-0.25,"."),1),A1)
Where A1 is a single date. Testing this with one date and not the range shows that it does match. When I do the range, the total comes to 0, even though multiple different dates should match. What am I doing wrong?
Assume A1 has the value: 2022-12-02T02:09:37Z
Apply this formula:
=LAMBDA(RAW,TUNEHOUR,
LAMBDA(DATE,TIME,
TEXT((DATE&" "&TIME)+TUNEHOUR/24,"yyyy-mm-dd hh:mm:ss")
)(TEXT(INDEX(RAW,,1),"yyyy-mm-dd"),REGEXREPLACE(INDEX(RAW,,2),"Z",""))
)(SPLIT(A1,"T"),-6)
returns:
2022-12-01 20:09:37
And assume you have a set of data like this:
you can apply this formula:
=ArrayFormula(
LAMBDA(DATES,AMOUNTS,START,END,DFORMAT,TFORMAT,SKIPBLANK,TUNEHOUR,
LAMBDA(DATES,AMOUNTS,DTFORMAT,START,END,
LAMBDA(DATES,TIMES,
LAMBDA(VALIDDATES,AMOUNTS,
TEXT(SUM(FILTER(AMOUNTS,VALIDDATES>=START,VALIDDATES<=END)),"$#,##0.00")
)(TEXT((DATES&" "&TIMES)+TUNEHOUR/24,DTFORMAT),IF(ISNUMBER(AMOUNTS),AMOUNTS,VALUE(REGEXEXTRACT(AMOUNTS,"^\$(.+)"))))
)(TEXT(INDEX(DATES,,1),DFORMAT),REGEXREPLACE(INDEX(DATES,,2),"Z",""))
)(SPLIT(QUERY({DATES},SKIPBLANK),"T"),QUERY({AMOUNTS},SKIPBLANK),DFORMAT&" "&TFORMAT,TEXT(START,DFORMAT)&" 00:00:00",TEXT(END,DFORMAT)&" 23:59:59")
)($B$5:$B,$C$5:$C,$B$1,$B$2,"yyyy-mm-dd","hh:mm:ss","WHERE Col1 IS NOT NULL",-6)
)
Where you enter a start date and an end date at B1 & B2 to sum up the amount with.
The provided date column will be deducted by 6 hours.
What this formula does is...
format the date column into a valid date,
compare dates from step 1 with a given start and end date as filter condition,
filter the given amount column with conditions from step 2,
sum the result of filter from step 3 as an array,
format the output as price.
Use regexreplace() and query(), like this:
=arrayformula(
query(
{
weeknum(
regexreplace(B2:B, "([-\d]+)T(\d\d:\d\d).+", "$1 $2")
-
"6:00"
),
C2:C
},
"select Col1, avg(Col2)
where Col1 is not null
group by Col1
label Col1 'week #' ",
0
)
)
I think you're trying to split the values and sum them. I can't understand fully what's the purpose of 19 in LEFT function, and why are you again splitting it? Maybe some approach similar to yours is use LEFT function with 10 characters for the date, and MID from 12th character to get the time. Then substract .25 for the 6 hours as you did, and ROUNDDOWN with 0 digits to get the only the day
=ARRAYFORMULA(ROUNDDOWN(LEFT('Sheet1'!B:B,10)+MID('Sheet1'!B:B,12,8)-0.25,0))
And then you can insert it in your SUMIF:
=SUMIF(Sheet1!C:C,ARRAYFORMULA(ROUNDDOWN(LEFT(Sheet1!B:B,10)+MID(Sheet1!B:B,12,8)-0.25,0)),A1)

Google Sheets: Cell formula NOT working in ARRAYFORMULA

I've a regularly updating sheet of daily foreign exchange rates (descending order sorted).
I've written a cell formula, which works fine if I drag it to the end.
=IFNA( VLOOKUP(A2,USD_TRY!$A$2:$B$3289,2,FALSE), INDEX(USD_TRY!$A$2:$C$3289, MATCH(A2,USD_TRY!$A$2:$A$3289,-1), 3 ) )
Column A2:A is daily dates, merged from 2 different sheets of daily rates and different currencies (so it skips some dates) but it has more dates than the column USD_TRY!A2:A. This formula gets the Price rate from column USD_TRY!B2:B if the VLOOKUP() date matches but if it doesn't match then it gets the Open rate from column USD_TRY!C2:C a row before (a day after) the closest match. However, if I convert the same formula to ARRAYFORMULA() then the VLOOKUP() part works fine but the INDEX(MATCH()) part gives a wrong result of USD_TRY!C2 every time.
IF(
AND(NOT(ISBLANK(A2:A)), NOT(ISBLANK('USD_TRY Historical Data'!A2:A)), NOT(ISBLANK('USD_TRY Historical Data'!B2:B)), NOT(ISBLANK('USD_TRY Historical Data'!C2:C)) ),
ARRAYFORMULA(
IFNA(
VLOOKUP(A2:A,'USD_TRY Historical Data'!A2:B,2,FALSE),
INDEX('USD_TRY Historical Data'!A2:C, MATCH(A2:A,'USD_TRY Historical Data'!A2:A,-1), 3 ) )
)
)
}
How do I correct the ARRAYFORMULA() and is there any simpler way to get the correct results as array?
Source data:
Correct output (with cell formula):
Wrong result (with array formula):
try:
=ARRAYFORMULA(IFNA(
VLOOKUP(A2:A4, E2:F6, 2, 0),
VLOOKUP(90000-A2:A4, {90000-E2:E6, G2:G6}, 2, 1)))

How do I convert a duration string to number? [duplicate]

This question already has answers here:
ultimate short custom number formatting - K, M, B, T, etc., Q, D, Googol
(3 answers)
Closed 8 months ago.
In a Google sheet, I have a list of rows with a length attached to each:
Example 1 - 1h 30m
Using a formula, I need to convert "1h 30m" to a numerical value.
The longest duration I have in the sheet are 4 digit durations (ie 1000h 30m)
Does anyone know how to best do this?
Assuming the text string 1h 30m is in cell B2, use a regexreplace() formula in another cell, like this:
=to_date( value( regexreplace(B2, "(\d+)h (\d+)m", "$1:$2") ) )
Format the formula cell as Format > Number > Duration or a custom time format of your choosing.
See this answer for an explanation of how date and time values work in spreadsheets.
To learn the exact regular expression syntax used by Google Sheets, see RE2.

How to sum the maximum value of each column in Google Spreadsheets?

I have a Google Spreadsheet of numbers. How do I take the maximum value from each column, and summarize them using only one formula? (No temp cells, no scripts.)
1 2 1
0 1 3
0 2 0
For the table above the result should be 6 (1+2+3, the maximum value of each column). But I'd like a solution that works for much larger tables, too.
As a more general question, I'd like to find out how I could fold 2D ranges into 1D arrays using an arbitrary operator (like MAX and SUM in this case).
Assuming your data in range A2:D, to get the maximum of every row (array output) try
=query(transpose(query(if(row(A2:D)>=transpose(row(A2:D)),transpose( A2:D)),"select max(Col1),max(Col2),max(Col3),max(Col4) ",0)),"Select Col2", 0)
If you need to process a lot of columns, this may be better
=ArrayFormula(QUERY(TRANSPOSE(QUERY(TRANSPOSE( A2:D) , "Select "&"MAX(Col"&JOIN( ", MAX(Col",ROW(INDIRECT( "YY1:YY"&ROWS(A2:A)))&")"))), "Select Col2", 0))
To sum, just wrap SUM() around the above formulas.
MAX by columns in A1:C3
=INDEX(QUERY({A1:C3},"Select "&"MAX(Col"&JOIN(", MAX(Col",SEQUENCE(COLUMNS(A1:C3))&")"),0),2)
MAX by rows in A1:C3
=TRANSPOSE(INDEX(QUERY(TRANSPOSE(A1:C3),"Select "&"MAX(Col"&JOIN(", MAX(Col",SEQUENCE(ROWS(A1:C3))&")"),0),2))
Substitute MAX with MIN to get the minimums.

Repeating time windows in Google Spreadsheets?

I'd like to insert time windows repeatedly in a column, like this:
10:00-10:20
10:20-10:40
10:40-11:00
11:00-11:20
11:20-11:40
12:00-12:20
Is there a way to achieve this?
Put data in cells:
B1 = 10:00 (start time)
B2 = 12:20 (end time)
B3 = 20 (interval in minutes)
Here's single arrayFormula, that will generate your column:
=ARRAYFORMULA(TEXT(B1+B3*1/24/60*(row(OFFSET(B8,,,(B2-B1)/(B3*1/24/60)))-row(B7)-1),"HH:MM")&"-"&TEXT(B1+B3*1/24/60*(row(OFFSET(B8,,,(B2-B1)/(B3*1/24/60)))-row(B7)),"HH:MM"))
Explanations
Look at sample file to explore more about this formula. Pay attention on some details:
any kind of logical sequence could be done with help of series 1,2,3... Formula like =ARRAYFORMULA(row(OFFSET(B8,,,7))-row(B7)) gives us column from 1 to 7.
Time treated like numbers in sheets: 1 day is 1, 1 hour is 1/24, 1 minute is 1/24/60 and so on
Time can't be properly converted into text as it's number. So you have to use text(time, "HH:MM") formula to convert time into text.
This will repeat your time window. The formula assumes the time range is in A2:A6.
The 3 in the formula is the number of repeats (change to you need). You might want
to consider placing A2:A6 on another sheet and referencing it in the formula.
=TRANSPOSE(SPLIT(JOIN(",", ARRAYFORMULA(SPLIT(transpose(rept(join(",",A2:A6)&",",3)),",")&",")), ","))

Resources