SSRS - Aggregate Total of MAX field in row groups & column groups - reporting-services

I'm working with a data set to show customer margins (product) before & after freight costs.
I have just about everything working, but I am stumped on how to do freight correctly. My boss wants Freight to appear as a column rather than a row.
I have my dataset as such:
Customer # | CustomerName| FiscalYear | FiscalMonth | Itemcode | Revenue | Cogs | Freight | [RN]
In my report, my row group is CustomerNo
My column group is FiscalMonth (I'm doing a pivot with SSRS)
For Freight, I am using MAX(FREIGHT) since freight is the same for every item for a customer in a fiscal month. I used MAX since Distinct isn't an option in SSRS. This appears to be working for individual customers and fiscal month appropriately.
Where I am stuck, is how to get the SUM(MAX(FREIGHT)) for the fiscal month of all Customers (Grand Total) as well as the grand total for a customer for all fiscal months. For the grand total, I've tried several variations of =sum(Max(Fields!Freight.Value,"FiscalMonth"),"CustomerNo") or =sum(Max(Fields!Freight.Value,"CustomerNo"),"FiscalMonth") and keep getting errors like:
"The Value expression for the textrun ‘Textbox13.Paragraphs[0].TextRuns[0]’ has a scope parameter that is not valid for an aggregate function. The scope parameter must be set to a string constant that is equal to either the name of a containing group, the name of a containing data region, or the name of a dataset."
"The Value expression for the text box Textbox uses both row and column scopes or scopes from two different data axes in the same aggregate expression. All nested aggregate functions must specify a named scope along the same data axis as the scope of the containing aggregate."
I've done some searching and keep trying to adjusting my expression but cannot seem to find the answer.

I had this same issue before and ended up writing a function to add the unique values. The data is sent as a single field with a Pipe | separating the values. It then checks to see if a customer is unique and adding the value if so.
FUNCTION SUMCustomers(BYVAL ITEMS AS OBJECT()) AS DECIMAL
'Returns Sum of unique Customers. Use as Code.SUMCustomers(Customer & "|" & Amount)
IF ITEMS IS NOTHING THEN
RETURN NOTHING
GOTO EXITSUB
END IF
DIM TEMP AS STRING
DIM Customers AS STRING = ""
DIM Customer AS STRING = ""
DIM VALUE AS DECIMAL
FOR EACH ITEM AS OBJECT IN ITEMS
TEMP = CONVERT.TOSTRING(ITEM)
Customer = "|" & LEFT(TEMP, InStr(TEMP, "|"))
VALUE = CDEC(MID(TEMP, InStr(TEMP, "|") + 1, LEN(TEMP)))
IF InStr(Customers, Customer) = 0 Then
Customers = Customers + Customer
SUMCustomers = SUMCustomers + VALUE
End If
NEXT
EXITSUB:
END FUNCTION
The expression for your issue would be something like
=Code.SUMCustomers(Fields!CustomerNo.Value & "|" & Fields!Freight.Value)

Related

How to create a particular SSRS Expression for this example?

if some could help me to i will be very grateful.
This can be done by separating the table into 2 tables but I want to do it with a formula if possible.
We have the following report:
We need to get the data from the table and add them into the totals on line 2 (those are textbox, not a table)
"TOTAL ID" and "TOTAL AMOUNT" is easy to do using the expressions:
=CountDistinct(Fields!id.Value, "opp_win_lose") (opp_win_lose = dataset) (we have 3 datasets so we need to put to which dataset it belongs)
=ReportItems!Textbox44.Value
The problem gets at "TOTAL ID STATUS PENDING" and "TOTAL AMOUNT STATUS PENDING"
I need to create the expression with the condition that status = Pending (or Running) that is a group, so we have
TOTAL ID STATUS PENDING = 3
TOTAL AMOUNT STATUS PENDING = 100
Thanks.
Nothing worked, try a few expressions.
It sounds like you just need to add a condition to the COUNT and SUM fields for the Pending ones.
=CountDistinct(IIF(Fields!STATUS.Value = "Pending", Fields!id.Value, NOTHING), "opp_win_lose")
=SUM(IIF(Fields!STATUS.Value = "Pending", Fields!AMOUNT.Value, 0), "opp_win_lose")
It looks like the summary data is from the same table. It might have been easier to use a table for your summary. Group the table on 1 (the number) so there's only one total line. Then you don't need the name the dataset.

How to Combine Fields from Two Datasets SSRS?

I am working on a report to show the total number of hours an employee spent working. Our company tracks labor hours by Service Request and Work Order so I need to bring totals for each into the report.
I created two datasets- one for Work Orders and one for Service Requests. Ideally, I would like to combine the total number of Work Order hours with the total number of Service Request hours and present that number listed by employeeID since both datasets have the employeeID field.
I thought it would be as simple as:
=(SUM(Fields!TOTALHOURS_WO.Value, "DataSet1") + SUM(Fields!TOTALHOURS_SR.Value, "DataSet2"))
I don't get an error, however, I am getting a number which repeats for each employee so I know I'm doing something wrong.
Any help is greatly appreciated.
Mal,
As #StevenWhite mentioned, LOOKUP is probably the function you are looking for.
Here is an example for you. For the example datasets:
EmployeeID | TOTALHOURS_WO
-----------------------------------
123 | 12
456 | 3
EmployeeNum| TOTALHOURS_SR
-----------------------------------
123 | 2
456 | 5
You will note that each table in a SSRS report needs a DataSet assigned to it. I will assume your table is using our first DataSet, which we will name "DataSet1". The second dataset above will be "DataSet2".
For your total hours you will use an expression. It should look something like this:
=TOTALHOURS_WO + LOOKUP(Fields!EmployeeID.Value, Fields!EmployeeNum.Value, Fields!TOTALHOURS_SR.Value, "DataSet2")
So you will be adding the TOTALHOURS_WO from your local dataset to the result from the LOOKUP function. What lookup is doing is taking the first field from your local dataset, finding a match in the dataset provided to the function (as a string), and returning the field from the row it matched to. The last parameter is the dataset to search.
Just in case you get an error... it's always a good idea to cast data to the type you want to work with in case it comes in wrong. So...
=CINT(TOTALHOURS_WO) + CINT(LOOKUP(Fields!EmployeeID.Value, Fields!EmployeeNum.Value, Fields!TOTALHOURS_SR.Value, "DataSet2"))
This assumes you have a one to one match on employee ID. If you have to SUM both fields you can try this:
=SUM(CINT(TOTALHOURS_WO)) + SUM(LOOKUPSET(Fields!EmployeeID.Value, Fields!EmployeeNum.Value, CINT(Fields!TOTALHOURS_SR.Value), "DataSet2"))
SUM for TOTALHOURS_WO will give you the SUM in your current table group (so make sure you are grouping by staff ID in the table). It will then add it to the SUM of LOOKUPSET. LOOKUPSET works the same as lookup but returns an array of matches instead of the first.
Hope this helps.

Dynamic label caption in a report using vba

I am trying to design an indididual report card for the students of my college. I have a table called "tbl_student" where their marks are stored. I have 6 columns for 6 different subjects. A student can choose only 5 subjects i.e 4 being required and Computer and Maths are optional subjects where a student can choose either one.
Now, if a std chooses Comp. then marks in the maths column is 0, likewise for maths.
I am trying to print an individual report cards for 10 students. But one of the label for the optional should display Computer or Mathematics based on the value of the column.
Here is the code i tried
'declare the variables
Dim d As Database
Dim r As Recordset
Dim comp As Field, maths As Field
'the data from the table
Set d = CurrentDb()
Set r = d.OpenRecordset("tbl_student")
Set id = r.Fields("Student ID")
Set comp = r.Fields("Computer")
Set maths = r.Fields("Mathematics")
'check for the column value
While Not r.EOF
If (comp = 0) Then
Me.labelOptional.Caption = "Mathematics"
ElseIf (maths = 0) Then
Me.labelOptional.Caption = "Computer"
Else
Me.labelOptional.Caption = "none"
End If
The result is it captions all the labels the same for all students.
If you want to display different values for different rows in report/form, you should use bound text boxes. Labels and unbound text boxes will be the same for all rows in details section. Add new calculated column for optional label in base query and use it instead of label.

Compare 2 dynamically created matrix columns to get a difference

I have a matrix set up with a Row Group called "company", a Column Group called "Year" and a value field that is a sum of charges through the year called revenue. The column Group will end up having 2 columns in it that are provided through user input. The end results is a matrix that will look something like this:
Year 1 | Year 2
Company: $500 $250
Company2: $750 $250
What I would like to do is add a column to the matrix that calculates the change from year 1 to year 2. Is there a way to do this within the matrix such as adding a new column with an expression that compares the 2 entries in the row or will I need to manipulate the SQL code to create a column that does this within the code? To that end here is a view of the code for the dataset if that is the way I need to go:
SELECT
company.cmp_id
,company.Company
,ChargeDetails.[Bill To ID]
,ChargeDetails.[Delivery Year]
,ChargeDetails.Revenue
FROM
ChargeDetails
LEFT OUTER JOIN company
ON ChargeDetails.[Bill To ID] = company.cmp_id
WHERE
ChargeDetails.[Delivery Year] = #DeliveryYear
OR
ChargeDetails.[Delivery Year] = #ComparisonYear2
ORDER BY ChargeDetails.[Delivery Year] DESC,ChargeDetails.Revenue DESC;`
Try to add a column outside the Year group in header type Change or what you want to put, in the below cell use this expression:
=Sum(iif(Max(Fields!DeliveryYear.Value)=Fields!DeliveryYear.Value,Fields!Revenue.Value,0))-
Sum(iif(Min(Fields!DeliveryYear.Value)=Fields!DeliveryYear.Value,Fields!Revenue.Value,0))
Note I am substracting the min year (1) revenue sum to the max
year (2) revenue sum.
In your example it will produce:
+-----------+--------+--------+--------+
| Company | Year 1 | Year 2 | Change |
+-----------+--------+--------+--------+
| Company A | 500 | 250 | -250 |
+-----------+--------+--------+--------+
You can define change in many ways maybe in percentage or any other measure, this is only an example, learn what the above expression is doing in order to calculate the measure you need.
EDIT 1:
Add the matrix with this data arrangement.
The matrix looks like this one in preview:
Be sure you added the Change column outside the DeliveryYear group as shown in above image. Also check the fields names correspond to yours in the expression.
EDIT 2:
If Revenue has null values you can try this:
Try replace the null values at query level using T-SQL ISNULL() Function, change your query in this part as follows
,ISNULL(ChargeDetails.Revenue,0)
However if DeliveryYear has null values you may want to ignore that records, so try to exclude it in the where clause.
Let me know if you need further help.
I ended up using the following as the expression in the change column.
=sum(iif(Fields!Delivery_Year.Value=Parameters!DeliveryYear.Value,1,0)*Fields!Revenue.Value) - sum(iif(Fields!Delivery_Year.Value=Parameters!ComparisonYear2.Value,1,0)* Fields!Revenue.Value)

How can I assign a number to each group and a total number of groups on the dataset to display

I have a dataset that is grouped by the CustomerId with multiple row information for each CustomerId.
I'm trying to create a numbering for each group (customerId) that gets created sequentially and then a total of groups.
So basically I am looking for the report to calculate that there will 5 groups here and then go 1 of 3, 2 of 3, 3 of 3 on the group header row (so I'm assigning a number of each CustomerId and seeing how many are on that Company)....
I have used the page breaks in the past for this but not possible this time around because I cannot break the pages. I have tried using RunningValue but not working so I'm lost here.
Header | Customer A 1 of 3
Details
Header | Customer B 2 of 3
Details
Header | Customer C 3 of 3
Details
Say I have data like this:
And a simple table with a Group based on Customer:
The expression I'm using in the group header row is:
="Customer " & Fields!Customer.Value & " ("
& RunningValue(Fields!Customer.Value, CountDistinct, Nothing)
& " of "
& CountDistinct(Fields!Customer.Value, "DataSet1") & ")"
Which is using a couple of aggregate functions and using these to create a longer string with the Customer detail.
You can see that using CountDistinct is the key here - it's used in RunningValue to get the group ranking and also as an aggregate expression by itself to get the total in the Dataset (where DataSet1 is the Dataset name).
Results look good:
You will of course need to tweak slightly for your field names and your exact formatting requirements.