How to handle #ERROR, NAN and INFINITY in a single expression in SSRS Report - reporting-services

So, if current and previous both are blank then I need to show result also blank. My Formula looks like this (Current-Previous)/Previous*100
I tried like this
=IIF((SUM(Current)= "" OR SUM(Previous) = ""),"",(SUM(Current) - SUM(Previous))) / SUM(Previous)
but it was giving #ERROR, NAN and INFINITY I want solution for all these issues in a single expression. Please help me on this

This is a well documented issue with SSRS. It evaluates both sides of the iif so it always ends up with divide by zero errors if it encounters one.
One way to handle it is through vb code in your report.
Go to report properties -> Code
Paste the following code :
Public Shared Function divbyzero(ByVal Standard As Decimal, ByVal Actual As Decimal) As Decimal
If Actual = 0 Then
Return 0
End If
If Standard = 0 Then
Return 0
End If
Return (Standard / Actual )
End Function
The above function will return a zero if either a numerator or the denominator is a zero.
Now on your report, go to the text box where you are performing your equation and do the following instead.
=code.divbyzero(SUM(fields!Current.value) - SUM(fields!Previous.value) ,SUM(fields!Previous.value))

Related

How to remove an NaN and Inf in a formula

I am writing a report with a column that calculates year over year comps in sales. The problem I am having is that we do not have any sales history that dates before the beginning of this year. I am using the formula below to calcute the percent change but am getting NaN and Inf errors due to the fact that there is zero in the denominator. Is there a way to write this formula to exclude those, perhaps an iif statement?
=(SUM(Fields!MTDInvoiced.Value)-SUM(Fields!PYMTDInvoiced.Value))/SUM(Fields!PYMTDInvoiced.Value)
You could write a custom function to do this, that's probably the best way especially if you will need this often, but the expression only version below should work.
=IIF(
SUM(Fields!PYMTDInvoiced.Value)=0,
0,
(SUM(Fields!MTDInvoiced.Value) - SUM(Fields!PYMTDInvoiced.Value))
/
IIF(SUM(Fields!PYMTDInvoiced.Value)=0,1,SUM(Fields!PYMTDInvoiced.Value))
)
I've not tested this but hopefully it's correct.
The first thing we do is test is if the denominator is zero, then return 0 if it is. If it's not then we do the standard expression but we again test that the denominator is not zero. Even though this last check will never return the final output, we still have to test for it as each part of the expression is evaluated in all cases.
Another way to do this is via VB code.
Go to report properties -> code
paste the following
Public Function fdivide (Byval a As Decimal,Byval b As Decimal, Byval c As Decimal) As Decimal
' Fix for divide by zero problem in VB
' calculates a/b and either returns result or c if b = 0
if b = 0 then
return c
else
return a/b
end if
end function
now on the text box you want to divide, simply call this function like so :
=Code.fdivide(Fields!numerator.value, Fields!denominator.value,0)
The code is self explanatory. Can be reused without having to worry about nested IFF statements.

In SSRS, does the 'swich' statement execute all options, then only return the one with the true condition?

I am using the switch statement in SSRS as shown.
=switch(Fields!TOTAL_TIME_HRS.Value=0, 0,
Fields!TOTAL_TIME_HRS.Value<0, -1,
Fields!TOTAL_TIME_HRS.Value>0, 1/Fields!TOTAL_TIME_HRS.Value)
Executing my report throws a divide by zero warning and for rows that the Fields!TOTAL_TIME_HRS.Value does equal 0, the result on the report is "#Error". Shouldn't the switch statement be catching the possible error, and avoiding it?
No. SSRS evaluate both sides regardless
One way to get around this is to put some VB code in your report to handle the possible divide by zero error
right click on your report and select report properties - go to the code tab and enter the following code
Public Function NDZ(Byval a As Decimal,Byval b As Decimal, Byval c As Decimal) As Decimal
' Fix for divide by zero problem in VB
' calculates a/b and either returns result or c if b = 0
if b = 0 then
return c
else
return a/b
end if
end function
now in your report on the cell you want to do the division..
enter the following :
=code.NDZ(1,Fields!TOTAL_TIME_HRS.Value,0)
or you can simply replace the division part in your switch statement with the = code.ndz bit

How to get group total inside a row in a rdl report?

How do I get the total of the group inside a row item?
I have tried Fields!Sales.Value/SUM(Fields!Sales.Value) but it returns 1 instead of the row_amount/group_total the report returns row_amount/row_amount
PS: Data comes from a SSAS cube. I made picture bellow1 to summarize what I wanna do
You could potentially just compare the values by the ReportItems. That is, you can specify a name for the sales textbox and for the totalsales textbox and do the comparison using those values. The following expression would likely work as intended.
= (ReportItems!SalesTextbox.Value / ReportItems!SalesTotalTextbox.Value) * 100.0
The other thing to consider with this is that if your result is 1, you may be dealing with integer division from your data. Make sure the data being returned is coming in with a double or decimal datatype, not an integer. It may work as you have it currently if you get the datatype corrected.
You also need to handle "divide by Zero' errors. Using an "=IIf (denominator = 0, 0, numerator/denominator) doesn't work since an "IIf" function evaluates both the "then" and the "else" and will still return an error. We use a bit of custom code that I found on SO (I wish I could remember where it came from so I could give credit where it's due).
Public Function HandleDivideByZero(ByVal numerator As Decimal, denominator As Decimal) As Decimal
If denominator = 0 Then
Return 0
Else
Return numerator / denominator
End If
End Function

SSRS 2008 RunningValue Multiplication

Is it possible to calculate rolling throughput yields in SSRS with RunningValue function? If not, is there another way to?
Currently I am using the expression for the orange line series:
=(RunningValue(((Sum(Fields!StartQty.Value) - Sum(Fields!LossQty.Value)) / Sum(Fields!StartQty.Value)), SUM, "DataSet1"))
And getting this expected outcome because of the SUM aggregate in RunningValue:
I need to get it to display 0.88, 0.62, 0.62 all the way to the end of every step unless it ran into another low first pass yield in a step.
So the calculation should be, 0.88 * 0.71 = 0.62
If it hit another bad yield on a step, 0.62 * 0.92 = 0.57 to the end.
The closest thing I could find was another question similar here on Stack Overflow but could not figure out a way to implement it in my case: Function equivalent to SUM() for multiplication in SQL Reporting
Edit 1
I forgot you cannot have nested aggregates in SSRS 2008, so I would be interested to see if there is a solution for both SSRS 2008 and 2012+
Edit 2
As requested in a comment, a sample data set:
The simple expression to calculate the blue bars is the following:
=((Sum(Fields!QtyStart.Value) - Sum(Fields!ScrappedQty.Value)) / Sum(Fields!QtyStart.Value))
I've recreated your scenario with some simpler data. For this requeriment you can use custom code to get each value by step.
Go to Report menu / Report properties... / Code tab. In the box use this VB code:
Dim prev As Double = - 1.0
Public Function GetYield(ByVal current As Double) As Double
if prev = -1.0 then
prev=current
return prev
End if
if (current*prev) <= prev then
prev = current*prev
End if
return prev
End Function
Now add an additional expression to the Chart Values.
=Code.GetYield(
(Sum(Fields!QtyStart.Value) - Sum(Fields!ScrappedQty.Value)) / Sum(Fields!QtyStart.Value)
)
In order to this works you can only call the GetYield function once per report, since it changes the variable prev per call and its value is shared across the report at runtime.
Also note prev variable is initialized with -1 to determine the first time the function is called so if eventually the expression we are passing to the function produces -1, it will return unexpected values. Set the initial value to something you know won't be produced.
It should produce:
Let me know if this helps.

SSRS report shows #value Error

I am using an Expression
=IIF(sum(Fields!Target.Value)=0,0,
(sum(Fields!Achievement.Value)/sum(Fields!Target.Value))*100)
but i want divide(200/0)*100 ="NAN" but it show me #Value Error
If you would like another condition you can nest IIF inside IIF statement is that what you ae asking??
You can use nested IIF to solve this in expression but for me it's quite a mess.
This is another way to solve your problem using report code.
In the Menu go to Report > Report Properties > Code and paste the code below
Public Function Divider (ByVal numerator As double, ByVal denominator As double)
If IsNothing(denominator) Or denominator = 0
Return "NaN"
Else
Return (numerator/denominator) * 100
End If
End Function
Now you could use this in your expression like this
=Code.Divider(sum(Fields!Achievement.Value),sum(Fields!Target.Value))
Note: You could change "NaN" to 0 if you want it another way around.
reference: http://williameduardo.com/development/ssrs/ssrs-divide-by-zero-error/
UPDATE:
I notice in your picture your output in Variance column is not 0 its 0.00. Is that just that a format in SSRS? or that's the actual output? If 0.00 is the actual output then you should use If IsNothing(denominator) Or denominator = 0.00 in report code of my answer. And also it could be the problem in your expression.