Category Archives: Visualization

Yoke Dashboard

I was chatting with a colleague recently about trends in BI and I brought up what I call the “commoditization of metrics” .  Google Analytics is an early example of this — your data crunched and delivered at the KPI level.

I recently ran across a great example of the commodity metrics idea:  Yoke.io.

Yoke let’s you build your own dashboard using metrics gleaned from cloud services such as Gmail, Twitter and Github. Here’s a portion of my Yoke dashboard. It’s all built with a few clicks and no coding.

Yoke Image

Give Yoke.io a try, it’s free!

-Rob

Join me at the upcoming “Masters Summit for Qlik” in Milan on 5-7 April. In addition to learning about all things Qlik, we’ll be talking about trends in Dashboarding and BI. 

Share

Scoping Selections with Aggr()

Summary: Selections can be made in Calculated Dimensions, although the result may not always be what is expected or desired.   The Aggr() function can be used to control what field(s) get selected.

The technique discussed in this post applies to both QlikView and Qlik Sense.  The screenshots shown are from QlikView.  Some of the visuals are a bit different in Qlik Sense, but the idea and expressions demonstrated are the same.

A downloadable example to accompany this post is available here.

Consider a listbox created with an <Expression> value of:

=Customer & ' -- ' & Country

A listbox constructed this way is useful for providing additional context or an  additional search.

Selections made in that listbox will make underlying selections in both Customer and Country.

The user is probably  expecting a selection in Customer only.  To limit the selection to Customer, add an Aggr() function to the expression:

=aggr(
 Customer & ' -- ' & Country
 ,Customer)

Only the Customer field is listed in the Aggr() dimension, so selections will be made only in Customer.

A side effect of adding Aggr() is that gray (unassociated) rows no longer display.  We can fix that with a bit of Set Analysis.

=aggr(
 only({1<Customer={"*"}>} Customer & ' -- ' & Country)
 ,Customer)

Now the listbox looks and behaves as expected.

 

Another place you may need Aggr() to control selection intent is chart Calculated Dimensions.

Hovering over a Salesrep value in the chart below gives a contextual popup that identifies Manager and Hire Date associated with the Rep.

The column was created as a Calculated Dimension:

=SalesPerson
& chr(10) & 'Reports to ' & [Sales Manager]
& chr(10) & 'Hire Date ' & date(HireDate,'YYYY-MMM-DD')

Clicking Michelle in the chart correctly selects her name as SalesPerson, but makes unexpected selections in HireDate and SalesManager.

I’m going to say that the dimension is “improperly scoped” and correct it by adding Aggr() to the Calculated Dimension.

=Aggr(
 SalesPerson
 & chr(10) & 'Reports to ' & [Sales Manager]
 & chr(10) & 'Hire Date ' & date(HireDate,'YYYY-MMM-DD')
 ,SalesPerson)

Selections will now be correctly limited to the “SalesPerson” field.

 

We’ve seen that Aggr() can narrow selections. We can widen selections as well.  This listbox will make selections in Customer, Country, SalesPerson and Year, even though only Customer is displayed in the listbox.

=aggr(
 only({1}
 Customer
 )
 ,Customer, Country, SalesPerson, Year)

 

We don’t have to include the display field in the selections.  In what I’ll call a  “backdoor associative search” , this expression will display Customer, but selects only the OrderID values associated with the Customer.

=aggr(
only({1}Customer )
,OrderID)

It’s usually a best practice to pre-create Calculated Dimensions in the script, when possible, for performance reasons. Returning to our first example, we might create a new field in the script as:

Customer & ' -- ' & Country AS CustomerAndCountry

We can use the new field as a display value, but we want selections to be made in Customer.

=aggr(
 only({1}  CustomerAndCountry)
 ,Customer)

 

As a last example,  we can create  “bookmark” like alternatives; either new fields linked in the data model or advanced search at run time.

Here I’ve linked a hidden field named “Bookmark” into specific OrderIDs in the script.  I want selections to be reflected in the OrderID field.

=aggr(only({1}Bookmark), Bookmark,OrderID)

Here is an advanced search that presents a listbox of Customers who have placed at least one order with a value >50K.

=aggr(
only({1<OrderID={"=sum({1}OrderAmount)>50000"}>}Customer )
,Customer)

Aggr() can be a “heavy resource consumer” and has the potential to slow down your application. Use only when required and avoid using or benchmark the impact in large applications.  Calculated Dimensions can also be a source of slow performance, precalculate fields in the script when possible.

Download the  example qvw for this post .

-Rob

 

 

Share

A Better Show Frequency

I like using “Show Frequency” in a Listbox, but the feature suffers two drawbacks.

  1. If the Field is in a Dimension table, the frequency — usually 1 — is not particularly useful to the user.
  2. Excluded (gray) rows show a blank frequency value.

As an alternative to “Show Frequency”, we can use the Expression pane of the Listbox to provide a more meaningful number, such as count of orders.

num(
 count(DISTINCT OrderID)
,'#,##0')

Listbox Expressions don’t provide for a heading.   We can fake one by adding it the Listbox Title with enough spaces to align the heading.

The excluded values show zero. We can fix that by adding a Set to the expression. The Set should honor selections in other fields such as Product or Year, so we only need to ignore the selection in this field.

num(
 count({<Customer=>} DISTINCT OrderID)
,'#,##0')

Optionally, we can use the same expression as a Sort Expression if we want to sort by Order count.

There you have it.   A more useful Frequency for the QlikView Listbox.

The Qlik Sense Filter Pane does not provide an Expression property, but you can achieve a similar result in Qlik Sense by creating the Field as an expression,

aggr( 
    only({<Customer=>}Customer) 
    & repeat(chr(160),8)
    &num(
    count({<Customer=>}DISTINCT OrderID)
    ,'#,##0')
,Customer)

 

 

The “repeat(chr(160),8)” is a trick to insert 8 “non-breaking” spaces. A string of multiple regular ‘  ‘ spaces will display as only a single space when displayed in the browser.

You may want to place the numbers on the left side to make the numbers clearer.

And yes, you could dynamically calculate the number of spaces required to get multiple digits right-aligned.

Using  aggr() to create a Filter Box is a much “heavier calculation” than just using the Field. If you have a large application, test this technique for performance before deciding to use it there.

-Rob

Share

Pivot Table Grids

Using dimensions on the X and Y axis and plotting measures at the intersection is a useful visualization. The out of the box solution in QlikView is the Grid chart.

The grid chart does have limited options for representing data.

The Pivot Table can be a more robust alternative.  A Pivot Table grid (Crosstable) is created by dragging one of the dimensions to the horizontal position.

 

Now we can represent the measures as a heatmap by coloring the background of the cells.  This is frequently a more effective visualization than circles,  .

We can also display numbers in the cells.

 

We can display multiple expressions per dimension.

 

Here I show both the number and a linear gauge allowing for clear comparisons between Regions. The user can swap the dimensions if desired.

 

You can mix colors and numbers to show interesting patterns. Here’s a map of average Sunrise/Sunset/Daylight for my home town.

Maybe it’s not a design winner, but I find it interesting.

 

We can blank some cells in the grid to make meaningful shapes, in this case a rough outline of the United States.

All of the examples shown can be downloaded here.

A few styling tips:

  • Style format “Clean” is a good starting point for managing border lines and spacing.
  • “Custom Format Cell” Border before/after (double line) can be used to create white space between rows as shown in the Minimum Wage example above.  Also, setting Text Size to other than the default 100% can be useful.

Do you have any examples of Pivot Grids to share?

-Rob

 

Share

Bar Chart Viz Tidbits in Version 12

It’s been quite a while since my last post. Summer vacations, Masters Summits in New York and Copenhagen, a Luminary meetup in Lund. Lots of new input for blogging.

I’ve been testing the QV Version 12 Beta and am pleased to see  a few simple but useful enhancements in bar charts.

  •  Multi-line horizontal legends on x-axis. Works in both vertical and horizontal orientation.
  • “Plot Values Inside Segments” now honors scaling/symbols property from the Number pane,
  •  New Presentation option: “Still Show Total on Top” when plotting Values in Segments.

These enhancements allow you to easily create charts like this example, even with values in  thousands or millions.

 

 

You will need to create your own line breaks in the dimension. There is no auto wrap yet.  Create a calculated dimension that replaces blanks with the newline char:

=replace(ProductName,' ', chr(10))

Another QV12 plus — those annoying false syntax errors in the expression editor have been cleaned up and the expression editor is my friend again.

I’m looking forward to discovering more new features in QV12 as my testing continues.

-Rob

Share

Using SR11 “SilentErrorInChart” Switch

Last month I wrote about error handling changes in Qlikview SR11. Today I want to relate my experience in using the new “SilentErrorInChart” switch during development.

Let’s start with an excerpt from the SR11 Release Notes:

As a result of fixing bug 69228 “Syntax checker not working”, syntax error messages in object expressions are now returned to objects instead of returned as NULL. This may result in an object which rendered in SR10 or earlier, displaying an error message in SR11 (”Error in expression”).

This feature changes what you see — if a chart column has an error. Prior to QV11,  the chart would render, but values in the error column would display a null (“-“):

With SR11, the default behavior is to not render the chart and instead display a chart level error message:

This is useful. It clearly raises the flag that one of this chart’s expressions is returning an error. But which expression? You will need to go through the expressions one by one, and if there is more than one column in error, you will repeat the exercise.

Can I return to the pre-SR11 behavior? Where the chart renders what columns it can, so I can identify what columns are returning errors? Yes! There is a setting for that.

The setting is not (yet) configurable through the User Preferences Dialog. So we need to use the backdoor “easter egg” to modify the setting. To reach the easter egg settings dialog, select “Help. About QlikView”  and then Right-Click on the QV bullseye logo in the lower left of the dialog box.

 

In the Settings list, scroll down and select (left click) “SilentErrorInChart” to display or modify the current setting.

A Value of “0” for this setting means to use the new SR11 behavior. That is, any column in error will cause the entire chart to not render.

A Value of “1” will return to the pre-SR11 behavior. QV will render what columns it can, and display “-” for those columns with errors.

To modify the setting, overtype the Value, press the Set button followed by the Close button. There is no need to exit QV to recognize a change for this setting. However, the chart must be “re-rendered” to utilize the setting. Easiest method I have found is to edit and save (“OK”) the chart Properties.

I’m finding that during most development, I set “SilentErrorInChart” to “1”. I want to identify columns in error as I create them.

In my final pre-production check, I’m finding that changing “SilentErrorInChart” to “0” is a useful quality control check to dramatically surface any chart expression problems.

-Rob

Share

SR11 Error Handling Changes

SR11 introduces two changes to error handling that you should be aware of.

The first change is that syntax errors marked with the “red squiggle” in the expression editor will always generate a status message of “Errors in expression”. This was not the case prior to SR11.

In SR10 and prior there could be a difference of opinion between the red squiggles and the status message. Valid syntax such as this–

SR10

in SR10 could be marked with squiggles but the “Expression OK” message would reassure us that this was just a syntax checker bug.

In SR11 the status message will always be “Errors in expression” when a red squiggle appears — even when the syntax is valid.

SR11

This applies as well to the very common squiggles that appear when using set expressions with variables. Again, this is a functional expression:

SR11

So now the squiggles and the status message are in alignment. I’m not sure this is a good thing. We  can no longer say “Ignore the squiggles. If it says ‘Expression OK’ then it’s fine”. If this change sticks then we will have to get more aggressive about reporting and fixing syntax checker bugs.

The second Error Handling change you should be aware of is documented in the SR11 release notes. Charts that contain invalid expressions will now fail to render. In SR10 they assumed some sort of default and the chart was rendered. This new behavior applies to chart expressions,  dimension attributes and expression attributes such as Text Color. If any of those expressions are in error, you will get various error messages in the chart frame. I don’t understand  the pattern of the messages yet.

The good news is that this behavior is not implemented in Server until you explicitly turn it on with a Server Settings.ini switch. By default, Server charts will continue to render as they did in SR10. When you turn the setting on, the Server will log the “bad charts” to the event log. Unfortunately, the logging does not happen until you activate the new behavior. This means your logs and your users see  the problem at the same time. Pity we can’t log before we turn the option on.

So what’s the combination of these two changes? If the syntax checker declares a perfectly good expression to be bad will the chart render? Yes, it will render. The syntax checker’s opinion and the actual evaluation of the expression are not connected.

I’m still trying to understand how these changes will affect my customers and I am holding off recommending SR11 until I can experience a few upgrades. If you have some experience good or bad with these changes please leave a comment.

-Rob

Share

Cell Popups in Straight Table

Last week my Masters Summit colleague Kevin McCann showed me a cool technique for generating popups (hover text) in individual cells of a Straight or Pivot Table. This can be useful for providing contextual info like order line detail:

 Or contact info when hovering over a name:

The Dimensions are created as multi-line Calculated Dimensions. Sorting and selections work as expected. If not done correctly, selections will be made in the referenced fields of the popup as well. The trick to avoiding the secondary selections is the use of aggr(). Customer is defined as:

[qlikview type=”exp”]=Customer & chr(10)
& aggr( EmailAddress & chr(10)
& Phone
,Customer )[/qlikview]

A complete example with instructions can be downloaded here: Qlikview Cookbook: Cell Popups In Straight Table

-Rob

Share

Info on INFO or What is the “i” for?

You may have noticed that “i” icon appearing in a QlikView listbox and wondered “why is it there?” and “what’s it good for?”. Or you may have seen script “INFO LOAD…”and wondered what it did.

The “i” icon and INFO LOAD are both associated with the QV Info feature which has some interesting and useful applications.

Some INFO is created for you right out of the box with no effort required. Create a listbox for Field $Table.  (If $Table is not available in your list of fields,  Right-Click, Select Fields and check Show System Fields).

Select one $Table name The “i” appears in the caption when one value is selected.

Clicking the i will display information about the table source. If the table was created from a database, the SQL statement is shown.

If the table was created from an excel or other local text file, the external file will be opened!

Internally, INFO is a two column table that associates a Field value with an external image or data file. The $Table example shown above was created automatically. You can create your own INFO tables using the INFO LOAD script statement. The following  script connects OrderNumbers with the associated Invoice PDF file.

[qlikview type=”qvs”]
InvoicePDF:
INFO LOAD * Inline [
OrderNumber, InvoiceFile
SO67707, PDF\Invoice_SO67707.pdf
SO67710, PDF\Invoice_SO67710.pdf

[/qlikview]

Clicking the i opens the associated PDF file in Adobe Reader or the default application for *.PDF on your machine.  If the file is not physically available, the the text string “PDF\Invoice_SO67707.pdf” will display in a popup.

For Access Point usage, note that opening external files in this way does not work from the Ajax client. It does work with the IE Plugin or Desktop client. (The workaround is to use Open URL Action).

Note that tables created using INFO LOAD do not appear in the Table Viewer.

A common use of INFO is image files. The  optional prefix, “BUNDLE”, may be used to include the external file contents in the qvw itself. This is done for portability, as the files need not be available at runtime (works with all clients).

[qlikview type=”qvs”]
T1:
BUNDLE INFO LOAD * INLINE [
Fruit, val
Cherry, Image\Cherry.jpg
Banana, Image\Banana.jpg
Apple, Image\Apple.jpg
Lemon, Image\Lemon.jpg
];
[/qlikview]

Note that the name of the second field (“val” in this case) does not matter as it is never referenced in expressions or the UI.

We can use the Fruit INFO in a number of ways.  First we can use the field Fruit in a listbox and select “Info as Image” Representation on the Presentation tab:

The listbox will show the associated images instead of the text. Sort and Search in this listbox will use the Fruit text values, as we might expect.

Once again, when a single Fruit is selected we get our friend i. Clicking i will display the image in it’s original size in a moveable window. The window remains until the user closes it.  You can pull up multiple images side by side and arrange them. Imagine pulling up multiple insurance claim or property photos.

Another way to utilize INFO data is in an expression using the Info(fieldname) .  In the Straight Table below I’ve used the expression Info(Fruit) to create the second column. The Representation for that Expression has been set to “Image” on the Expressions pane.

The  Info() function produces results only when there is one value for the given context.  In a Text Object,  Info(Fruit) would produce a null value as long as there is more than one Fruit possible.  In this way, Info() works similar to the Only() function. Unlike Only(), Info() does not accept a Set expression to select a specific value. That kind of conditional logic requires using the qmem syntax instead of Info(). (For more on qmem, see the Help for BUNDLE ).

So what happens if we try to BUNDLE LOAD non-media files like excel or PDF? Disappointment I’m afraid.  They will load. Your qvw will get larger. However the Info display won’t work correctly. You can of course leave off the BUNDLE prefix for those file types and make sure they are available at runtime to the user.

Info can also be invoked as an Object Action.  The Action is “Show Information” and it can be found in the External Action Type.

Have fun and let me know how you use INFO.

-Rob

PS  I hear the early bird discount for the May SF Masters Summit has been extended. See the news here

Share

Listbox Expressions

Prior to the introduction of Listbox Expressions in QV11, the only additional data you could put in a listbox was Frequency.  The Show Frequency option has some shortcomings:

  • The meaning of frequency is dependent on the data model. For a customer name in an orders table, frequency may correctly reflect the order count.  If the customer name is moved to a dimension table, the  frequency is “1” .
  • Frequency values show only for possible rows — green and white. Excluded gray rows show nothing in the Frequency column.
  • Show Frequency is not available for Key fields.

Listbox Expressions solve these problems and more. Here are are a few tips on using Listbox Expressions.

On the Expressions tab of a listbox properties,  you can add one or more expression columns, as you would in a chart. The “Dimension” will be the listbox field.

While the dialog may be similar to a chart, there are a few features that are not available, notably:

  • Number format — you must do any desired formatting in the expression.
  • Column labels — the workaround is to include the “label” text in the Caption.
  • Totals.

If you want your Listbox sorted by the expression value, repeat the expression in the Sort pane “Expression” property. There is no need to include the “Num()” formatting in the Sort Expression, but no harm in leaving it in either.

Now we have a nicely sorted listbox that provides context about “customer size”.

When selections are made, excluded data shows zero, probably not what we want. Fix that up by adding a Set  to the expression.

sum({1}LineSalesAmount)

What if we want to the Sales expression to reflect other selections, like Product, but still want to see all Customers? Simple, add a set modifier to ignore Customer.

sum({<Customer=>}LineSalesAmount)

Like a chart, we can add additional expressions such as order count,  days since last order, or account rep name.  We also have the full range of expression representations; Image, Gauge, Mini Chart etc. We can even put pictures in the listbox.

There is no visible vertical line separating  columns, but the columns may be resized by dragging at the invisible  boundaries.

If you get frustrated trying to make a listbox look like a chart, take a step back. Listbox expressions are meant to guide the user in making selections, not present a finished analysis.

-Rob

Share