Crystal Report group sort order - sorting

I'm making a report that will display a list of costumers and some numeric values.
I use a formula in order to sort my group, wich is the following :
if {Db.SortOrder} = 0 then
{Db.CostumerName}
else
ToText({Db.Value},'00000000',0,'')
In this way i can group by costumer name or value, the problem is that i need to use a different sorting order for them, ascending order when i group by CostumerName and descending when i group by Value. How can i achieve that ? I've tried the "Sort group by formula" using crAscendingOrder,crDescendingOrder but it said i needed tu use a costant and not a variable (in my case i used db.SortOrder)

My approach:
First, create a parameter field ({?Sorted Field}) to choose the sorted field: String; static list that includes 'Customer' and 'Value'; default value is 'Customer'
Next, create a custom function that will convert a string into its ASCII representation, allowing the order to be changed:
// ASCII()
Function (Stringvar characters, Optional Numbervar direction:=crAscendingOrder)
Local numbervar i;
Local stringvar c;
For i:= 1 To Len(characters) Do (
If direction=crAscendingOrder Then
c:=c + ToText( Ascw(Mid(characters,i,1)), "#")
Else
c:=c + ToText( 256- Ascw(Mid(characters,i,1)), "#")
);
c;
Next, create a formula field that will be used for sorting:
// {#Sorted Field}
Select {?Sorted Field}
Case "Customer": {Db.Customer}
Case "Value": ASCII(ToText({Db.Value},'00000000',0,''), crDescendingOrder)
Default: {Db.Customer}
Finally, reference this field in the record-sort expert:

in my case i only needed to choose the field to sort by. i created the parameter field called SortField as static text and created the three friendly values i wanted to show, then created the formula that referenced it. i have crystal 2011 so my formula looks like this:
// {#Sorted Field}
Select {?SortField}
Case "BIN":{V_ITEM_MASTER.BIN}
Case "ORDER REF":{V_ITEM_MASTER.HEAT}
Case "PART":{V_ITEM_MASTER.PART}
Default: {V_ITEM_MASTER.BIN}

Related

How to Select multiple related columns in add calculated fields in Quicksight parameter using ifelse?

I have a parameter 'type' in a table and it can have multiple values as follows -
human
chimpanzee
orangutan
I have 3 columns related to each type in the table -
human_avg_height, human_avg_weight, human_avg_lifespan
chimpanzee_avg_height, chimpanzee_avg_weight, chimpanzee_avg_lifespan
orangutan_avg_height, orangutan_avg_weight, orangutan_avg_lifespan
So if i select the type as human, the quicksight dashboard should only display the three columns -
human_avg_height, human_avg_weight, human_avg_lifespan
and should not display the following columns -
chimpanzee_avg_height, chimpanzee_avg_weight, chimpanzee_avg_lifespan
orangutan_avg_height, orangutan_avg_weight, orangutan_avg_lifespan
I created the parameter type and in the add calculated fields I am trying to use ifelse to select the columns based on the parameter selected as follows -
ifelse(${type}='human',{human_avg_height}, {human_avg_weight}, {human_avg_lifespan},{function})
I also tried -
ifelse(${type}='human',{{human_avg_height}, {human_avg_weight}, {human_avg_lifespan},{function}})
And -
ifelse(${type}='human',{human_avg_height, human_avg_weight, human_avg_lifespan},{function}})
But none of it is working. What am i doing wrong ?
One way to do this would be to use three different calculated fields, one for all the heights, one for weights and one for lifespan. The heights one would look like this:
ifelse(
${type}='human',{human_avg_height}, ifelse(
${type}='chimpanzee', { chimpanzee_avg_height}, ifelse(
${type}='orangutan',{ orangutan_avg_height},
NULL
)))
Make another calculated field for weights and lifespan and then add these calculated fields to your table, and filter by type.
To make it clear to the viewer what data is present, edit the Title of the visual to include the type:
${type} Data
You have to create one calculated field for each measure using the ifelse with the type to choose the correct vale, but is not necessary to create inner ifelse as skabo did, the if else syntax is ifelse(if, then [, if, then ...], else) so you can define the calculated fields as follows:
avg_height = ifelse(${type}='human', {human_avg_height}, ${type}='chimpanzee', {chimpanzee_avg_height},${type}='orangutan', {orangutan_avg_height}, NULL)
avg_weight = ifelse(${type}='human', {human_avg_weight}, ${type}='chimpanzee', {chimpanzee_avg_weight},${type}='orangutan', {orangutan_avg_weight}, NULL)
avg_lifespan = ifelse(${type}='human', {human_avg_lifespan}, ${type}='chimpanzee', {chimpanzee_avg_lifespan},${type}='orangutan', {orangutan_avg_lifespan}, NULL)
Then use those calculated fields in your visuals.

using WHEN and CASE in Data Studio formulas

I'm used to writing in JavaScript so I am approaching this thinking about SWITCH statements and of course the classic if else...
I just want to check if the data in a row is TRUE, and if it is count it. If the value is not true, don't add it to the count.
I'm thinking something like this would work:
CASE
WHEN is_it_true_or_false = false
THEN COUNT_DISTINCT ( id ) //using id to address that specific row and add it to the count
END
It can be achieved by using either of the following CASE statements and aggregating the Calculated Field as required - COUNT_DISTINCT (Unique IDs of TRUE values) or COUNT (All TRUE values):
1) Where is_it_true_or_false is a Boolean OR String Field:
CASE
WHEN REGEXP_MATCH(is_it_true_or_false, "((?i)TRUE)") THEN id
ELSE NULL
END
2) Where is_it_true_or_false is a Boolean Field:
CASE
WHEN is_it_true_or_false = TRUE THEN id
ELSE NULL
END
Google Data Studio Report and GIF to elaborate:

Is there an ISNUMBER() or ISTEXT() equivalent for Power Query?

I have a column with mixed types of Number and Text and am trying to separate them into different columns using an if ... then ... else conditional. Is there an ISNUMBER() or ISTEXT equivalent for power query?
Here is how to check type in Excel Powerquery
IsNumber
=Value.Is(Value.FromText([ColumnOfMixedValues]), type number)
IsText
=Value.Is(Value.FromText([ColumnOfMixedValues]), type text)
hope it helps!
That depends a bit on the nature of the data and how it is originally encoded. Power Query is more strongly typed than Excel.
For example:
Source = Table.FromRecords({[A=1],[A="1"],[A="a"]})
Creates a table with three rows. The first row's data type is number. The second and third rows are both text. But the second row's text could be interpreted as a number.
The following is a query that creates two new columns showing if each row is a text or number type. The first column checks the data type. The second column attempts to guess the data type based on the value. The guessing code assumes everything that isn't a number is text.
Example Code
Edit: Borrowing from #AlejandroLopez-Lago-MSFT's comment for the interpreted type.
let
Source = Table.FromRecords({[A=1],[A="1"],[A="a"]}),
#"Added Custom" = Table.AddColumn(Source, "Type", each
let
TypeLookup = (inputType as type) as text =>
Table.FromRecords(
{
[Type=type text, Value="Text"],
[Type=type number, Value="Number"]
}
){[Type=inputType]}[Value]
in
TypeLookup(Value.Type([A]))
),
#"Added Custom 2" = Table.AddColumn(#"Added Custom", "Interpreted Type", each
let
result = try Number.From([A]) otherwise "Text",
resultType = if result = "Text" then "Text" else "Number"
in
resultType
)
in
#"Added Custom 2"
Sample output
Put it in logical test format
Value.Type([Column1]) = type number
Value.Type([Column1]) = type text
The function Value.Type returns a type, so by putting it in equation thus return a true / false.
Also, equivalently,
Value.Type([Column1]) = Date.Type
Value.Type([Column1]) = Text.Type
HTH
ISTEXT() doesn't exist in any language I've worked with - typically any numeric or date value can be converted to text so what would be a false result?
For ISNUMBER, I would solve this without any code by changing the Data Type to a number type e.g. Whole Number. Any rows that don't convert will show Error - you can then apply Replace Errors or Remove Errors to handle them.
Use Duplicate Column first if you don't want to disturb the original column.
I agree with Mike Honey.
I have a SKU code that is a mix of Char and Num.
Normally the last 8 Char are Numbers but in some weird circumstances the SKU is repeated with an additional letter but given the same EAN which causes chaos.
by creating a new temp column using Text.End(SKU, 1) I get only the last character. I then convert that column to Whole Number. Any Error rows are then removed to leave only the rows I need. I then delete the temp Column and am left with the Rows I need in the format I started with.

Spotfire Expression Value for Max(Row Count)

I'm trying to make a Calculated Value Control expression on the below columns:
Row Count | Date | Value
What I want to get is the Value for the 'newest' date, which will also be the highest row count. How can I write an expression to get this, it seems like it ought to be simple. I'm having trouble writing it in only expression language, without SQL.
Using the expression below you can limit the records in your table to those with the highest (aka most recent) date which should have your Value of interest.
[Date] = Max([Date])
You can do the same with row count since you mentioned the record of interest being the highest row count:
[Row Count] = Max([Row Count])
If you're looking to create a calculated column you can use a case statement to spit out the value:
case when [Date] = Max([Date]) then [Value] end
Lastly, should you want to display this value in a Text Area to show off your value you can utilize the calculated column above:
1) Create a new Text Area
2) Type some text about what it is: "Value for newest Date: " (optional)
3) Click "Insert Dynamic Item" -> "Calculated Value"
4) Under "Data" ensure the appropriate data table is selected. Note: You can uncheck the "Use Current Filtering..." box here if you do not want your value to update as you filter.
5) Under Values, utilize our calculated column with "Max" wrapped around it to avoid Summing duplicate values:
Max(CALCULATED_COLUMN)
Here is a screenshot of my work with random filler dates and values: http://i.imgur.com/hFapS8c.png
The larger text is to show the calculated value dynamic items. I used Max([Date]) for the date value.

How do I split birt dataset column into multiple rows

My datasource has a column that contains a comma-separated list of numbers.
I want to create a dataset that takes those numbers and turns them into groupings to use in a bar chart.
requirements
numbers will be between 0-17 inclusive
groupings: 0-2,3-5,6-10,11-17
x-axis labels have to be the groupings
y-axis is the percent of rows that contain that grouping
note that because each row can contribute to multiple columns the percentages can add up to > 100%
any help you can offer would be awesome... i'm very new to BIRT and have been stuck on this for a couple days now
Not sure that I understand the requirements exactly, but your basic question "split dataset column into multiple rows" can be solved either using a scripted dataset or with pure SQL (depending on your DB).
Either way, you will need a second dataset (e.g. your data model is master-detail, and in your layout you will need something like
Table/List "Master bound to master DS
Table/List "Detail" bound to detail DS
The detail DS need the comma-separated result column from the master DS as an input parameter of type "String".
Doing this with a scripted dataset is quite easy IFF you understand Javascript AND you understand how scripted datasets work: Create a report variable "myValues" of type object with a default value of null and a second report variable "myValuesIndex" of type integer with a default value of 0.
(Note: this is all untested!)
Create the dataset "detail" as a scripted DS, with one input parameter "csv" of type String and one output parameter "value" of type String.
In the open event of the scripted DS, code:
vars["myValues"] = this.getInputParameterValue("csv").split(",");
vars["myValuesIndex"] = 0;
In the fetch event, code:
var i = vars["myValuesIndex"];
var len = vars["myValues"].length;
if (i < len) {
row["value"] = vars["myValues"][i];
vars["myValuesIndex"] = i+1;
return true;
} else {
return false;
}
For example, for the master DS result row with csv = "1,2,3-4,foo", the detail DS will result in 4 rows with
value = "1"
value = "2"
value = "3-4"
value = "foo"
Using an Oracle DB, this can be done without Javascript. The detail DS (with the same input parameter as above) would then look like:
select t.value as value from table(split(?)) t
For the definition of the split function, see RedFilter's answer on
Is there a function to split a string in PL/SQL?
If you get ORA-22813, you should change the original definition
create or replace type split_tbl as table of varchar2(32767);
to
create or replace type split_tbl as table of varchar2(4000);
as mentioned on https://community.oracle.com/thread/2288603?tstart=0
It's also possible with pure SQL in 11g using regexp_substr (see the same page).
create parameters in the scripted data set. we have to pass or link actual dataset values to scripted dataset parameters through DataSet parameter Binding after assigning the scripted data set to Table.

Resources