In excel I wanted to differentiate the starting time of a trip into 4 'times of day' (Morning, afternoon, evening, Night)
I made this script, the start_time column consists of time (hh:mm:ss)
=IF(
AND([#[start_time]] >= TIME(20,0,0),
[#[start_time]] <= TIME(23,59,59)
),
"Night",
IF(
AND([#[start_time]] >= TIME(0,0,0),
[#[start_time]] < TIME(6,0,0)
),
"Night",
IF(
AND([#[start_time]] >= TIME(6,0,0),
[#[start_time]] < TIME(12,0,0)
),
"Morning",
IF(
AND([#[start_time]] >= TIME(12,0,0),
[#[start_time]] < TIME(16,0,0)
),
"Afternoon",
"Evening"
)
)
)
)
I was wondering if there is any way to improve this function or make it more easy
Thanks in advance!
So, using vlookup() as suggested:
VLOOKUP(E2,$B$4:$C$8,2,1)
The advantage I find is that the times and the text are easily edited.
Firstly, you can significantly simplify your IF statement by removing the ANDs:
=IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(6,0,0), "Night",
IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(12,0,0), "Morning",
IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(16,0,0), "Afternoon",
IF([#[Start Time]]-ROUNDDOWN([#[Start Time]],0) < TIME(20,0,0), "Evening", "Night")
)
)
The -ROUNDDOWN([#[Start Time]],0) here, allows you to enter a time with or without a date. It is not needed if your times do not also have a date attached.
Using a lookup table instead
The benefit of using a lookup table is that you can easily see and change the cut off times in a single place, rather than searching through multiple formulas.
For Lookups, you should NEVER use VLOOKUP. INDEX/MATCH is better in every way. It is more efficient, less fragile, more versatile, and arguably easier to use, once you are familiar with it.
=INDEX(RefTbl[Times Of Day],MATCH([#[Start Time]]-ROUNDDOWN([#[Start Time]],0),RefTbl[End Time],-1))
Recent Excel version has two functions you might use for this: switch() handles the multiple IF() and LET() gives you the opportunity to create a temporary variable inside your formula. (I would have put this in a comment, but two large URLs make this comment too large)
Related
In my pivot table I added a custom column like this:
=CALCULATE(MAX([Column1]),FILTER(table,expr))
I want to add a new condition and after a few tries, this is working as I expected
=IF([Column2]>5, CALCULATE(MAX([Column1]),FILTER(table,expr)) + 10,
CALCULATE(MAX([Column1]),FILTER(table,expr))
)
but this function is quite long (because expr pretty much the condition), I wonder if there is a LET function or some way that can shorten the above function
=CALCULATE( IF (
[Column2]>5,MAX([Column1])+10, MAX([Column1])
)
,FILTER(table,expr))
However this formula doesn't work,
Is there a better solution for this?
I have the following nested IFs (I know the comments aren't Excel comments, but using them in my text editor helps me through the logic)
// start by seeing if there is an order date
=IF(
$C46<>"",
//there is an order date. have the parts begun to arrive # P2?
IF(
$D46<>"",
//parts have begun to arrive # P2. Have they finished transferring to Brevard?
IF(
$F46<>"",
// product has finished transferring to warehouse. has it begun to ship?
IF(
$G46<>"",
// product has begun to ship. Has it shipped completely?
IF(
$H46<>"",
// has shipped completely. this ends the cycle
IF(
AND(J$5>=$G46,J$5<=$H46),
"S",
"error - shipped completely"
),
// has NOT shipped completely. Here's where to TODAY() formula comes in
IF(
AND(J$5>=$G46,J$5<=TODAY()),
"S",
"error - began shipping, but not complete"
)
)
// product has NOT begun to ship; HAS completely transferred to Brevard. It's in inventory until shipping begins
IF(
AND(J$5>$F46,J$5<=TODAY()),
"I",
"error - finished transferring to Brevard. in Inventory. Not begun to ship"
)
),
// product has begun assembly, but has not finished transferring to Brevard.
IF(
AND(J$5<=$D46,J$5<=TODAY()),
"A",
"error - assembly has begun, has not finished transferring"
)
),
//there is an order date, but parts have not arrived at P2
IF(
AND(J$5<=C46,J$5<=TODAY()),
"O",
"error - order has been taken, assembly has not begun"
)
),
// there is no order date
""
)
When rendering all this, Excel is stringing together the FALSE values and as a result, they are turned into #VALUE, which ruins the entire formula.
What am I doing wrong? If I remove the FALSE values, it still renders #VALUE. I don't understand how to tell it to do exactly nothing, especially multiple times in one algorithm.
You are having too many ELSE in the formula. Thus, after some debugging this is what you get:
at some point. Thus, the #VALUE appears. In general, the nested if syntax in Excel is like this:
Thus, every new =IF is in the ELSE place. Thus, only one ELSE is written (number 5 from the screenshot above)
IF function – nested formulas and avoiding pitfalls
F9 is a good friend in the evaluation of a big formula. Once you select the formula, select a whole internal formula and press F9 to see the result.
I am trying to write a formula that takes a word and process it through a IF function in excel, The Values are list in the formula. My issue right now is the fact that I have Large, X-Large and 1X-Large text. The X-Large and 1X-Large are unique strings and need the IF function to be able to differentiate the two.
Here is what i have so far.
=if(or(isnumber(search("Small",af2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),,ISNUMBER(SEARCH("X-Large",AF2))),"Small",or(isnumber(search("1X-Large",af2)),isnumber(search("2X-Large",af2)),isnumber(search("3X-Large",af2)),isnumber(search("4X-Large",af2))),"1X-Large")
I cant understand why it's showing an error and only displays small when it works.
All help is appreciated
Your current formula shouldn't work, it should be giving you an error about having too many arguments. A breakdown of your function:
=if(
or(isnumber(search("Small",af2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),,ISNUMBER(SEARCH("X-Large",AF2))),
"Small",
or(isnumber(search("1X-Large",af2)),isnumber(search("2X-Large",af2)),isnumber(search("3X-Large",af2)),isnumber(search("4X-Large",af2))),
"1X-Large"
)
You cannot use 4 parameters in an IF. You need to have a maximum of 3. Maybe what you meant was:
=if(
or(isnumber(search("Small",af2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),,ISNUMBER(SEARCH("X-Large",AF2))),
"Small",
IF(
or(isnumber(search("1X-Large",af2)),isnumber(search("2X-Large",af2)),isnumber(search("3X-Large",af2)),isnumber(search("4X-Large",af2))),
"1X-Large"
)
)
But that doesn't solve your issue about the X-Large part. To cater for that, you can check whether the X-Large series exist first, then the others.
=IF(
OR(ISNUMBER(SEARCH("1X-Large",AF2)),ISNUMBER(SEARCH("2X-Large",AF2)),ISNUMBER(SEARCH("3X-Large",AF2)),ISNUMBER(SEARCH("4X-Large",AF2))),
"1X-Large",
IF(
OR(ISNUMBER(SEARCH("Small",AF2)),ISNUMBER(SEARCH("Medium",AF2)),ISNUMBER(SEARCH("Large",AF2)),ISNUMBER(SEARCH("X-Large",AF2))),
"Small"
)
)
Although you can make it shorter with this:
=IF(
OR(ISNUMBER(SEARCH({"1X-Large","2X-Large","3X-Large","4X-Large"},AF2))),
"1X-Large",
IF(
OR(ISNUMBER(SEARCH({"Small","Medium","Large","X-Large"},AF2))),
"Small"
)
)
In one line...
=IF(OR(ISNUMBER(SEARCH({"1X-Large","2X-Large","3X-Large","4X-Large"},AF2))),"1X-Large",IF(OR(ISNUMBER(SEARCH({"Small","Medium","Large","X-Large"},AF2))),"Small"))
I have Excel sheets where the same column can contain a value with % formatting and also with decimal notation.
To clarify: In Excel both have the same formatting but due to different Excel versions (locations) SSIS shows them like this:
1,3% or 0.814260540128523
These values come in as strings so I'm trying to figure out a way to divide the % formatted values by 100 and leave the others as is.
Initially I used:
(DT_R8)[F5_CONV] < 1 ? (DT_R8)[F5_CONV] : (DT_R8)[F5_CONV] / 100
in a second derived column but I then realized that 0,23% is also a possible value.
I think something like this should do it but I'm having trouble with the DT_WSTR and DT_R8 types.
(F5 == "" || ISNULL(F5)) ? NULL(DT_WSTR,40) : FINDSTRING(F5,"%",1) > 0
? (DT_WSTR,40)REPLACE(REPLACE(F5,".",","),"%","") / 100
: (DT_WSTR,40)REPLACE(F5,".",",")
Hope you can help me out here.
Thank you.
(F5 == "" || ISNULL(F5)) ? NULL(DT_WSTR,40) : FINDSTRING(F5,"%",1) > 0
? (DT_WSTR,40)((DT_R8)REPLACE(REPLACE(F5,".",","),"%","") / 100)
: (DT_WSTR,40)REPLACE(F5,".",",")
You can also use script component. Here is a quick solution; you may need to add validations for null. Let us know, if you need help.
I have two excel functions that I am trying to convert into R:
numberShares
=IF(AND(N213="BOH",N212="BOH")=TRUE,P212,IF(AND(N213="BOH",N212="Sell")=TRUE,ROUNDDOWN(Q212/C213,0),0))
marketValue
=IF(AND(N212="BOH",N213="BOH")=TRUE,C213*P212,IF(AND(N212="Sell",N213="Sell")=TRUE,Q212,IF(AND(N212="BOH",N213="Sell")=TRUE,P212*C213,IF(AND(N212="Sell",N213="BOH")=TRUE,Q212))))
The cells that are referenced include:
c = closing price of a stock
n = position values of either "buy or hold" or "sell"
p = number of Shares
q = market value, assuming $10,000 initial equity (number of shares*closing price)
and the tops of the two output columns that i am trying to recreate look like this:
output
So far, in R I have constructed a dataframe with the necessary four columns:
data.frame
I just don't know how to write the functions that will populate the number of shares and market value columns. For loops? ifelse?
Again, thank you!!
Covert the AND()'s to infix "&"; the "=" to "=="; and the IF's to ifelse() and you are halfway there. The problem will be in converting your cell references to array or matrix references, and for that task we would have needed a better description of the data layout:
numberShares <-
ifelse( N213=="BOH" & N212=="BOH",
#Perhaps PosVal[213] == "BOH" & PosVal[212] == "BOH"
# ... and very possibly the 213 should be 213:240 and the 212 should be 212:239
P212,
ifelse( N213=="BOH" & N212=="Sell" ,
round(Q212/C213, digits=0),
0))
(You seem to be returning incommensurate values which seems preeety questionable.) Assuming this is correct code despite my misgivings the next translation involves apply the same substitutions in this structure (although you seem to be missing an else-consequent in the last IF function:
marketValue <-
IF( AND(N212="BOH", N213="BOH")=TRUE,
C213*P212,
IF(AND(N212="Sell",N213="Sell")=TRUE,
Q212,
IF( AND(N212="BOH",N213="Sell")=TRUE,
P212*C213,
IF(AND(N212="Sell",N213="BOH")=TRUE,
Q212))))
(Your testing for AND( .,.)=TRUE is I believe unnecessary in Excel and certainly unnecessary in R.)