Alternating row color expression in SSRS matrix not working correctly - sql

In the only row group I am trying to get a alternate row color with the following expression:
Expression for background color : =IIf( RunningValue (Fields!SP.Value, CountDistinct, Nothing) MOD 2, "White", "blue")
SQL code:
select
ROW_NUMBER() OVER (ORDER BY DataDate) AS SSRSRowNumber
,datepart(dw,datadate) SSRSDateFilter
,DataDate
,SP
,sum(TMI) as TotalCI
from table
where DataDate>GETDATE()-20
group by DataDate,SP
order by 1, 2
The result is the picture below, what's wrong in the expression listed above?
Edit-:Solution

The missing dates in your data is causing the issues with the background row color not working correctly.
You can waste lots of time trying to make your query work.
Or you could just use the Alternating Row Color function.
Private bOddRow As Boolean
'*************************************************************************
' -- Display green-bar type color banding in detail rows
' -- Call from BackGroundColor property of all detail row textboxes
' -- Set Toggle True for first item, False for others.
'*************************************************************************
Function AlternateColor(ByVal OddColor As String, _
ByVal EvenColor As String, ByVal Toggle As Boolean) As String
If Toggle Then bOddRow = Not bOddRow
If bOddRow Then
Return OddColor
Else
Return EvenColor
End If
End Function
For the first column that controls the color:
=Code.AlternateColor("AliceBlue", "White", True)
For the remaining columns, don't toggle with the third argument:
=Code.AlternateColor("AliceBlue", "White", False)
You may need to switch the colors in the first column in a matrix.
SSRS Alternating row color issues when some rows are not visible

This has occurred for me where I don't have an intersection between my row groups and column groups.
Example:
- I have stored procedures 1 and 2
On 1/1, both 1 and 2 ran, so I record them
On 1/2, only 1 need to run, so I only record 1
On 1/3, they both ran again, so I recorded both
I'm going to have a messed up looking cell on 1/2 for sp 2 (the color won't change) because SSRS can't calculate a new value for the running total (it's still 1). On 3, it recognizes a value and gets that the running value is now 3, so coloring resumes as expected.
To solve this, you could perform a cross apply to get the cartesian product of all dates and SPs so that every distinct date has a row for every distinct date and store this in a temp table. Store your current query in a temp table or CSV and join onto your cross apply based query. This will ensure no missed cells. Note, this will have a performance impact so test accordingly (it is most likely negligible).
Let me know if you need help writing the queries.

Related

Extracting "hidden" data from expanding/collapsing pivot table - Excel

I'm not sure if this is possible but as you can see I have a pivot table with multiple dependent and expandable fields. I am trying to concatenate the data from columns A:D into one cell which works fine in row 2 but doesn't work with blank parent cells, as you can see in column F.
Any ideas for how to achieve this?
Pivot table
This answer assumes that you don't want to just Repeat All Item Labels in the PivotTable from the "Report Layout" drop-down on the Pivt Table Tools "Design" tab.
A formula to get the first non-blank value on or above the same row as the current cell from Column B can be constructed with a combination of AGGREGATE, SUMPRODUCT and OFFSET, like so:
=OFFSET($B2,SUMPRODUCT(AGGREGATE(14,6,ROW($B$1:$B$100)*--(ROW($B$1:$B$100)<=ROW())*--(LEN($B$1:$B$100)>0),1))-ROW(),0)
How does it work?
Starting with the outermost part, OFFSET($B2, VALUE, 0) - this will start in cell B2, then look up or down by VALUE rows to get the value.
Next we need to know how many rows we will need to look up-or-down. Now, if we can work out the bottom-most row with data, we can subtract the current ROW() from that, giving us OFFSET($B2, NON_BLANK-ROW(),0)
So, to finish up we need to work out which rows are not blank, AND which rows are on-or-above our current row, then take the largest of those. This is going to take an ArrayFormula, but we can use SUMPRODUCT to make that calculate properly. To find the largest number we could use MAX or LARGE - but we get less errors if we pick AGGREGATE(14,6,..,1). (The 14 means "we want the kth largest number", the 6 means "ignore error values", and the 1 is k - so "we want the largest number, ignoring errors")
But, what list of numbers are we going to look at, I don't hear you ask. Well, we want the ROW for output from our range (I'm using $B$1:$B$100, because using the whole column B would take far to long to calculate repeatedly), a comparison against the current ROW(), and check that the LENgth is > 0. Those last two are comparisons, so let's write them out first:
ROW($B$1:$B100)<=ROW()
and
LEN($B$1:$B$100)>0
We want to use -- to convert TRUE and FALSE to 1 and 0 - this means that any "bad" values become 0, and any "good" values are larger than 0:
ROW($B$1:$B$100)*--(ROW($B$1:$B$100)<=ROW())*--(LEN($B$1:$B$100)>0)
This gives us the Row number when the Row is on-or-before the current row AND Column B is not blank - if either of those are False, then we get 0 instead. Stick that in the AGGREGATE to find the largest number:
AGGREGATE(14, 6, ROW($B$1:$B$100)*--(ROW($B$1:$B$100)<=ROW())*--(LEN($B$1:$B$100)>0), 1)
Then put it in a SUMPRODUCT to force Excel to treat it as an ArrayFormula, and that's your NON_BLANK. This then gives you that first formula right at the top of the post

How to create Alternative Row Background colors in SSRS for values in a group

I am using this expression to get alternative colors for my row group:
=iif(RunningValue(Fields!Status_Reason.Value,CountDistinct,Nothing) Mod 2, "LightBlue", "White")
And everything works fine except for some rows:
I am assuming its because of some values are "-", which are 0.
What could be the work around in this situation?
This is my groups:
I use some VB code for Alternating the row color. It's a little more work to set up at first, but it always works right and you can re-use the code in other reports by copying the VB code.
Expression:
=code.AlternateColor("AliceBlue", "White", 1, 1)
=code.AlternateColor("AliceBlue", "White", 0, 1)
The first column should have the first expression - the first 1 in the argument tells it to change color. The remaining columns use the second expression with the 0 indicating that the color won't change.
VB CODE:
Private bOddRow(10) As Boolean
Function AlternateColor(ByVal OddColor As String, ByVal EvenColor As String, ByVal Toggle As Boolean, ByVal Type AS INTEGER) As String
If Toggle Then bOddRow(Type) = Not bOddRow(Type)
If bOddRow(Type) Then
Return OddColor
Else
Return EvenColor
End If
End Function
If you have multiple levels of grouping in one table, you would change the second number of the expression so the rows are unique for each group. In the below example, the main grouping is colored in white and AliceBlue and the sub group is whitesmoke and a lighter blue.

Visual Basic in Excel - WorksheetFunction.max

What is the behavior of this function to be when the values being compared are equal?
If
Cell1 = 10
Cell2 = 11
Debug.Print WorksheetFunction.max(Cell1,Cell2)
Will return Cell2. But if
Cell1 = 10
Cell2 = 10
It returns Cell1.
What am I missing here?
UPDATE:
I have a label at Offset(0,-3)
If one value is greater then I get the appropriate label.
When the values are equal I get on label in particular.
Since I have not defined a consequence when the vales are equal, I wonder what I am missing
about the behavior of this function such that it will choose one value over the other when they are equal.
How much more coding should I assume is necessary?
Function testWinner(rng As Range) As String
testWinner = WorksheetFunction.Index(rng, WorksheetFunction.Match(WorksheetFunction.max(rng), rng, 0)).Offset(0, -3)
End Function
It's nothing to do with Max (now that you've edited your question). Max simply returns the value (since they are all the same) and your Match function is looking for an exact match so it scans through the range until it finds the first match then that position is passed to Index.
WorksheetFunction.Max does not return a cell/range. It returns the largest value in a set of value.
By the way: in case of when both values are equal (10,10), the result of Min, Max and Average function will be the same: 10.
If by saying the behaviour of function you mean how it works, it sorts data and gets the highest value. So, in case of set of value: {10, 10, 8}
Max(10,10,8)** = 10
Max.K({10,10,8},2) = 10 'where K = 2, which means the second highest value
Max.K({10,10,8},3) = 8 'where K = 3, which means the third highest value
On the other hand...
row/column A B
1 10 =RANK(A$1:A$3,A1) 'returns 1
2 10 =RANK(A$1:A$3,A2) 'returns 1
3 8 =RANK(A$1:A$3,A3) 'returns 3
Is it more understandable, now?
In your updated example the following happens in your testWinner function:
The Max value is determined: in example one this is 15 (in example 2 it's 14). Note that only the value but not a reference to any cell is returned
The MATCH function searches through through D2:D3 for the value 15 (14). It does so top down and return the first exact match. I.e. in the first example, this results in 1 (in the second example the result is 2)
INDEX will return the 2nd element of D2:D3 (the 1st in the second example), i.e. cell D2 (D3 in ex. 2)
OFFSET returns the cell three to the left
Thus, the answer to your question is not the return of the MAX function - but the MATCH function - which goes top to bottom until it finds the first element matching your criteria, in your case the max.
Independent of this: why do you use a User-Defined-Function for this? If you'd build this with the normal Excel functions, performance would be higher - and non-VBA users could still understand it. Using =INDEX($A$2:$A$3,MATCH(MAX($D$2:$D$3),$D$2:$D$3,0)) you would save the OFFSET - and make it less error prone, as you can now insert columns between A and D without breaking your model!

Multiple charts in an report for a specific column value

I need to display multiple charts in an SSRS-Report. With multiple charts i don't mean multiple series in one chart area - i mean for each value a new chart area with an own chart. I don't know if this is possible but i'll give it a try :).
The data source is a table containing multiple rows and columns. One column contains a value containing the material no. Now i need to create a new chart for each material no. in this data table. The whole thing should look like this:
The number in the brackets is the material no. As you see i need to create one own chart for each material no. Is this possible?
Important: The material no. can exist multiple times in the data table but only one chart should be displayed for one material no. The values which belong to the specific material no. will be aggregated
Update #1:
First a screenshot showing the data the data source returns:
The expression for the hiding looks like this:
Table 1
=iif((RowNumber(Nothing) Mod 2) <> 0 AND (RowNumber(Nothing) Mod 3) <> 0, False, True)
Table 2
=iif((RowNumber(Nothing) Mod 2) = 0, False, True)
Table 3
=iif((RowNumber(Nothing) Mod 3) = 0, False, True)
Here is a screenshot of the three tables inside the report.
All three tables display the material no. They are all bound to the same data source with the row visibility expression posted aboth. The group expression for the row looks like this (typeMaterial is the column yieldTypeMaterial):
At the end, it results in this:
We can achieve this by putting the chart in table list and group the row by "Material No." and design the chart as per your requirement. By this, 1 chart will be displayed per row, but not as per your screenshot.
(I think below given is not a great idea, but we can try that).
I guess, to display as per your screenshot take 3 different tables, place them side-by-side and write filter conditions such that to hide some rows in table1(Ex. Display row no.'s in "table1" 1,4,7,10), display some rows in table2(2,5,8,11) and in Table3(3,6,9,12) as described in this answer about faking multiple columns with tables.
Use below expressions for 3 Tables:
Table1
=iif((RunningValue(Fields!TypeMaterial.Value ,CountDistinct,Nothing) Mod
2) <> 0 AND (RunningValue(Fields!TypeMaterial.Value ,CountDistinct,Nothing) Mod
3) <> 0, False, True)
Table2
=iif((RunningValue(Fields!TypeMaterial.Value ,CountDistinct,Nothing) Mod
2) = 0, False, True)
Table3
=iif((RunningValue(Fields!TypeMaterial.Value ,CountDistinct,Nothing) Mod
3) = 0, False, True)

rdlc skip hidden rows on condition

I know this may sound trivial but I just can't find an answer to it.
I have a rdlc report in which I like to alternate row background color and for this I've used the following formula:
=iif(RowNumber(Nothing) Mod 2, "#e5e5e5", "White")
I also need to hide some rows and for this I use the following formula:
= Fields!MeanAeb.Value <> ""
where MeanAeb is a field in my report. My problem is that rowNumber also counts the hidden rows, so my table may have two consecutive rows with the same background. is there a way to take only visible rows into account?
So if anyone has the same problem, I have an answer;
in the Code section of your ReportProperties add the following
Dim customRowNumber as Integer = 0
Dim previousRowNumber as integer = 0
Function CustomRowCounter(conditionToTest as Boolean, rowNumbner as Integer) as Integer
if(conditionToTest and rowNumbner <> previousRowNumber)
customRowNumber = customRowNumber + 1
previousRowNumber = rowNumbner
end if
return customRowNumber
End Function
then on the background field in your column properties add this condition:
=iif(Code.CustomRowCounter(Fields!MeanAeb.Value="",RowNumber(nothing)) Mod 2, "#e5e5e5", "White")
this is nice because you can add any condition you like in place of Fields!MeanAeb.Value="". Just remember to use the inverse of the condition in your rowVisibility field, otherwise you may cause strange effects.
Oh and if you want a chess board look to your report just drop the previousRowNumber :)