Error occurs when the field is empty during a multiply expression - reporting-services

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

Related

SSRS Report Shows #Error When Converting Number to Currency

I am trying to get the report to show the purchase price which the user enters in a parameter. If the user doesn't enter anything it will say "Undisclosed" otherwise I want it to show the purchase price as currency. I have tried the following:
=IIF(Parameters!PurchasePrice.Value = "", "Undisclosed", Cstr(Format(Parameters!PurchasePrice.Value, "C")))
=IIF(Parameters!PurchasePrice.Value = "", "Undisclosed", Format(Parameters!PurchasePrice.Value, "C"))
=IIF(Parameters!PurchasePrice.Value = "", "Undiscloded", FormatCurrency(Parameters!PurchasePrice.Value,0))
=IIF(Parameters!PurchasePrice.Value = "", "Undiscloded", FormatNumber(Parameters!PurchasePrice.Value,0))
I can get "Undisclosed" to appear but every time I enter a number it shows #Error
You can try the following solution:
=IIF(IsNumeric(Parameters!PurchasePrice.Value), Format(Val(Parameters!PurchasePrice.Value), "C"), "Undisclosed")
I would approach this slightly differently. This will avoid SSRS trying to format a non numeric to a currency. IIF will evaluate both the true and false outcomes even though only one result can be true for each instance.
I would set the textbox that shows the purchase price up as follow...
Set the Value expression to be
=VAL(Parameters!PurchasePrice.Value)
This will return a zero if the parameter value is left as blank/empty string
Then set the Format property of the textbox to
$#.00;-$#.00;Undisclosed
Assuming you want $ as the currency symbol. This format string will format the number to two decimals for positive and negative numbers and prefix the $ symbol but for zero values, it will show the work "Undisclosed"

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.

SSRS Sharepoint List IIF Field Value = "area 1" then add 60 days to date value

I hope someone can assist or point me in the right direction
I have a report that contains Fields!District.Value, If this value = "area 1" then i would like to add 60 days to the Field!Date.Value
Obligatory "I'm still learning" SSRS and I have tried the following with no success;
=IIf(Fields!District.Value="North Lanarkshire","DateAdd("d", 60, Fields!Date.Value)"
I'm assuming it's placement of a , or )
thanks in advance for your help :)
There are a couple of mistake here. Let's break it down.
To start with the IIF function syntax can be thought of like this..
IIF([Expression to evaluate to true or false], [expression to return if true], [expression to return if false])
So your first expression Fields!District.Value="North Lanarkshire" is fine, this will return true or false.
Next expression, what to return if true is close but not correct. "DateAdd("d", 60, Fields!Date.Value)". There is no need for the outer quotes and instead of "d" you should use DateInterval.Day so this should end up being DateAdd(DateInterval.Day, 60, Fields!Date.Value).
Finally we need something to return if the result is false (i.e. District is not "North Lanarkshire"). I'll assume you just want the original date column's value returned here so we can just use Fields!Date.Value
So, the final expression should look like this.
=IIF(Fields!District.Value="North Lanarkshire", DateAdd(DateInterval.Day, 60, Fields!Date.Value), Fields!Date.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

MySQL - JSON - return attribute where value equal true

I have something like this in my table "superheroes":
name | attributes
Batman | {"dead": false, "orphan": true, "billionaire": true, "goodboy" : true}
how can I return all attributes that are true?
I know how to retrieve the value of specific attribute such as
select json_extract((SELECT attributes from superheroes where name = 'Batman'),'$.orphan')
this will return true, which is correct. But I need to find all attributes that are true. Is there a way in MySQL?This is just example, but real situation is little bit too much complicated... Thanks in advance.
I think the closest to what you want is JSON_SEARCH()
SELECT JSON_SEARCH(attributes, 'all', 'true')
FROM superheroes
WHERE name = 'Batman';
However, for this to work, the values have to be strings, not booleans, because JSON_SEARCH treats the search string as a LIKE pattern to match against strings, not a JSON value. So the JSON has to be:
{"dead": "false", "orphan": "true", "billionaire": "true", "goodboy" : "true"}
DEMO