SSRS Chart for Milestones - reporting-services

I need to create a SSRS report to present actual start date vs. planned start dates for milestones of a project (selected as input parameter)
The chart should look like this:
I have created the table in a separate table. However, I don’t know which chart type should I use and how do I have to set up the chart? (Chart Data, Category Groups and Series Groups).
(Data comes from SQL Server, SSRS Version 14.0.1016.285; SSDT 15.6.4)
Many Thanks in advance

This might look a bit long winded but it's fairly simple so stick with it :)
To start with I did not know your data structure so I've just made some assumptions. You may have to rework some of this to get it to fit but I've tried to keep it simple.
The approach will be to use a subreport to plot the dots and a main report to show the overall table. With this in mind, as we will have more than one dataset referencing our data I added some tables to my sample database before I started wit the following.
The first is a simple table containing months and years, you could a use view over a date table if you have one but this will do for now.
CREATE TABLE prjYearMonth (Year int, Month int)
INSERT INTO prjYearMonth VALUES
(2018, 8),
(2018, 9),
(2018, 10),
(2018, 11),
(2018, 12),
(2019, 1),
(2019, 2)
Next is the project milestone table
CREATE TABLE prjMileStones (msID int, msLabel varchar(50), msPlannedStart date, msActualStart date)
INSERT INTO prjMileStones VALUES
(1, 'Milestone 1', '2018-10-30', '2018-12-13'),
(2, 'Milestone 2', '2018-11-12', '2018-12-10'),
(3, 'Milestone 3', '2018-10-21', '2018-12-25'),
(4, 'Milestone 4', '2018-10-18', '2018-11-28'),
(5, 'Milestone 6', '2019-01-08', '2019-01-29')
OK, Now let's start the report...
Create a new empty report then add a dataset with the following query
SELECT
*
FROM prjYearMonth d
LEFT JOIN prjMileStones t on (d.Year = YEAR(t.msPlannedStart) AND d.Month = Month(t.msPlannedStart))
or (d.Year = YEAR(t.msActualStart) AND d.Month = Month(t.msActualStart))
Now add a matrix item to the report. Add a Row Group that groups on msLabel.
Next add two Column Groups. First a group that groups on Month and then add a parent group that groups on Year.
Add columns on the row group so that you end up with 4 columns msID; msLabel; msPlannedStart; msActualStart.
Finally (for now) set the Expression of the Month field (the one in the column header) to be
= Format(DATESERIAL(2017, Fields!Month.Value, 1), "MMM")
This will just give us the month name rather than the number (the 2017 is irrelevant, any year will do). Now just format as required.
You report design should look something like this..
If we run the report now we will get this..
Now to plot the dots...
For this we will create a small subreport. The subreport will accept 3 parameters. Year, Month, msID (the milestone ID from your main table). We will need the data in a slightly different structure for this sub report but the work can be done in the dataset query so nothing new is required in the database itself.
So, create a new report, let's call it _subMonthChart.
Next add a dataset with the following query..
DECLARE #t TABLE(msID int, msLabel varchar(50), PlannedOrActual varchar(1), msStartDate date)
INSERT INTO #t
SELECT msId, mslabel, 'P', msPlannedStart FROM prjMileStones
UNION ALL
SELECT msId, mslabel, 'A', msActualStart FROM prjMileStones
SELECT
1 AS Y, Day(msStartDate) as Day, PlannedOrActual
FROM prjYearMonth d
LEFT JOIN #t t on (d.Year = YEAR(t.msStartDate) AND d.Month = Month(t.msStartDate))
WHERE [Year] = #Year and [Month] = #Month and msID = #msID
Your report should now have 3 parameters that were automatically created, edit all three to Allow Nulls.
Note: The Y in the dataset is just some arbitrary value to help plot on the chart,. I will set the Y axis to range from 0 - 2 so 1 will sit in the middle.
Next, add a line chart with markers. Don't worry about the size for now...
Set the Values as Y
Set the Category Groups as Day
Set the Series Groups as PlannedOrActual
Right click the horizontal Axis, choose properties and set the Axis Type to Scalar, switch off 'Always include zero' then set Min = 1, Max = 31, Interval = 1, Interval Type = Default.
Note that for data in months that don't have 31 days the plots points will not be accurate but they will be close enough for your purposes.
Right click the Vertical Axis, choose properties and set the Mn=0, Max=2, Interval = 1, Interval Type = Default
Next, right click on one of the series lines and choose properties. Set the marker to Diamond, the marker size to 8pt and the Marker Color this expression =IIF(Fields!PlannedOrActual.Value = "P", "Blue", "Green")
The report design should look something like this... (check the highlighted bits in particular)
Now let's quickly test the subreport, based on my sample data I set the parameters to 2019, 1 and 5 and get the following results....
As we can see, our two dates that fall in January for this milestone were plotted in roughly the correct positions.
Nearly there...
Next right click on both Axes and turn off 'Show Axis' so we hide them.
Now resize the chart to something that will fit in the main report cell. In my example I set the size to 2cm, 1.2cm and moved it top left of the report. Then set the report to be the same size as the chart (2cm,1.2cm again in my case).
Save the sub report and go back to your main report...
For the 'Data' cell where the rows and columns intersect, set the size to match the subreport size (2cm, 1.2cm) then right click the cell and insert subreport.
Right click the newly inserted subreport item and choose properties.
Choose _subMonthChart as the subreport from the dropdown.
Click the parameters tab. Add an entry for each parameter (Year/Month/msID) and set its value to be the corresponding field from the dataset.
FINALLY !!!! Set the border on the cell containing the subreport to have borders all round, just so it matches your mock-up..
Your report design should now look like this...
Now when the report runs, it will pass in the month, year and milestone ID to the subreport in each cell which in turn will plot the dates as required.
When we run the report we should finally get this...
This may need some refining but hopefully you can get this going based on this. If you have trouble I suggest you recreate this example in its entirety, get it working and then swap out the database parts to fit your current database.

Related

SSRS Matrix columns show currrent month

I'm stuck with a problem in SSRS 2012 that maybe is very simple:
I have a matrix with a group row (employee) and a group column (last 12 months); the values are COUNT(practicesDone) - i.e. the amount of practices worked.
I want the matrix to show an extra column on the right (after all the columns of the months, and clearly outside the column group) with again the number of practices for the current month.
Is it possible to achieve that?
thank you in advance!
You can do this, it's pretty simple.
I have assumed that your dataset contains a column that has a date for each entry and that the data returned only covers 12 months so the same month would not appear for different years. If your data does have multiple years, look at the second expression below.
Right-click your month column and then to "Insert Column --> Outside Group - Right"
Now set the expression for the text box to
=COUNT(IIF(MONTH(Fields!myDateColumn.Value) = MONTH(TODAY()), 1, Nothing))
You could swap COUNT for SUM and it should do the same thing but either will work.
All we are doing here is comparing the all data in scope which, due to the placement of the text box means the scope is the entire rowgroup. Then for all that data, check if the month matches the current month, if it does set it to 1 is not set it to nothing then count/sum all results. Count conveniently ignores 'nothing'.
If you data covers more than 12 months then you can still do this but you'll have to add a bit more to handle years and months like this.
=COUNT(
IIF(
MONTH(Fields!myDateColumn.Value) = MONTH(TODAY())
AND YEAR(Fields!myDateColumn.Value) = YEAR(TODAY()),
1,
Nothing
)
)

Show multiple line chart in SSRS

I am developing report in SSRS where i have to show data over line chart.
Line chart vary on parameter selected by user.
Now my issue is how to produce line chart based on parameter selected. Sometimes line chart may be 2 and sometime it may be 4, based on parameter selected by user.
Please advise how to do so.
In the following example, I used some basic population data, it returns
Country, Year and Population.
here is the SQL to generate the sample data
DECLARE #t TABLE(Country varchar(20), [Year] int, Population float)
INSERT INTO #t VALUES
('France', 2000, 59.0),
('France', 2005, 61.1),
('France', 2010, 62.9),
('France', 2015, 64.5),
('France', 2020, 65.3),
('Germany', 2000, 81.4),
('Germany', 2005, 81.6),
('Germany', 2010, 80.8),
('Germany', 2015, 81.8),
('Germany', 2020, 83.8),
('UK', 2000, 58.9),
('UK', 2005, 60.3),
('UK', 2010, 63.5),
('UK', 2015, 65.9),
('UK', 2020, 67.9)
SELECT * FROM #t
WHERE Country = #Country
The final WHERE clause uses a parameter #Country which will get passed in from the report.
The approach
We will create a report that shows a single country's population, this will be used as a sub report.
We will then create a master report that calls the sub report as many times as is required.
Create the sub report
I created a new report, added a dataset using the query above and called the dataset dsPopulation. This automatically generates the parameter #Country. There is no need to do anything with this parameter as the user will not use it directly.
I then added a line chart to the report and dragged Population to the Values section, Year to the Category Groups section and Country to the Series Groups section as shown below.
Save the report, call it something like _sub_PopulationReport
.
Now create the master report
Create a new report.
Add a new dataset 'dsCountries' that contains a list of distinct countries. You'll have to decide how best to do this. You might be able to do something like SELECT DISTINCT Country FROM myDataTable ORDER BY Country. For this example I will hardcode the list.
The datatset query looks like this,
DECLARE #t TABLE(Country varchar(20))
INSERT INTO #t VALUES
('France'), ('Germany'), ('UK')
SELECT * FROM #t
WHERE Country IN (#Country)
This will automatically create a Country parameter.
Edit the parameter and set the available values list to a list of countries. You can do this either by pointing it to a query of just adding them by hand.
Set the parameter to be Multi-Value
Now add a Table to the report design.
Next, right-click on any of the row or column headers (any one will work) and choose "Tablix Properties". Set the "Dataset Name" option to the dataset you just created (dsCountries).
Next, remove the header row and two of the columns so you are left with one 'cell'.
Make the table wide enough to fit your chart in (the height it not important).
Inside the remaining cell, right-click and choose "Insert => Subreport"
Right-click the <Subreport> placeholder and choose "Subreport properties". Under the option "Use this report as a subreport" choose the report we created earlier (_sub_PopulationReport).
Click the "Parameters" tab on the left then "Add"
Under "Name" choose or type Country and under "Value" choose or type [Country]
That's it!
The report design should look something like this... (note my subreport name is different than above, ignore this.)
If I run the report for and select 1 country I get this..
If I select more countries (all of them in this case) I get this...

SSRS: Range Bar Chart not displaying repeated status based on Date Range

I have a query that gives me the daily status of an item based on desired date range (parameters). This status will vary and can repeat. For example, it can chronologically be: Operational, Repair, Inspection, Operational, Inspection. As you can see Operational & Inspection are represented twice but at different times. While this is true, I cannot seem to get this represented graphically in a Range Bar Chart because it will only display one instance of each status (as shown in the picture). The picture indicates where the remaining status should be presented.
Range bar Chart Error
The data set I am working with is as follows:
Range bar Chart Error Data
As you can see, the chart should represent 4 status in the following order: Inspection, Operational, Repair, Operational but does not display the 2nd Operational status.
Can anyone assist me to overcome this particular hurdle or is this not possible?
This should point you in the right direction... This is how I would probably approach it.
You need to add an additional column to your dataset. I replicated your dataset into a table variable and then used the following to get the additional column
-- this just replicates your data..
DECLARE #t TABLE(StatusDate DATE, StatType varchar(20), statStart DateTime, statEnd DateTime, StatusDays int)
INSERT INTO #t VALUES
('2017-02-16', 'Inspection', '2017-01-30 12:49:14', '2017-02-21 12:49:14', 22),
...
...
('2017-03-14', 'Operational', '2017-03-01 11:49:11', '2017-04-19 15:19:48', 49)
-- the important bit
SELECT
*
, DENSE_RANK() OVER(ORDER BY statStart) as Sort
FROM #t
This gives us the following output.
We can use this extra field in SSRS to group and sort the data correctly.
I then used the following expression for the chart series color property to make sure that the colours are consistent with the statType
=SWITCH(
Fields!StatType.Value = "Inspection", "Tan",
Fields!StatType.Value = "Operational", "Green",
Fields!StatType.Value = "Repair", "Red",
True, "Blue"
)
(the Blue line is there in case we are missing a type, it'll show on the chart n blue.)
This gives us..
Hopefully that will give you enough to go on.

SSRS Tablix and Chart Filtering

I have a chart and matrix that shows records for a given date range. User wants to see the records for indidual months.If the user selects date range from January to April then the results would be 4 charts and 4 tablix based on month instead of single chart and single tablix that shows for all months. Could anyone please help me on how to do that. TIA
Create a list
Insert your existing Tablix/Matrix into the body of the list
Right click the Row header (grey box) of the List and on the General tab set the Group expression to group on the Month value, i.e.
=Month(Fields!myDate.Value)
Right click the Row header (grey box) of the List and on the Filters tab set two expressions.
Expression Operator Value
-------------------- -------- --------------------------
=Fields!myDate.Value >= =Parameters!StartDate.Value
=Fields!myDate.Value <= =Parameters!EndDate.Value
This approach will then take an output that looks like this (for all months)
When applied, and the parameters set so that StartDate = 01/Jan/2015 and EndDate = 28/Feb/2015, will look like this
Note how the data for each month appears separately.
Let me know if this approach works for you, or if you need any further assistance.

Show Totals displayed as column header but not blanks in a matrix report for SSRS

Okay so let's walk through a problem I have and see if someone can help me out. I am creating a matrix report in SSRS 2012 (VS 2010). I am choosing to collapse a column group and have the default 'visibility' of columns as 'Hide' and can be toggled by a text box. Now I have the rows containing states and the data field containing a value field. Now the default of SSRS is to sum up the data field when the the 'Column Group' is collapsed.
Part 1 issue:
That is great, however I would like it to say: 'Totals' instead of showing a blank. When I apply an expression to the field to be something like
=IIF(Fields!Code.Value = "", "Totals", Fields!Code.Value)
It then applies it ONLY to the column I expand, NOT the totaled parent group header. Any ideas how to get around this?
Part 2 issue:
The default of SSRS is to show BLANK CELLS AND BLANK HEADERS if part of your dataset DOES not have a column you specified in your collection. You can easily solve this by clicking the 'Column Grouping' property. Clicking Visibility and changing 'When the report is initially run:' to an expression like:
=IIF(IsNothing(Fields!Code.Value), false, true)
Now I have gotten rid of my blank headers and cells but now my main grouping when collapsed is now gone.
All I want is this with my data:
COLLAPSED
Place|Total(s)
AL|2
AZ|1
OR|
WA|7
EXPANDED
Place|A|B
AL| |2
AZ|1 |
OR| |
WA|5 |2
THE DEFAULT OF GROUPING IS SO FAR LIKE THIS:
Place|(BLANK)
AL|2
AZ|1
OR|
WA|7
EXPANDED
Place|(BLANK COLUMN)|A|B
AL| | |2
AZ| |1|
OR| | |
WA| |5|2
You can make a simple test data sample for this example loading up SSRS with any datasource you choose and just populating a table variable for this example:
declare #Temp table ( Place char(2), Code char(1), Value int)
insert into #Temp values ('AZ', 'A', 1), ('AL', 'B', 2), ('WA', 'A', 5),('WA','B',2),('OR', null, null)
select *
from #Temp
Okay so basically I scoured the internet and am finding that SSRS wants things it cannot equate to be there. EG: Headers that have null values are where the problem lies in that SSRS assumes a null you do not want to have values for and thus when you do the totals it wants to show an unknown. You can trick it in the backend though, however it takes some work.
Essentially in the simplest terms you want to take your data collection and identify the nulls as zeros so they can be recognized. Therefor I do a grid layout accounting for the nulls to be then shown as zeros in a CTE, I then take that CTE and unpivot it to get back essentially what I originally had. However the key difference is now that the values for nulls are represented as zeros. You may say: "But then you get zeros on your grid and why would I want that?" Well you can do some formatting principles in SSRS to trick that too.
Let's walk through my example above and change some things to show how the whole process works and I will add color background expression formatting too as that is something someone wanted as well.
_1. Lets take our code and show a before and after for our data set.
SQL CODE
declare #Temp table ( Place char(2), Code char(1), Value int)
insert into #Temp values ('AZ', 'A', 1), ('AL', 'B', 2), ('WA', 'A', 5),('WA','B',2),('OR', null, null)
select *
from #Temp
order by Place
;
with a as
(
Select
Place
, sum(Case when Code = 'A' then Value else 0 end) as A
, sum(Case when Code = 'B' then Value else 0 end) as B
from #Temp
group by Place
)
select
Place
, Code
, Value
from a
unpivot(Value for Code in (A, B)) as unpvt1
order by Place
_2. Ignore the first set but use the second (remove the select * from #Temp order by Place) in an SSRS report as your data set
_3. Set up a matrix report with the Place being the rows, the Code being the column, and the Value being the data
_4. Set up an expression to hide the columns if there is nothing in them now by right clicking the 'Columns Groups'(Should be Code showing example)> Click Group properties>Click Visibility>Click Function tab under first section: (You can also toggle this if you want as well as I did on another text cell)
=IIF(IsNothing(Fields!Code.Value), false, true)
_5. Click the 'Code' Column then Click the gray bar above it. Click insert column to the right and then populate the header with 'Totals' and the cell with '[Sum(Value)]' to give you a totals. I could not for the life of me get an expression to show the totals header different if it summed up in place. This method just shows the totals either collapsed or not.
_6. Now if you preview the zeros may show and we do not want that in all cases so let's manipulate the text value a little bit. Right Click the 'Value' under 'Code' and select 'Text Box Properties'. Click 'Number' on the left pane. Check the checkbox for 'Show zero as: ' and select ' ' (nothing). Now your zeros are gone.
_7. Now I have pretty much what I originally wanted but want to dynamically color code the cells based on what the header shows. Get the properties of the cell value under the code header and select 'background color'>Hit the dropdown and choose expression. Put in this expression:
=IIF(Fields!Code.Value = "A", "Wheat",
IIF(FIelds!Code.Value = "B", "LightBlue", "White"))
I now can get something that for some reason most people on the internet make sound almost impossible. I can set my columns to be a consistent color as the positioning is now tied to a value that is there as a zero but hidden now to the end user.
But you may say: "Great but I want money values not simple ints". I can do that too. Hit the properties for 'value' cell under 'Code' and look at the 'format' property. It should default to this:
0.00;(0.00);''
If you want money do this instead:
$###,##0;0.00,''
I hope this helps someone and keep in mind too if you are saying: "That is great for small data sets but I have a million or more rows I want to do something like that on." Well I would replace my cte for a temp table or permanent table and dump your data to either memory or a permanent table to massage it first.