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

Qlik Luminary Program

TLDR: Shameless self promotion and extensive use of links.

The Qlik Luminary Program “brings together the best and brightest customers, partners and enthusiasts in the Qlik ecosystem”. Being selected as a Luminary is an honor that acknowledges a significant contribution to the community of Qlik practitioners and customers.

The point of my post today is that all four presenters at the Masters Summit for Qlikview were selected as Qlik Luminaries in 2014.  What are the odds of that! I expect that one of my colleagues or a QlikCommunity member will post the applicable probability expression — written in QlikView syntax of course. Followed up by a gentle refinement by Henric Cronström — who was a special guest at our 2013 London Summit.  At that very  same summit Henric not only took us back in time to a QlikView 0.9 demo but also busted the count distinct myth.

Speaking of the London Summit, Steve Dark, another 2014 Luminary,  contributed valuable experiences during the general sessions and followed up with detailed posts in his blog on questions raised during the summit.

While the 2015 Luminary class has not been officially announced, I expect a least a couple of us will repeat as Luminaries. If we don’t all make it, I’ll chalk that off to a  smaller class rather than anyone slacking off.

Stephen Redmond has announced that he is a member of the 2015 Luminary class.  Stephen certainly deserves the honor, having written several excellent and well regarded books on QilkView. Stephen graced us as the guest speaker in the aforementioned London Summit.

Speaking of Summit memories, I have fond recollections of the Barcelona Summit. I forgot to pack my trademark hat. Frank Buender of Lynxx BV bought me a substitute hat during our evening social time. Frank also posited many challenging and provocative questions to the Masters  and went on to contribute in the private LinkedIn group for Summit attendees.

At each Summit, we have a carefully selected guest speaker.  In Amsterdam, Christof Schwarz of Qlik wowed the audience with his innovative tips and solutions.

I hope to see you at one of the 2015 Masters Summit for Qlikview.  I anticipate we’ll see a number of QlikView Luminaries.  I expect we will push the boundaries of QlikView, and  of course, now Qlik Sense.

-Rob

 

Share

Using Variables as Metadata

A customer asked me today if there was a QVW property for an application description that could be pulled as metadata by his scanner app.

I’ve found that using Variables is a very simple way to define additional metadata.

[qlikview]SET vAppDescription = This is the main Sales app. blah blah;[/qlikview]

A different script can load that variable with this bit of script:

[qlikview]Meta:
LOAD [RawValue] as AppDescription
FROM [some qvw path.qvw]
(XmlSimple, Table is [DocumentSummary/VariableDescription]) WHERE Name = ‘vAppDescription’ ;[/qlikview]

-Rob

Join me at the San Francisco Masters Summit for QikView for more scripting tips.

Share

SF Masters Summit Early Bird Discount ends Feb 27

SFBannerThe bird is in this photo is not a seagull. She’s an earlybird, headed to masterssummit.com to take advantage of the earlybird registration discount available until February 27.

At the Summit, birds of the Qlikview Developer variety will be immersed in three days of hands-on advanced and intermediate QlikView Developer training. We’ll be covering topics such as advanced scripting, advanced expressions & aggregation, visualization, data modeling, performance, server administration and Qlik Sense for QlikView  customers.

Training will be led by four popular instructors, all well known as Consultants, Bloggers, Qlik Luminaries and longtime QlikCommunity contributors.

Barry Harmsen: Co-author of the seminal book “QlikView 11 for Developers” and founder of the Q-on Training Center.

Oleg Troyansky:  Author of the upcoming “QlikView Your Business” , QlikView veteran and one of the all time top contributors to QlikCommunity.

Rob Wunderlich (hey that’s me!):  Publisher of QlikViewCookbook.com and founder of the QlikView Components open source script library.

Bill Lay: Visualization wizard and everyone’s favorite presenter. Bill’s entertaining  presentation style makes any topic interesting and engaging.

In addition to the class material, we’ll have an evening panel discussion, guest speakers and plenty of opportunities to network with peers.

Read more about the Masters Summit for Qlikview and Register here.  See you in San Francisco!

 

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

Focus not Filter

I always enjoy Barry Harmsen’s popular-culture-and-Qlikview posts like last week’s “What QlikView developers can learn from The Karate Kid“.

If I got you back from reading Barry, here’s my bit of Mr Miyagi wisdom: “Focus not Filter”.

Green/white/gray in a listbox provides focus on the selected data while still keeping all data visible. The same concept can sometimes be useful in charts. Emphasizing selected data while keeping all data visible  maintains context and provides for consistent comparison.

Here are a few examples of techniques I use with QlikView charts to “Focus not Filter”.

All data and selected data can be shown side by side on a chart with the currently selected data emphasized.

 

Maintaining  constant scale as users make selections can be a good way to maintain context.  The image on the left is in the clear state, the image on the right  has 13 of 51 values selected. The y-axis scale remains constant which makes it clear to the user that they are now working with a relatively small number of schools.

 

 

“Graying out” unselected data is another favorite technique.

 

A variation on “graying out” is  maintain  color but mute unselected data and highlight selected data. In this line chart, unselected data is partially transparent and  lines for selected data are shown at 1.5 times standard width.

 

If you are trying to find the Karate Kid scene where Mr Miyagi says “Focus not Filter”, stop looking. It’s not in there, I made it up. But I’m sure Mr Miyagi would have said it if he used QlikView.

-Rob

Share

How to Choose an Expression

This is a follow on to my post “How Not to Choose an Expression” that described the performance problem sometimes experienced in large apps when choosing one of several expressions.

I received a number of questions about the scalability of my suggested solution to define multiple Expressions using the Expression Conditional property. In this post I’ll present an alternative for when you have a large number of option combinations.

Before I dive in,  an important comment about coding for performance. First, you should code for clarity and maintainability. If your document contains only a few million rows, it probably won’t matter if you use if() or an alternative technique.  I’m fond of the  Donald Knuth quote “Premature optimization is the root of all evil (or at least most of it) in programming”. The techniques presented in this post are meant to solve an identifiable performance problem. I wouldn’t bother implementing them unless I have a need.

Let’s use a scenario where calculations should reflect user selected options.

  • US Dollars or Local Currency  — USD | LC
  • Include VAT?  — Y|N

I’m only dealing with two options to keep my example manageable. You should be able to extend the concepts into many options.

The if method chart Expression for our choice may look like this:

if(CurrencyType='USD' AND [Include VAT?]='N'
 ,Sum(SalesAmount_USD)
,if(CurrencyType='USD' AND [Include VAT?]='Y'
 ,Sum(SalesAmount_USD + VAT_USD)
,if(CurrencyType='LC' AND [Include VAT?]='N'
 ,Sum(SalesAmount_LC)
,if(CurrencyType='LC' AND [Include VAT?]='Y'
 ,Sum(SalesAmount_LC + VAT_LC)
))))

The [CurrencyType] field controls which field we will sum() and the [Include VAT?] field controls if the associated VAT field is included in the sum(). What’s the difference between the alternatives? Only the fields listed in the sum().

Our Document contains 100M rows and we’ve identified this expression as a bottleneck. What are some alternatives to make this perform better?

In my previous post, I discussed dividing this into four expressions and making a choice using the Expression Conditional property. I won’t repeat the details of it here.  In this case, I don’t want to create multiple expressions in the charts. What is another possible technique?

Start by loading a table that reflects the choice fields and the associated sum() fields.

This is an island table that is not linked to any other tables in our model.

Create Listboxes for [CurrencyType] and [Include VAT?]. Set the “Always One Selected” property in the Listboxes.  This will force the user to make selections and at any given time only one row will be possible in our table.

We will then reference the SalesExprField in our chart using Dollar Sign Expansion (DSE). DSE is performed before the expression is evaluated. Our chart expression is now:

Sum($(=SalesExprField))

The “=” within the DSE says to evaluate this as an expression. In other words, substitute in the value of the SalesExprField and then evaluate the Sum().

Do you want to see what DSE is actually substituting? In a Straight Table, clear the Label field. The substituted expression will be visible in the column heading.

If we are not sure that “Always On Selected” is guaranteed, we should use some type of aggregation function to ensure a single SalesExprField is selected. For example, to take the first possible value:

Sum($(=FirstSortedValue(DISTINCT SalesExprField,1)))

Instead of just parameters to  the sum() function, we could have included the entire expression in our island table,  eg “Sum(SalesAmount_LC + VAT_LC)”. In that case our chart expression would be:

$(=SalesExprField)

What if want to control options via variables instead of fields? Use a Set expression in the Only() function.

Sum(
$(=only({<CurrencyType={$(vCurrencyType)},[Include VAT?]={$(vIncludeVAT)}>}SalesExprField))
)

If you’ve read this far, you are probably wondering “Is there a downloadable example”. Yes, it can be found here. Qlikview Cookbook: How to Choose an Expression.

-Rob

Want more performance tips?  Come see Oleg Troyansky’s Performance Tuning session and  additional tips  from other presenters at the “Masters Summit for Qlikvew”.

Share

How Not to Choose an Expression

We sometimes have a  requirement to select between two or more expressions  dependant on user selections or some other condition. For example, this chart Expression.

if(vWithCommission=1
 // Calculate with Commision
 ,sum({<CommissionFlag={1}>}
     SalesAmount - SalesAmount * CommissionRate)
 // Calculate without Commission
 ,sum(SalesAmount)
 )

The  if()  will select one or the other sum() expression based on the value of the vWithCommmision variable.  Because a variable is being tested —  not a row value — only one sum() will be chosen for the entire chart.

If performance is important,  this is not a good way to implement the requirement. QlikView does not “short circuit”. Short circuit means to stop evaluating when the condition is true. QlikView will calculate both sums and then return one of those results.

Some people mistakenly believe that putting the above expression in a variable changes the behavior. This is incorrect. The if() evaluation is still done at the chart level and the performance impact remains.

A performant way to solve the requirement is to put each calculation into a separate chart Expression and use the  Conditional property to select the Expression.

An Expression with  a Conditional evaluating to False will not be calculated or displayed.

There is also the possibility of choosing the calculation in a variable, but you have to follow a few rules.

  1. The variable should return the string representation of the formula. Note the single quotes in the example below.
  2. The variable definition should begin with “=”. This causes the if() to be evaluated only once.
  3. In the chart Expression, reference to the variable should be made with $(). eg  $(vChooseCalc)
=if(vWithCommission=1
    ,'sum({<CommissionFlag={1}>}
        SalesAmount - SalesAmount * CommissionRate)'
    ,'sum(SalesAmount)'
)

-Rob

For more performance tips, join us at the upcoming “Masters Summit for Qlikvew”  in San Francisco May 2015 where Oleg Troyansky presents an always enlightening session on Performance Tuning. Can’t make SF? Check out the other dates and locations on the website.

 

Share

Qlik Sense Opportunity for QlikView Customers

I had a great time participating in the Hackathon at the recent Qlik World Conference in Orlando. The Hackathon challenge was to create a visualization solution to a United Nations challenge using the Qik Sense Mashup APIs. It was a stimulating exercise for a number of reasons — the subject matter, the company of talented practitioners, and the Sense API ease of use and powerful functionality.

Through my experience with using the APIs and talking with a number of customers at the conference, I see a clear opportunity for existing QlikView customers to leverage Sense as an Extranet or Mashup solution.

Many QlikView customers have apps that currently deliver great value inside the company. These apps may be mature, data dense and backed by a sophisticated data model. Everyone is happy, but there may be some discussion about providing a subset of the solution to external users like B2B customers over the web.   That has been  possible with QlikView, but it can be to be complex to implement. It’s much easier with Sense and I think Sense could be the killer solution for extranet reuse. Here’s why:

  • The existing QlikView data model can be reused by Sense with a simple Binary Load. No need to write additional script and you maintain a single-version-of-truth for both internal and external users.
  • The sense charts and visualizations are much more “webby” in appearance and behavior,  meeting the modern expectations of web users and web developers alike.
  • The APIs are powerful, clearly designed and will be easily understood by web developers tasked with integrating Qlik content and data into portals or other  interface.
  • Better APIs to get data from the Qlik engine. For example, there are methods to create and return “hypercubes” of data. Pass in Dimensions and Expressions and calculated data is returned — without the need to create a chart. The returned data can be visualized or used to drive another process.
  • The new Session Authentication API can delegate user authentication to an existing portal session, eliminating the need for a piggybacking WebTicketing exchange. This satisfies the common customer requirement that “when the portal session ends, the Qlik session should end”.

-Rob

 

Share

Listbox Color Chips

I was recently poking around in the QlikView 11 demo “Social Media Data Analysis“.  This app was first brought to my attention in the excellent blog post “Use of a Silent Legend” by  Jennell McIntire.  I like how color is used to quickly create linkage between elements on the sheet. It’s one of my favorite tips.

Looking at the mechanics of the color & object construction, I thought that while fine for a demo, there were a few things I would do differently. One item in particular — the Company listbox — stood out because of a new technique available in QV11.

The listbox contains a color chip for each Company that maps to the color used in the charts. Very effective.

The color chips are constructed as 6 individual Text Objects. This is maybe the only possible way to get that particular effect in a V10 listbox.

However, that means that I, the challenged artist, have to line those boxes up and keep them aligned. It also means that I have to be very sensitive to the contents of the listbox changing.

V11 introduced Listbox Expressions which opens up a new option.  I took the individual color boxes and put them in  jpg files. I bundle loaded (embed in the qvw) the images with this script:

Images:
bundle info load * inline [
Company, image
Company A,image\Square_Orange.jpg
Company B,image\Square_Blue.jpg
Company C,image\Square_Green.jpg
Company D,image\Square_Brown.jpg
Company E,image\Square_Red.jpg
My Company,image\Square_Purple.jpg
];

Next step was to add this Expression to the listbox:

='qmem://Company/' & Company

and select “Image” for the Expression Representation.

And now my color chips are an integral part of the listbox. Also, the chips now disappear for excluded values which is consistent with the visual behavior of the rest of the sheet.

             

I won’t be surprised if commenters come up with an even better way 🙂

-Rob

Share

Recipes for Qlikview Success