How to use multiple IIFs condition in expression in SSRS Reports? - reporting-services

I want to display records in MS SSRs based on multiple IFFs Condition. Any idea? Please help me!
My table is "customers" and columns are "cust1", "cust2", "cust3", "cust4"
if(cust1.value!=null)
{
display cust1;
if(cust2.value!=null)
{
display cust1+","+cust2;
}
if(cust3.value!=null)
{
diplay cust1+","+cust2+"and+"+cust3
}
if(cust4.value!=null)
{
diplay cust1+","+cust2+","+cust3+"and"+cust4;
}
}else
diplay cust1;
I just wrote C# syntax for understand logic. I want to display like result
Ex: for SSRS I tried
=First(Fields!cust1.value,"customername")&
IIF(First(Fields!Cust2.value,"customername")+" ">" ",
IIF(First(Fields!Cust3.value,"customername")+" ">" ",
IIF(First(Fields!cust4.value,"customername")+" ">" ",
", "+First(Fields!Cust4.Value,"customername")+
", "+First(Fields!Cust3.Value,"customername")+
", "+First(Fields!Cust2.Value,"customername"),
" and"+First(Fields!cust1.Value,"customername"))," ")," ")
but no idea how to implement "cust2", "cust3". Any help?

This is how the IIF expression works.
IIF( CND , DWT , DWF )
CND = The condition that is checked:
In your example: Len(First(Fields!cust1.value,"customername")) > 0 (or IsNothing(First(Fields!cust1.value,"customername")) but then you need to turn it around)
DWT = What to do/display when true. So when the condition is met.
In your example you wish to display the value.
DWF = What to do/display when false. Familiar to the "else" part of an if-block.
In your example you wish to display nothing or an empty string.
If you actually want to nest multiple IIF expressions it is possible by just replacing a DWT or DWF (or both) with another IIF expression. This can be nested as many times as you desire. Here is a simple example:
IIF( CND1 , IIF( CND2 , DWT2 , DWF2 ) , IIF( CND3 , DWT3 , DWF3 ) )
------------------|________DWT1________|---|________DWF1________|---
However, when applied on your example I don't believe it is necessary to nest. The following expression should give you the desired result:
=IIF(Len(First(Fields!cust1.value,"customername")) > 0, First(Fields!cust1.value,"customername") + " ", "") +
IIF(Len(First(Fields!cust2.value,"customername")) > 0, First(Fields!cust2.value,"customername") + " ", "") +
IIF(Len(First(Fields!cust3.value,"customername")) > 0, First(Fields!cust3.value,"customername") + " ", "") +
IIF(Len(First(Fields!cust4.value,"customername")) > 0, First(Fields!cust4.value,"customername"), "")

Related

SSRS - show field in expression based on where clause?

I have a data table that looks like the below. This shows the top 3 subcallcategories based on the amount of calls. The "order" column is a row number that shows which order the subcallcategory was in based on the calls.
I am trying to write some DAX in SSRS which displays the following
Anxiety was the most common counselling call, followed by Work Related
Stress and Bereavement
I have written the below code however it doesn't seem to be picking up the last 2 categories? Anyone have any ideas what I am doing wrong?
=IIf(Fields!Order.Value = "1" and Fields!Category.Value = "Counselling", Fields!SubCallCategory.Value, "") &
" was the most common counselling call, followed by " &
IIf(Fields!Order.Value = "2" and Fields!Category.Value = "Counselling", Fields!SubCallCategory.Value, "") &
" and " & IIf(Fields!Order.Value = "3" and Fields!Category.Value = "Counselling", Fields!SubCallCategory.Value, "")
Below is my current output
As Alan mentioned, your expression is just looking at a single row of data.
You would need to put this expression in a table with Grouping by Category.
Then you would look for the ones in your ORDER and use that Sub Cat value. I use MAX and NULL to get matching values like
=MAX(IIf(Fields!Order.Value = 1, Fields!SubCallCategory.Value, NOTHING)) &
" was the most common " & Fields!Category.Value & " call, followed by " &
MAX(IIf(Fields!Order.Value = 2, Fields!SubCallCategory.Value, NOTHING)) &
" and " & MAX(IIf(Fields!Order.Value = 3, Fields!SubCallCategory.Value, NOTHING))
The MAX will get the SubCat value over NOTHING (SSRS for NULL) for the ones in the right ORDER.
This would give one line for Counselling and one for Legal.
You could also add the totals in with
MAX(IIf(Fields!Order.Value = 1, Fields!Calls.Value, 0))
I assume your ORDER field is an INTEGER and doesn't need the quotes.

How to get a drop-down filter in Spotfire Information Link?

Generally people use the default option that Spotfire gives. Connect to the DB and pull the set of columns that you need and create an Information Link and load the data to Spotfire.
However, I am using SQL Query to fetch data to Spotfire. I am creating a table similar to Views, and writing a simple stored procedure to pull the data:
Create procedure ProcA(In Start_Date date, IN End_Date date, In Site_Name text)
Begin
SELECT * FROM TableA where day between Start_Date and End_Date and
site_name = Site_Name;
This works fine if I am not using site name filtering.
The Information Links helps in filtering the date properly. But when it comes to Site Name, nothing works.
There are 2 requirements:
Is it possible to give a drop-down just like how filter comes for Date
How to pass multiple site names to pull only those sites into the Spotfire file
TL;DR: There are better ways to do this; if it's just for the column names, I don't think it's worth it to do part 2, since it's easy enough to change the sql in the information link, but it's possible.
Okay, I will try (read: fail) not to be too long-winded.
1) Is it possible to do a drop-down for dates? Yes. The easiest way to do this would be to pull a data table with all of your date choices available for the end user. Here's an example finding a list of better way to generate months/year table Remember when creating your dropdownlist that your Document Property has to have the Data type "Date", and then you should be able to set property values through Unique Values in column against your date column from the new data, the same as you would do for a string drop-down list.
If you have a small subset of specific dates to choose from, this probably isn't too bad. If the drop down list gets longer, your end-users can type in the date they're looking for to speed up their search (though in my experience, a lot of them will scroll through until they find the date they're looking for).
While this is perfectly acceptable, if you're at all comfortable adding javascript, I'd personally recommend using a Popup Calendar These are fairly straightforward for end-users, and can allow them to use the calendar or type it themselves. (And if they type something that isn't a date in, it's even kind enough to inform them with red letters and an exclamation mark that they haven't typed an actual date)
2) How to pass multiple site names to pull only those sites into the Spotfire file
Hoo boi, where to start.
Step one: How do you want to select your list of Site Names? I'm going to go ahead and assume you have a data table with a list of distinct Site Names.
Your next choice is how to let your user select which Site Names they want. General options are using a List Box Filter, displaying a table and using marked rows, or providing a text area where the user can type their selections themselves.
When I needed to do this, I did a combo of a data table and a text area, so that's what I'm going to describe here.
I start off by providing the user with a text area, formatted to "specific size" with a larger than usual height to prompt that, yes, they are allowed to type multiple rows. If they know the values they're looking for, they can type them in manually, or copy paste from an excel file, etc.
If they don't know what they're looking for, the list of Site Names would be in a Table displayed for the user, where they can then mark the rows they want on the visualization and push a button which will do a cursor through the list of marked Site Names, concatenate them together, and put them in the text box previously mentioned (Note: if you don't want to let them enter their list manually, you can leave off the text area, combine these next two pieces of code, and throw it straight into the SpecialFilterProperty).
Please note that cursors are slow; if you have more than a few thousand rows to cycle through, this may stall out for a few seconds.
Code for the button:
from Spotfire.Dxp.Application.Visuals import CrossTablePlot
from Spotfire.Dxp.Data import IndexSet
from Spotfire.Dxp.Data import RowSelection
from Spotfire.Dxp.Data import DataValueCursor
from Spotfire.Dxp.Data import DataSelection
TextFltr = ""
crossSource = Document.Data.Tables["Distinct_SiteNames"]
##Get a Row Count
rowCount = Document.Data.Tables["Distinct_SiteNames"].RowCount
##Index Set of all our rows
rowIndexSet=Document.ActiveMarkingSelectionReference.GetSelection(Document.Data.Tables["Distinct_SiteNames"]).AsIndexSet()
allRows = IndexSet(rowCount,True)
if rowIndexSet.IsEmpty != True:
allRows = rowIndexSet
colCurs = DataValueCursor.CreateFormatted(crossSource.Columns["Site_Name"])
##Optional: Loop through to determine average value
colTotal = ''
for row in crossSource.GetRows(allRows, colCurs):
colTotal += ', ' + colCurs.CurrentValue
if TextFltr == "":
TextFltr += colTotal[2:]
else:
TextFltr += colTotal
Document.Properties["SelectedSiteNames"] = TextFltr
from System.Collections.Generic import Dictionary
from Spotfire.Dxp.Application.Scripting import ScriptDefinition
import clr
scriptDef = clr.Reference[ScriptDefinition]()
Document.ScriptManager.TryGetScript("Change Special Filter Value", scriptDef)
params = Dictionary[str, object]()
Document.ScriptManager.ExecuteScript(scriptDef.ScriptCode, params)
At the bottom it references a second script; this is the script attached to the button that parses through the text area when the user wants to submit their selections and refresh the data table.
The General Code I've used is here, script titled "Change Special Filter Value", which allows delimiting by newline, tabs, commas, quotes, and a few others. Feel free to add or subtract here, depending on your user-base's needs.
strVals = Document.Properties["SelectedSiteNames"]
lst = ""
cnt = 0
x = 0
y = 0
z = 0
for letter in strVals:
if y == 1:
if letter == " ":
lst = lst + "'" + strVals[x:z] + "', "
y = 0
elif letter == ",":
lst = lst + "'" + strVals[x:z] + "', "
y = 0
elif letter == "\n":
lst = lst + "'" + strVals[x:z] + "', "
y = 0
elif letter == "\r":
lst = lst + "'" + strVals[x:z] + "', "
y = 0
elif letter == "'":
lst = lst + "'" + strVals[x:z] + "', "
y = 0
elif letter == '"':
lst = lst + "'" + strVals[x:z] + "', "
y = 0
elif letter == '\t':
lst = lst + "'" + strVals[x:z] + "', "
y = 0
else:
if letter <> " " and letter <> "," and letter <> "\n" and letter <> "\r" and letter <> "'" and letter <> '"' and letter <> "\t":
if y == 0:
cnt += 1
print letter
x = z
y = 1
z += 1
if y == 1:
lst = lst + "'" + strVals[x:z] + "', "
print lst
lst = lst.upper()
if len(lst) > 0:
lst = lst[1:len(lst) - 3]
Document.Properties["SpecialFilterValue"] = lst
Step one is now complete! You have a list of all your selected site names in a property that you can now pass to your stored procedure.
Note: I believe there's a limit to the number of characters Spotfire can pass through a string value. In my previous testing, I think it's been over 500,000 characters (it's been a while, so I don't remember exactly), so you have a lot of leeway, but it does exist, and depending on which data source you're using, it may be lower.
Step Two: Alter the stored Procedure
Your stored procedure will basically be something along the lines of this:
Create procedure ProcA(In Start_Date date, IN End_Date date, In Site_Name text)
Begin
DECLARE #Script nvarchar(max) =
N'
Select * from TableA where day between Start_Date and End_Date and Site_Name in (' + #Site_Name + ') '
EXECUTE (#Script)
Downright easy in comparison!
(No loop after all! The bizarre use case I was remembering doesn't apply here, unless you're also using a data base that doesn't allow you to pass parameters directly...)

SQL Server Reporting Services Expression BackgroundColour Based On DateDiff

I'm trying to use conditional formatting in SQL Server Reporting Services to change the colour of a row if a value is the same as today's date or not. The column contains the date in the format 13/07/2018. I have also set the field to be in date format (31/01/2000) within place-holder properties.
My expression however is not working
=switch(DateDiff("d", Fields!LastSuccessfulBackupTime00.Value,Format(Now(),"dd/MM/yyyy")) = 0, "Green",DateDiff("d", Fields!LastSuccessfulBackupTime00.Value,Format(Now(), "dd/MM/yyyy")) = 1, "Yellow",DateDiff("d", Fields!LastSuccessfulBackupTime00.Value,Format(Now(), "dd/MM/yyyy")) >= 2, "Red")
The exception that is being thrown is
Argument matching parameter 'DayOfWeek' narrows from 'String' to 'Mcrosoft.VisualBasic.FirstDayOfWeek'
Which is strange because I'm just doing simple datediff calculation to count the number of days between two dates.
Can anyone suggest how to fix this ? Google just says to turn off strict compilation something which I can't find in SQLRS
Try the expression below (expression 1)
=switch(
DateDiff("d", Cdate(Fields!LastSuccessfulBackupTime00.Value),Today()) = 0, "Green"
,DateDiff("d", Cdate(Fields!LastSuccessfulBackupTime00.Value),Today()) = 1, "Yellow"
,DateDiff("d", Cdate(Fields!LastSuccessfulBackupTime00.Value), Today()) >= 2, "Red"
)
Also because Cdate is regional setting dependant you could use Split to create a valid date format for datediff (expression2)
=switch(
DateDiff("d", Fields!LastSuccessfulBackupTime00.Value.Split("/")(2) & "-" & Fields!LastSuccessfulBackupTime00.Value.Split("/")(1) & "-" & Fields!LastSuccessfulBackupTime00.Value.Split("/")(0),Today()) = 0, "Green"
,DateDiff("d", Fields!LastSuccessfulBackupTime00.Value.Split("/")(2) & "-" & Fields!LastSuccessfulBackupTime00.Value.Split("/")(1) & "-" & Fields!LastSuccessfulBackupTime00.Value.Split("/")(0),Today()) = 1, "Yellow"
,DateDiff("d", Fields!LastSuccessfulBackupTime00.Value.Split("/")(2) & "-" & Fields!LastSuccessfulBackupTime00.Value.Split("/")(1) & "-" & Fields!LastSuccessfulBackupTime00.Value.Split("/")(0),Today()) >= 2, "Red"
)

IsNothing error

I have the following error which I can't understand from my expression.
=IIF(IsNothing(Fields!month.Value),"6mr",LEFT(Format(DateValue(MonthName(Right(Fields!month.Value, 2))
+ "," +
Left(Fields!month.Value,4)), "Y"),3) + " '" + RIGHT(Format(DateValue(MonthName(Right(Fields!month.Value, 2))
+ "," +
Left(Fields!month.Value,4)), "Y"),2))
This works perfectly without the IsNothing element.
I have tested the IsNothing element and that works in the following case:
=IIF(IsNothing(Fields!month.Value),"6mr",0).
Help to correct much appreciated.
You are experiencing this "issue" because Reporting Services evaluates both sides of the Iif.
This is not really an issue, it is by design, see this technet article for more details:
SSRS - IIF function evaluates both True & False
Yes , By design the SSRS evaluates both True & False statements even
though the condition is not satisfied and through error if something
is not right.
Now, to get your expression working, you have to consider that Fields!month.Value could be nothing even in the false part of your expression.
So in your expression, you could just replace
Fields!month.Value
by
Iif(IsNothing(Fields!month.Value), "1", Fields!month.Value)
Here is an expression with this fix:
=Iif(IsNothing(Fields!month.Value),"6mr",Left(Format(DateValue(MonthName(Right(Iif(IsNothing(Fields!month.Value), "1", Fields!month.Value), 2))
+ "," +
Left(Iif(IsNothing(Fields!month.Value), "1", Fields!month.Value),4)), "Y"),3) + " '" + Right(Format(DateValue(MonthName(Right(Iif(IsNothing(Fields!month.Value), "1", Fields!month.Value), 2))
+ "," +
Left(Iif(IsNothing(Fields!month.Value), "1", Fields!month.Value),4)), "Y"),2))
You could also create a custom function or use a variable if you want to reduce the expression length.

Two different formats of field in report Access 2013

I'm trying to find a way to do the following:
I want to have two different formats for a certain text box. To do so, I've done the following: User types one or two digits in a form text box(who's input and format are both "#,0;0;_") and has "yes/no" box on the right of that number field which asks if it's "kg per bag"(so by default it's the other measurement unit which is Percentages), then an OnLoad event is fired when viewing the report for that form, which checks if the yes/no value is yes or no. If "yes" then the format is set to "#.0 & " kg/bag"", if no it's set to "#.0 & " %"".
I will have to additionally divide by 100 when percentages are the ones picked, but first I want the whole thing to work... Which I still can't do!
Sadly, I'm nowhere near getting it to work... Here is my current macro on the onload event of the report, which is marked as not valid expression:
Link to the image on Imgur
Or here is the MacroBuilder Code:
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<UserInterfaceMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application"><UserInterfaceMacro For="Report" Event="OnLoad"><Statements><ConditionalBlock><If><Condition>[yn]=False</Condition><Statements><Action Name="SetValue"><Argument Name="Item">[Text0].[Format]</Argument><Argument Name="Expression">#,0 & " kg/bag"</Argument></Action></Statements></If><Else><Statements><Action Name="SetValue"><Argument Name="Item">[Text0].[Format]</Argument><Argument Name="Expression">#,0 & " %"</Argument></Action></Statements></Else></ConditionalBlock></Statements></UserInterfaceMacro></UserInterfaceMacros>
Which is displayed as:
If [yn]=False Then
SetValue
Item = [text0].[format]
Expression = #,0 & " kg/bag"
Else
SetValue
Item = [text0].[format]
Expression = #,0 & " %"
End if
Can anyone give me a hint on where to go with this? Thank you!!
P.S. Comma is my decimal separator in regional settings!
You don't really need to change format only concatenate the numeric value with unit (kg/bag or %).
Using VBA, try the following code in the OnLoad event (I am assuming the recordsource field behind the text0 control is called the same -text0):
If Forms!yourformname![yn] = False Then
Reports!yourreportname!text0 = Me.text0 & " kg/bag"
Else
Reports!yourreportname!text0 = (Me.text0)/100 & "%"
' ALTERNATIVELY: Reports!yourreportname!text0.Format = "percent"
End If
Alternatively in the OnLoad event, use an embedded macro or call an external macro with the following one action (if/then changed into the IIF function):
SetValue
Item: text0
Expression: =IIF(Forms!yourformname![yn] = False, text0 & " kg/bag", text0/100 & "%")