In SSRS 2008 I am trying to maintain a SUM of SUMs on a group using custom Code. The reason is that I have a table of data, grouped and returning SUMs of the data. I have a filter on the group to remove lines where group sums are zero. Everything works except I'm running into problems with the group totals - it should be summing the visible group totals but is instead summing the entire dataset. There's tons of articles about how to work around this, usually using custom code. I've made custom functions and variables to maintain a counter:
Public Dim GroupMedTotal as Integer
Public Dim GrandMedTotal as Integer
Public Function CalcMedTotal(ThisValue as Integer) as Integer
GroupMedTotal = GroupMedTotal + ThisValue
GrandMedTotal = GrandMedTotal + ThisValue
Return ThisValue
End Function
Public Function ReturnMedSubtotal() as Integer
Dim ThisValue as Integer = GroupMedTotal
GroupMedTotal = 0
Return ThisValue
End Function
Basically CalcMedTotal is fed a SUM of a group, and maintains a running total of that sum. Then in the group total line I output ReturnMedSubtotal which is supposed to give me the accumulated total and reset it for the next group. This actually works great, EXCEPT - it is resetting the GroupMedTotal value on each page break. I don't have page breaks explicitly set, it's just the natural break in the SSRS viewer. And if I export the results to Excel everything works and looks correctly.
If I output Code.GroupMedTotal on each group row, I see it count correctly, and then if a group spans multiple pages on the next page GroupMedTotal is reset and begins counting from zero again.
Any help in what's going on or how to work around this? Thanks!
Finally found the solution myself. Here it is, add Shared to the variable declarations:
Public Shared Dim GroupMedTotal as Integer
Public Shared Dim GrandMedTotal as Integer
Just changing the variables to shared won't work. If you set them to shared they'll be DOUBLED when you export to PDF / XLS / etc (because it just kept adding to the existing var). You have to do something like this:
Public Shared Dim grandTotal as Decimal
Public Shared Dim costCenterTotal as Decimal
Public Shared Dim workerTotal as Decimal
Public Shared Function Initialize()
grandTotal = 0
costCenterTotal = 0
workerTotal = 0
End Function
Public Function AddTotal(ByVal b AS Decimal) AS Decimal
grandTotal = grandTotal + b
costCenterTotal = costCenterTotal + b
workerTotal = workerTotal + b
return b
End Function
Public Function GetWorkerTotal()
Dim ret as Decimal = workerTotal
workerTotal = 0
return ret
End Function
Public Function GetCostCenterTotal()
Dim ret as Decimal = costCenterTotal
costCenterTotal = 0
return ret
End Function
Public Function GetGrandTotal()
Dim ret as Decimal = grandTotal
grandTotal= 0
return ret
End Function
I don't know where do you use this. but in your case, if I were you, I just use simple expression to check visibility of SUM
for example I'd use Right Click On Sum Box \ Select Expression \ then use IIF(SUM <> 0, sum. "")
It worked on every where and wont reset, in your case you have a Region and your code will reset in every region so you willface with serios isses if you don't change your way.
Related
Hi I am trying to include Variance in my SSRS matrix for Percentages on a month by month basis.
This is what I want to achieve:
the expression I am trying to use which I have got from a forum is as follows:
=ReportItems!Textbox15.Value - Code.GetPreviousValue(ReportItems!Textbox15.Value)
And this references custom code again from the same forum as follows:
Private previousValue As Integer = 0
Public Function GetPreviousValue(ByVal runningValue) As Integer
Dim temp As Integer = previousValue
previousValue = runningValue
Return temp
End Function
My issue is this does not work for the variance between April and May for example giving me results that are incorrect.
To be clear April% and May% figures are correct but the variances do not appear as in my example. When I check them they are incorrect.
If I alter the (variance) query so instead of taking the query that calculates the % I just calculate variance between the numerator of April% and numerator of May%, variances are correct.
I think the issue is that percentages don't go through the custom code portion correctly. Could this be due to the fact that this works according to INT?
I appreciate this may be as clear as mud... Struggling a bit to explain my problem. Thanks
Yes the integer makes the problem, because you have values with dots (97.3, 91.8, etc...). When these values get converted to integer, they lose the right decimal places. Just replace the datatype in your function like this:
Private previousValue As Double = 0
Public Function GetPreviousValue(ByVal runningValue) As Double
Dim temp As Double = previousValue
previousValue = runningValue
Return temp
End Function
I have a 100% Stacked Bar chart. Students are banded based on their attendance,and the report simply tracks changes in the band populations as a percentage of the total student population. In Report Builder, this works totally fine (except in that it highlights our rubbish attendance of course...)
The problem arises when:
The report is exported from Report Builder to PDF/Word/Excel/whatever
The report is deployed to an SSRS server and run through the browser
You change to a subsequent page of the report, and then change back to the page with the graph.
In all case although the actual chart remains unchanged, the Legend loses its mind a little bit and shows the top three items as 100%:
I can't think of any reason that that should happen...the report was particularly finicky to make as a result of the underlying data structure (which regrettably is based on a Report Model, meaning I can't tweak it with SQL) and I had to use custom vb code in the end to get it to do what I wanted, but I can't see why any of that should change its behaviour either on the server or when exported.
So my question is; why does this happen, and how do I stop it happening?
EDIT: By Request:
The dataset inherently returns data in the format below. There's a row per learner ID per "Week Start Date".
The custom code I am using is pasted below (inept I know - no laughing!):
Private attendance_table As New System.Collections.Hashtable()
Private last_added_table As New System.Collections.Hashtable()
Public Function band_calc(ByVal attendance As Double) As String
REM Define the bands that I want to track
If attendance = 1 Then
Return "A"
ElseIf attendance >= 0.975 Then
Return "B"
ElseIf attendance >= 0.95 Then
Return "C"
ElseIf attendance >= 0.925 Then
Return "D"
ElseIf attendance >= 0.90 Then
Return "E"
ElseIf attendance >= 0.85 Then
Return "F"
ElseIf attendance >= 0.8 Then
Return "G"
Else
Return "X"
End If
End Function
Public Function get_attendance_band(ByVal week_start_date as String, ByVal learnerID As Integer, ByVal possibles As Integer, ByVal presents As Integer) As String
If attendance_table Is Nothing Then
Dim attendance_table As New System.Collections.Hashtable()
End If
If last_added_table Is Nothing Then
Dim last_added_table As New System.Collections.Hashtable()
End If
REM check if attendance_table has the Learner already
If attendance_table.ContainsKey(learnerID) Then
REM check if we've already added this week's data in
If attendance_table(learnerID).ContainsKey(week_start_date) Then
REM just return the band_calc for those data
Return band_calc(attendance_table(learnerID)(week_start_date)(1) / attendance_table(learnerID)(week_start_date)(0))
Else
REM Add in this week to the hashtable. Add this weeks data to the last weeks data
attendance_table(learnerID).Add(week_start_date, New Object() { possibles + attendance_table(learnerID)(last_added_table(learnerID))(0), presents + attendance_table(learnerID)(last_added_table(learnerID))(1)})
REM record that this is now the last date updated for this learner
last_added_table(learnerID) = week_start_date
REM show the band!
Return band_calc(attendance_table(learnerID)(week_start_date)(1) / attendance_table(learnerID)(week_start_date)(0))
End If
Else
attendance_table.Add(learnerID, New System.Collections.Hashtable())
attendance_table(learnerID).Add(week_start_date, New Object() {possibles, presents})
last_added_table.Add(learnerID, week_start_date)
Return band_calc(attendance_table(learnerID)(week_start_date)(1) / attendance_table(learnerID)(week_start_date)(0))
End If
End Function
For the series properties; The sort, group and label (which defines the Legend obviously) are all set to this:
have an access database with a form that has multiple textboxes for production data. I need to do a calculation with a few of the boxes, they are set up as
txtA * txtB * txtC = txtD
I need to take the values from each of the boxes and perform this calculation behind the scenes. So I need the value from txtA * txtB * txtC and display the answer to that calculation in txtD. I keep running into issues because of the number of textboxes on my form it will always pick up the wrong data?? HeLP!
Private Sub btnCalculate_Click()
Dim ctrl As Control
Dim txt As TextBox
For Each ctrl In Form.Controls
If TypeOf ctrl Is TextBox Then
Set txt = ctrl
If txt.Name = "txtD" Then
Set txt = ctrl
ctrl.SetFocus
ctrl.Text = calculate
End If
End If
Next ctrl
End Sub
Public Function calculate()
Dim calc1 As Double
calc1 = txtA.Value * txtB.Value * txtC.Value / 144
End Function
I keep getting this error:
Run-time error '2185':
You can't reference a property or mathod for a control unless the control has the focus.
This is in regards to txtA, txtB, txtC.
Try
txtD = calculate()
Or
Me!txtD = calculate()
If, for some reason, you want to access a control by its name, do it like this
Dim name As String
name = "txtD"
Me(name) = calculate()
Your calculation function must assign the result to the function name. A potential problem is that you are ignoring types. Of which type is the result of the function? It will be typed as Variant if you don't specify a type (and a variant can contain about anything). Better
Public Function calculate() As Double
calculate = CDbl(txtA.Value) * CDbl(txtB.Value) * CDbl(txtC.Value) / 144
End Function
Now, everyone who looks at the function knows what kind of data the textboxes should contain and, more important, what kind of result the function returns.
First off, the line
ctrl.Text = calculate
should be
ctrl.Text = calculateBoardFeet()
Next, the code
calc1 = txtA.Value * txtB.Value * txtC.Value / 144
should be
calculateBoardFeet = txtA.Value * txtB.Value * txtC.Value / 144
I have an access database that has a number of calculations in it. One the the issues I am having is I have multiple textboxes and access want me to enter data into all of them before it calculates the formula. I keep getting an error when I leave a textbox blank
Run-time error '94':
Invalid use of Null
How do I set it to ignore all the nulls. Here is my code
Public Function calculate() as double
calculate = cdbl(textbox1.value) * cdbl(textbox2.value) * cdbl(textbox3.value) * cdbl(textbox4.value) / 144
End Function
Private Sub btn1_click()
Dim x as double
x = calculate
textbox5.value = x
End Sub
Any help would be aprecciated. Thanks!
In your circumstance, I'd use the NZ method.
calculate = cdbl(nz(textbox1.value,1)) * cdbl(nz(textbox2.value,1)) * cdbl(nz(textbox3.value,1)) * cdbl(nz(textbox4.value,1)) / 144
Consider the following data on excel:
1|0.2
2|0.2
3|3.4
4|
5|1.5
6|1.8
7|
8|4.2
Write a VBA function that scans through the selection, finds the empty spots and then t
fills them with a numerical value which is passed through the signature of the function.
Output:
Numbers
1|0.2
2|0.2
3|3.4
4|0
5|1.5
6|1.8
7|0.0
8|4.2
Hi everyone, i have a question above.
I was wondering if anyone can look at my code and tell me whats wrong with my code.
Public Function MyFill(thisRange As Range)
Dim x As Range
Set x = thisRange
ReDim Y(x.Length)
Dim i As Integer
For Each x In thisRange
If (x.Value = Empty) Then
Y(i) = 0
i = i + 1
End If
Y(i) = x.Value
Next x
MyFill = Y
End Function
Public Function MyFill(thisRange As Range)
Dim X As Range
Set X = thisRange
MyFill = X
End Function
Apparently the answer i was looking for is much simpler than I thought.