I have an SSRS (2008) report that takes in a raw transactions, then groups and totals them. At the "Total" level, I would like to round the final numbers to the nearest .25, however I cannot find a method to do this. According to what I've read, the Round() function in SSRS only rounds to integers. I have found a couple ways to do it in SQL, but the problem is, I want to do all the calculations with the REAL numbers and just round the result so that I don't introduce a significant amount of error from the real numbers. Here's the best SQL solution I could find:
dec(round(number * 4, 0)/4,11,2) as Nearest_Qtr
Anyone know how I could do the equivalent in the actual SSRS report?
Thanks in advance for the help!
You can define a function on the Report code:
Function MyRound(dblFigure As Double, dblMultiplier As Double) As Double
MyRound = Round(dblFigure / dblMultiplier, 0) * dblMultiplier
End Function
And then call it on your report:
=Code.MyRound(value, 0.25)
Related
In my report I'm trying to remove the decimals without rounding. I'll be using this to set the minimum value in the vertical axis of the area chart.
So I tried =Format(98.56, "N0"), but this returns 99, which is incorrect. It should return 98.
I've been searching specifically for SSRS, but most of the results are for tsql.
My question: How can I remov decimals in SSRS without rounding?
Thanks
Try using "Floor". It effective rounds down to the nearest integer. You'll find this under the Math functions.
=Floor(Fields!Number.Value)
Note, there's also a Floor function in Transact-SQL that works the same way in case you need to do some of the processing in your SQL script.
Update based on request in comments
If you wanted to achieve the same result after the decimal point, all you need is a little algebra.
=Floor((Fields!Number.Value*10))/10
That should turn 99.46 into 99.4. Given that it shaves off the remainder, you could then tack on any additional zeroes you wanted.
I ended up converting to Int. The following expression in SSRS returns 98:
=Int(98.56)
I know the question is quite old, but as I ended up here having the same question I would like to share my answer:
While FLOOR and CEILING are fine if you take extra measures to handle numbers <0 or know they are always >=0, the easiest way to simply strip off the decimals is to use
=Fix(Fields!Number.Value)
FIX only returns the integer part of a number, without any rounding or transformation. For negative numbers Int rounds up.
Source: Examples for Fix, Floor and Ceiling
Source: Difference between Int and Fix
Prevously I had a result from a Database Connection SQL statement that resembled the following:
[{"BALANCE":111.11},{"BALANCE":222.12},{"BALANCE":444.30}]
And I used the following contents of an expression node to calculate the sum:
sum = 0;
foreach (row : message.payload) {
sum += row['BALANCE'];
}
message.payload = sum;
This did not quite work out, but notice below that there are no quotes around the numeric variable that was returned
777.5299999999999994315658113919199
From an excellent answer from a previous thread, I switched to the following expression node contents:
sum = 0;
foreach (row : message.payload) {
sum += row['BALANCE'];
}
message.payload = new java.text.DecimalFormat("#.##").format(sum);
This resulted the accurate result below:
"777.53"
My only problem is that it has quotes around the number. How can I eliminate the quotes?
Thanks
The real fix to your problem is the following: do not use floating point numbers to store currency amounts. This is prone to rounding errors (as you've experienced above) and it turns out people don't like to lose cents here and there.
Read https://stackoverflow.com/a/3730040/387927 for more on this.
So fix the database to store only integers, for example in cents, 111111 instead of 111.11, and only perform integer calculations on these cents.
Or review the DB query to return java.math.BigDecimal instances instead of the floats or doubles it seems to be returning. That way you would have no adverse rounding playing tricks on you.
Any other approach where you first would go through a lossy floating point data type and then perform rounding (like in user1760178's answer), will expose you to rounding issues.
You may try converting the sum to BigDecimal and then set scale on it to 2.
message.payload = new BigDecimal(sum).setScale(2,java.math.RoundingMode.CEILING)
This keeps your payload as number instead of a String.
Hope this helps.
I am using Visual Studio to build my report and I have tried to use those three expressions:
=IIF(Fields!A.Value = 0 or Fields!B.Value = 0, 0,SUM(Fields!A.Value)/SUM(Fields!A.Value)
=IIF(SUM(Fields!A.Value) = 0 or SUM(Fields!B.Value =0),0,SUM(Fields!A.Value)/SUM(Fields!A.Value)
=Replace(Round((((SUM(Fields!A.Value)/SUM(Fields!B.Value)))*100),0),"NaN","0")+"%"
The first 2 give me only 0 as % and the last one doesnt get rid of Infinity but does get rid of NaN.
Can someone please help where I can use both these expressions together and not get only 0% and Infinity when I use either the top 2 or the last one?
At first, you need to be sure that the fields you are using to calculate your value are really numbers.
Normally, you get NaN when trying to divide 0 / 0 or Infinity when you are dividing any number by 0.
So, a generic resolution for NaN, Infinity or even #Error (that happens when a null value is passed to a division) is to create a Function that will work on this values for you.
Right click on the background of your report and go to Report Properties as shown:
Then you can go on tab Code and add your custom code:
Public Function Divide(ByVal dividend As Double, ByVal divisor As Double) As Double
If IsNothing(divisor) Or divisor = 0 Or IsNothing(dividend) Or dividend = 0 Then
Return 0
Else
Return dividend / divisor
End If
End Function
We use IsNothing() to avoid #Error and check whether the divisor or the dividend are 0 to avoid NaN and Infinity.
And then you replace your expression with:
= Code.Divide(Sum(Fields!A.Value), Sum(Fields!B.Value))
To make this looks like a percentage, I strongly recommend you change your Textbox properties. So, right click on it, go on Textbox Properties and over tab Number. Select category Percentage.
By doing this, you make sure that de SSRS will consider this value as percentage and not a text even when it is exported to other platforms such as Excel.
You can also check the Microsoft documentation on adding code to a Report (SSRS)
If you're getting 0% and NaN I'd check check your field data types. You should have at least one non-integer, and both need to be numeric. I'd still expect to see some 1s, but this is a start at the 0% and NaN. In terms of your check, you only need to check the denominator to avoid a calculation error.
Try:
=IIF(Sum(Fields!B.Value) <> 0 , Sum(Fields!A.Value) / Sum(Fields!B.Value), 0 )
Control your presentation (decimal places, % sign etc.) with the textbox Format properties, or the equation number properties.
I have a report that should return something along the lines of
SELECT brand, ROUND(SUM(count * price) / SUM(count), 2)
WHERE ... GROUP BY brand, ...;
The problem is, I sometimes get 9990.32999999999992345 in my perl code instead of 9990.33 which direct SQL request returns.
The number starts looking that way right after fetchrow_hashref, if it ever does. The same number can come in 'good' or 'bad' form in different queries, but always the same way in any specific query.
How can I track this down?
Read all about floating point accuracy problems here: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
As mellamokb said, you have to round your floating-point numbers. More importantly, count and price probably means that you are calculating the price of something. As this page explains for the FLOAT and DOUBLE datatype, calculations are approximate while for DECIMAL they are exact. For your particular example, the chance is low that will give problems but not if you do a lot of calculations with your price. The usual rule is to always use exact datatypes for calculating prices.
Always round floating point numbers when displaying them on the screen. And do it as the final step as it is displayed. Any intermediate operation has the potential to cause problems like this.
I can think of a couple of causes of this, but first:
Does it make any difference to put a CONCAT( '', ... ) around your ROUND? What version of perl are you using? What does perl -V:nvtype report?
33/100 is a periodic number in binary just like 1/3 is a periodic number in decimal.
$ perl -e'printf "%.20f\n", 0.33'
0.33000000000000001554
Therefore, it would take infinite storage to store it as a floating point number. To avoid the problem, you'll need to store the number as a string, either early (in the query before it's a float) or late (by rounding).
It's an issue inherent with floating point numbers. It's a design feature, not a flaw.
Make sure the value returned from the database is not a floating point value, but a string or decimal. (If the data types of `price` and `count` are both DECIMAL, then the resulting expression should be DECIMAL.
If either of those is a floating point, then you can convert to DECIMAL...
SELECT brand, CONVERT( SUM(count * price) / SUM(count), DECIMAL(18,2) )
WHERE ... GROUP BY brand, ...;
Or convert to a string
SELECT brand, CONVERT(CONVERT( SUM(count * price) / SUM(count), DECIMAL(18,2)),CHAR)
WHERE ... GROUP BY brand, ...;
You can let the conversion to DECIMAL do the rounding for you. If you return a DECIMAL or VARHCAR to Perl, that should avoid floating point issues.
More generally, to handle representation (rounding) of floating point in Perl, you can format using the sprintf function, e.g.
my $rounded_val = sprintf(%.2f, $float_val);
Using visual studio BI dev studio 2008.
I have a chart that has a Y axis of numbers ranging from 0 to about 1500 (Values), an x axis of dates (Category Group). The Y-axis numbers are integers representing minutes.
I want to convert the Y-Axis of minutes to hh:mm form and I thought it would be simple to write a custom function to do so. However, after going to Vertical Axis Properties -> Number -> Custom format, I am finding that the custom expression will not calculate most expressions that I give it.
For example, I have tried
=(Fields!RealRunTimeMin.Value) * 2
=(Fields!RealRunTimeMin.Value) + 1000
But when I go to Preview the report, the y-Axis is in the same range (0 to 1500) rather than displaying 0-3000.
I have also tried
=CInt(Fields!RealRunTimeMin.Value) + 1000
But the chart remains unchanged. The only thing I seem able to do is convert the number to a string.
Any idea on what I am doing wrong? Note: I'm not asking for the logic to format to hh:mm, but rather I am asking why all attempts to maniuplate numbers in SSRS's axis labels seem to be defeating me.
Thanks in advance,
T
Expressions are not supported with this set of functionality. I do realize that the UI suggests that it is, but that is a bug in the current product. You will need to perform the calculations at either the query or dataset level.