CONTAINS statement in COGNOS - if-statement

what I am trying to accomplish is as follows:
I am trying to have an expression that returns a value "A" if 'apple' is anywhere in the string, and return value "B" if 'bell' is anywhere in the string.
if 'apple' or 'bell' is not in the string, then 'null'
eg, the column will have 'apple', 'bell', 'any other word' at different positions in the string and I need a formula that returns "A" if 'apple' in present and "B" if 'bell' is present
column value example:
'applebee'
'appletart'
'bellview'
'bellmont'
'apple fritter'
'freedom bell'
'bird'
'coffin'
'...'
desired outcome:
"A"
"A"
"B"
"B"
"A"
"B"
"null"
"null"
"null"
i have tried:
[description] contains 'INV' then 1
[description] contains 'VOL' then 2
else 'null'
maybe an if statement could work better?

What happens when you try:
if(lower([description]) contains 'apple') then ('A') else
if (lower([description]) contains 'bell') then ('B') else
(Null)

Related

Reconstructing chain of linked observations

I have a dataset in which firms can be owned by people (type 0) or by other firms (type 1).
Here is an example:
* Example generated by -dataex-. To install: ssc install dataex
clear
input str1(firmid ownerid) str7 last_name byte type
"A" "B" "" 1
"A" "C" "" 1
"A" "D" "" 1
"B" "E" "" 1
"B" "F" "" 1
"E" "I" "Smith" 0
"E" "J" "Johnson" 0
"F" "G" "" 1
"G" "I" "Smith" 0
"G" "J" "Johnson" 0
"G" "H" "" 1
end
Firms can be owned by other firms which in turn are owned by other firms and so on. For example, A is owned by B, B is owned by E and F, etc. I would like to reconstruct these ownership chains until I get to the ultimate owner(s) (a person, like I or J, or a firm with no owners in the data, like C, D, or H).
The final output would look like this:
* Example generated by -dataex-. To install: ssc install dataex
clear
input str1(firmid ownerid1 ownerid2 ownerid3) str5 last_name1 str7 last_name2 byte(type1 type2 type3) str1(ultimate_owner1 ultimate_owner2 ultimate_owner3 ultimate_owner4 ultimate_owner5)
"A" "B" "C" "D" "" "" 1 1 1 "I" "J" "H" "C" "D"
"B" "E" "F" "" "" "" 1 1 . "I" "J" "H" "" ""
"E" "I" "J" "" "Smith" "Johnson" 0 0 . "I" "J" "" "" ""
"F" "G" "" "" "" "" 1 . . "I" "J" "H" "" ""
"G" "I" "J" "H" "Smith" "Johnson" 0 0 1 "I" "J" "H" "" ""
end
I thought vlookup would be a good place to start. With the following code I retrieve all intermediate and final owners (so I'm close to the goal), but the code is cumbersome and I can't see how to generalize it to an arbitrarily long ownership chain.
ssc inst missings
by firmid, sort: g rep=_n
reshape wide ownerid last_name share type, i(firmid) j(rep)
qui forv j=1/3{
g rep_ownerid`j'=ownerid`j'
forv i=1/3{
vlookup rep_ownerid`j', gen(ownerid`j'`i') key(firmid) value(ownerid`i')
forv k=1/3{
vlookup ownerid`j'`i', gen(ownerid`j'`i'`k') key (firmid) value(ownerid`k')
forv m=1/3{
replace ownerid`m'="99" if ownerid`m'==""
vlookup ownerid`j'`i'`k', gen(ownerid`j'`i'`k'`m') key (firmid) value(ownerid`m')
}
}
}
}
qui foreach x of varlist ownerid* {
replace `x'="" if `x'=="99"
}
qui missings dropvars, force
drop rep*
I was wondering if there is a better / more general way to achieve my goal?
The original data is rather big (3M observations).

how to write out a list variable with the original format

In TCL, there is an array var defined.
set array_var(a1) "this is a string, not list"
set array_var(a2) [list a b c d e]
set array_var(a3) [list { "aa" "bb" } { "bb" "cc" }]
I want to write out array_var definition which can be source back later.
foreach key [array names array_var] {
set nameString [format %s(%s) array_var $key]
puts $SI_fh "set $nameString \"$array_var($key)\""
}
How to generate output file just as original definition with and without "[list "?
set array_var(a1) "this is a string, not list"
set array_var(a2) [list a b c d e]
set array_var(a3) [list { "aa" "bb" } { "bb" "cc" }]
parray array_var
prints
array_var(a1) = this is a string, not list
array_var(a2) = a b c d e
array_var(a3) = { "aa" "bb" } { "bb" "cc" }
At this point, you can't go back and see how these values were created: the array elements contain just the values, not the history.
There are many ways to create these values:
list "this" "is" "a" "string," "not" "list"
string cat this " " is " " a " " string ", " not " " list
dict create this is a string, not list
And a string with an even number of space separated words is indistinguishable from a list with an even number of elements, or a dictionary value.
for storing the state of this array, I'd do
foreach {key value} [array get array_var] {
puts [list set "array_var($key)" $value]
}
set array_var(a3) {{ "aa" "bb" } { "bb" "cc" }}
set array_var(a1) {this is a string, not list}
set array_var(a2) {a b c d e}
If you want to store an array for later, and are not particularly bothered about the stored format being very readable, the simplest method is this (yes, sourceing the file is how to load it back in):
puts $SI_fh [list array set array_var [array get array_var]]
The array get command serializes an array (without any traces, but that's usually not a problem at all) and array set takes the serialized form (which is a dictionary) and reinflates it back into an array. The list is because that creates exactly the quoting we want to make a substitution-free command (it's how the format of lists is defined to work).
The only disadvantage is that the format actually in the file is not optimised for humans, being something like this (the actual order is arbitrary; Tcl's arrays have never made order guarantees):
array set array_var {a2 {a b c d e} a1 {this is a string, not list} a3 {{ "aa" "bb" } { "bb" "cc" }}}

Crystal Reports 'if-statement' assistance

I'm currently using Crystal Reports 2013 to run reports. I'm having an issue with a formula that needs to look at an SAP order status and only print out a specific few. The SAP Order Status field is made up of 2 sections.
Section 1: 'A' 'B' 'C' 'D' (Only a single selection is pulled from
this list)
Section 2: 'E' 'F' 'G' 'H' (This can have multiple selections within
the Status)
Example Order #1111 Status: "A: F: G"
I currently have a formula that pulls the status of an order from the 1st Section.
if (isnull({user_status}) or
{user_status}=" " or
not ({user_status} like ["*A*", "*B*", "*C*", "*D*"])) then "N/A" else
if {user_status} like "*A*" then "A" else
if {user_status} like "*B*" then "B" else
if {user_status} like "*C*" then "C" else
if {user_status} like "*D*" then "D"
The above snippet would only bring in "A" for Order #1111 and omit "F" & "G".
I need assistance with a formula that would omit "A" and list out both "F" & "G".
I've tried the following:
if (isnull({user_status}) or
{user_status}=" " or
not ({user_status} like ["*E*", "*F*", "*G*", "*H*"])) then "N/A" else
if {user_status} like "*E*" then "E" else
if {user_status} like "*F*" then "F" else
if {user_status} like "*G*" then "G" else
if {user_status} like "*H*" then "H"
But that formula just returns the full "A; F; G" status.
Figured out the answer. (6/9/2020) I used the following code to create an array and loop through it pulling out only what I needed.
NumberVar Counter;
StringVar finalStatus:= "";
StringVar array statusList;
statusList:= split({user_status},";");
//Loop through array and only print out Status w/o No values
FOR Counter := 1 to UBound(statusList) DO
(if statusList[Counter] like ["E", "F", "G", "H"] then
finalStatus:= finalStatus+statusList[Counter]+";" else "");
finalStatus
Thanks for the input.

Filter/grep functions behaving oddly

Take the following code to select only alphanumeric strings from a list of strings:
isValid = function(string){
return(grep("^[A-z0-9]+$", string))
}
strings = c("aaa", "test#test.com", "", "valid")
print(Filter(isValid, strings))
The output is [1] "aaa" "test#test.com".
Why is "valid" not outputted, and why is "test#test.com" outputted?
The Filter function accepts a logical vector, you supplied a numeric. Use grepl:
isValid = function(string){
return(grepl("^[A-z0-9]+$", string))
}
strings = c("aaa", "test#test.com", "", "valid")
print(Filter(isValid, strings))
[1] "aaa" "valid"
Why didn't grep work? It is due to R's coercion of numeric values to logical and the weirdness of Filter.
Here's what happened, grep("^[A-z0-9]+$", string) correctly returns 1 4. That is the index of matches on the first and fourth elements.
But that is not how Filter works. It runs the condition on each element with as.logical(unlist(lapply(x, f))).
So it ran isValid(strings[1]) then isValid(strings[2]) and so on. It created this:
[[1]]
[1] 1
[[2]]
integer(0)
[[3]]
integer(0)
[[4]]
[1] 1
It then called unlist on that list to get 1 1 and turned that into a logical vector TRUE TRUE. So in the end you got:
strings[which(c(TRUE, TRUE))]
which turned into
strings[c(1,2)]
[1] "aaa" "test#test.com"
Moral of the story, don't use Filter :)
You could go the opposite direction with this and exclude any strings with punctuation, i.e.
isValid <- function(string){
v1 <- string[!string %in% grep('[[:punct:]]', string, value = TRUE)]
return(v1[v1 != ''])
}
isValid(strings)
#[1] "aaa" "valid"

VBScript if condition specific

I'd like create specific condition "IF", but I don't know how.
I need create one scprit do something when user digit specifics numbers. For example:
If String = "" or String = 0 and > 5 Then.....
Script only do something if user digit: 1,2,3,4
Anybody know how to create it?
Here are a couple of ways.
Convert the string to a number and test the bounds:
If IsNumeric(someString) Then
i = CLng(someString)
If i >= 1 And i <= 4 Then
' Match
End If
End If
Use Select Case and you can specify multiple values to match:
Select Case someString
Case "1", "2", "3", "4"
' Match
End Select
Or, if you just want to do multiple individual tests, here's the basic If structure:
If someString = "1" Or someString = "2" Or someString = "3" Or someString = "4" Then
End If