ms SSRS 2008 R2: Display Computed Values #Error - sql-server

The Report will display Two Columns Foo and Bar
Some Rows of Foo are Empty Some have a numerical Value:
Foo:
+----+
| |
+----+
|10.0|
+----+
then There is the Bar Column, this column will take the Values from Foo and add 10 to them, the report should yield Results like this:
Foo: Bar:
+----+----+
| | |
+----+----+
|10.0|20.0|
+----+----+
Thats the Expression i use to determine whether Foo is numeric inside Bar:
=IsNumeric(ReportItems!FooBox.Value)
And this is the Result that Expression will Yield:
Foo: Bar:
+----+-----+
| |False|
+----+-----+
|10.0|True |
+----+-----+
Okay, thats exactly the way i want it so far, thus i write My Expression that way:
=IIf(IsNumeric(ReportItems!FooBox.Value),
ReportItems!FooBox.Value +10,
"")
This will Yield the Following Results:
Foo: Bar:
+----+------+
| |#Error|
+----+------+
|10.0|20.0 |
+----+------+
And most Bizare, when i remove the little addition in the Truepart of the IIf, it will execute:
=IIf(IsNumeric(ReportItems!FooBox.Value),
ReportItems!FooBox.Value,
"")
Foo: Bar:
+----+------+
| | |
+----+------+
|10.0|10.0 |
+----+------+
It's almost as if the "wrong" part of the Ternary operator gets executed Anyway, thus generating this castError or whatever it might be.
How can i convert the Values properly in order to Show the Results as Explained before?

Indeed - using IIf will cause both statements (true and false) to be evaulated and that leads to the error you are getting.
being in your situation, I would create my own function to handle this - you can place it in Code field of your Report (click outside of Page area to access Report object)
your function might look like this:
Public Function MyAdd(val As Object) As Nullable(Of Integer)
If TypeOf(val) Is Integer Then
Return val + 10
Else
Return Nothing
End If
End Function
you might need to play with types used (Object and Nullable Of Integer are maybe not what will work for you)
then, of course, use MyAdd in your expression and pass ReportItems!FooBox.Value as parameter

Related

Postgresql function has unsupported return

I'm very new in work with data base, and this is my first time with triggers and functions. I have two tables:
main table "orders"
id | order_status_id | tracking_code
----+-----------------+---------------
12 | 2 | 123456
9 | 2 |
6 | 2 |
7 | 2 |
10 | 2 |
8 | 2 |
11 | 2 |
and another one "order_statuses"
id | status
----+-------------
1 | QUEUE
2 | IN_PROGRESS
3 | IN_DELIVERY
4 | DELIVERED
5 | CANCELED
6 | RETURNED
I want to change value in column order_status_id automatically (from 2 to 3) when I change the value in column tracking_code (default value is null).
I wrote trigger and function:
CREATE TRIGGER change_status
BEFORE UPDATE
OF tracking_code
ON orders
EXECUTE PROCEDURE update_status();
CREATE FUNCTION update_status() RETURNS TRIGGER
AS
$$
DECLARE
passed bigint;
BEGIN
SELECT id INTO passed FROM order_statuses WHERE status = IN_DELIVERY;
NEW.order_status_id = passed;
return NEW;
END;
$$;
but when I try to run this code, I get error:
[2020-09-07 15:22:53] [42804] ERROR: function "update_status" in FROM has unsupported return type trigger
[2020-09-07 15:22:53] Где: PL/pgSQL function inline_code_block line 5 at OPEN
I tried to implement a lot of answers for the same question from stack overflow, but nothing helps.
can someone tell me what I do wrong and if is my code "good" in general?!
Your trigger definition is OK, except for one thing; the documentation says:
FOR EACH ROW
FOR EACH STATEMENT
This specifies whether the trigger function should be fired once for every row affected by the trigger event, or just once per SQL statement. If neither is specified, FOR EACH STATEMENT is the default.
So you probably want to specify FOR EACH ROW.
The error message, however, has a different cause:
There is a DO statement somewhere in your code (“inline_code_block”) that calls update_status directly. That doesn't work. You can use trigger functions only in trigger definitions.

Use TQuery.Locate() function to find other then first matching

Locate moves the cursor to the first row matching a specified set of search criteria.
Let's say that q is TQuery component, which is connected to the database with two columns TAG and TAGTEXT. With next code I am getting letter a. And I would like to use Locate() function to get letter d.
If q.Locate('TAG','1',[loPartialKey]) Then
begin
tag60 := q.FieldByName('TAGTEXT');
end
For example if I got table like this:
TAG | TAGTEXT
+---+--------+
| 1 | a |
+---+--------+
| 2 | b |
+---+--------+
| 3 | c |
+---+--------+
| 1 | d |
+---+--------+
| 4 | e |
+---+--------+
| 1 | f |
+---+--------+
is it possible to locate the second time number one occurred in table?
EDIT
My job is to find the occurrence of TAG with value 1 (which occurrence I need depends on the parameter I get), I need to iterate through table and get the values from all the TAGTEXT fields till I find that value in TAG field is again number 1. Number 1 in this case represents the start of new segment, and all between the two number 1s belongs to one segment. It doesn't have to be same number of rows in each segment. Also I am not allowed to do any changes on table.
What I thought I could do is to create a counter variable that is going to be increased by one every time it comes to TAG with value 1 in it. When the counter equals to the parameter that represents the occurrence I know that I am in the right segment and I am going to iterate through that segment and get the values I need.
But this might be slow solution, and I wanted to know if there was any faster.
You need to be a bit wary of using Locate for a purpose like this, because some
TDataSet descendants' implementation of Locate (or the underlying db-access layer) construct a temporary index on the dataset. which can be discarded immediately afterwards, so repeatedly calling Locate to iterate the rows of a given segment may be a lot more inefficient than one might expect it to be.
Also, TClientDataSet constructs, uses and then discards an expression parser for each invocation of Locate (in its internal call to LocateRecord), which is a lot of overhead for repeated calls, especial when they are entirely avoidable.
In any case, the best way to do this is to ensure that your table records which segment a given row belongs to, adding a column like the SegmentID below if your table does not already have one:
TAG | TAGTEXT|SegmentID
+---+--------+---------+
| 1 | a | 1
| 2 | b | 1
| 3 | c | 1
| 1 | d | 2
+---+--------+---------+ // btw, what happened to the 2 missing rows after this one?
| 4 | e | 2
| 1 | f | 3
+---+--------+---------+
Then, you could use code like this to iterate the rows of a segment:
procedure IterateSegment(Query : TSomeTypeOfQueryComponent; SegmentID : Integer);
var
Sql; String;
begin
Sql := Format('select * from mytable where SegmentID = %d order by Tag', [SegmentID]);
if Query.Active then
Query.Close;
Query.Sql.Text := Sql;
Query.Open;
Query.DisableControls;
try
while not Query.Eof do begin
// process row here
Query.Next;
end;
finally
Query.EnableControls;
end;
end;
Once you have the SegmentID column in the table, if you don't want to open a new query to iterate a block, you can set up a local index (by SegmentID then Tag), assuming your dataset type supports it, set a filter on the dataset to restrict it to a given SegmentID and then iterate over it
You have much options to do this.
If your component don´t provide a locateNext you can make your on function locateNext, comparing the value and make next until find.
You can also bring the sql with order by then use locate for de the first value and test if the next value match the comparision.
If you use a clientDataset you can filter into the component filter propertie, or set IndexFieldNames to order values instead the "order by" of sql in the prior suggestion.
You can filter it on the SQL Where clausule too.

Excel Lookup IP addresses in multiple ranges

I am trying to find a formula for column A that will check an IP address in column B and find if it falls into a range (or between) 2 addresses in two other columns C and D.
E.G.
A B C D
+---------+-------------+-------------+------------+
| valid? | address | start | end |
+---------+-------------+-------------+------------+
| yes | 10.1.1.5 | 10.1.1.0 | 10.1.1.31 |
| Yes | 10.1.3.13 | 10.1.2.16 | 10.1.2.31 |
| no | 10.1.2.7 | 10.1.1.128 | 10.1.1.223 |
| no | 10.1.1.62 | 10.1.3.0 | 10.1.3.127 |
| yes | 10.1.1.9 | 10.1.4.0 | 10.1.4.255 |
| no | 10.1.1.50 | … | … |
| yes | 10.1.1.200 | | |
+---------+-------------+-------------+------------+
This is supposed to represent an Excel table with 4 columns a heading and 7 rows as an example.
I can do a lateral check with
=IF(AND((B3>C3),(B3 < D3)),"yes","no")
which only checks 1 address against the range next to it.
I need something that will check the 1 IP address against all of the ranges. i.e. rows 1 to 100.
This is checking access list rules against routes to see if I can eliminate redundant rules... but has other uses if I can get it going.
To make it extra special I can not use VBA macros to get it done.
I'm thinking some kind of index match to look it up in an array but not sure how to apply it. I don't know if it can even be done. Good luck.
Ok, so I've been tracking this problem since my initial comment, but have not taken the time to answer because just like Lana B:
I like a good puzzle, but it's not a good use of time if i have to keep guessing
+1 to Lana for her patience and effort on this question.
However, IP addressing is something I deal with regularly, so I decided to tackle this one for my own benefit. Also, no offense, but getting the MIN of the start and the MAX of the end is wrong. This will not account for gaps in the IP white-list. As I mentioned, this required 15 helper columns and my result is simply 1 or 0 corresponding to In or Out respectively. Here is a screenshot (with formulas shown below each column):
The formulas in F2:J2 are:
=NUMBERVALUE(MID(B2,1,FIND(".",B2)-1))
=NUMBERVALUE(MID(B2,FIND(".",B2)+1,FIND(".",B2,FIND(".",B2)+1)-1-FIND(".",B2)))
=NUMBERVALUE(MID(B2,FIND(".",B2,FIND(".",B2)+1)+1,FIND(".",B2,FIND(".",B2,FIND(".",B2)+1)+1)-1-FIND(".",B2,FIND(".",B2)+1)))
=NUMBERVALUE(MID(B2,FIND(".",B2,FIND(".",B2,FIND(".",B2)+1)+1)+1,LEN(B2)))
=F2*256^3+G2*256^2+H2*256+I2
Yes, I used formulas instead of "Text to Columns" to automate the process of adding more information to a "living" worksheet.
The formulas in L2:P2 are the same, but replace B2 with C2.
The formulas in R2:V2 are also the same, but replace B2 with D2.
The formula for X2 is
=SUMPRODUCT(--($P$2:$P$8<=J2)*--($V$2:$V$8>=J2))
I also copied your original "valid" set in column A, which you'll see matches my result.
You will need helper columns.
Organise your data as outlined in the picture.
Split address, start and end into columns by comma (ribbon menu Data=>Text To Columns).
Above the start/end parts, calculate MIN FOR START, and MAX FOR END for all split text parts (i.e. MIN(K5:K1000) .
FORMULAS:
VALIDITY formula - copy into cell D5, and drag down:
=IF(AND(B6>$I$1,B6<$O$1),"In",
IF(OR(B6<$I$1,B6>$O$1),"Out",
IF(B6=$I$1,
IF(C6<$J$1, "Out",
IF( C6>$J$1, "In",
IF( D6<$K$1, "Out",
IF( D6>$K$1, "In",
IF(E6>=$L$1, "In", "Out"))))),
IF(B6=$O$1,
IF(C6>$P$1, "Out",
IF( C6<$P$1, "In",
IF( D6>$Q$1, "Out",
IF( D6<$Q$1, "In",
IF(E6<=$R$1, "In", "Out") )))) )
)))

How to apply Multiple ng-pattern with one input control

I am trying to Validate Postal code and Phone Number in Text box using Angularjs. But it's not working
<input type="text" class="form-control errorfields" id="postalCode"
name="postalCode" ng-model="postalCode"
ng-pattern="/(^(\d{5}(-\d{4})?|[A-CEGHJ-NPRSTVXY]\d[A-CEGHJ-NPRSTV-Z]
?\d[A-CEGHJ-NPRSTV-Z]\d)$)||(^[0-9])/" required>
See this answer:
Angularjs dynamic ng-pattern validation
You can add a function from scope that returns a true or false based on the validation test. Here is some code below to check out. See the answer for additional information:
Controller:
$scope.postalCodeValidation = (function() {
var regexp = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
return {
test: function(value) {
return regexp.test(value);
}
};
})();
HTML:
<input type="text" class="form-control errorfields" id="postalCode"
name="postalCode" ng-model="postalCode"
ng-pattern="postalCodeValidation " required>
First, having double pipes in your regex syntax as mico pointed out, is invalid and will break your expression.
Second, ng-pattern can only validate one pattern per input. If you need it to validate either or, you will need to go one of two routes, create a custom directive, or add some logic to the controller to determine which expression we should check against and pass it into ng-pattern using data binding. This is bad practice in the angular world, so your best bet is to make a directive.
Edit: This will only work for regular expressions with starting ^ and ending $ metacharacters.
Like many of my StackOverflow answers, I'm super late to this party. This question got me on the right track, but none of the answers given were good enough to make a final solution.
Here's something I wrote recently after reading this thread which didn't fully answer my question, which made my code reviewer exclaim, "WTF IS THIS?!" Followed by him hitting the MERGE button.
My problem was I had a form input which I wanted to accept and validate against latitude or longitude regular expressions. I wanted to match against DMS, DDM, and DD style inputs. I could have written one giant expression, but I also needed to test the input at the component level to determine which type the user input and convert it to DD. The expressions for lat/long would make this answer even more complicated, so I am using what I think the original author intended.
If you're interested in lat/long expressions, here's a gist: https://gist.github.com/pjobson/8f44ea79d1852900457bc257a4c9fcd5
Here's kind of a rewrite of my code for this exercise, I abstracted it from angular to make it more accessible as it could be used for other purposes.
It looks like you're accepting: North America Zip Code OR UK Zip Code OR something which starts with 0-9.
Fleshing out the regex a bit, I haven't tested these myself very well, so your mileage may vary. This is what the need seemed to look like to me, it is just sample code, so it doesn't really matter that much 3+ years later.
N.America Zip or Zip+4 (from sample above)
^(\d{5}(-\d{4})?$
UK Zip Code (from wikipedia)
^([A-Za-z][A-Ha-hJ-Yj-y]?[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$
N.America Phone Number (from RegExLib.com)
^[2-9]\d{2}-\d{3}-\d{4}$
UK Phone Number (from RegExLib.com)
^(\s*\(?0\d{4}\)?\s*\d{6}\s*)|(\s*\(?0\d{3}\)?\s*\d{3}\s*\d{4}\s*)$
In an object...
const expressions = {
naZip: /^\d{5}(-\d{4})?$/,
ukZip: /^([A-Za-z][A-Ha-hJ-Yj-y]?[0-9][A-Za-z0-9]? ?[0-9][A-Za-z]{2}|[Gg][Ii][Rr] ?0[Aa]{2})$/,
naPhone: /^[2-9]\d{2}-\d{3}-\d{4}$/,
ukPhone: /^(\s*\(?0\d{4}\)?\s*\d{6}\s*)|(\s*\(?0\d{3}\)?\s*\d{3}\s*\d{4}\s*)$/
};
Now the problem is ng-pattern ONLY accepts one regex, but I have four. I want to keep those as four different things so in my component I can test to figure out which one the user input and do different actions based on whatever it is.
This looks like garbage, but it works really well.
const combinedExpression = new RegExp(`^(${_.map(expressions, exp => `(${exp.toString().replace(/^\/\^(.+?)\$\/$/,'$1')})`).join('|')})$`);
From here of course you can add this to your model and set your ng-pattern to it.
I'll try to explain this in several different ways here...
Here is a break down of what it is doing.
new RegExp(`^(${_.map(expressions, exp => `(${exp.toString().replace(/^\/\^(.+?)\$\//g,'$1')})`).join('|')})$`);
^ ^^^^ ^ ^ ^ ^ ^ ^ ^ ^ ^^
| |||| | | | | | | | | ||
| |||| | | | | | | | | |+- end of the 1st template literal
| |||| | | | | | | | | +- end the expression with $
| |||| | | | | | | | +- join all stringified expressions with a pipe so (a|b|c|d)
| |||| | | | | | | +- end of 2nd template literal
| |||| | | | | | +- replace the like /^(\d{5}(-\d{4})?$/ to (\d{5}(-\d{4})?
| |||| | | | | +- convert the expression to a string
| |||| | | | +- new Expression interpolation
| |||| | | +- 2nd templte literal
| |||| | +- each expression is represented by exp
| |||| +- Using lodash map the expressions
| |||+- Expression interpolation
| ||+- Regex group match, we will be grouping each of the expressions
| |+- Regex starts with ^
| +- Starting a new template literal
+- Establish a new combined expression.
Further clarification...
What I'm doing is taking each of the expressions, converting them to strings, removing the starting end ending characters, joining them back together as an OR Group and then converting the whole thing to one huge combined regular expression.
Further clarification...
If that was too confusing, which I can see how it may be...
Loop through each of the expressions.
Convert each of those values to a string removing the starting and ending components so /^(\d{5}(-\d{4})?$/ converts to (\d{5}(-\d{4})?.
Join all of those together into one big OR Group so you'd get something like (a|b|c|d) where a, b, c, d are each of your stringified expressions.
Wrap the OR Group with starts with ^ and ends with $.
Wrap the entire thing with in a new RegExp.
Further clarification, in long hand JS.
// Instantiate a new empty array
const strings = [];
// Loop the expressions
for (let key in expressions) {
// Console log to see what we're getting
console.log('original expression', expressions[key]);
// assign the current expression
let stringifiedExp = expressions[key];
// convert the current expression to a string
stringifiedExp = stringifiedExp.toString();
// replace the starting /^ and ending $/ with the contents
stringifiedExp = stringifiedExp.replace(/^\/\^(.+?)\$\/$/,'$1');
// Console log to see what we got.
console.log('stringified expression', stringifiedExp);
// Push the stringified expression to strings.
strings.push(stringifiedExp);
}
// Instantiate a new string which we'll build the regex with
let expString = '^(';
expString += strings.join('|');
expString += ')$';
// Console log to see what we've got.
console.log(expString);
// Make a new Regular Expression out of the string
const combinedExpression = new RegExp(expString);
// Console log what we've got
console.log(combinedExpression);
Your regex has two || instead of single, which breaks the regex validation clause.
I pasted it to (https://regex101.com) and it says that char breaks it.
I think you need to wrap a ng-form around your input. And then you can use
[formName].postalCode.$error

sort 2d Array re-order the first column

For example:
Array
ID | Primary | Data2
------------------
1 | N | Something 1
2 | N | Something 2
3 | Y | Something 3
I'm trying to sort it based on the primary column and I want the "Y" to show first. It should bring all the other column at the top.
The end result would be:
Sorted Array
ID | Primary | Data2
------------------
3 | Y | Something 3
1 | N | Something 1
2 | N | Something 2
Is there a pre-made function for that. If not, how do we do this?
It is declared like this:
Dim Array(,) As String
regards,
I like using LINQ's OrderBy and ThenBy to order collections of objects. You just pass in a selector function to use to order the collections. For example:
orderedObjs = objs.OrderByDescending(function(x) x.isPrimary).ThenBy(function(x) x.id).ToList()
This code orders a collection first by the .isPrimary boolean, then by the id. Finally, it immediately evaluates the query into a List and assigns it to some variable.
Demo
There's a similar C# question whose solution applies just as well to VB. In short, you can use an overload of Array.Sort if you first split your 2D array into separate (1D) arrays:
Dim Primary() As String
Dim Data2() As String
// ...
Array.Sort(Primary,Data2)
This would reorder Data2 according to the Y/N sort of Primary, after which point you could then recombine them into a 2D array.

Resources