SSRS if Statement with two lines in the false condition - reporting-services

I'm converting crystal reports over to SSRS and need to put the equivalent of this if statement in an expression.
if({RPT_ReceiptStatusHeader.receipt_id_type} = "Trailer ID") then
BarcodeC128B({RPT_ReceiptStatusHeader.trailer_id})
else
BarcodeC128B({RPT_ReceiptStatusHeader.receipt_id_type})
BarcodeC128B({RPT_ReceiptStatusDetails.item})
Here is what I've come up with but this is incorrect.
=IIf(RPT_ReceiptStatusHeader.receipt_id_type = "Trailer ID", StringToBarcode({RPT_ReceiptStatusHeader.trailer_id}), StringToBarcode({RPT_ReceiptStatusHeader.receipt_id_type}), BarcodeC128B({RPT_ReceiptStatusDetails.item})
The syntax for an SSRS if else is for example....
=IIF(Fields!LineTotal.Value > 100, True, False)
But how can I put multiple statements in the false condition?

Are you trying to create 2 barcodes with this? With barcodes, I'm assuming that you would want them separated vertically (so that they are one above the other, since putting them next to each other would make accurate scanning very problematic). If this is the case, then I would try something along the lines of:
=IIf(RPT_ReceiptStatusHeader.receipt_id_type = "Trailer ID",
StringToBarcode({RPT_ReceiptStatusHeader.trailer_id}),
StringToBarcode({RPT_ReceiptStatusHeader.receipt_id_type}) & chr(10) &
StringToBarcode({RPT_ReceiptStatusDetails.item})
What you will end up with is 2 barcodes oriented one above the other. You will have to handle font size and possibly even the height of the control.
BTW - I changed the "BarcodeC128B" to "StringToBarcode" in the second part of the "then" portion of your statement.
BTW2 - I'm feeling your pain with the CR to SSRS conversion. We're making the conversion ourselves and have most of the easy (scheduled and "on demand") work done, we just have a couple hundred application based reports to convert over.

Related

SSIS Derived Column - REPLACENULL doubling column width

I'm using a derived column to concatenate two WSTR columns, either of which could be NULL.
Alert (3000 width column) and customAlert (125 wide column)
The problem I'm having is that when I run this with REPLACENULL so that the concatenation happens properly if one of the columns is NULL, it's doubling the calculated destination column width for each column, which is pushing the derived column outside the limit for a WSTR column (so for the expression as written, it wants 6254 column width, which is not possible without moving to NTEXT, which causes its own problems when I have to convert it back.) The column size requirements don't change if I don't use REPLACENULL, but that comes with other problems.
REPLACENULL(Alert,"") + REPLACENULL(customAlert,"")
I could work around this using a C# script in the data flow to do the work, but I'd rather understand why this is happening.
Congratulations, it is not often that I get to learn something new about SSIS.
It sure feels like there's a bug in the REPLACENULL expression but I was also unaware of its existence
Set up
I defined a data flow with an OLE DB Source using the following query
SELECT
REPLICATE(N'A', 3000) AS Alert
, REPLICATE(N'C', 125) AS customAlert;
That results in pipeline metadata of
Alert - DT_WSTR 3000
customAlert - DT_WSTR 125
I can concur that as provided the expression fails out with an error about the invalid length of the resulting string. What's really weird to my brain is that the computed string length, is as you say, 6254. That's not a perfect doubling so ... I have no idea what is going on there.
I advocate for breaking things down in SSIS to smaller pieces as they make debugging easier.
I started by splitting your 3 operations into 2 separate ones with an eye towards the concatenation in a later step.
Right off the bat, this alone errors out.
REPLACENULL(Alert, "")
Error approximately
the length is not valid. Must be between 0 and 4000. Computed length 6002
6002? I really have no idea what's going on behind the scenes. We'll pin that and come back to it.
I added
REPLACENULL(customAlert, "")
and that worked by itself but once again the length is doubled + 2 for an expected width of 252.
So, we can't use replacenull with Alert and using it with customAlert doubles our space.
What else can we do?
Invent a time machine and cut your teeth on SSIS 2005. ;) A different way of solving the problem is to use the ternary operator test condition ? true clause : false clause
ISNULL(Alert) ? "" : Alert
and
ISNULL(customAlert) ? "" : customAlert
That results in a column of length 3000 and 125 respectively. Personally, I'd add a derived column after the one that makes these two new columns and then the concatenation because the next error you run into, is going to make the all-in-one expression more difficult to diagnose
(ISNULL(Alert) ? "" : Alert ) + (ISNULL(customAlert) ? "" : customAlert )
This has a correct length of 3125
Nowhere in the documentation for REPLACENULL does it identify this unexpected behaviour. Tested using SQL SERVER 2017
SQL Server Integration Services
Microsoft SQL Server Integration Services Designer
Version 14.0.3002.92

Is it possible to have a group by parameter in a SSRS Matrix report and have the columns rearranged depending on the group by chosen?

I haven't really worked with SSRS Matrix reports and I'm not sure if what I am trying to do is even possible.
The user can enter a begin and end year. They want the ability to group on either CBA, CRA or Client. The CBA and CRA choice would subtotal after each name, but the client would not. The columns to include would remain the same for each choice. However, they want whatever is grouped by to be moved to the front of the report. If you choose CBA, the columns relating to CBA should appear first. If you choose client, the columns relating to client should appear first.
Is any of this possible with a matrix report? If so, where do I start? Should any of this be done in the stored procedure or should it all be done in Visual Studio? I am using Visual Studio 2017. Below is a sample of what the output should look like.
Any help is greatly appreciated.
report sample
This is certainly possible. There are several ways to do this and you will have to choose how much of it is done in your dataset query/stored proc and how much is done via SSRS expressions.
There are a few things to think about no matter what route you decide on.
Your dataset query or stored proc must always return a dataset that has the same column names with the same datatypes and in the same order
Avoid hiding columns in the report designer as this does not work well
If the dataset returns lots of rows then you might want to do some of the work in the query
The SSRS Way:
If you wanted to do this entirely in the report designer, all the affected columns and groups would need to be set as expressions. For example, in a simplified version of your report, the second column expression would be something like.
=SWITCH(
Parameters!myParam.Value = "CBA", Fields!CBAName.Value,
Parameters!myParam.Value = "CRA", Fields!CRAName.Value,
Parameters!myParam.Value = "Client", Fields!ClientName.Value
)
The Columns header would also have to be a similar expression.
=SWITCH(
Parameters!myParam.Value = "CBA", "CBA Name",
Parameters!myParam.Value = "CRA", "CRA Name",
Parameters!myParam.Value = "Client", "Client Name"
)
The Row Group total (in grey on your example) would also have to be a similar expression.
You would have to repeat this for all affected columns.
Next
You would also need to change the RowGroups in a similar fashion. So you would add a row group and then the "Group On" and "Sort By" expressions to the same thing.
=SWITCH(
Parameters!myParam.Value = "CBA", Fields!CBAName.Value,
Parameters!myParam.Value = "CRA", Fields!CRAName.Value,
Parameters!myParam.Value = "Client", Fields!ClientName.Value
)
It's quite a long winded process but it's not actually that bad to do.
The SQL Method
The idea is basically the same, based on the parameter we pass in, we swap out the columns in the results but we alias them so they look the same in the SSRS dataset. We also have to provide the text for the column headers in the results so we don't have to work it out in the report designer.
Here's a very simple example.
SELECT
CASE #myParam
WHEN 'CBA' THEN CBAName
WHEN 'CRA' THEN CRAName
WHEN 'Client' THEN ClientName
END AS ColumnAValue
CASE #myParam
WHEN 'CBA' THEN 'CBA Name'
WHEN 'CRA' THEN 'CRA Name '
WHEN 'Client' THEN 'Client Name'
END AS ColumnACaption
, *
FROM myTable
Here we are swapping out the content of ColumnAValue and ColumnACaption. In the report designer, we would display ColumnAValue and set the Column Header expression to
=FIRST(Fields!ColumnAHeader.Value)
The Row Groups would both simply sort by ColumnAValue
This method means a lot less work in the report designer.
There are other options but these two methods I what I usually go for as they are the simplest. The SQL method is easier for other developers to understand because there is not much 'hidden' such at the row groups sorting and grouping properties.
At the end of the day it's down to you to decide what you feel comfortable with but hopefully this gives you enough to start.

SSRS - possible to share the same filter definition for a chart and a tablix?

In Excel you have the option of showing a table below your chart that shows the data used in the chart - I am trying to replicate that behavior in SSRS.
Scenario:
I have one dataset from which I want to populate two (Chart + Table) elements (so two charts and two tables). Each Chart + Table combo needs to use the exact same filter, but I don't want to manually define that exact same filter on each object (if I need to change it, I don't want to have to make the change on two entities).
Yes I know there are other ways to accomplish the same end result, such as perform the filter in the SQL, or to instead define two separate datasets, and then apply the filter on the dataset itself (so it will then cascade down to both the Chart and Table).....or in other words, I'm not asking if this is a good idea, I'm asking if it is possible. :)
Closest thing I can think of to what you want is to define the logic of your filter in custom code, and call the custom code in your two filters.
If the logic ever changes, you would only have to change it in one place.
But it's not possible to define the filter on your tablix, for instance, and then in your chart put in some kind of "use the same filter as my tablix" command.
I would add a Calculated Field that checks your criteria and gives a 1 or 0 depending on whether it meets all the criteria or not.
Field Name: MeetCriteria
=IIF(Fields!AGE.Value < 10 and Fields!status.Value = "PAID", 1, 0)
Then you just need to filter on the new calculated column:
Expression: Fields!MeetCriteria.Value
Type: INTEGER
Operator: =
Value: 1
Not quite what you want but much easier than duplicating the criteria everywhere.
For a multi-value Status parameter, you could do something like:
=IIF(Fields!AGE.Value < 10
AND INSTR("|" & Join(Parameters!Status.Value, "|") & "|", "|" & Fields!Status.Value & "|") > 0,
1, 0)

How to align each string in text in field column of ssrs

I have a field like this in the column field in ssrs.
QUINIDINEssssssssssssssssssssssssssssssssssssssssssssssssssssss GL INJ 80MG/ML
FLECAINIDEssssssssssssssssssssssssssssssssss TAB 50MG
TAMBOCORsssssssssssssssssssssssssssssssssssssssssssss TAB 50MG
and how can i align align like this...
QUINIDINEssssssssssssssssssssssssssssssssssssssssssssssssssssss GL INJ 80MG/ML
FLECAINIDEssssssssssssssssssssssssssssssssss(emptyspaceeeeeeeee)TAB 50MG
TAMBOCORsssssssssssssssssssssssssssssssssssssssssssss(emptyspa)TAB 50MG
each part of string align properly...
Any help...
Well, there are two ways to do this that I worked out, and neither is particularly elegant so I'd be surprised if someone doesn't have a better solution.
"t.a" in the code below is your table and column.
The SQL way:
SUBSTRING(t.a,1,CHARINDEX(' ',t.a,1))+REPLICATE('_',20)+REVERSE(SUBSTRING(REVERSE(t.a),1,CHARINDEX(' ',REVERSE(t.a),1)))
Change the value being replicated above from '' to ' ' and you are in business. I left it as '' to illustrate what it's doing.
The SSRS way, which is better from a DB standpoint:
=Mid(Fields!a.Value,1,InStr(Fields!a.Value," "))+StrDup(20,"_")+StrReverse(Mid(StrReverse(Fields!a.Value),1,InStr(StrReverse(Fields!a.Value)," ")))
This is precisely the same formula, executed by SSRS instead of by SQL Server.
I once used Switch to append spaces to a column field, like in the following example:
=Switch(LEN(Fields!FamilyMemberName.Value) = 1, " ",
LEN(Fields!FamilyMemberName.Value) = 2, " ",
LEN(Fields!FamilyMemberName.Value) = 3, " ")
But I didn't have to bother about the expression getting longer, since I know exactly how many spaces I should append and it wasn't more than 15.
You could use Switch in your case too or you could write a VB function in the Code tab of Report Properties window and pass the values, use some loops to generate the spaces you require.
Or it's much easier in MS SQL, all you got to do is append SPACE(NoOfSpacesInInteger) to the field.

How to display a sub-set of the selection of a multi-valued parameter in a text-box in SSRS

I have a multi-valued parameter called Faculty on a report. I want to display the selection in a textbox at the top of the report. The obvious solution would be:
JOIN(Parameters!Faculty.Label,", ")
The problem that I am having is that the first option in the list (the default) is "All Faculty". This is distinct from the "Select All" checkbox that SSRS provides. We have created this hardcoded "All" option because it looks cleaner on the parameters screen (the user sees "All Faculty" instead of "Adam, Arbor, Altman..." etc.). If the user leaves this checked and makes any other selections, we assume that they meant to only select the other items and the stored procedure ignores the "All" selection.
So I would like to display something like this:
IIF(Parameters!Faculty.Value(0) = "0000000", [*display all selections except value 0*], (JOIN(Parameters!Faculty.Label,", "))
The section in square brackets is what I am having trouble with. The 0000000 value represents "All Faculty".
Answered by OP in comments to original question:
I ended up using substring. In case anyone else reading this needs the
final code, here it is:
IIF(Parameters!Faculty.Count < 6,
IIF(Parameters!Faculty.Value(0) = "0000000",
IIF(Parameters!Faculty.Count = 1, (JOIN(Parameters!Faculty.Label,";
")), (JOIN(Parameters!Faculty.Label,"; ").Substring(13))),
(JOIN(Parameters!Faculty.Label,"; "))), "Multiple")
I added a check so
that it will only display up to 5 at a time, otherwise it says
"Multiple". I did Substring(13) because "All Faculty; " is 13
characters including spaces.
The solution above worked initially, but failed when the string was
less than 14 characters (due to the IIF). You set me on the right
track and I came up with a fairly elegant solution:
Switch(Parameters!Faculty.Count > 5, "Multiple Selected",
Parameters!Faculty.Count <= 5,
Replace((JOIN(Parameters!Faculty.Label,"; ")),"All Faculty; ",
""))'code'