1 2 3 Previous Next

Qlik Design Blog

383 posts

If you don't already know, enigma.js is an open source library for communicating with Qlik Sense backend services. The QIX Service of enigma.js provides an API to communicate with a QIX Engine, giving you the ability to build applications powered by Qlik.

 

Vega calls itself a visualization grammar. It is a declarative language for creating visualizations. You just describe the appearance and behavior of the visualization you want to create, and Vega does the rest. And it can render with canvas, avoiding costly dom manipulations.

 

I'm going to demonstrate using enigma.js and Vega to create a simple bar chart. I'll be reusing the qApp.js module and qSessionObject class I introduced in Getting started with enigma.js, so check that out first if you haven't already.

 

Getting Setup

You can review Getting started with enigma.js, and follow the "Setup", "Connecting to an app", and "Creating Session Objects" sections. You'll also want to load jQuery and Vega (https://cdnjs.cloudflare.com/ajax/libs/vega/3.0.0-beta.25/vega.min.js).

 

Alternatively, you can download the getting-started.zip file below. The getting-started.zip file includes package.json and webpack.config.js files, the qApp.js and qSessionObject.js files, as well as an index.html file, and a main.js file. There's also a .qext file, in case you want to use Qlik Sense as your server for your static files.

 

For this demonstration, I'm using fields from the Helpdesk Management app, so make sure your qApp.js file is connecting to a copy of the Helpdesk Management app.

 

The Project

Now that you're setup, we can start the project. We'll do everything in main.js for this demonstration. So open up main.js. We'll need to import qSessionObject.js and create our session object.

import qSessionObject from "./qSessionObject";

let chartCube = new qSessionObject({
  qInfo: {
    qType: "visualization"
  },
  qHyperCubeDef: {
    qDimensions: [{
      qDef: {
        qFieldDefs: ["[Case Owner Group]"]
      },
      qNullSuppression: true
    }],
    qMeasures: [{
      qDef: {
        qDef: "Avg([Case Duration Time])"
      }
    }],
    qInitialDataFetch: [{
      qWidth: 2,
      qHeight: 1000
    }]
  }
});






 

Now that our qSessionObject has been created, let's define the Vega spec for our bar chart. The spec is roughly based on the spec from Vega's tutorial Vega: Let's Make A Bar Chart Tutorial, so feel free to check that out if you like. I simplified it a bit, and removed the data values so that we can stream the values in using data returned from enigma.js. It looks like this:

let barchartSpec = {
  "$schema": "https://vega.github.io/schema/vega/v3.0.json",
  "width": 400,
  "height": 200,
  "padding": 5,
  "data": [
    {
      "name": "table"
    }
  ],
  "scales": [
    {
      "name": "xscale",
      "type": "band",
      "domain": {"data": "table", "field": "category"},
      "range": "width"
    },
    {
      "name": "yscale",
      "domain": {"data": "table", "field": "amount"},
      "nice": true,
      "range": "height"
    }
  ],
  "axes": [
    {
      "orient": "bottom",
      "scale": "xscale",
      "encode": {
        "labels": {
          "update": {
            "angle": {"value": -50},
            "align": {"value": "right"},
            "baseline": {"value": "middle"},
            "radius": {"value": -2}
          }
        }
      }
    },
    {
      "orient": "left",
      "scale": "yscale"
    }
  ],
  "marks": [
    {
      "type": "rect",
      "from": {"data":"table"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "category", "offset": 1},
          "width": {"scale": "xscale", "band": 1, "offset": -1},
          "y": {"scale": "yscale", "field": "amount"},
          "y2": {"scale": "yscale", "value": 0}
        },
        "update": {
          "fill": {"value": "steelblue"}
        },
        "hover": {
          "fill": {"value": "red"}
        }
      }
    }
  ]
}





 

With our qSessionObject and our bar chart spec created, we can create the bar chart. After the dom is ready, we'll initialize the Vega view (Vega: View API), open the qSessionObject, get the layout of the qSessionObject, reformat the matrix to work with Vega, insert the values into our Vega view, setup updating the Vega view when the qSessionObject changes, and add an event listener to the Vega view to enable selections. It all looks like this:

$(() => {

  //initialize vega view
  let view = new vega.View(vega.parse(barchartSpec))
    .renderer('canvas')
    .initialize('#view')
    .hover();

  //open cube
  chartCube.open().then(() => {

    //get object layout and insert data into vega view
    chartCube.object.getLayout().then((layout) => {
      let values = layout.qHyperCube.qDataPages[0].qMatrix.map((row) => {
        return {"category": row[0].qText, "qElemNumber": row[0].qElemNumber, "amount": row[1].qNum}
      });
      view.insert('table', values).run();
    });

    //when object data changes, update data in vega view
    chartCube.object.on("changed", function() {
      chartCube.object.getLayout().then((layout) => {
        let values = layout.qHyperCube.qDataPages[0].qMatrix.map((row) => {
          return {"category": row[0].qText, "qElemNumber": row[0].qElemNumber, "amount": row[1].qNum}
        });
        view.remove('table', (d) => { return true; }).run();
        view.insert('table', values).run();
      });
    });

    //add event listener to make selections on hypercube when a bar is clicked
    view.addEventListener('click', function(event, item) {
      if(item){
        chartCube.object.selectHyperCubeValues("/qHyperCubeDef", 0, [item.datum.qElemNumber], true);
      }
    });

  });
});




 

And that's it. Don't forget npm run webpack, and check out the results. Here's what it should look like - Vega bar chart.

I've attached the full project in case you'd prefer to just download that and play around too.

Today I am going to blog about five Counter Aggregation Functions that can be used in Qlik Sense and QlikView in both charts expressions and the script.

  1. Count()
  2. MissingCount()
  3. NullCount()
  4. NumericCount()
  5. TextCount()

Before taking a closer look at how we can use each of these functions, let’s first look at the data set I will use for the examples.  Below is the Excel data I will load.  It is a simple list of fruits, their color and quantity.

Excel.png

1. Count()

The Count function is probably one of the most common functions that can be used.  In a chart, Count() aggregates the number of values in each chart dimension.  In the script, Count() returns the number of values aggregated in the expression as defined by a group by clause.

 

Expression for a chart: Count(Distinct Fruit)

 

In the script below, Count() will return color and the number of fruits that have that color.

Count.png              Count Table.png

2. MissingCount()

In a chart, the MissingCount() function will aggregate the number of missing values in each chart dimension.  In the script, it will return the number of missing values aggregated in the expression, as defined by the group by clause.

 

Expression for a chart: MissingCount(Quantity)

 

In the script below, MissingCount() will return 1 if the Quantity field is missing a value.

MissingCount.png              MissingCount Table.png

3. NullCount()

NullCount() will return the number of null values in each chart dimension in a chart.  In the script, NullCount() returns the number of null values aggregated in the expression, as defined by a group by clause.

 

Expression for a chart:  NullCount(Color)

 

In the script below, NullCount() returns 1 if the Color field is null.

NullCount.png              NullCount Table.png

4. NumericCount()

In a chart, NumericCount() aggregates the number of numeric values by each chart dimension and in the script, NumericCount() returns the number of numeric values found in the expression, as defined by a group by clause.

 

Expression for a chart: NumericCount(Quantity)

 

In the script below, the total Quantity fields that have numeric data is returned.

NumericCount.png              NumericCount Table.png

5. TextCount()

In a chart, TextCount() aggregates the number of non-numeric values by each chart dimension and in the script, TexCount() returns the number of non-numeric values found in the expression, as defined by a group by clause.

 

Expression for a chart:  TextCount(Color)

 

In the script below, TextCount() will return the total number of text values in the Fruit field.

TextCount.png              TextCount Table.png

Here is a table with all these functions used in a chart:

Table.png

While I have not used all of the counter aggregation functions in my work with QlikView and Qlik Sense, I think they can be valuable when auditing and checking the health of your data.  They can highlight gaps in the data that should not be there and point out data type issues in the data.  I would be interested in hearing how you use these functions in your apps.

 

Thanks,

Jennell

Another great mashup from the Demo Team!

 

After my favorite CIO where we introduced KPIs into the navigation, salesforce is beautiful, elegant and made mostly of custom extensions!

 

I started with the custom Selection toolbar (Angular Directive) that I introduced in the CIO dashboard. This changes based on the number of selections, if it's only one item of that dimension selected, or more than 6, it displays "Dimension: item selected". If there are more than one, but less than 6 items selected, it changes to a dropdown menu with the x button to deselect it. This is listening to selections, which means that whatever selections are made in the webpage, they will be displayed here as well.

2017-03-03 08_51_07-Salesforce.png

Then, we needed Sense like filters but as drop down menus (Angular Directive). I have done this with the UN Gender Statistics site but this one is more advanced and stays open until you finish making all selections and sorts them by state. It scrolls if many items.

2017-03-03 08_56_03-Salesforce.png

 

Another issue we were faced with, was that we created a combo chart in Sense but we needed to customize the colors to match our webpage. This lead me to create the Combo Chart extension. This not only gives you the option of changing colors but, hover states, borders, set bar widths, dot widths, has a better display of the labels etc.

2017-03-03 11_23_51-Salesforce_Mashup_Demo_Team _ Sheets - Qlik Sense.png

 

In the same page, we had to display and compare two vertical bar charts. The problem is that when we placed the out-of-the-box ones, the y-axis max were different thus visually misleading.  So I used the combo chart with only one measure and set the max to achieve the desired results

2017-03-03 09_32_24-_Salesforce_Mashup_Demo_Team - Dashboard 2 _ App overview - Qlik Sense.png

2017-03-03 11_26_06-Salesforce.png

 

Moving on to the next page, we had two more issues to solve.

We needed to have a Stacked bar Chart based on the value of the measure and not the number of measures. For this, I created the SenseUI-ValueStackedbarChart. I used the same tooltips, coloring, hover states etc as I used in my other extension like my most popular one, SenseUI-BarChart.

2017-03-03 10_27_46-_Salesforce_Mashup_Demo_Team - Opportunities 1 _ Sheets - Qlik Sense.png

The other issue was that we needed a horizontal menu for quarters and years. For this I used an older extension, the SenseUI-Filter.

2017-03-03 10_47_36-Salesforce.png

Lastly, I used my SenseUI-BarChart extension for all of the horizontal bars. I used the same bar color, border and hover color to match the rest of the website's objects.

2017-03-03 14_04_16-Salesforce.png

The mashup is found at http://webapps.qlik.com/salesforce/index.html

Please note that this is a work in progress. I still have to work on the mobile version and some other UI issues

 

Extensions mentioned here:

Senseui-ComboChart

SenseUI-ValueStackedbarChart

SenseUI-BarChart

SenseUI-Filter

 

For more of our work, you can go to webapps.qlik.com

 

Yianni

 

NOTE: To increase resolution or size of the video, select the YouTube logo at the bottom right of the player. You will be brought directly to YouTube where you can increase the resolution and size of the player window. Look for the 'settings' gears icon in the lower right of the player once at YouTube.

 

What

Just that, a mashup template for dev-hub (aka dead simple drag and drop mashup creator) that ships with a bunch of cool features such as:

 

  • Dev-hub ready
  • Multi Page
  • KPI row built in
  • Prebuilt CSS color library
  • Cards with full screen toggle
  • Offcanvas filters pane
  • Help modal popup
  • Responsive design
  • Bootstrap built in
  • Custom fonts ready

 

Why

Because we’ve heard you asking for a more powerful and good-looking template that can constitute a solid framework to create your customized mashups.

 

Who

Anyone looking for a feature rich mashup template designed for use in the dev-hub.

 

When

Available today!

 

Where

You can grab the latest* version here GitHub - fkabinoff/qs-dev-hub-dashboard-template: Dashboard template for Qlik Sense dev hub

 

*Please notice this is a live project, we will keep updating it frequently. Right now the project documentation (readme.md) is far from what we would like it to be.

mitul.png
In this week's edition of the Qlik Design Blog, I'd like to introduce Mitul Vadgama. Mitul is a member of our Qlik Consulting Services team in the UK. He has worked on a variety of consulting projects using both Qlik Sense and QlikView with many enterprise customers. His passion is transforming data into valuable business insights, knowledge sharing, and enabling customers to get the most value out of Qlik products. Mitul is going to show you how to optimize a powerful and unique capability in Qlik Sense, Smart Search. Thanks for your valuable contribution Mitul!

 

Smart Search

 

Smart Search provides powerful functionality allowing users to search dimensions and values found within an application’s data model. When working with customers on consulting projects I have found that sometimes the business users, data architects, and app designers want to control which fields are included or excluded in the search. Did you know that you can control which fields are included or excluded from Smart Search?

 

Here is an example using Smart Search in action where I search for “Rob” in my sales application:

 

1.png

 

You can see Qlik Sense finds the value “Rob” in the following fields:

 

•    First Name

•    SalesPerson

•    CompanyName

•    ContactName

 

Consider a scenario where you want Smart Search to exclude searching in the “ContactName” field when the users search. You can achieve this by inserting the exclude clause in the Search statement in your script.

 

The Search statement

 

The Search statement is a script function used for including or excluding fields in smart search.

 

It can contain two clauses:

 

Syntax:

  • Search Include *fieldlist
  • Search Exclude *fieldlist

In our case I want to exclude ContactName from my results. I do this by opening my data load editor and typing in the following right after the SET statements:

 

Search exclude ContactName;

 

2.png

 

....and reload.

 

When I search again for “Rob” you can now see ContactName excluded from the results:

 

3.png

Tip: If you want to exclude multiple fields, simply list the fields you want to exclude using comma separators while ensuring your field name syntax is correct.

 

Search exclude field1,field2,field3;

 

Another common scenario may be you want to hide most of the ID fields from your Smart Search (maybe because they are only needed for the data model building process).

 

A possible way you can achieve this is through the following syntax:

 

4.png

 

The above contains two lines of code:

 

  • Search Exclude '*ID';
  • This excludes all fields ending with ID from searches in Smart Search.

 

  • Search Include CustomerID;
  • This includes the field CustomerID in searches in Smart Search.

 

This way I am ensuring all but one ID field is included in my Smart Search.

 

We hope through this post you can see how the Search syntax along with Exclude and Include keyword clauses is a simple yet powerful way to control which fields a user can search on your Qlik Sense application. It also speeds up the search index creation when the data model is first loaded.

 

For a full list of services offered by Qlik Consulting check out: http://www.qlik.com/us/services/qlik-consulting.

 

Regards,

 

Mitul Vadgama

Consulting Services, UK

 

For more information on the Smart Search feature check out these videos:

 

enigma.js is Qlik’s open source library for communicating with Qlik Sense backend services. I’m going to show you how to get started using enigma.js, as well as a couple general patterns I’ve been using.

 

I’m going to use ES2015, Babel, and webpack. These are not necessarily requirements for building an app with enigma.js, but I recommend them.

 

Setup

Create a new folder for your project. Run npm init or just create your own package.json file, however you prefer. Now run npm install babel-loader babel-core babel-preset-es2015 webpack --save-dev. This will install our development dependencies and save them to our package.json file. Next, run `npm install enigma.js --save`. This will install enigma.js, and save it to our package.json file.

 

For convenience, we’ll add webpack to the scripts property of our package.json file. This will let us run npm run webpack instead of having to supply the entire path to webpack. Open up the package.json file and add ”webpack”: “webpack” to the scripts property. Your package.json file should now look something like this:

{
  "name": "enigmapatterns",
  "version": "1.0.0",
  "description": "",
  "dependencies": {
    "enigma.js": "^1.0.1"
  },
  "devDependencies": {
    "babel-core": "^6.23.1",
    "babel-loader": "^6.3.1",
    "babel-preset-es2015": "^6.22.0",
    "webpack": "^2.2.1"
  },
  "scripts": {
    "webpack": "webpack"
  }
}






 

We’ll also need to create a webpack.config.js file, which should look like this:

module.exports = {
  entry: './main.js',
  output: {
    path: __dirname,
    filename: 'bundle.js'
  },
  devtool: 'source-map',
  module: {
    loaders: [
      {
        exclude: /(node_modules)/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015']
        }
      }
    ]
  }
}






 

Finally, we’ll want to create a main.js file which will be our entry point, and an index.html file which loads the bundle.js file that our build will output.

 

Connecting to an app

The pattern I’ve been using to connect to the app is to create a qApp.js file, and export the promise to connect to the app. This way, anywhere I need to use the app I can simply import this file and do something like getApp.then((app) => { //code here }).

 

So create a file named qApp.js, which looks like this:

import enigma from 'enigma.js';
const qixSchema = require('./node_modules/enigma.js/schemas/qix/3.1/schema.json');

const config = {
  schema: qixSchema,
  session: {
    host: 'localhost',
    prefix: '',
    port: 4848,
    unsecure: true
  }
};

export default enigma.getService('qix', config).then((qix) => {
  return qix.global.openApp('Helpdesk Management.qvf').then((app) => {
    return app;
  });
});






 

Creating session objects

I like to have a class for creating session objects. That way I can have an open() and close() method for each session object. The open() method calls createSessionObject on the app and returns the promise if the object does not exist in the app, and simply returns otherwise, so that I can always check to see if an object is available, without inadvertently creating a duplicate object in the app. The close() method calls destroySessionObject on the app, passing along the object’s id.

 

So create a file named qSessionObject.js, which looks like this:

import getApp from "./qApp";

class qSessionObject {

  constructor(properties) {
    this.properties = properties;
    this.object = null;
  }

  open() {
    if (!this.object) {
      return getApp.then((app) => {
        return app.createSessionObject(this.properties).then((object) => {
          this.object = object;
        });
      });
    }
  }

  close() {
    if (this.object) {
      return getApp.then((app) => {
        return app.destroySessionObject(this.object.id).then(() => {
          this.object = null;
        });
      });
    }
  }

}

export default qSessionObject;





 

You can also put other methods in this class which may be helpful. For example, I recently built an app that had 2 alternate states, and when the states changed I needed to call applyPatch on each object and change the state of the object. Having a class for the session objects made this really easy.

 

Usage example

So now we have our project setup, a qApp.js file for connecting to the app, a qSessionObject.js file for creating session objects, let’s cover a simple use.

 

We’ll create 3 lists objects, and 3 filters in our UI with those list objects. For this, we’ll use the Filter class which you can find at the end of this post, along with the rest of the source code. You'll need the filter.js file from the zip below.

You’ll also find a .qext file in the source code. That’s so we can put this project in the Extensions folder of Qlik Sense Desktop to use it as a server, but you can serve this any way you’d like, just make sure that your config in qApp.js is pointing to your Qlik Sense server.

 

So first, let’s get our html ready. The Filter class relies on jQuery and Bootstrap 4 alpha v6, so we’ll load those. Also, we'll need to load our bundle.js and main.css files. Then we can add the html we’ll need to the body. Your index.html should look like this:

<!doctype html>
<html>
<head>
  <title>Enigma patterns</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
  <!-- jQuery -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <!-- Tether -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/css/tether.min.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
  <!-- Bootstrap 4 -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css">
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
  <!--Project code -->
  <script src="bundle.js"></script>
  <link rel="stylesheet" href="main.css">
</head>
<body>
  <div id="loading">Loading...</div>
  <div id="loaded" style="display: none">
    <div class="filters row">
      <div class="col-auto">
        <div class="filter" id="case-number-filter"></div>
      </div>
      <div class="col-auto">
        <div class="filter" id="subject-filter"></div>
      </div>
      <div class="col-auto">
        <div class="filter" id="case-owner-filter"></div>
      </div>
    </div>
  </div>
</body>
</html>



 

Grab the main.css file from the attached source code and save it in your project folder.

 

Now open main.js. We’ll import the qSessionObject class and the Filter class, create 3 list objects, create 3 filters, open the 3 list objects, and then initialize the filters. This is what that should look like:

import qSessionObject from "./qSessionObject";
import Filter from "./filter";

let caseNumberList = new qSessionObject({
  qInfo: {
    qType: "visualization"
  },
  qListObjectDef: {
    qDef: {
      qFieldDefs: ["[CaseNumber]"],
      qFieldLabels: ["Case Number"]
    },
    qAutoSortByState: {
      qDisplayNumberOfRows: 1
    },
    qShowAlternatives: true,
    qInitialDataFetch: [{
      qWidth: 1,
      qHeight: 1000
    }]
  }
});
let subjectList = new qSessionObject({
  qInfo: {
    qType: "visualization"
  },
  qListObjectDef: {
    qDef: {
      qFieldDefs: ["[Subject]"],
      qFieldLabels: ["Subject"]
    },
    qAutoSortByState: {
      qDisplayNumberOfRows: 1
    },
    qShowAlternatives: true,
    qInitialDataFetch: [{
      qWidth: 1,
      qHeight: 1000
    }]
  }
});
let caseOwnerList = new qSessionObject({
  qInfo: {
    qType: "visualization"
  },
  qListObjectDef: {
    qDef: {
      qFieldDefs: ["[Case Owner]"],
      qFieldLabels: ["Case Owner"]
    },
    qAutoSortByState: {
      qDisplayNumberOfRows: 1
    },
    qShowAlternatives: true,
    qInitialDataFetch: [{
      qWidth: 1,
      qHeight: 1000
    }]
  }
});

$(() => {
  let caseNumberFilter = new Filter(caseNumberList, "#case-number-filter");
  let subjectFilter = new Filter(subjectList, "#subject-filter");
  let caseOwnerFilter = new Filter(caseOwnerList, "#case-owner-filter");

  Promise.all([caseNumberList.open(), subjectList.open(), caseOwnerList.open()]).then(() => {
    $("#loading").hide();
    $("#loaded").show();
    caseNumberFilter.init();
    subjectFilter.init();
    caseOwnerFilter.init();
  });
});


 

Don’t forget to run npm run webpack to build your bundle.js file.

 

If you’ve followed along, you should have 3 dropdowns on your page now that look like this - Enigma patterns. You can also just download the source code below, put it in the Extensions folder of your Qlik Sense Desktop installation, run npm install and then npm run webpack, and check out the project that way.

Simon Kirby.jpg
In this week's design blog I have the pleasure of introducing our newest guest blogger, Simon Kirby. Simon is a Director of SI Industry Solutions with our Financial Services group out of the UK and has prepared an introduction and video that shows you how Qlik Sense can be used to analyze car insurance claims data.

 

Insurance Whiplash Fraud

 

It was recently announced in the UK that car insurance premiums are at their highest ever levels (The Actuary Magazine) and one of the key factors for this is an increase in whiplash injury claims. In addition to legitimate whiplash injury claims, insurance companies are struggling to cope with an increasing trend in fraudulent whiplash claims. These claims occur when a third party deliberately creates an accident by causing another car to crash into the back of them. They then feign a whiplash injury and receive thousands in compensation. It’s been discovered that these people repeat these accidents regularly and effectively earn a living from scamming the insurance industry.

 

How Qlik Sense can help

 

A key weapon for insurers in identifying these fraud perpetrators is the analysis of data. Insurers need to be able to search for associations in data between similar types of claims, in similar locations, including something unique like a mobile phone number. These associations between the data can lead to a significant increase in identifying the groups of people that commit these types of fraud. This is exactly where Qlik Sense can play an important role in this activity.  The QIX Associative engine, at the heart of Qlik Sense, is designed to make the discovery of these associations easy and intuitive. Together with the ability to quickly create drag and drop visualizations, Qlik Sense can help Insurance Fraud Analysts identify trends, patterns and examples of fraudulent Whiplash claims. (view more about Qlik's Associative Model: Qlik Snippets - The Qlik Associative Model - YouTube and Qlik's Associative Model - Part I - YouTube)

 

See and try it for yourself

 

The next step for insurers would be to combine the power of Qlik Sense with their fraud detection models.  The result would be a Qlik Sense visualization embedded into the claims system that showed the claims handler the real-time results of the fraud model at the time of the Notification of Loss.  This would allow the insurer to push suspicious claims to a dedicated fraud management team for further investigation which could potentially save the company millions.

 

If you would like to see how Qlik Sense can be used to identify claims fraud, take a look at our video on YouTube and the attached Qlik Sense app. For more details on this app, please visit this link available on the Qlik Financial Services Community site: Insurance Claims App

 

Regards,

Simon Kirby

Director, SI Industry Solutions - Financial Services

Qlik

 

 

NOTE: To increase resolution or size of the video, select the YouTube logo at the bottom right of the player. You will be brought directly to YouTube where you can increase the resolution and size of the player window. Look for the 'settings' gears icon in the lower right of the player once at YouTube.

 

Can't see the video, YouTube blocked? Download the attached .mp4.

 

If using Qlik Sense Desktop please copy .qvf file to your C:\Users\<user profile>\Documents\Qlik\Sense\Apps and refresh Qlik Sense Desktop with F5. If using Qlik Sense Enterprise Server please import .qvf into your apps using the QMC - Qlik Management Console.

Jennell McIntire

Binary Statement

Posted by Jennell McIntire Feb 10, 2017

Have you ever used a Binary statement in your script or done a “binary load” as folks familiar with Qlik scripting may say?  The Binary statement can be used in both QlikView and Qlik Sense scripts to load data from another QlikView document or Qlik Sense app.  When using QlikView, the Binary statement can only be used to load another QlikView document.  When using Qlik Sense, the Binary statement can be used to load another Qlik Sense app or a QlikView 11.2 or earlier document.  Note that you cannot use a Binary statement in a QlikView script to load a Qlik Sense app.  The Binary statement will load not only the data but the section access data as well.  It does not load variables or any layout information such as charts, sheets or stories from the app or document.

 

The Binary statement is helpful when you want to use the data model from an existing app or document in a new app or document.  Instead of copying the app/document and then deleting the sheets, stories, etc., you can create a new app/document and load just the data using the Binary statement.  Then you have a fresh slate to build out the sheets and visualizations.  Chuck Bannon wrote a blog on ways you can extract data from a document which you may find useful.  In his blog, he uses the Binary statement to get the data from another document and then he stores the data into QVDs.  I personally prefer the second option he discusses that uses a for loop to create the QVDs.  Storing the data into QVDs is useful if you need to manipulate the data when loading it.

 

There is one thing you must remember to do when using the Binary statement in order for it to work – you must make the Binary statement the first statement in the script.  This means adding it before the Set statements.  The syntax varies for QlikView and Qlik Sense so let’s take a look at both.

 

In QlikView, either statement below can be used.  In the first example, the MyApp document will need to be in the working directory otherwise the absolute file path will need to be included as seen in the second example.

QV1.png

QV2.png

In Qlik Sense, you will need to create a folder connection to the app you would like the use.  In the example below Demo Apps is the folder connection I created to access the MyApp QVF.

QS1.png

Simple, right?  The Binary statement when loaded as the first statement in the script will load the data from another QlikView document or Qlik Sense app providing you with the same data model as the original app and a clean slate to build out your visualizations.  Good luck scripting!

 

Jennell

starwars.pngRecently, I worked with a Qlik Community member to help them understand the Qlik REST Connector with Qlik Sense and QlikView. At first it appeared simple, but then he soon realized he needed to understand a bit more about how the data came back (the response), what the pagination settings were (pages of data used to retrieve more rows) and finally how to link (join, associate) other attributes that came back from the results of multiple REST API endpoints / resources. We got it all working and the results were pleasing. Needless to say were able to perform text analytics from a barrage of Facebook comments.  However, as I finalized all this in my head, I wanted to share what I've learned but in the simplest way possible. So I decided to find a very simple, publicly available RESTful service API in which I can demonstrate my findings easily. The below video presents those findings in a educational and entertaining way using the Star Wars API. Yes, that is correct, I said the Star Wars API. As a bonus, stick to the end of the video to see the Media Box Extension in action.

 

See this video on YouTube as well. Using the Qlik REST Connector - Pagination and Multiple JSON Schemas - YouTube

 

 

 

 

Do you know of other simple and fun, publicly available RESTful services? Share them with the Qlik Community in the comments below.

 

Regards,

Michael Tarallo (@mtarallo) | Twitter

Qlik

 

Special shout out to: Paul Hallett    (@phalt_) | Twitter - for creating an awesome resource http://swapi.co/about that allowed me to easily demonstrate the Qlik Sense REST Connector.

 

Resources used in this video:

 

 

 

Other Resources:

 

 

If using Qlik Sense Desktop please copy .qvf file to your C:\Users\<user profile>\Documents\Qlik\Sense\Apps and refresh Qlik Sense Desktop with F5. If using Qlik Sense Enterprise Server please import .qvf into your apps using the QMC - Qlik Management Console.

 

Disclaimer: Star Wars, the Star Wars logo, all names and pictures of Star Wars characters, vehicles and any other Star Wars related items are registered trademarks and/or copyrights of Lucasfilm Ltd., or their respective trademark and copyright holders.

As we were working on one of our projects, we had the need of creating multiple combo charts. The problem was that we could not change the colors to match our mashup/webpage. So, I decided to make an extension, that gives full control of the chart appearance and it's labels. The same as my Barchart extension this is wrapping text labels underneath the bars. If you still have problems with the text, then just increase the width of the bars and everything should be back in place.

 

Installation

- [Download zip file](https://github.com/yianni-ververis/SenseUI-ComboChart/archive/master.zip)

- Desktop - Unzip at the extension folder (C:\Users\<user>\Documents\Qlik\Sense\Extensions\SenseUIComboChart)

- Server - Upload the zip file

 

 

Usage

 

Dimensions and Measures

- Set 1 dimension for the x Axis

- Set 1 Measure for an additional Line Chart

 

 

General Settings

- Font Size

- Font Color

- Display the Legend

- Enable/Disable Selections

 

 

Bar Chart Settings

- Bar Color

- Bar Hover Color

- Bar Width (0 for auto scaling)

- Bar Border Color

- Bar Border Width

 

 

Line Chart Settings

- Line Color

- Line Width

- Dot Color

- Dot Stroke Color

- Dot Stroke Width

- Dot Radius

 

preview2.png

 

preview2.png

 

Barnch: http://branch.qlik.com/#!/project/5894e07a75db504d76ac3123

Git: GitHub - yianni-ververis/SenseUI-ComboChart: Qlik Sense Combo Chart

 

Yianni


Hello Qlik Community! image1.pngIn my last blog entry Introducing Qlik GeoAnalytics - I um...well....introduced our latest product offering... Qlik GeoAnalyitcs. I also included a promo video showcasing its various capabilities.  (In case you have not seen it, I suggest you start with that first.)

 

I've been working with Qlik GeoAnalytics for a few weeks now and I am really enjoying it. I'm gathering tremendous knowledge (thanks to the fantastic Idevio team who is now part of the Qlik family) and compiling it so I can share it with you so you can get started quickly. You can see some of the efforts in this new video index which provides a few primers to help you get started with Qlik GeoAnalytics for both Qlik Sense and QlikView. If you have Qlik GeoAnalytics related questions you can also start a discussion in our new section on the Qlik Sense forums: Qlik GeoAnalytics Community.

 

Over the next few weeks I'll be presenting other topics in a series of blogs and community posts that will help you learn more about Qlik GeoAnalytics, presenting its various capabilities. To that point, I recently discovered the Qlik GeoAnalytics Connector which can grab data from a variety of external geo-data services to return route information, distance, time and spatial relationships and associate them with your 'decision making data'. Look at this fun example using Qlik GeoAnalytics Line, Bubble (flags), and Heatmap layers to represent long and short travel routes, along with a fictional "area of concern" depicted by the heatmap. With Qlik Sense small devices mode it even fits and reacts perfectly on my iPhone too, I did not have to create a separate mobile-version of the app....."Oh, no - I don't want to take that shortcut through Central Park, there are way too many street performers along that route!!"  ...but more on that later. What I love the most about Qlik GeoAnalytics, it's more than just plotting simple dots on a map, it moves Qlik beyond visualization and supports a broad range of advanced geoanalytic use cases. I hope you will see the value and benefits it has to offer and that you have as much fun with it as I.

 

To kick of the knowledge share, in this below video I show you how to create a very simple Area map, which can also be known as a boundary or choropleth map, that you can drill-down into.

 

 

If you cannot see the video, or you would like the sample data, you can find both here: Qlik GeoAnalytics - Creating a Drill-down Area Map

 

Let me know what you think and I looking forward to joining the conversation on the Qlik GeoAnalytics Community.

 

Regards,

Michael Tarallo (@mtarallo) | Twitter

Senior Marketing Manager
Qlik

Qlik Explorer for Developers (QEfD) is a tool that will let you to explore Qlik Sense content and obtain some valuable info. You can connect to a Qlik Sense server and drag and drop code snippets and IDs into whichever IDE you are using to build mashups or similar solutions.

 

You can learn more about QEfD here:

    Qlik Explorer for Developers is here!

 

I mainly use QEfD for two tasks, to obtain objects ID so I can inject them into my webpage, and eventually to poke around object properties.

 

QEfD.PNG

 

To copy an object ID I just connect it to my server (you can also try it with your localhost:4848 or just try out the default connection to PlayGround) and then QEfD will show me a tree-list with all the apps available on that server. From there it gets pretty simple, navigate to the object I want to incorporate into my webpage, the preview tab gets very helpful to double check you are where you want to be, and then using a template* called "id" I can copy the object’s ID.


*What’s a template: is a set of code snippets which are bound to different nodes in Qlik Sense. A node is for instance a Qlik Sense application, a sheet or an object.

 

Since the introduction of the Visualization API a developer can create her own charts on-the-fly, this way we become independent from the Qlik Sense client and from the visualization layer within the qvf (you don’t have to create a chart first on Sense client).


To create your own charts, you are supposed to construct the object by yourself. QEfD can be super handy here. I use it to learn, and let’s face it, to copy all JSON properties from existing objects. It makes it super easy to create some pretty advanced on-the-fly charts. It almost feels like cheating, in a good way.


If you want to download now Qlik Explorer for Developers, please do it here:

Download Qlik Explorer for Developers

Built by Developers for Developers


If you want to see QEfD in action, please check out this video:

    Qlik Analytics plugin for Visual Studio - YouTube

    Please note that this stand alone tool works exactly as the Qlik Analytics for Visual Studio plugin.


Enjoy it!

AMZ

Today - Jeff Goldberg is back and will introduce us to using session attributes to pass security and other information to a Qlik Sense session.


Introduction

Did you know with Qlik Sense security rules, it's possible to use attributes delivered to Qlik Sense Enterprise during the authentication process?  Yup, it's true. While the conventional approach to using attributes is to import them using a User Directory Connector, session attributes are a flexible alternative to storing attributes in the repository to control capabilities and authorization in Qlik Sense Enterprise.

 

Qlik Sense supports session attributes through SAML, ticketing, and session authentication schemes.  Session attributes are attributes sent in the request for access to the Qlik Sense server.  The attributes are not stored in the repository, but in the user's Qlik Sense session.  Session attributes can be referenced in security rules using the user.environment (e.g. user.environment.attributename) syntax.  In addition, if there is an attribute named group sent to Qlik Sense using SAML, ticketing, or session, it can be used in Section Access data reduction.

 

Session Attributes in SAML

When you setup a SAML virtual proxy in Qlik Sense, there is an additional attributes section where you can add attribute names from the saml response sent by the identity provider, and the name you want to use in Qlik Sense.  Here you can see I have a SAML integration with Okta.  I have an additional attribute that comes in from Okta named Groups.  In Qlik Sense I have it use the name group.  The name on the left must match what is sent by the idp.  The name on the right can be whatever you want it to be.

 

jeff1.png

How do you identify the names of the attributes contained in the SAML response?  I use SAML Message Decoder chrome extension.  It's a great tool for reading through the messages sent to an IDP and sent to the Qlik Sense server.

 

jeff2.png

 

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
        Destination="https://gss.qlikpoc.com:443/okta/samlauthn/"
        ID="id1026813850591869499238360"
        InResponseTo="_583b079d-39d2-44ab-9824-1336e628770e"
        IssueInstant="2016-12-13T14:03:23.898Z"
        Version="2.0"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
<...>
    <saml2 :AttributeStatement xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
      <saml2 :Attribute Name="email"
             NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
        <saml2 :AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:type="xs:string">goldbergjeffrey@yahoo.com</saml2:AttributeValue>
      </saml2:Attribute>
          <saml2 :Attribute Name="groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
          <saml2 :AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:type="xs:string">QlikGroup</saml2:AttributeValue>
          <saml2 :AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:type="xs:string">Everyone</saml2:AttributeValue>
        </saml2:Attribute>
    </saml2:AttributeStatement>
</saml2p:Response>



 

In Qlik Sense, I've created a stream for members of the QlikGroup group to access in the Qlik Sense Hub. The security rule I put in place uses the user.environment.group attribute and evaluates it against the QlikGroup group value.

 

jeff3.png

 

When I log into Qlik Sense,  you see that I have access to the stream I created because in my SAML response I am a member of the QlikGroup group.

 

jeff4.png

 

Session Attributes in Ticketing and Session

 

When ticketing and session authentication schemes are used session attributes are sent as part of the request. Here is a snippet from some sample code that demonstrates how to send attributes in a ticketing request. Notice that in the JSON message there is the UserDirectory and UserId properties and then the attributes property which is an array inside you specify an additional JSON object for each key value pair that's used to send an attribute to Qlik Sense.

 

ticket request message body
{...}
//The body message sent to the Qlik Sense Proxy api will add the session to Qlik Sense for authentication
string body = "{ 'UserId':'" + user + "','UserDirectory':'" + userdirectory +"',";
    body+= "'Attributes': [{"group":"QlikGroup"},{"group":"Sales"}],";
    body+= "}";

byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
{...}



 

Once a session attribute has been sent through the ticketing or session request system those attributes are stored for the duration of the users access and are used for security rules just like in the SAML example. Let's take a quick at how this works. I'll navigate to my webpage that uses the ticketing code.  Inside the ticketing code I've supplied a group attribute that will grant me access to the QlikGroup stream. During authentication, security rules will evaluate and determine that I have a group attribute and the security rule uses user.environment.group to grant me access to the QlikGroup stream.

 

Section Access


 

In the previous examples I sent along an attribute named group. In reality I could send any attribute I want through the session attributes mechanism. But the group attribute name has some additional capabilities within Qlik Sense. Using the group attribute name allows those values to pass into an application for section access data reduction purposes.

Let's go ahead and open up a sales application as Anne Foster.

 

Her data is reduced to only the United States because the session attribute named group has a value of "SalesUS".

 

jeff567.png

 

When I log in as Eddie Reese, he is only able to see Australia because his the session attribute value for him is "SalesAUS".

 

jeff8910.png

Wrap up

 

Session attributes are a powerful and flexible alternative to user directory connectors when using SAML, ticketing, or session authentication schemes.  Session attributes are accessible in security rules with the user.environment syntax, and when the session attribute is named "group", the values may be used with Section Access data reduction.  To learn more Qlik products and discover additional technical materials, join the conversation on our Qlik Community, Qlik Help YouTube channel and view the video libraries on the Qlik Community: New to Qlik Sense Videos - New to QlikView Videos

 

About Jeff:

IMG_2582.JPG

 

Jeff is a Principal Enterprise Architect on the North America Enterprise Architecture team who has worked in various technology positions for over 16 years. Jeff focuses on integration, deployment, automation, security, and api topics across a wide range of software. Thanks for this valuable contribution Jeff!





(Hey Jeff - this pic is going to give me nightmares!)


Follow us:
Jeff Goldberg (@goldbergjeffrey) | Twitter

Mike Tarallo (@mtarallo) | Twitter




If you haven't yet heard, Qlik recently released 3 open source software projects, now available for use and open to contributions!

 

enigma.js

enigma.js is a framework that communicates with Qlik Sense backend services. The Rest Service allows communication with Qlik REST APIs, while the Qix Service allows communication with the Qix Engine. enigma.js is now my preferred method for communicating with Qlik Sense backend services, and if you're a developer that works with javascript, I strongly suggest you check it out.

 

leonardo-ui

leonardo-ui is a UI component library that has a Qlik Sense look and feel. It works well with popular CSS frameworks such as Bootstrap and Foundation. Using leonardo-ui can speed up your UI development process, and keeps styles in sync with other Qlik Sense assets.

 

after-work.js

after-work.js is a unified testing framework capable of performing unit, component, integration, and end-to-end tests. It is the testing framework used by enigma.js and leonardo-ui.

 

Contributing

You can contribute to any of the Qlik open source projects. Each project has its own contribution guidelines, linked below.

Contributing to enigma.js

Contributing to leonardo-ui

Contributing to after-work.js

Jennell McIntire

Field Functions

Posted by Jennell McIntire Jan 13, 2017

There are several field functions that can be used in Qlik Sense and QlikView charts to return information about a field and/or selections in an app.  They are:

 

  1. GetSelectedCount
  2. GetAlternativeCount
  3. GetPossibleCount
  4. GetExcludedCount
  5. GetCurrentSelections
  6. GetFieldSelections

 

In this blog, let’s take a look at how each of these functions can be used in your chart expressions.

 

GetSelectedCount

getselectedcount(field_name [, include_excluded])

This function returns the number of selected (green) values in a field.

 

The GetSelectedCount of the Product Group field below will return 3 for the 3 selected (green) items.

GetSelectedCount 1.png

If the optional include_excluded parameter is set to True(), the returned count will include selected values which are currently being excluded by selections in other fields.  If it is False() or omitted, then these values will not be included in the count.  In the image below, the selection of Jam and Jelly in the Product Sub Group field has excluded Alcoholic Beverages and Baked Goods so they are now gray instead of green.  The GetSelectedCount function for the Product Group will now return 1.  If the include_excluded parameter is set to True(), then it will return 3, counting the excluded selections.

 

GetSelectedCount([Product Group]) = 1

GetSelectedCount([Product Group], True()) = 3

 

GetSelectedCount 2.png


GetAlternativeCount

getalternativecount(field_name)

This function returns the number of alternative (light gray) values in a field.

 

The GetAlternativeCount of the Region Name field below will return 3 for the light gray items in the field.

GetAlternativeCount.png

 

GetPossibleCount

getpossiblecount(field_name)

This function returns the number of possible values in the field.  If the field includes selections, then the selected items (green) are counted.  Otherwise associated (white) values are counted.

 

In the image below, the GetPossibleCount function for the Product Sub Group field will return 3 for the 3 associated (white) items in the list.

GetPossibleCount.png

If I were to select Muffins in the Product Sub Group field (see image below), then the GetPossibleCount function will return 1 for the selected item.

GetPossibleCount 1.png

 

GetExcludedCount

getexcludedcount(field_name)

This function returns the number of excluded (dark gray) values in the field.

 

In the image below, GetExcludedCount of the Product Line field would return 1 for Drink which is dark gray.

GetExcludedCount.png

 

GetCurrentSelections

getcurrentselections([record_sep [,tag_sep [,value_sep [,max_values]]]])

Unlike the other functions we have looked at so far, this function returns a string containing the current selections in an app.  The optional tag_sep parameter allows you to select the separator between the field name tag and the field values.  The default is a colon (:).  The optional value_sep parameter allows you to select the separator between the field values.  The default is a comma (,).  The optional max_values parameter allows you to set the maximum number of field values that can be individually listed.  The default is 6 and anything more than that is shown as 'x of y values'.

 

In the image below the GetCurrentSelections function will return the following:

 

Product Group: Beverages

Product Line: Drink

Product Sub Group: Juice, Soda

GetCurrentSelections.png

 

GetFieldSelections

getfieldselections(field_name [, value_sep [, max_values]])

This function also returns a string with the current selections for a field.  The optional value_sep parameter allows you to select the separator between the field values.  The default is a comma (,).  The optional max_values parameter allows you to set the maximum number of field values that can be individually listed.  The default is 6 and anything more than that is shown as 'x of y values'.

 

In the Product Sub Group filter pane above, Juice, Soda will be returned by the GetFieldSelections for the Product Sub Group field.

 

Field functions provide valuable information about selections in a field that can be used in an app to display information or help determine if another action needs to take place.  For instance, if more than one field value is selected, do something.  Try using a field function next time you are building an app to see how they work.

 

Thanks,

Jennell

Filter Blog

By date:
By tag: