I have an SSRS report in which I am trying to hide columns based on the select value from a multi-select dropdown. I tried using multiple IIF statements as well as SWITCH CASE but it always throws an error.
Following is my IIF and CASE statements for 2nd and 3rd columns.
=IIF(Parameters!columns.Count >= 1, IIF(Parameters!columns.Value(0) = "3", true, false),
IIF(Parameters!columns.Count >= 2, IIF(Parameters!columns.Value(1) = "3", true, false),
IIF(Parameters!columns.Count >= 3, IIF(Parameters!columns.Value(2) = "3", true, false),
false)))
=IIF(Parameters!columns.Count >= 1, IIF(Parameters!columns.Value(0) = "2", true, false),
IIF(Parameters!columns.Count >= 2, IIF(Parameters!columns.Value(1) = "2", true, false),
false))
=SWITCH(Parameters!columns.Count = 1, IIF(Parameters!columns.Value(0) = "2", false, true),
Parameters!columns.Count = 2, IIF(Parameters!columns.Value(1) = "2", false, true))
=SWITCH(Parameters!columns.Count = 1, IIF(Parameters!columns.Value(0) = "3", false, true),
Parameters!columns.Count = 2, IIF(Parameters!columns.Value(1) = "3", false, true),
Parameters!columns.Count = 3, IIF(Parameters!columns.Value(2) = "3", false, true))
Please help me what I am doing wrong in here
Based on the comments, it appears you are getting an Array Out Of Bounds error which will occur when you attempt to reference a position in an array that does not exist. In this case, your multi-value parameter is considered an array and you are referencing that in the syntax .Value(0). The problem occurs because SSRS will evaluate the entire IIF or SWITCH statement at execution regardless of which value is ultimately returned. This means that when your report has less than 3 values selected, these expression will always be trying to call an array position that does not exist, resulting in the error you are seeing.
So, in order to fix this and check the values as you intend, there is actually a fairly simple workaround that should get you the correct results. The following expression uses JOIN to put all of the parameter's values into a single result with a comma delimiter. You can then use the InStr function which will return a numeric value indicating the position in a string where the search value is first found. In this case, we are searching for the value 3. If 3 is not found, the InStr function will return a value of 0 and any other value will indicate that 3 is present in the joined parameter list.
=IIF(InStr(Join(Parameters!columns.Value, ","), "3") > 0, true, false)
Related
I have to hide a column in a report depending on a parameter.
The Parameter (#vExclude) is a text type. It has the following available Options: the Label "None" with Value 0 or Label "Type1" with Value 1 or Label "Type2" with Label 2, it's possible to select multiple values, the default is 0.
The Column (SumCalc) i wanna hide is type money in SQL.
basically the logic is if #vExclude != "none", then show SumCalc in Report.
I've tried the following expressions:
=iif(Parameters!vExclude.Label is ("none"), true, false)
=iif(Parameters!vExclude.Value is ("0"), true, false)
=iif(Parameters!vExclude.Value is ("0"), false, true)
=iif(InStr(Join(Parameters!vExclude.Label,","),"none")=0,true,false)
they all work without error, but do not hide the column correctly. Either SumCalc is always shown or never, but my condition never works.
Following expressions provided an error message:
=iif(Parameters!vExclude.Label = ("none"), true, false)
=iif(Parameters!vExclude.Label = "none", true, false)
=iif(Parameters!vExclude.Value = 0, true, false)
=iif(Parameters!vExclude.Value is 0, true, false)
=iif(Parameters!vExclude.Value = "0", true, false)
=iif(Parameters!vExclude.Value = ("0"), true, false)
=iif(Parameters!vExclude.Value = (0), true, false)
=iif(Parameters!vExclude.Value is (0), true, false)
Does anyone has an idea what I am doing wrong in my expression?
The following should work. Note that we have used the Value as we are checking for umbers here.
=Join(Parameters!vExclude.Value,",").Contains(0)=False
This basically reads "If vExclude does not contain 0" which will return True of it does not contain zero or False if it does contain 0. No need to use an IIF(), just use this as the expression for the Hidden property.
I have a column of data called Date and I am using that to perform a switch. Basically the figure needs to be 120 on a weekday and 0 on a weekend so I have used.
=SWITCH
(Weekday(Fields!Date.Value) = "1", "0",
Weekday(Fields!Date.Value) = "2", "120",
Weekday(Fields!Date.Value) = "3", "120",
Weekday(Fields!Date.Value) = "4", "120",
Weekday(Fields!Date.Value) = "5", "120",
Weekday(Fields!Date.Value) = "6", "120",
Weekday(Fields!Date.Value) = "7", "0"
)
Which works great. However I also want a Total at the bottom of the sheet. I (somewhat naively) tried adding
=SUM( ... )
to the expression but that resulted in an #Error in the textbox. I also tried
=SUM(ReportItems!Textbox85.value)
and that didn't even run throwing the error
The Value expression for the textrun
'Textbox84.Paragraphs[0].TextRuns[0]' uses an aggregate function on a
report item. Aggregate functions can be used only on report items
contained in page headers and footers.
So my question is how do I sum up this switch function or do I need to rethink this? I guess functionally all I really need is count of the total weekdays so far "this" month (that stays accurate no matter what month is picked using the date parameters). I can then * that number by 120.
So I came at it from a different angle and tried a SQL based solution. I added a column with the code
,CASE
WHEN
DATEPART(dw,convert(date,format(dateadd(hh,1,[Start Time]),'dd/MM/yyyy'),103)) in (1,7)
THEN 0
ELSE 1
End as [weekday]
Then used
=Fields!weekday.Value*120
in my textbox and
=Sum(Fields!weekday.Value, "DataSet1")*120
in my total. Got the desired results.
I came accross a strange problem:
When I use a simple expression like:
=iif(Fields!Length.Value = "", "empty", Fields!Length.Value)
then everything works, and I get my value, or the word "empty" in my report.
If I would change my expression to a sum of 2 times the length, then my "empty" would still appear.
=iif(Fields!Length.Value = "", "empty", (Fields!Length.Value + Fields!Length.Value))
But when I multiply, then my "empty" goes to #Error, While the rest of the data works fine...
=iif(Fields!Length.Value = "", "empty", (Fields!Length.Value * Fields!Length.Value))
Any idea? I find this behavior very, very weird.
Your problem is that IIF evaluates both the true and false results everytime, even if the false result won't be used in the final output. So it's trying to do
'' * ''
when you value is an empty string.
You can fix this by using VAL which will return the numeric value of the string first, like this.
=IIF(Fields!Length.Value = "", "empty", (VAL(Fields!Length.Value) * VAL(Fields!Length.Value)))
I'm trying to implement a footerCallback in DataTables that do a conditional sum of some columns, based on a cell that's in a different column in the same row.Can anyone help me with this? I have used below code and check alert(cur_index); but I think it is not working as expected. And I did not get a correct sum of values of a column. My code is:
pageTotal6 = api
.column( 6, { page: 'current'} )
.data()
.reduce( function (a, b) {
var cur_index = api.column(6).data().indexOf(b);
alert(cur_index);
alert(api.column(3).data()[cur_index]);
if (api.column(3).data()[cur_index] != "Pending review") {
return parseInt(a) + parseInt(b);
}
else { return parseInt(a); }
return intVal(a) + intVal(b);
}, 0 );
And in 3rd column I have some repeated value and I want sum only for distinct value from 3rd column. How can I do this 2 thing using datatable & html
Theres two ways you can go about this.
First Method
(I will assume you are reading JSON data from Database [ViewModel] in C#, and using server-side processing)
Using the image below as reference to how I solved the problem
I wanted to sum of the "Amount" column where "Measure Type" (last column) != 99. First thing I did with the ViewModel that was going to pass the list to my JSON object was add a column sum column that didnt read any MeasureType = 99 rows from the table.
So essentially my JSON object has two columns that read the Amount column data, one is visible that you see in the image that has all figures and another invisible that only reads the values I want to sum in my footer.
while (MyDataReader.Read())
{
//get all other columns
//column with amount figures measuretype != 99
if (reportData.q_measuretype != 99)
{
reportData.amountNo99 = Convert.ToDecimal(String.Format("{0:0.00}", read["q_amount"]));
}
else
{
reportData.amountNo99 = 0;
}
list.Add(reportData);
}
After that step, then within the footerCallback function you can keep it simple by just summing the invisible column, because the condition has already been set when you get the list of rows onto the page
totalNettNo99 = api
.column(8, { page: 'current' }) //remember this is the last invisible column
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
});
You can then update your footer with that sum on the visible column 3 (index 2)
$(api.column(2).footer()).html(
'€' + totalNettNo99.toFixed(2)
);
Remember to set the invisble column this way in "columnDefs"
"ajax": {
"url": "/Reports/loadTransactionList",
"type": "POST",
"datatype": "JSON"
},
"columnDefs": [
{
"targets": [8],
"visible": false,
"searchable": false,
"render": false
}
],
"columns": [
{
"data": "convertDateToString"
},
{
"data": "convertTimeToString"
},
{
"data": "q_receiptnumber"
},
As you can see from the image, only the rows with Guinness Pint total the sum on the footer. Its a bit more typing but solves the problem if you have been tearing your hair with script solution.
Second Method
You can have a look at this answer here done purely in script and less typing that my solution
https://stackoverflow.com/a/42215009/7610106
credit to nkbved
i have columns with imperial values and columns with metric values. i want to hide one or the other based on which region a customer may be from but also if they are part of the company or not. So example if person.value = "Employee" then show imperial and metric but if person.value = "Customer" then CustomerRegion.Value = "Europe" , would be shown metric and CustomerRegion.Value = "North America" would be shown imperial. what would i use to construct an expression to hide one or the other and what would be the easiest way to do it.
You would need to use an IIF statement and add the logic for the various possibilities by nesting multiple IIFs inside each other.
Since you always want to show Imperial to Employees, I would make that the first part of the IIF. For showing and hiding, one column would have one expression while the other would have the same with the TRUEs and FALSEs reversed.
Imperial Hide:
=IIF(PARAMETERS!person.value = "Employee", False,
IIF(PARAMETERS!person.value = "Customer AND PARAMETERS!CustomerRegion.Value = "North America", False,
IIF(PARAMETERS!person.value = "Customer AND (PARAMETERS!CustomerRegion.Value = "Europe" OR PARAMETERS!CustomerRegion.Value = "Asia"), True, True))
Swap the TRUE and FALSE for the Metric column.
Instead of hiding one of the columns, why not use the expression to determine which data to show in a single column? Instead of TRUE or FALSE, you could use the IMPERIAL or METRIC fields.
Apologies Hannover, I've used your answer as a template for mine.
A SWITCH statement would be a better option here IMHO. IIF evaluates all parts of the expression which can be slower whereas SWITCH stops at the first expression that returns TRUE. If more conditions need to be added, nesting IIF's quickly gets messy.
The SWITCH version would be slightly cleaner but definitely more extensible.
Imperial would be
=SWITCH(
Parameters!Person.Value = "Employee", False,
Parameters!Person.Value = "Employee" AND Parameters!CustomerRegion.Value = "Europe", True,
Parameters!Person.Value = "Employee" AND Parameters!CustomerRegion.Value = "North America", False,
True, False)
The last pair of expressions act like an ELSE, it will always return true. Here I set the return to False so by default the column would be shown (Hidden = False)
The metric column would just be the opposite except you would probably want to leave the last pair (the True, False at the end) so the metric column is also shown by default.
This could be made even simpler assuming you only ever have Employee and Customer for person.value as you would not have to check it past the first expression. You can also add multiple checks for regions in a nice consice way rather than put them on separate lines, although you could do this with the IIF answer too..
Something like this.
=SWITCH(
Parameters!Person.Value = "Employee", False,
Parameters!CustomerRegion.Value = "Europe", True,
"North America Asia Somewhere Else".ToLower.Contains(Parameters!CustomerRegion.Value.ToString.ToLower), False,
True, False)
I've used ToLower to make the comparison case insensitive but you could exclude that if you wish.
Thanks for all the insightful answers guys. They all work and give the desired result but i have chosen to go with the "Switch" Statement
I Had structured it in this way for the metric column;
=SWITCH(Parameters!Person.Value = "Employee", False, Parameters!CustomerRegion.value = "North America", True)
And i just changed CustomerRegion.value to "Europe" for the imperial columns. It worked just fine this way. Hope this helps :)