SSIS Expression cannot be evaluated -- why not? - sql-server

I have variable in an SSIS package name User::FileFullPathLDR.
From this variable at run time of the SSIS package I want to extract the file name from FileFullPathLDR and put it in another variable called User::FileName.
I have tried all types of combinations to try and get this code to resolve in Expression Builder to resolve except standing on my head with incense burning saying OM 4 million times, and nothing seems to work.
I put the following expression in Expression Builder for the variable User::FileName:
REVERSE(SUBSTRING(REVERSE(#[User::FileFullPathLDR]),1,FINDSTRING(REVERSE(#[User::FileFullPathLDR] ),"\\",1)-1))
From the full path I expect to get the filename similar to: LDRFile01242019.txt.
But I keep getting the following error when expression builder parses this statement:
The length -1 is not valid for function "Substring". The length parameter cannot be negative. Change the length parameter to zero or a positive value.

I tested this expression:
REVERSE(SUBSTRING(REVERSE(#[User::FileFullPathLDR]),1,FINDSTRING(REVERSE(#[User::FileFullPathLDR]),"\\",1)-1))
against this test string:
C:\Folder1\Folder2\FileName.TXT
and it returned
FileName.TXT
There was no error
I tested it by creating a variable and defining an expression for it, then evaluating that expression.

You can try the following expression:
RIGHT(#[User::FileFullPathLDR],FINDSTRING(REVERSE(#[User::FileFullPathLDR]),"\\",1)-1)
Also try to add a conditional operator to avoid bad values errors:
FINDSTRING(REVERSE(#[User::FileFullPathLDR]),"\\",1) == 0 ? "" : RIGHT(#[User::FileFullPathLDR],FINDSTRING(REVERSE(#[User::FileFullPathLDR]),"\\",1)-1)
References
SSIS Expression to get filename from FilePath
SSIS Expression to Get File Name From Full Path

The part FINDSTRING(#[User::FileFullPathLDR],"\\",1) returns 0 if FileFullPathLDR does not contain a \. Since you are subtracting -1, you might end up with a negative value if your string doesn't match the pattern, or if the variable is set at runtime (you might have an empty string during validation).
If you need it to work with an empty string as well, you could add a \\ in front of it if there is no \\ present yet, using something like FINDSTRING(#[User::FileFullPathLDR],"\\",1) == 0 ? "\\"+ #[User::FileFullPathLDR] : #[User::FileFullPathLDR]
So the whole thing will be:
REVERSE(
SUBSTRING(
REVERSE(
#[User::FileFullPathLDR]),1,FINDSTRING(REVERSE(FINDSTRING(#[User::FileFullPathLDR],"\\",1) == 0 ? "\\"+ #[User::FileFullPathLDR] : #[User::FileFullPathLDR])
,"\\",1
)-1
)
)
So, if there is no \ present, it will just return the string itself.

Related

Why is this Loop not working in qlik sense script?

I am having a problem trying to do a FOR LOOP as it produces no values.
I am doing 3 steps, but not sure what is the problem, I have attached the APP.
/// 1. These are the FOR values to PASS for the variables below.
for i= -1 to -7 ;
for j=-8 to -15;
for z= -16 to -21
//// 2.These are variable FUNCTIONS with same structure
LET
V_result1=(sum(Peek(Result_1,$i))*0.45+sum(Peek(Result_1,$j))*0.35+sum(Peek(Result_1,$z))*0.2)*1/5;
V_result2=(sum(Peek(Result_2,$i))*0.45+sum(Peek(Result_2,$j))*0.35+sum(Peek(Result_2,$z))*0.2)*1/5;
//// 3. The table where to apply those VARIABLES from a RESIDENT table.
DATE_PRODUCTION_4;
LOAD
"Date",
Sum($(V_result1)) as Forecast1,
sum($(V_result2)) as Forecast2
Resident [DATE_PRODUCTION_3]
GROUP BY "Date";
APP TEST
Couple of things going wrong here:
If we look here, we see this:
Argument Description
field_name Name of the field for which the return value is required. Input value must be given as a string (for example, quoted literals).
"Input value must be given as a string (for example, quoted literals)."
So instead of:
Peek(Result_1,$i)
You should use:
Peek('Result_1', $i)
If we look here, we see this:
When using a variable for text replacement in the script or in an
expression, the following syntax is used:
$(variablename)
So building on step one, instead of this
Peek('Result_1', $i)
You should use:
Peek('Result_1', $(i))
Your for loop starts at -1 and goes to -7, but in the app you added, -7 will always return NULL, since your data only consists of 4 rows. So change your for loop to a smaller range and first start of with one loop, then nest another for loop and then nest another. That way you can solve it step-by-step.

Why does this SSIS Conversion Expression syntax the way it is?

I'm looking at an SSIS package with a Derived Column Data Flow Component
When, I open it, I see 1 transformation:
Derived COLUMN Name : CLIENT_ID
Derived COLUMN: "REPLACE 'CLIENT_ID'"
EXPRESSION: TRIM(CLIENT_ID) == "" ? (DT_STR,9,1252)NULL(DT_STR,9,1252) : CLIENT_ID
DATA TYPE: string [DT-STR]
LENGTH: 9
PRECISION:
SCALE:
CODE PAGE: 1252 (ANSI- LATIN I)
I'm trying to understand the SSIS expression and I'm not sure that I understand the syntax.
TRIM(CLIENT_ID) == "" ? (DT_STR,9,1252)NULL(DT_STR,9,1252) : CLIENT_ID
I believe that the code is reading in the CLIENT_ID field from a flat file and that the field is coming in as a string. The conversion appear to check to see if the value read is all whitespace and if so, converts to a NULL string value, otherwise uses the original CLIENT_ID string value.
The syntax of the conversion confused me, perhaps because I am trying to relate it to C# code. I expected the following for the EXPRESSION:
TRIM(CLIENT_ID) == "" ? NULL : CLIENT_ID
or perhaps
TRIM(CLIENT_ID) == "" ? (DT_STR,9,1252)NULL : CLIENT_ID
Why is NULL surrounded by two conversions: (DT_STR,9,1252)?
SSIS has a separate null for each datatype. E.g., NULL(DT_STR,9,1252) means a null that is specific to a nine character string on that code page.
As in C#, the first (DT_STR,9,1252) is a type cast. Of course, the cast is not necessary here, since this NULL already has the correct data type.

IIF construct not resolving the correct way (SSRS)

I've got a problem with this piece of code inside a parameter in SSRS2012.
=IIF(InStr(Parameters!P1.Value,"#")=0,
"missing #",
Left(Parameters!P1.Value(InStr(Parameters!P1.Value,"#")-1)))
My aim is to check if the parameter P1 contains a "#" if it doesn't i will print "missing #" otherwise i want to remove from that parameter what's after the "#" ("#" inculded).
example:
P1 = 123456 --> print "missing #"
P1 = 123#56 --> print 123
The problem is that SSRS drops the error: "Argument 'length' must be greater or equal to zero" when i insert a value with no "#". (when i insert a value with an "#" it goes all well)
It seems like the IIF resolves the 2 expressions first (rather than one is true or false) and after that it gives you the correct one based on the evaluation of the first condition.
Looking for some help. Thanks!
it is a weird bug, here is one solution
=replace(replace(IIF(InStr(Fields!P1.Value,"#")<> 0,
left(Fields!P1.Value,InStr(Fields!P1.Value,"#")),"missing"),"#",""),"missing","missing #")

SSIS Derived Column - Text in Numeric Field is not converting

I'm importing thousands of csv files into an SQL DB. They each have two columns: Date and Value. In some of the files, the value column contains simply a period (ex: "."). I've tried to create a derived column that will handle any cell that contains a period with the following code:
FINDSTRING((DT_WSTR,1)[VALUE],".",1) != 0 ? NULL(DT_R8) : [VALUE]
But, when the package runs it gets the following error when it reaches the cell with the period in it:
The data conversion for column "VALUE" returned status value 2 and status text
"The value could not be converted because of a potential loss of data".
I'm guessing there might be an escape character that I'm missing in my FINDSTRING function but I can't seem to find what that may be. Does anyone have any thoughts on how I can get around this issue?
Trying to debug things like this is why I always advocate adding many Derived Columns to the Data Flow. It's impossible to debug that entire expression. Instead, first find the position of the period and add that as a new column. Then you can feed that into the ternary operation and bit by bit you can add data viewers to ensure you are seeing what you expect to see.
Personally, I'd take a different approach. It seems that you'd like to make any columns that are . into a null of type DT_R8.
Add a derived column, TrimmedValue and use this expression to remove any leading/trailing whitespace and then
RTRIM(LTRIM(Value))
Add a second derived column component, this time we'll add column MenopausalValue as it will remove the period. Use this expression
(TrimmmedValue == ".") ? Trimmedvalue : NULL(DT_WSTR, 50)
Now, you can add your final Derived Column wherein we convert the string representation of Value to the floating point representation.
IsNull(MenopausalValue) ? NULL(DT_R8) : (DT_R8) MenopausalValue
If the above shows an error, then you need to apply the following version as I can never remember the evaluation sequence for ternary operations that change type.
(DT_R8) (IsNull(MenopausalValue) ? NULL(DT_R8) : (DT_R8) MenopausalValue)
Examples of breaking these operations into many steps for debugging purposes
https://stackoverflow.com/a/15176398/181965
https://stackoverflow.com/a/31123797/181965
https://stackoverflow.com/a/33023858/181965
You can do it like this:
TRIM(Value) == "." ? NULL(DT_R8) : (DT_R8)Value

Set local variable in rdlc expression

Is it possible to somehow create variable in rdlc report expression in 'online' manner?
For example, I have following expression:
=IIf(First(Fields!BillingAccount_billtostateprovince.Value, "Invoice") <> "",
First(Fields!BillingAccount_billtostateprovince.Value, "Invoice") + " ",
"")
I suppose that I'm evaluating following expression First(Fields!BillingAccount_billtostateprovince.Value, "Invoice") twice. I don't like it and it looks ugly... I would prefer to create variable in the scope of current expression and use it.
Is it possible?
As user3056839 said, Welcome to SSRS!
Anyway, what you want is not possible since what you are writing right now is not a script but it's just an expression. It's a single statement that returns a value, so you cannot declare variables, use loops or anything that is part of a script.
You have to use exactly what you are writing.
Also it's not rare to see an IIF expression like yours. The one I constantly see is IFF( IS NOT NULL, , 'N/A'). The field may actually be evaluated twice, but there's nothing you can do. It's ugly but it's the only way you can do that.
Just think about the CASE WHEN clause:
SELECT
CASE WHEN MyField IS NOT NULL THEN
MyField ELSE 0
END
You are evaluating the field twice, but there's nothing you can do :)
It is possible to do it in SQL Server 2008 and above. You can create a Report Variable which can be accessed through out your report.
Reference: sqlchick.com

Resources