Protecting TIMEVALUE usage inside SUMPRODUCT from input errors - excel

First question here, thanks in advance for your patience and assistance!
I have a spreadsheet that contains course types (column A, e.g. "Lec" or "Dis"), enrollment numbers (column B, as integers), and session times (column C, string time interval e.g. "10:00AM - 01:00PM").
I need to sum the enrollment numbers for all classes of a certain type (say "Lec") that end before a certain time (say 3:00 PM). The following code accomplishes that:
=SUMPRODUCT(--((A2:A8="Lec")), --(TIMEVALUE(MID(B2:B8,11,5)&" "&MID(B2:B8,16,2))<=TIMEVALUE("03:00 PM")), C2:C8)
The problem is that some of the session times may be blank, which renders a "#VALUE!" error. As best I can tell this is because TIMEVALUE is unable to accept an empty cell as input, so whenever that occurs it breaks the whole thing. I therefore need in this case for the formula to ignore the row and not progress to the various other evaluations.
I have attempted to protect the TIMEVALUE content behind various conditional statements, e.g. only considering that row if the time session length is correct (length=17). I have not been able to do this successfully, however. Nor have my internet searches found a similar-enough situation to use for help.
Because of the circumstances around this project, I am strongly interested in formula solutions before considering things like changing the overall spreadsheet format or adding dummy columns for computations. That said, I welcome any and all suggestions!

Unfortunately, using AGGREGATE as SUM does not skip errors if there is a Calculation in the formula. Similarly, IFERROR and ISERROR only work properly with Ranges/Arrays when in an Array Formula, not when in SUMPRODUCT. That's the easiest options out unless you want a calculation column.
However, all is not lost! First, we reduce your SUMPRODUCT to a single argument with * in place of ,:
=SUMPRODUCT(--(A2:A8="Lec")*--(TIMEVALUE(MID(B2:B8,11,5)&" "&MID(B2:B8,16,2))<=TIMEVALUE("03:00 PM"))*C2:C8)
Next, we change this from =SUMPRODUCT(X) to =SUM(IFERROR(X,0)):
=SUM(IFERROR(--(A2:A8="Lec")*--(TIMEVALUE(MID(B2:B8,11,5)&" "&MID(B2:B8,16,2))<=TIMEVALUE("03:00 PM"))*C2:C8),0)
Just remember to press [Ctrl]+[Shift]+[Enter] instead of just [Enter] to convert to an Array Formula - the formula will display in {Curly brackets}

Related

Error in Excel with Time function within Match function

I am trying to use the Match function to return the row of an indicated table that a certain time value is on. The time is in mm:ss format on the table, so I want users to input the desired time to match as text for their simplicity (with data validation to ensure its correct format), and then use the Time function within the Match function to convert the input to match the format of the table for comparison. However, when using the Time function, the Match function returns the incorrect row, one row number short of what it should be to be precise. I attempted to do some debugging (shown below) and looked into the documentation of both the Time and Match functions, but can't figure out why this would happen. Is there something about the Time function I'm missing?
Here is a breakdown of what I'm using and what I've done to debug and figure out it's the Time function that's causing me issues. Column R has the functions I've been using and their results, and Column S has direct links to the table to show what the output should be. Column T shows that the time values are exactly the same but that using them yields different results in the Match function. Column U is the user input time in text format, and columns V through X are just used to ensure we get to the correct column in the lookup table.
(https://i.stack.imgur.com/ageCW.png)
Here is a snip of the table being referenced in the Match function.
(https://i.stack.imgur.com/FgfGG.png)
Well, this is curious. This is NOT a proper answer, but I needed to enter this as an answer rather than a comment because I needed the space and the markup of a table. I created my own table and ran my own experiment.
I entered the time value of 00:01:23 three different ways:
I typed "00:01:23" into a cell manually.
I entered =TIME(0,1,23) in a cell
I typed "00:01:15" and "00:01:16" into two consecutive cells, and then dragged it down and let Excel autofill.
Here's the results I got:
How Entered
Value
Typed "00:01:23" in Excel
0.0009606481481481480000
=TIME(0,1,23)
0.0009606481481481480000
Fill
0.0009606481481481490000
I emphasized the digit that turned out unexpectedly different.
I then did a MATCH(x,x,1) down this column for each value and it resulted in exactly the behavior you observed. The first two matched 1:22, as they should, because they were ever so slightly less than the table value. The self-referencing MATCH() of the 1:23 cell correctly matched on 1:23.
What is puzzling to me is that my test revealed to me that the value in the lookup table was a tiny bit off, by (0.0000000000000000010000), where your test presented the exact same number, concealing the difference. So in my test, the MATCH() behaved correctly for the data given, even if the data was wrong.
Excel is limited to 15 significant digits, and I have no way of knowing what rounding shenanigans Excel goes through to drop the remaining digits.
My thought goes to wondering how the time values in your lookup table were first created to begin with. Like, were they initially entered in a google sheet and then opened in excel? Is the 15 significant digit rounding handled identically among excel versions and OSes?

Excel Formula Slow

is there anything i can do to further improve performance of this formula ?
=IF($A3<>"",IF(Jan!$E6<>"",LET(d_patt,IF(Jan!$E6<>"",VLOOKUP(Jan!$E6,SETTINGS!$A$12:$B$27,2,FALSE)&IF(Jan!$B6<>"",Jan!$B6,0)&IF(Jan!$C6<>"",Jan!$C6,0)&IF(Jan!$D6<>"",Jan!$D6,0),""),"ROT"&IF(LEN(Teams!$BHR4)>0,MID(Teams!$BHR4,MOD(NETWORKDAYS.INTL(Teams!$C4,I$2,"0000000")-1,LEN(Teams!$BHR4)/3)*3+1,3),"000")&IF(LEFT(d_patt,3)="OVT",d_patt,"OVT000")&IF(LEFT(d_patt,3)="SSI",d_patt,"SSI000")&IF(LEFT(d_patt,3)="SSO",d_patt,"SSO000")&IF(LEFT(d_patt,3)="SDS",d_patt,"SDS000")&IF(LEFT(d_patt,3)="HOL",d_patt,"HOL000")&IF(LEFT(d_patt,3)="LID",d_patt,"LID000")&IF(LEFT(d_patt,3)="UNP",d_patt,"UNP000")&IF(LEFT(d_patt,3)="FLD",d_patt,"FLD000")&IF(LEFT(d_patt,3)="MAT",d_patt,"MAT000")&IF(LEFT(d_patt,3)="LIS",d_patt,"LIS000")&IF(LEFT(d_patt,3)="CBR",d_patt,"CBR000")&IF(LEFT(d_patt,3)="ABS",d_patt,"ABS000")),"ROT"&IF(LEN(Teams!$BHR4)>0,MID(Teams!$BHR4,MOD(NETWORKDAYS.INTL(Teams!$C4,I$2,"0000000")-1,LEN(Teams!$BHR4)/3)*3+1,3),"000")&"OVT000SSI000SSO000SDS000HOL000LID000UNP000FLD000MAT000LIS000CBR000ABS000"),"")
i have this on a sheet for each day of the year x 400 people so 146k+ times. this is therefor taken up 80% of the sheet load time.
The sheet basically gets shift patters from Teams, check if there is any holidays, overtime etc from the relevant month tab and relevant cell for the day, and then will generate a code like below.
ROT080OVT000SSI000SSO000SDS234HOL000LID000UNP000FLD000MAT000LIS000CBR000ABS000
i have so far managed to make this faster by using the LET function, but not show if its possible to make any further improvements.
if you need an example file i can send this or upload somewhere, not sure if that is possible via stackoverflow or a preferred site to upload to.
Thanks
The following is a shortened version of your formula to reduce the complexity of computations.
Instead of building the 'OVT000SSI000...' string one piece after another while always checking if the first 3 characters of 'd_patt' match the current piece, we can set the whole string with '000's as default and only replace the section that matches 'd_patt' (see highlighted elements in screenshot below)
Which results in the full formula:
=IF(LEN($A3)>0,"ROT"&IF(LEN(Teams!$BHR4)>0,MID(Teams!$BHR4,MOD(NETWORKDAYS.INTL(Teams!$C4,I$2,"0000000")-1,LEN(Teams!$BHR4)/3)*3+1,3),"000")&LET(default,"OVT000SSI000SSO000SDS000HOL000LID000UNP000FLD000MAT000LIS000CBR000ABS000",d_patt,VLOOKUP(Jan!$E6,SETTINGS!$A$12:$B$27,2,FALSE)&IF(LEN(Jan!$B6)>0,Jan!$B6,0)&IF(LEN(Jan!$C6)>0,Jan!$C6,0)&IF(LEN(Jan!$D6)>0,Jan!$D6,0),IF(LEN(d_patt)>0,REPLACE(default,SEARCH(LEFT(d_patt,3),default),6,d_patt),default)),“”)
If $B6, $C6 and $D6 can only be either empty or a numerical number, in other words, if they are never a letter or special character, the 'd_patt' function can be further shortened as follows:
Which results in the full formula:
=IF(LEN($A3)>0,"ROT"&IF(LEN(Teams!$BHR4)>0,MID(Teams!$BHR4,MOD(NETWORKDAYS.INTL(Teams!$C4,I$2,"0000000")-1,LEN(Teams!$BHR4)/3)*3+1,3),"000")&LET(default,"OVT000SSI000SSO000SDS000HOL000LID000UNP000FLD000MAT000LIS000CBR000ABS000",d_patt,VLOOKUP(Jan!$E6,SETTINGS!$A$12:$B$27,2,FALSE)&(Jan!$B6+0)&(Jan!$C6+0)&(Jan!$D6+0),IF(LEN(d_patt)>0,REPLACE(default,SEARCH(LEFT(d_patt,3),default),6,d_patt),default)),“”)

Excel percentage increase based on formula

I am trying to fill the sell price column in an Excel spreadsheet with the increased values in colors based on the round up columns value (1 to 50 green, 50 to 100 blue, 100 to 150 yellow, 150+ pink).
I've opted for the percentage table because some items can be sold for a lot more than what I have purchased them for, so that's just for my benefit. I am open to any other suggestions and I am new to this whole business thing.
I was using IF in my formula which would work great for using one percentage increase in the formula:
=IF($E27<50,ROUNDUP(I$27,-1))
If I try to enter a second argument like
=IF(OR($E28<50,ROUNDUP(I$28,-1)OR($E28>50,<100,ROUNDUP(J$28,-1))))
I will get an error.
I'm probably using the formulas wrong, I've tried "AND" and a couple other formulas, but I can't find anyone else trying to achieve the same or similar.
So something like this:
=IF($E28<50,ROUNDUP(I$28,-1),IF($E28>50,ROUNDUP(J$28,-1),"Error"))
But not sure what the <100 was for.
Although the problem is not completely clear, I understand that you want to add a formula with nested if statements.
I will recommend you to try nested ifs in parts.
=IF($E27<50,ROUNDUP(I$27,-1),"First if condition is false")
If everything is working as per the requirement then edit that text in the formula to add another if statement.
=IF($E27<50,ROUNDUP(I$27,-1),IF(OR(condition 1, condition 2,more conditions),"value if true","value if false"))
In the second argument provided by you, the arguments of the OR function has not been properly provided. Ensure that all the arguments of an OR function are conditions separated by a comma.
$E28<50 This is a condition so it's ok.
But other arguments are not making sense.
Also, using OR multiple times inside the first OR arguments is not clear.
It would be beneficial if you could provide the basic table and mention the requirement clearly.

Finding the right range from excel table

What is the best way to find the right column for the travelled miles using visual basic coding or some excel function and return the price from that column? HLOOKUP can't be used here because the lookup value isn't exact and the ranges in the table are also not with specific intervals (If they were, I could use e.g. FLOOR(travelled miles/100)*100 and find the price with HLOOKUP). Obviously, it's easy to find the price manually with a small table but with a big table computer will be faster.
Note that, if x is between a and b, then MEDIAN(x,a,b)=x. Combine this with some nested IFs:
=IF(MEDIAN(B5,B1,C1-1)=B5,B2,IF(MEDIAN(B5,C1,D1-1)=B5,C2,IF(MEDIAN(B5,D1,E1-1)=B5,D2)))
I'm on my phone, so just done the first three cases, but hopefully you can see how it continues.
(should note you need to remove the dashes for this to work)
Edit:
I also want to answer your question in the comments above. You can use the following to keep the dash, but get a number to work with.
Assume cell A1 has got the value 10-. We can use the FIND function to work out where the - occurs and then use the LEFT function to only return the characters from before the dash:
=LEFT(A1,FIND("-",A1)-1)
This will return the value 10, but it will return it as a string, not a number - basically Excel will think it is text. To force Excel to consider it as a number, we can simply multiply the value by one. Our formula above therefore becomes:
=(LEFT(A1,FIND("-",A1)-1))*1
You may also see people use a double minus sign, like this:
=--LEFT(A1,FIND("-",A1)-1)
I don't recommend this because it's a bit complex, but combining with the formula above would give:
=IF(MEDIAN(B5,--LEFT(B1,FIND("-",B1)-1),--LEFT(C1,FIND("-",C1)-1)-1)=B5,B2,IF(MEDIAN(B5,--LEFT(C1,FIND("-",C1)-1,--LEFT(D1,FIND("-",D1)-1-1)=B5,C2,IF(MEDIAN(B5,--LEFT(D1,FIND("-",D1)-1,--LEFT(E1,FIND("-",E1)-1-1)=B5,D2)))

Excel functions: indirect address column

First time asking a question after reading a lot in the past.
I'm running the following array function excel:
INDEX('Available Options'!$A$1:$CM$137,$B$1,
SMALL(
IF(
INDIRECT("'Feasibility Options'!"&ADDRESS($B$1,COLUMN('Feasibility Options'!$G$1),1,1)&":"&ADDRESS($B$1,COLUMN('Feasibility Options'!$O$1),1,1))=2,
COLUMN(INDIRECT("'Feasibility Options'!"&ADDRESS($B$1,COLUMN('Feasibility Options'!$G$1),1,1)&":"&ADDRESS($B$1,COLUMN('Feasibility Options'!$O$1),1,1)))),
ROW('Available Options'!1:1)))
The idea behind this is that there are a number of cells which either have 1s, 2s or 3s in (1 means default, 2 means an alternative and 3 means inactive) in a separate tab called 'Feasibility Options', and the prices for these options are held in the 'Available Options' tab. $B$1 contains a row number produced through a separate calculation.
Evaluating this formula gives a value error when resolving the Indirect part of the function, but the function works if I replace the column number formulae with column numbers as below:
INDEX('Available Options'!$A$1:$CM$137,$B$1,
SMALL(
IF(INDIRECT("'Feasibility Options'!"&ADDRESS($B$1,7,1,1)&":"&ADDRESS($B$1,15,1,1))=2,COLUMN(INDIRECT("'Feasibility Options'!"&ADDRESS($B$1,7,1,1)&":"&ADDRESS($B$1,15,1,1)))),ROW('Available Options'!1:1)))
Could someone explain why this would happen and how to fix it? I ideally need to use cell references rather than hardcoded column numbers as I will likely need to add more columns in at a later date.
Thanks for any help you can give and apologies if I've missed a previous thread which answers this sort of question.
I haven't tested this but I suspect the problem is caused by the COLUMN function which returns an array (even for a single value) and sometimes Excel has trouble processing this:
You can normally make it work by wrapping COLUMN in a SUM or MAX function, e.g.
MAX(COLUMN('Feasibility Options'!$G$1))
or using COLUMNS function instead, something like
COLUMNS('Feasibility Options'!$G$1:G1)
which can be dragged to increment
Better still would be to replace the whole INDIRECT/ADDRESS parts with INDEX, which should be simpler, shorter and more efficient. I can give you more detail on that if you're interested

Resources