Friday, 11 October 2013

Bucket analysis by copying states

Alternate States were introduced in QlikView 11.  This allows different objects to be in different selection states.

You can have, for example, 2 list boxes, both with the same field, and both with a different set of selections.

One of the things that this enables a whole new way of "bucket" analysis - allow a user to compare the values from one set of selections against any other set of selections that they may want to make.  It is incredibly powerful.

Many examples that I have seen will have two or three list boxes in each state, side by side, and some chart or set of charts displaying the results.  The reason that you might have only two or three list boxes is really a practical one - there is only so much space on the screen.

My own solution to this is to put the sets of list boxes into containers.  You can then fit many more list boxes for your side-by-side comparison.  However, what if you want to have more than two sets?  If I want to have, say, 4 states that I want to compare then it becomes more difficult to display those and still leave space for the charts.

You can, of course, do some funky stuff with hiding and showing different sets based on a click of a button.  This can be a little confusing so I want to suggest a simpler approach.

Along with the Alternate States came a couple of new Actions - Swap State Contents and Copy State Contents.  So, my approach is to have only one set of selections, that are in either their own State or event the default state, and make my selections in these.  I can then have a button to Copy State Contents from the list boxes to the State that I want them in.


The screen shot shows the Action setup to copy the state contents from the "Default" state (blank) to a state that I have setup called "Selection1".

I would have this action attached to a button called "Save Selection 1" (or something that will make sense to my users) and then have some charts that will show this versus Selection2, Selection3, etc.

To extend a model that uses Show/Hide boxes means having to do quite a bit of work.  To extend this model means adding one new button.


Stephen Redmond is author of QlikView for Developer's Cookbook
He is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond

Thursday, 10 October 2013

Flags and Dual values in Set Analysis

To avoid having to create very complex Set Analysis, it can be quite a good idea to create flags in your script.  Doing the complex calculation in the script to create a simple 1 or 0 value means it happens once - when your users are not involved - and makes the front end calculations a lot quicker - when your users are involved.

Sometimes we want to dual-purpose that flag field.  As well as having the value of 1 or 0, we want to allow the users to select the field.  "1" and "0" are not very friendly so we want to have the users click on something like "Yes"/"No" or "True"/"False".  There are a few ways of achieving this:

1.  Just create the 1 or 0 in the script and in the front-end use an Expression in the list box like:

   If(Flag=1, 'True', 'False')

This works fine but, of course, is putting some calculation back into the front-end.  While it is not an arduous calculation, it will re-calculate on all selections so it does add some clock cycles.  It also makes no impact on how you would use the value in Set Analysis so I don't need to worry about this option any further in this post.

2.  Create the 1 or 0 in the Flag field and create a 2nd field (e.g. Flag_Text) with the text values that you want.  The user gets to select the value from Flag_Text, but we use the Flag value in Set Expressions.

There are a couple of issues with this.  First off, it adds additional overhead in the Script because we need to do the same calculation twice and create 2 fields.  Secondly, if we use the Flag value in a Set, we need to ensure that we also exclude the Flag_Text value from that set:

   Sum({<Flag={1}, Flag_Text=>} Sales)

There is also the possibility that a user using collaboration features might add the Flag field as a list box and that might cause confusion.

3.  Instead of creating the values as 1 or 0, we create Dual values:

   ...
   If(Condition=True, Dual('Yes',1), Dual('No',0)) As Flag,
   ...

This is more efficient because everything happens in the script and we are only creating the one field there from one piece of code.

There is a complication though in your Set Analysis.  You would like to do something like this:

   Sum({<Flag={1}>} Sales)

But it will now fail!  This is because the set comparison always compares against the text value of a dual (except for Dates - more of that below).  That means that you would have to use:

   Sum({<Flag={'Yes'}>} Sales)

Of course, this is a text comparison so will not execute as efficiently as a numeric one.  What can we do?

Well, we can force the calculation to be numeric by using a search syntax instead of the actual value and that search should involve > or <.  For example:

   Sum({<Flag={">0"}>} Sales)

Will work!

Interestingly, this does not work immediately with a date value that has been created with one of the date functions (like Date(), MakeDate, etc.)  I am not totally sure of why but I suspect that this is handled differently because the system recognizes it as a date (so it understands what ">2/6/2013" means) and doesn't handle the same way as other numeric Duals.

This means that we often need to add formatting into a date set to get it to work.  Like this:

   Sum({<Date={$(=Date(vDate,'M/D/YYYY'))}>} Sales)

We can override this and make our dates handle like other Duals by loading them as a Dual explicitly in the Script.  Instead of this:

   ...
   Date(date_field) As Date,
   ...

We can do this:

   ...
   Dual(Date(date_field), Num(date_field)) As Date,
   ...

Have fun!


Stephen Redmond is author of QlikView for Developer's Cookbook
He is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond

Monday, 16 September 2013

Dynamic ApplyMap

I use ApplyMap all the time in QlikView scripts.  It is one of the best ways of getting data from a lookup table - especially with the facility to specify a default value.

I use it so much that I often forget about one quite useful aspect of it - the name of the mapping table is provided as a text value.  Usually this means that I am passing a literal string, but it can also mean that I can pass a dynamically calculated string - use a different map for different values.

In the scenario below, we have a currency table with a value per month.  Often the approach might be to join this table to the fact table and then do a second load to calculate the base value (or even not bother and handle that in the front-end).

You could, of course, just concatenate a number of fields to create a key for mapping, but I prefer a different and, I think, more elegant method.

In this this example, I load the currency table into multiple mapping tables and then dynamically pick the right mapping table while loading the fact table:

Monthly_Exchange_Rates:
Load 
Currency, 
Num(Date#(Month, 'YYYY-MM')) As Month,
Rate
Inline [
Currency, Month, Rate
EUR, 2013-05, 1
EUR, 2013-07, 1
EUR, 2013-06, 1
EUR, 2013-09, 1
EUR, 2013-08, 1
GBP, 2013-09, 0.842711
GBP, 2013-05, 0.848677
GBP, 2013-06, 0.851957
GBP, 2013-08, 0.858893
GBP, 2013-07, 0.862144
USD, 2013-05, 1.297799
USD, 2013-07, 1.307939
USD, 2013-06, 1.317866
USD, 2013-09, 1.323692
USD, 2013-08, 1.331518
CNY, 2013-05, 7.972392
CNY, 2013-07, 8.027845
CNY, 2013-06, 8.088211
CNY, 2013-09, 8.100795
CNY, 2013-08, 8.151601
];

Temp_Curr:
Load Distinct Currency as Currency_List
Resident Monthly_Exchange_Rates;

For i=0 to FieldValueCount('Currency_List')-1
Let vCurr=Peek('Currency_List', $(i), 'Temp_Curr');

Exch_Rate_Map_$(vCurr):
Mapping
Load Month, Rate
Resident Monthly_Exchange_Rates
Where Currency = '$(vCurr)';

Next

Drop Tables Temp_Curr, Monthly_Exchange_Rates;


SalesTable:
Load
*,
Sales_Local/ExRate as Sales_Base;
Load
Date,
Country,
Currency,
Sales as Sales_Local,
ApplyMap(
'Exch_Rate_Map_' & Currency, 
Floor(MonthStart(Date)), 

1) as ExRate
Inline [
Date, Country, Currency, Sales
2013-05-02, Ireland, EUR, 123
2013-05-13, Ireland, EUR, 322
2013-06-11, France, EUR, 343
2013-07-02, USA, USD, 343
2013-08-12, UK, GBP, 233
2013-08-30, China, CNY, 223
2013-09-01, UK, GBP, 543
2013-09-24, USA, USD, 412
];

It's common enough to come across a scenario like this, so I hope you find it useful.


Stephen Redmond is author of QlikView for Developer's Cookbook
He is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond

Wednesday, 26 June 2013

Win a copy of QlikView for Developers Cookbook

Packt have kindly agreed to give away 2 copies of my book.  See the competition page for details:

http://www.qliktips.com/p/competition.html



Stephen Redmond is author of QlikView for Developer's Cookbook
He is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond

The one that got away - linking Section Access to multiple dimensions

During the writing of QlikView for Developer's Cookbook, I added a new recipe quite late on but, for one reason or another, it never made it into the final cut.

So, what we have done is to publish this recipe as an article on the Packt website:

   Linking Section Access to multiple dimensions

I hope that you find it useful.


Stephen Redmond is author of QlikView for Developer's Cookbook
He is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond

Monday, 24 June 2013

Recipes for success

The new book should be ready to purchase in the next couple of days via the Packt site:

http://www.packtpub.com/qlikview-developers-cookbook/book

and shortly thereafter via Amazon, Barnes & Noble and all the usual suspects.

I though that I would publish a list of the recipes that are in the CookBook so that all can see what you are getting.

1.  Charts

- Creating custom pop up labels in a bar chart
- Creating a box plot chart for a simple data set
- Using the wizard to create a box plot chart
- Creating a "Stephen Few" bullet chart
- Creating a modified bullet chart in a straight table
- Creating a bar chart in a straight table
- Creating a Redmond Aged Debt Profile chart
- Creating a waterfall chart
- Replacing the legend in a line chart with labels on each line
- Creating a secondary dimension in a bar chart
- Creating a line chart with variable width lines
- Brushing parallel coordinates
- Using redundant encoding with a scatter chart
- Staggering labels in a pie chart
- Creating dynamic ad hoc analysis in QlikView

2.  Layout

- Changing the default object layout options
- Changing the default selection color scheme
- Modifying the green, white, and gray selection color schemes
- Modifying the green, white, and gray selection color schemes on QlikView Server
- Using containers as an alternative to multi-boxes
- Using the design menus to custom format a cell

3.  Set Analysis

- Using dollar expansion in Set Analysis to enable from-date and to-date selection
- Using alternate states with Set Analysis
- Using Set operators to exclude values from results
- Using Set Analysis with a Date Island
- Using Sets to avoid key tables

4.  Advanced Aggregations

- Using TOTAL to calculate the percentage of total and the percentage of subtotal
- Using AGGR to calculate the percentage of the maximum value
- Using AGGR to resolve a "Sum of Rows" issue
- Creating a dynamic AGGR expression for a Group dimension using Dollar Expansion
- Using RangeMax to return only positive numbers
- Creating a dynamic Part-to-Whole pie chart
- Creating a colored treemap using colormix
- Using RangeSum to calculate a rolling total in a multi-dimension table
- Showing only the top 3 values in a pivot table
- Creating a Statistical Control Chart using Standard Deviation
- Creating a Moving Range chart
- Creating a Control Chart using Moving Range

5.  Advanced Coding

- Extracting QlikView data to a Word report
- Printing reports to PDF using PDFCreator
- Creating a chart using a macro
- Using VBS functions in charts

6.  Data Modeling

- Concatenation of fact tables to avoid loops and synthetic keys
- Creating a Key/Link table in QlikView

7.  Extensions

- Creating a simple HTML extension
- Creating a simple HTML table
- Creating an interactive extension
- Using external libraries with extensions

8.  Useful Functions

- Handling null in numeric fields or calculations
- Using Dual to handle period name sort
- Parsing text to numbers and dates
- Calculating Year To Date dynamically
- Labelling a pie chart to replace the legend
- Calculating the lowest or highest value in a range
- Consolidating a date-time value into quarter hourly segments
- Dynamically filtering by From/To dates

9.  Script

- Creating flags in the script
- Replacing IsNull
- Storing and dropping using a subroutine
- Keeping a trace on things
- Using AND Mode in listboxes
- Using Exists and Keep to limit the data load
- Setting the default display format
- Setting the default sort order
- Matching financial periods to dates
- Handling partial reload in the script
- Using Peek and Previous to calculate against loaded records
- Creating a simple Gantt for a dashboard using Interval Match
- Reading users from Active Directory
- Getting a sub-URL using the Table wizard
- Using parameters in Dollar Sign Expansion
- Removing fields with a wildcard
- Handling multiple subfolders in a script

10.  Improving Performance

- Reducing the number of distinct values
- Creating counter fields to avoid Count Distinct
- Creating flag fields to avoid Sum of If and other inefficient expressions
- Denormalizing for performance

11.  Security

- Section Access Gotcha's
- Blocking user access to a field using OMIT
- Making all values available to Admins

There was one additional Security recipe that didn't make it into the final cut - Linking Section Access to multiple dimensions.  This will be released as a free article on the Packt website.


Stephen Redmond is author of QlikView for Developer's Cookbook
He is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond

Wednesday, 12 June 2013

Squeaky bum time

Sir Alex Ferguson, the most successful football manager in history, often had an interesting turn of phrase.  One of his most famous was the description of that time at the end of season where everyone started to get nervous and excited at the same time - he called it "squeaky bum time".

Well, we are at that stage with my new book!  All of the final drafts are in, the cover design is agreed and the Packt website is now up:

http://www.packtpub.com/qlikview-developers-cookbook/book

It's even listed on Amazon:

http://www.amazon.com/QlikView-Developers-Cookbook-Stephen-Redmond/dp/1782179739

I am just waiting now for the pre-final draft layouts.  Once all are agreed, then the book will be sent to the printers for publication.  Once it is sent off, it should be available within 6-7 days.

Would love to see it available before the end of June!

I want to take an opportunity to thank the technical reviewers - Barry Harmsen, Mike Garcia, Ralf Becher, and Steve Dark.  All of these guys have a huge amount of QlikView experience and their comments and suggestions have really helped to round the edges of this book.  They are all awesome!



Stephen Redmond is CTO of CapricornVentis a QlikView Elite Partner. We are always looking for the right people to join our team.
Follow me on Twitter: @stephencredmond