Trying to understand what the following conditional split expression is trying to do:
ISNULL(Employee_ID_WD) || (RIGHT(REPLACENULL(Employee_ID_WD,"0"),LEN(REPLACENULL(Employee_ID,"0"))) != REPLACENULL(Employee_ID,"0"))
I am new to SSIS, can anyone explain this?
It’s a relatively straight forward expression when you break it down.
To put it succinctly (tl;dr), if the Employee_ID_WD is null OR the Employee_ID value is not in the Employee_ID_WD value, then return true. Otherwise, return false.
Details:
The first part, ISNULL(Employee_ID_WD), checks to see of the Employee_ID_WD is null. If it is, the expression will return true, right away. The reason for that is the || right after. This is called a logical or. If you see this in many programming it indicates that the programmer wants to the expression to return right away if any part of it before the || is true. In other words, if something before the || is true, start doing what I need you to do, there is no sense in checking anything in this expression, I know what I need to know in order to move on. This is referred to as short-circuit evaluation. Wiki.
If the Employee_ID_WD is not null, we move on to the next part of the expression.
This part:
(RIGHT(REPLACENULL(Employee_ID_WD,"0"),LEN(REPLACENULL(Employee_ID,"0")))
is grabbing the characters on the right side of the Employee_ID_WD. The number of characters it is asking for is what is returned from the LEN (length) function being run on the Employee_ID. Also, both parts of this are checking if the value they pass in is null, as indicated by the REPLACENULL function. If they are null, a string with the value 0 is returned. This is done in case one of the values are null, this way you get a true value comparison. Using the REPLACENULL function in all parts of this expression makes it that much more robust, meaning inconsistencies with data will be handled without something error-ing out, or giving in consistent results in the end.
The results from the part above are compared to REPLACENULL(Employee_ID,"0"). If the part above and this are not equal (!= is not equal to), then the expression returns true.
SSIS Expression Reference
Related
I hope my title is clear enough. I'm working in MS Report Builder, using a function that applies a regular expression to a queried value in order to get back a certain substring. The regex works fine, so I'll demonstrate a simpler version here to make this less wordy. Here's the gist of my equation:
=IIF(Len(Fields!CourtLocation.Value) < 1, "none",System.Text.RegularExpressions.Regex.Match(Fields!CourtLocation.Value, "(?:[A-Z]{2,4})").Value))
The main purpose is to get that substring, but I added the IIF so that on those occasions when the CourtLocation.Value is empty (I tried Is Nothing in my expression as well), the function returns "none" rather than "#Error"
I've been looking around for a solution, but nothing has worked; it seems like most other people who talk about this are using a mathematical equation rather than trying to get a string. Can anyone help me get rid of that stupid "#Error" value?
You could try this (untested)
=System.Text.RegularExpressions.Regex.Match(
IIF(
Len(Fields!CourtLocation.Value) < 1,
"none",
Fields!CourtLocation.Value
)
, "(?:[A-Z]{2,4})"
).Value
This way the IIF is performed on the string that you want to pass to the regex function, so it always gets a valid value to process
Iif evaluates both sides, so you can nest two Iif statements to avoid the error.
Did you already read this one?
https://sqldusty.com/2011/08/01/ssrs-expression-iif-statement-divide-by-zero-error/
I'll copy the text into the answer if that solves it for you.
I am hoping someone can help me here. I am using the PMT function to calculate mortgage payments in SSRS. I am using the following Formula
=IIF(Note = "Present",-PMT(Rate/12,Term,Balance,0,DueDate.EndOfPeriod),Nothing))
The formula works perfectly when Note = Present. However on all other loans it is producing #ERROR. I don't understand why this is happening.
Is there some other error handling that needs to be done to simply leave the cell blank if the note is not present?
I'm not familiar with PMT but it could be that the values passed to PMT are invalid for loans where Note is not "Present". If this is the case then I would use a SWITCH statement instead. SWITCH will stop at the first expression that evaluates to True, whereas IIF evaluates all expressions, even the expression that does not get used!
try this..
=SWITCH(
Note <> "Present", Nothing,
True, -PMT(Rate/12,Term,Balance,0,DueDate.EndOfPeriod)
)
This way, if note is not "Present" then return nothing and only if it IS "Present" evaluate the PMT function and return its value. The True just acts like an else to save us writing Note = "Present" for the second condition
SSRS will always evaluate both sides of a conditional expression, no matter what the result of the first parameter boolean test. This means that
-PMT(Rate/12,Term,Balance,0,DueDate.EndOfPeriod)
must be a valid calculation for rows where Note <> "Present" as well or you will get an expressions error. I would suggest that probably some of the other fields aren't populated with appropriate "dummy" values in this scenario.
What is Nothing in your code?
=IF(Note = "Present",-PMT(Rate/12,Term,Balance,0,DueDate.EndOfPeriod),0))
I'm having an issue and everything i've tried doesn't work. I have a phone number datafield that returns numbers with no formatting '3055558798' but i want it to look like this '(305)555-8798'. I can get that done with this expression:
= Format(Convert.ToDouble(Fields!MyFieldName.Value), "(###)###-####")
The only issue is that when the return is null i get #ERROR in the space. I found an expression that got rid of the #ERROR but still no luck putting them both together. I would have to dig through my reports to find the expression but hopefully someone can help me. I've been doing reports for a couple of months but i'm still not very good with all the expressions that there are. I just need to format the phone number and if the return is null then not show anything. There's also this on the same site that i found the expression but it doesn't work so i dont know why the guy said it worked for him.
=Iif (Fields!MyFieldName.Value Is Nothing, Nothing,
Format(Convert.ToDouble(Fields!MyFieldName.Value), "(###)###-####"))
That just doesn't work for me, I believe the syntax is wrong but i don't know what to change to fix it. Thanks.
The error you have got is nothing to do with formatting, it is the conversion to Double that is failing. So your expression works perfectly as long as your field consists entirely of numeric characters. However, you have some data with non-numeric characters in it, causing the Convert.ToDouble() function to throw an error.
Unfortunately this can not be solved with an IIF expression because IIF is a function, not a language construct so both the true and false parameters get evaluated before being passed to the function regardless of the value of the boolean condition parameter. This means that:
=IIF(IsNumeric(Fields!Phone.Value), Format(Convert.ToDouble(Fields!Phone.Value), "(###)###-####"), Fields!Phone.Value)
will always attempt the conversion to double regardless of the result of the IsNumeric function. There are two ways to solve this:
Use Val instead of ToDouble
The problem with ToDouble is it errors when the string to be converted is an inappropriate form; Val doesn't have that problem - it simply grabs whatever numbers it can. So now we can use the expression:
=IIF(Fields!Phone.Value Is Nothing,
Nothing,
IIF(IsNumeric(Fields!Phone.Value),
Format(Val(Fields!Phone.Value), "(000)000-0000"),
Fields!Phone.Value)
)
(Use 0 rather than # so that leading zeroes aren't suppressed)
This expression returns Nothing if the field is Null, checks to see if it is numeric and if so converts it to a number and formats it, otherwise it just returns whatever is in the field.
Note that the Val function is still being run even when the field is not numeric but this expression succeeds because the Val function doesn't raise errors like ToDouble. We simply make the calculation and discard the result.
Custom code
On the Report menu, click Report Properties... and go to the Code tab. Insert the following code:
Function FormatPhone(Phone AS String) AS String
IF (Phone Is Nothing) Then
Return Nothing
Else If (IsNumeric(Phone)) Then
Return Format(Convert.ToDouble(Phone), "(000)000-0000")
Else
Return Phone
End If
End Function
Use the following expression in your phone number cell:
=Code.FormatPhone(Fields!Phone.Value)
Item in the recordset rstImportData("Flat Size") is = Null
With that, given the following statement:
IIF(IsNull(rstImportData("Flat Size")), Null, cstr(rstImportData("Flat Size")))
Result: Throws error 94: Invalid use of Null
If I change the statement by removing the type conversion upon a false comparison:
IIF(IsNull(rstImportData("Flat Size")), Null, 0)
Result: Null
It returns Null as it should have the first time. It appears that I cannot do a type conversion in an IIF if the value passed in should ever be null even if it passes an IIF test, it still attempts to evaluate it at both the true and false answer. The only reason I'm using IIF like this is because I have a 25 line comparison to compare data from an Import against a matching record in a database to see if I need to append the prior to history.
Any thoughts? The way data is imported there will be null dates and where the spreadsheet import is in a string format I must convert either side to the other to compare the values properly but if either side is null this exception occurs :(
EDIT
Example of why I was using IIF (and considering using a universal function)
If master("one") <> import("one") Or _
master("two") <> import("two") Or _
master("date") <> import("date") Or _ //import("date") comes from a spreadsheet, it comes in as string, CAN be a null value
master("qty") <> import("qty") Or _ //import("qty") comes from spreadsheet, comes in as a string can CAN be null
master("etc") <> import("etc") Then
....stuff....
End If
This code expands for roughly 20 columns to compare in the database. I would prefer to check as part of the statement. I can think of a bunch of solutions but they involve adding much more code. If that is the case power to it, however I'm not one to give in so easily.
Options I see are
Creating temp vars to do the work prior to comparing and using these new vars instead of the recordset
Creating an object to pass the record into to preformat and work with, though extra work would provide this functionality to each import type since there are different files with similar fields
I'm here for ideas, and I'm open to any interesting pieces that can be thrown my way as I get to decide how to do it I'm looking for the most reusable approach.
The simple expedient of changing the value to a string helps tremendously. The trick is that trimming a string which is NULL will get a null string. Which can then be operated on as if it wasn't a database null.
I frequently use the form:
CInt("0" & Trim(SomeVariant & " "))
To get a valid number without having to go through a bunch of hijinks. The null is a nonentity for this problem.
The behavior you described is the standard way IIf operates under VBA. This is part of what Access 2003 Help says about it:
"IIf always evaluates both truepart and falsepart, even though it returns only one of them. Because of this, you should watch for undesirable side effects. For example, if evaluating falsepart results in a division by zero error, an error occurs even if expr is True."
However, if you use an IIf statement in a query, evaluation short circuits after truepart when expr is True --- falsepart is not evaluated in that case. Unfortunately this information is not useful for you ... unless you can incorporate a query into your comparison.
I don't know of any other way to avoid your error with IIf. I would try appending the Excel data into a table whose structure matches that of the table you will compare against, thereby eliminating the need to do a string conversion at the same time you do the comparison.
I have a textbox in my SSRS 2005 report. The expresssion for this textbox is:
=IIF(IsDBNull(Fields!fOrgID), Code.SetMyVar("null"), Code.SetMyVar(Fields!fOrgID.Value))
I have also tried IsNothing(Fields!fOrgID) and a few other variations of checking for nulls.
I have modified the SetMyVar function for testing and it now looks like this:
Public Function SetMyVar (var as String)
MsgBox(var, VbOKCancel, "Test1")
If var Is Nothing Then
Return "NOTHING"
Else
MyVar = var
Return var
End If
End Function
I also have the public variable MyVar:
Public Shared Dim MyVar as String
When my database query returns data, this correctly evaluates, a messagebox is displayed with the value, the textbox gets set with the value, and the world is generally a happier place.
When my database query does not return a value though, I get the error:
The query returned no rows for the data set. The expression therefore
evaluates to null.
and the SetMyVar function never appears to be ran (you never get the messagebox popup). As expected, my emotions range from anger, sadness, and bitter hatred of SSRS.
I read something about SSRS evaluating both sides of an IF statement, so perhaps that is why I get the error (likely then on Code.SetMyVar(Fields!fOrgID.Value))... not sure how I get around that though.
Thoughts? Suggestions? Words of comfort?
From the sound of things, it seems likely that the issue is that SSRS is having a problem displaying zero records. I'd recommend one of the following:
1) Use a control that handles zero records appropriately (Tables do. I think Lists do as well).
2) Modify your query to return a single record with blank values if it would otherwise return zero records.
An answer to the original question:
=IIF(IsNothing(Fields!fOrgID),
Code.SetMyVar("null"),
Code.SetMyVar(IIF(IsNothing(Fields!fOrgID),"Foo",Fields!fOrgID.Value)))
The error was from both sides of IIF being evaluated. The extra IIF in the statement above will avoid Code.SetMyVar from ever being called with a null value.
I believe you're right about about Iif always evaluating both of its value arguments (at least, it does in Visual Basic). I'm not sure why you're getting this precise error (unless strings can't be assigned a value of DBNull?), but you almost certainly want to attack this problem with a different method.
The reason for this is that your current code will likely always call both set methods regardless of the conditional value.
Formula that worked for my SSRS 2008 reports.
=IIf(String.IsNullOrEmpty(Fields!NullableFieldwithPossibleBlankStrings.Value),"Yes","No")
I tried this too (also tried a version with IsNothing)...
=Code.SetField(IsDBNull(Fields!fOrgID))
And changed the function to be one that accepts a boolean. I figure this above function would always return a true or false, but in the event of a NULL, I again get "The query returned no rows for the data set. The expression therefore evaluates to null.".
I need to pass back to my code if the field is null or not (as this will let me know if the datasource is null or not).
Let me know if you can think of a better way because I cannot.