Why is this Loop not working in qlik sense script? - loops

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.

Related

How to split a search string into parts, then check parts against a database

Here's what I'm dealing with:
We have a database of machines and their part lists are specified using strings. For example, one machine might be specified with the string &XXX&YYY-ZZZ, meaning the machine contains parts XXX and YYY and not ZZZ.
We use &XXX to specify that a part exists in a machine, and -XXX to specify that a part does not exist in a machine.
It's also possible that a part is not listed (i.e. not specified whether or not it exists in the machine). For example I might only have &XXX&YYY (ZZZ is not specified).
Additionally, the codes can be in any order, for example I might have &XXX&YYY-ZZZ or &XXX-ZZZ&YYY.
In order to search for machines, I get a string like this: &XXX-YYY/&YYY&ZZZ (/ is an OR operator), meaning "I want to find all machines that either a) contain XXX and do not contain YYY, or b) contain both YYY and ZZZ.
I'm having trouble parsing the string based on the variable ordering, possibility that parts may not be shown, and handling of the / operator. Note, we use Microsoft 365.
Looking for some suggestions!
When I search for &XXX-YYY/&YYY&ZZZ, I should return the following machines:
Machine
Result
&XXX-YYY&ZZZ
TRUE (because XXX exists and YYY does not exist)
&XXX-YYY-ZZZ
TRUE (because XXX exists and YYY does not exist)
&XXX&YYY&ZZZ
TRUE (because YYY exists and ZZZ exists)
&XXX&ZZZ
FALSE (because YYY is specified in the search, but this machine doesn't specify it)
&ZZZ&YYY
TRUE (showing that parts can be in any order)
You can try it in cell C2 with the following formula:
=LET(query, A2, queries, TEXTSPLIT(query,, "/"), input, B2:B7,
qryNum, ROWS(queries),
SPLIT, LAMBDA(txt,LET(str, SUBSTITUTE(SUBSTITUTE(txt, "&",";1_"),
"-",";0_"), TEXTSPLIT(str,,";",TRUE))),
lkUps, DROP(REDUCE("", queries, LAMBDA(acc,qry, HSTACK(acc, SPLIT(qry)))),,1),
MAP(input, LAMBDA(txt, LET(str, SPLIT(txt),
out, REDUCE("", SEQUENCE(qryNum, 1), LAMBDA(acc,idx,
LET(cols, INDEX(lkUps,,idx), qry, FILTER(cols, cols<>""),
matches, SUM(N(ISNUMBER(XMATCH(str, qry)))),
result, IF(ROWS(qry)=matches,1,0),IF(acc="", result, MAX(acc, result))
))), IF(out=1, TRUE, FALSE)
)))
)
and here is the corresponding output:
Assumptions:
String values (operation and part) should be unique, i.e. the case &XXX-YYY&XXX is not considered, because &XXX is duplicated.
Explanation
The main idea is to transform the input information in a way we can do comparisons at array level via XMATCH. The first thing to do is to identify each OR condition in the search string because we need to test each one of them against the Input column. The name queries is an array with all the OR conditions.
We can transform the string inputs in a way we can split the string into an array. SPLIT is a user LAMBDA function that does that:
SUBSTITUTE(SUBSTITUTE(txt, "&",";1_"),"-",";0_"), TEXTSPLIT(str,,";",TRUE)))
What it does is convert for example the input: &XXX-YYY&ZZZ into the following array:
1_XXX
0_YYY
1_ZZZ
We change the original operations &,- into 1,0 just for convenience, but you can keep the original operation value, it is irrelevant for the calculation. It is important to set the fourth TEXTSPLIT input argument to TRUE to ensure no empty rows are generated.
The name lkUps is an array with all the OR conditions organized by column for query. In the format we want, for example:
1_XXX 1_YYY
0_YYY 1_ZZZ
Note: For creating lkUps we use the pattern: DROP/REDUCE/HSTACK, for more information about it, check the answer to the question: how to transform a table in Excel from vertical to horizontal but with different length provided by #DavidLeal.
Now we have all the elements we need to build the recurrence. We use MAP to iterate over all Input column values. For each element (txt) we transform it to the format of our convenience via SPLIT user LAMBDA function and name it str.
We use REDUCE function inside MAP to iterate over all columns of lkUps to check against str. We use SEQUENCE(qryNum, 1) as input of REDUCE to be able to iterate over each lkUps column (qry).
Now we are going to use the above variables in XMATCH and name the variable matches as follows:
SUM(N(ISNUMBER(XMATCH(str, qry))))
If all values from qry were found in str then we have a match. If that is the case the item of the SUM will be 1, otherwise 0. Therefore the SUM for the match case should be of the same size as qry.
Because we include in the XMATCH both parts and operations (1,0), we ensure that not just the same parts are found, but also their corresponding operations are the same. The order of the parts is not relevant, XMATCH ensures it.
The REDUCE recurrence keeps the maximum value from the previous iteration (previous OR condition). We just need at least one match among all OR conditions. Therefore once we finish all the recurrence, if the result value of REDUCE is 1 at least one match was found. Finally, we transform the result into a TRUE/FALSE.
Note: For a large list of operations instead of using the above approach of two SUBSTITUTE calls. The SPLIT function can be defined as follow:
LAMBDA(txt,tks, LET(seq, SEQUENCE(COLUMNS(tks),1),
out, REDUCE("", seq, LAMBDA(acc,idx, LET(str, IF(acc="", txt, acc),
SUBSTITUTE(str, INDEX(tks,1,idx), INDEX(tks,2,idx))))),
TEXTSPLIT(out,,";",TRUE)))
and the input tks (tokens) can be defined as follow: {"&","-";"1_", "0_"}, i.e. in the first row old values and in the second row the new values.

Pentaho data integration loop count variable

I want a simple loop function to count the number of loop like below in java programming:
for (int i = 0; i <3; i++) {
count = count+1;
}
System.out.println(count);
I am doing it using Pentaho data integration. so I have 1 job contain 3 transformations in it, where first transformation set the number of loop (above example 3), then second transformation click "Execute every input row" for looping, and set variable inside the transformation using Javascript with getVariable() and setVariable() function. the last transformation just get variable and write log to show the count.
The problem is every loop in the transformation 2 will get variable as 0. so it end up result = 1, what I expect is 3.
added the project files here: file
We'll need more details to help you, don't you have a simple sample of what you are trying to accomplish?
You can pass variables to a transformation from the job, so I don't think you'll need the getVariable() and setVariable() methods, you can just use the configuration properties of the transformation to execute:
I prefer using parameters (next tab) better than arguments/variables, but that's my preference.
The problem is that, in t2 transformation, you are getting the variable and setting a new value for the same variable at the same time, which does not work in the same transformation. When you close the Set variable step you get this warning:
To avoid it you need to use two variables, one you set before executing the loop, and another set each time you execute the loop or after executing the loop with the last value.
I have modified your job to make it work, in t1 transformation, I have added a new field (rownum_seq) created with the Add sequence step, to know how much to add to variable cnt in each execution of the loop. I could have used your id field, but in case you don't have a similar field in your real world job, that's the step you need to achieve something similar. I have modified the variable name to make more clear what I'm doing, in t1 I set the value of variable var_cnt_before.
In t2 transformation, I read var_cnt_before, and set the value of var_cnt_after as the sum of var_cnt_before + rownum_seq, this means I'm changing the value of var_cnt_after each time t2 is executed.
In t3 transformation, I read var_cnt_after, which has the value of the last execution of t2.
You could also calculate var_cnt_after in t1 and not modify it in t2, using the Group by step to get the max value of rownum_seq, so you don't need to modify that variable each time you execute t2, depending on what you need to achieve you might need to use it or change in t2 or you just need the final value so you calculate it in t1.
This is the link to the modified job and transformations.

Sybase - how can extract part of a text from a field with repetitive strings?

I have got fields like this:
UPDATE</transactionType><column><name>prio</name><newValue>5</newValue><oldValue>1</oldValue><newValue>aaa<oldValue>10863321</oldValue></column></row></table></businessObjectChanges>
UPDATE</transactionType><column><name>prio</name><newValue>51</newValue><oldValue>11</oldValue><newValue>bbb<oldValue>10863321</oldValue></column></row></table></businessObjectChanges>
and I am trying get extract text after first <newValue> from the left side. It will be either one or two numbers/letters. Also, at the same time I want to get first <oldValue> looking from left. SO the results are:
newValue oldValue
5 1
51 11
The usual mysql commands SUBSTRING_INDEX and REGEXP_SUBSTR do not work.
Please note that I need to do it without defining any variables.

SSIS Expression cannot be evaluated -- why not?

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.

select first two characters of values in a concatenated string

I am trying to create a formula field that checks a string that is a series of concatenated values separated by a comma. I want to check the first two characters of each comma separated value in the string. For example, the string pattern could be: abcd,efgh,ijkl,mnop,qrst,uvwx
In my formula I'd like to check if the first two characters are 'ab','ef'
If so, I would return true, else false.
Thanks.
To do this properly, you need to use a regular expression. Unfortunately the REGEX function is not available in formula fields. It is, however, available in formulas in Validation Rules and in Workflow Rules. You can, therefore, specify the below formula in either of a Validation or Workflow Rule:
OR(
AND(
NOT(
BEGINS( KXENDev__Languages__c, "ab" )
),
NOT(
BEGINS( KXENDev__Languages__c, "ef" )
)
),
REGEX( KXENDev__Languages__c , ".*,(?!ab|ef).*")
)
If it's a Validation Rule, you're done -- this formula will create an error if any of the entries do not start with "ab" or "ef". If it's a Workflow Rule, then you can add a Field Update to it to update some field with False when this formula is true (if this formula is true then there is at least one item that doesn't start with ab or ef, so that would make your field False).
Some may ask "What's with the BEGINS statements? Couldn't you have done this all with one REGEX?" Yes, I probably could, but that makes for an increasingly complex REGEX statement, and these are quite difficult to debug in Salesforce.com, so I prefer to keep my REGEXes in Salesforce.com as simple as possible.
I suggest you to search for ',ab' and ',ef' using CONTAINS method. But first of all you need to re implement method which composes this string so it puts ',' before first substring. At the end returned string should look like ',abcd,efgh,ijkl,mnop,qrst,uvwx'.
If you are not able to re implement method which compose this string use LEFT([our string goes here],2) method to check first two chars.

Resources