SSRS Compare Row of values in two diffrent textboxes. - reporting-services

I am trying to take the values from one text box and compare if they are less than or greater than each other.
One text box being "OngradeTrend" and the other being "OngradeTrendPrevious"
When I execute, it returns "0's" See Pictures Attached!
I have tried:
=IIF(ReportItems![OngradeTrend].Value < ReportItems![OngradeTrendPrevious].Value, "DOWN", IIF(ReportItems![OngradeTrend].Value > ReportItems![OngradeTrendPrevious].Value, "UP", 0))
Edit View
Result
Thanks.

It may just be getting confused because you're specifying two strings, "down" and "up", and one number, 0. Try encasing the zero in quotation marks to make it a string:
=IIF(ReportItems![OngradeTrend].Value < ReportItems![OngradeTrendPrevious].Value, "DOWN", IIF(ReportItems![OngradeTrend].Value > ReportItems![OngradeTrendPrevious].Value, "UP", "0"))
You can also use the SWITCH statement, preferably with a default value in case your other options fail (like if one of your test fields are NULL). SWITCH doesn't have an "else" default value, but you can trick it with "true", which always evaluates to "true":
=SWITCH(
ReportItems![OngradeTrend].Value < ReportItems![OngradeTrendPrevious].Value, "DOWN",
ReportItems![OngradeTrend].Value > ReportItems![OngradeTrendPrevious].Value, "UP",
true, "0")

Related

jq filter to ignore values in select statement based on array values

Given the following JSON input :
{
"hostname": "server1.domain.name\nserver2.domain.name\n*.gtld.net",
"protocol": "TCP",
"port": "8080\n8443\n9500-9510",
"component": "Component1",
"hostingLocation": "DC1"
}
I would like to obtain the following JSON output :
{
"hostname": [
"server1.domain.name",
"server2.domain.name",
"*.gtld.net"
],
"protocol": "TCP",
"port": [
"8080-8080",
"8443-8443",
"9500-9510"
],
"component": "Component1",
"hostingLocation": "DC1"
}
Considering :
That the individual values in the port array may, or may not, be separated by a - character (I have no control over this).
That if an individual value in the port array does not contain the - separator, I then need to add it and then repeat the array value after the - separator. For example, 8080 becomes 8080-8080, 8443 becomes 8443-8443 and so forth.
And finally, that if a value in the port array is already of the format value-value, I should simply leave it unmodified.
I've been banging my head against this filter all afternoon, after reading many examples both here and in the official jq online documentation. I simply can't figure out how to accomodate consideration #3 above.
The filter I have now :
{hostname: .hostname | split("\n"), protocol: .protocol, port: .port | split("\n") | map(select(. | contains("-") | not)+"-"+.), component: .component, hostingLocation: .hostingLocation}
Yields the following output JSON :
{
"hostname": [
"server1.domain.name",
"server2.domain.name",
"*.gtld.net"
],
"protocol": "TCP",
"port": [
"8080-8080",
"8443-8443"
],
"component": "Component1",
"hostingLocation": "DC1"
}
As you can see above, I subsequently lose the 9500-9510 value as it already contains the - string which my filter weeds out.
If my logic does not fail me, I would need to stick an if statement within my select statement to conditionally only send array values that do not contain the string - to my select statement but leave array values that do contain the separator untouched. However, I cannot seem to figure this last piece out.
I will happily accept any alternative filter that yields the desired output, however I am also really keen on understanding where my logics fails in the above filter.
Thanks in advance to anyone spending their valuable time helping me out!
/Joel
First, we split the hostname string by a newline character (.hostname /= "\n") and do the same with the port string (.port /= "\n"). Actually, we can combine these identical operations into one: (.hostname, .port) /= "\n"
Next, for every element of the port array (.port[]) we split by any non-digit character (split("[^\\d]";"g")) resulting in an array of digit-only strings, from which we take the first element (.[0]), then a dash sign, and finally either the second element, if present, otherwise the first one again (.[1]//.[0])
With your input in a file called input.json, the following should convert it into the desired format:
jq '
(.hostname, .port) /= "\n" |
.port[] |= (split("[^\\d]";"g") | "\(.[0])-\(.[1]//.[0])")
' input.json
Regarding your considerations:
As we split at any non-digit character, it makes no difference what other character separates the values of a port range. If more than one character could separate them (e.g. an arrow -> or with spaces before and after the dash sign -), simply replace the regex [^\\d] with [^\\d]+ for capturing more than one non-digit character.
and 3. We always produce a range by including a dash sign and a second value, which depending on the presence of a second item may be either that or the first one again.
Regarding your approach:
Inside map you used select which evaluates to empty if the condition (contains("-") | not) is not met. As "9500-9510" does indeed contain a dash sign, it didn't survive. An if statement inside the select statement wouldn't help because even if select doesn't evaluate to empty it still doesn't modify anything, it just reproduces its input unchanged. Therefore, if select is letting through both cases (containing and not containing dash signs) it becomes useless. You could, however, work with an if statement outside of the select statement, but I considered the above solution as a simpler approach.

Using SUM with a switch function in Report builder 3.0

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.

Error occurs when the field is empty during a multiply expression

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)))

Replace different values with specific text in report builder

I have a table that will return a number and i need to convert it into a text label
20 = Entered, 30 = Returned, 200 = Cancelled, 220 = Complete, 300 = Deleted
I want these to show in my report as simply 'Complete' etc.
Im able to use the replace function to get one value to show correctly in the report:
=Replace(Fields!status.Value,"220","Complete")
But i cant work out how to do this for each possible number that will show in this column
Best way would likely be modifying the query with a CASE statement as mentioned, if you are able to do that. But if not, a cleaner alternative to the nested Replaces would be to simply use a Switch statement:
=Switch(
Fields!Status.Value = "20", "Entered",
Fields!Status.Value = "30", "Returned",
Fields!Status.Value = "200", "Cancelled",
Fields!Status.Value = "220", "Complete",
Fields!Status.Value = "300", "Deleted"
)
This is not the most efficient way to do this, but it's a quick fix:
=Replace(Replace(Replace(Replace(Replace(Fields!status.Value,"220","Complete"), "200","Cancelled"),"300","Deleted"),"20","Entered"),"30","Returned")
A better way would be to modify your DataSet query to replace the numbers with a CASE statement. See this documentation:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql

Hiding a column based on more than 2 parameters in SSRS

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 :)