Skip to Content
Author's profile photo Former Member

SAP Lumira Extension: Google Maps

This blog post is the first part of my entry for the 2014 Data Geek Challenge.

Edit Nov 18th, 2014: addedRobert Russell ‘s application with crime data at the end

Edit Nov 24th, 2014: integrated coding improvements suggested by Matt Lloyd and David Dalley

During my research for the Data Geek Challenge, I found out that the map options available within SAP Lumira are focused on country / region / city. However, for the analysis of Delays for Buses in Chicago, I wanted to go down to the street level. Therefore, I took this challenge as an opportunity to extend SAP Lumira with the Google Maps API.

Before I go any further, I need to thank Matt Lloyd and Manfred Schwarz for their very detailed blog posts on SAP Lumira Extensions, as well as the documentation, especially the debug part. I will assume you have read these articles prior to reading this exercise. Also, David Dalley made valuable contributions to the code through GitHub. Lastly, I only tested this script with SAP Lumira 1.20.

Fast Track


If you are interested in testing the Google Maps API Extension without the development phase, you can simply download the coding from GitHub. Click on “Download ZIP”. Extract the files and merge them in “C:\Program Files\SAP\Lumira\Desktop\extensions”. Don’t forget to restart your Lumira.

CostingGeek/LumiraGoogleMaps · GitHub


Here’s the expected result:

SAP_Lumira_Extension_Google_Maps_Result.png

Prerequisites:

You probably need to know a little about Google Maps API. There are actually 2 types: static or dynamic. Since we would like the end user to be able to move around in the map and zoom in / out, we’ll need to focus on the dynamic one. Here’s a very small example (created as a .html file):

<!DOCTYPE html>

<html>

<head>

  <title>Google Map Test</title>

  <style>html, body, #map-canvas { height: 100%; margin: 0px; padding: 0px; }</style>

  <script src=”https://maps.googleapis.com/maps/api/js?v=3.exp&language=en“></script>

  <script>

  function initialize() {

    var chicago = new google.maps.LatLng(41.850033,-87.6500523);

    var mapOptions = { zoom: 8, center: chicago };

    var map = new google.maps.Map(document.getElementById(‘map-canvas’), mapOptions);

  }

  </script>

</head>

<body onload = “javascript:initialize();”>

  <div id=”map-canvas”></div>

</body>

</html>

This example can be found here: http://www.costinggeek.com/data_geek_3/map_test.html

Picture_01.png

Locating the Chicago Cloud Gate using Google Maps API


Note the following:

  1. Line 6: <script src=”https://maps.googleapis.com/maps/api/js?v=3.exp&language=en“></script>
    This loads the script and should happen in the <head> section. This is not possible in Lumira because of the RequireJS infrastructure
  2. Line 18: <div id=”map-canvas”></div>
    By default, Lumira uses SVG elements instead of DIV, so keep this in mind.

More documentation on Google Maps APIs here:

Solving the Asynchronous Call

In the above Lumira extension examples, one can add a script in the render.js. However, RequireJS and Google Maps API are not compatible because of the order in which the scripts are called. The solution is to perform an asynchronous call to the Google Maps API. Thanks to Miller Medeiros, a Brazilian designer and developer, such a script is supported under the MIT license and can be downloaded here: https://github.com/millermedeiros/requirejs-plugins

Simply download the “src/async.js” script from GitHub and indicate in your coding where the file is located. This is done in the requires.config call. A typical coding example looks like this:

requirejs.config({

    baseUrl : ‘<your_base_url>’,

    paths: {

        ‘async’: ‘<folder_to_async_file>’

    }

});

require([‘async!https://maps.googleapis.com/maps/api/js?v=3.exp&language=en&sensor=false‘], function ( ) {

    // Some coding here

});

For the moment, place it in: C:\Program Files\SAP\Lumira\Desktop\utilities\VizPacker\libs\js

Preparing VizPacker

We now have most of the pieces of the puzzle. Start your VizPacker like in the articles above. This time, don’t forget to check the “Use DIV Container” flag. As detailed in the javascript warning, all code changes will be lost, so do this first!

Picture_02.png

Notice a DIV named “chart” inserted on the HTML tab:

<!– <<container –>

    <div id=”chart” style=”position: absolute; left:0px; right: 0px; top:0px; bottom:0px; background-color: #ffffff”></div>

<!– container>> –>

Be careful when setting the properties of your chart. For every “.” you use in the Chart Id, a sub-hierarchy will be created, that needs to be reproduced. In my example, the chart id is “com.costinggeek.googlemaps”, which is a 3-level hierarchy.

Picture_03.png

Sample Data

VizPacker has its own way of testing data. Prepare a CSV file with the following data:

“Latitude”,”Longitude”,”Description”,”Quantity”

“49.293523”,”8.641915″,”Building WDF 01″,1000

“49.294583”,”8.642838″,”Building WDF 02″,500

“49.292876”,”8.644190″,”Building WDF 03″,750

“49.294149”,”8.644115″,”Building WDF 04″,350

“49.292246”,”8.639973″,”Building WDF 05″,50

Then, on the Data Model tab, upload your data from that CSV file and start the mapping:

  • Assign dimension “Latitude” to Set 1,
  • Assign dimension “Longitude” to Set 1,
  • Assign dimension “Description” to Set 1,
  • Assign measure “Quantity” to Set 1,
  • Rename dimension Set 1 to “Latitude / Longitude / Desc”,
  • Rename measure Set 1 to “Quantity”,
  • Click on Apply and confirm the warning.

Configuring RequireJS

In the render.js, remove all sample coding between

// START: sample render code for a column chart

and

// END: sample render code

Remove this section since we won’t need any SVG component:

var vis = container.append(‘svg’).attr(‘width’, width).attr(‘height’, height)

.append(‘g’).attr(‘class’, ‘vis’).attr(‘width’, width).attr(‘height’, height);

Then, insert the following coding:

require.config({

    paths: {

        ‘com_costinggeek_googlemaps-async’: ‘sap/bi/bundles/com/costinggeek/googlemaps/com_costinggeek_googlemaps-src/js/async’

    }

});

// add DIV but make sure it’s done only once

var mapsContainer = container.select(‘div’);

if (!mapsContainer.node()) {

    mapsContainer = container.append(‘div’).attr(‘width’, ‘100%’).attr(‘height’, ‘100%’).attr(‘class’, ‘com_costinggeek_googlemaps-cg_map’);

}

// create asynchronous call to google maps api

require([‘com_costinggeek_googlemaps-async!https://maps.googleapis.com/maps/api/js?v=3.exp&language=en&sensor=false‘], function ( ) {

    // call google maps API after everything is loaded

    load_gmap();

});

// MDL: Get the name of the dimension columns from dimension group: Latitude / Longitude / Desc

var dimArr_latLongDesc = data.meta.dimensions(‘Latitude / Longitude / Desc’);

var dim_lattitude   = dimArr_latLongDesc[0];

var dim_longitude   = dimArr_latLongDesc[1];

var dim_description = dimArr_latLongDesc[2];

// MDL: end

// MDL: Get the name of the measure column from the measure group: Quantity

var msrArr_Qty = data.meta.measures(‘Quantity’);

var msr_Quantity = msrArr_Qty[0];

// MDL: end

// set global variable accessible by all sub-functions

var my_map;

var my_LatLng;

var my_LatLngBounds;

// function to show popup when markers are clicked

function attach_details( my_marker, my_description, my_quantity ) {

    var infowindow = new google.maps.InfoWindow(

    {

content: ‘<div class=”com_costinggeek_googlemaps-infoWindow”><strong>’ + my_description + ‘: </strong> ‘ + my_quantity + ‘</div>’

    });

    google.maps.event.addListener( my_marker, ‘click’, function() {

infowindow.open( my_map, my_marker );

    });

}

// function to place a marker on the map

function add_marker_lat_long( my_description, my_lat, my_long, my_quantity ) {

    my_LatLng = new google.maps.LatLng( my_lat, my_long );

    my_LatLngBounds.extend( my_LatLng );

    var my_marker = new google.maps.Marker({

map:  my_map,

position:     my_LatLng,

//icon:       icon_shop,

title:my_description,

status:     ‘active’

    });

    attach_details( my_marker, my_description, my_quantity );

}

// initialize the google map

function load_gmap( ) {

    my_LatLngBounds = new google.maps.LatLngBounds();

    var my_center = new google.maps.LatLng( 49.2933, 8.6419 );

    var mapOptions = {

        mapTypeId: google.maps.MapTypeId.ROADMAP,

        center:    my_center,

        zoom:10

    };

    my_map = new google.maps.Map(mapsContainer.node(),

        mapOptions);

    // convert all data to markers

    var j = 0;

    for ( var i = 0; i < data.length; i++ )

    {

        // MDL: Updated to use column names from data set.

        if( data[i][dim_lattitude] != undefined && data[i][dim_longitude] != undefined )

        // MDL: end

        {

            // MDL: Updated to use column names from data set.

            add_marker_lat_long( data[i][dim_description], data[i][dim_lattitude],  data[i][dim_longitude], data[i][msr_Quantity] );

            // MDL: end

            j++;

        }

    }

    // Auto center the map based on given markers

    if( j > 0 )

    {

        my_map.fitBounds(    my_LatLngBounds );

        my_map.panToBounds( my_LatLngBounds );

    }

}

Styling

On the style.css tab, replace the whole content with your preferred options. For instance:

.com_costinggeek_googlemaps-cg_map{

    border: solid 1px black;

    width:  100%;

    height: 100%;

}

.com_costinggeek_googlemaps-infoWindow {

    width:   250px;

    padding:  10px;

}

Testing in VizPacker

Once all the coding is in place, you just need to open the preview window and click the “Run Code” button to let the magic happen:

Picture_04.png

Testing in Lumira

Now that your script is ready in VizPacker, it is time for its final test in Lumira. Click on the “PACK” button and extract your files to your Lumira extension folder, typically “C:\Program Files\SAP\Lumira\Desktop\extensions”. Your folder hierarchy should look close to this picture.

Picture_05.png

Then, copy your “async.js” file into the “js” folder, so it is alongside the “render.js” file. Based on Manfred Schwarz’s research, we also know that some changes have to be made in render.js. Located the require.config section and update the path as follows (beware typos):

require.config({

    paths: {

    ‘async’: ‘sap/bi/bundles/com/costinggeek/googlemaps/com_costinggeek_googlemaps-src/js/async’

    }

});

Start Lumira (restart if it was open) and create a new dataset with the sample CSV file. In the Prepare section, remove all measures, except “Quantity”. In Dimensions, click on the gear icon next to Latitude and choose “Display Formatting”. Make sure the number of decimals is set to 6 (by default, Lumira truncates to 2 decimals and you would end up with only one marker). In Visualize, select your new extension. As Dimensions, select “Latitude”, “Longitude”, and “Description”. As Measure, select “Quantity”.

Picture_06.pngPicture_07.png

Here is the final result:

SAP_Lumira_Extension_Google_Maps_Result.png


Conclusion

I hope you were able to follow this process to extend your SAP Lumira with Google Maps. Do not hesitate to ask your questions in the comments section below. If this was useful, let us know what you did with it!

Update 11/18/14: Thanks to Robert Russell for sharing his application with crime data:

Assigned Tags

      49 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ina Felsheim
      Ina Felsheim

      Thanks for the blog on a very popular topic!

      Author's profile photo Manfred Schwarz
      Manfred Schwarz

      Hi Julien,

      Nice post - i am looking forward to try your Lumira googlemaps visualization edition!

      Author's profile photo Ty Miller
      Ty Miller

      Capital! Just tried it and it worked no problem. Love the creativity Julien!

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Hi Ty,

      Thanks for giving it a try. I'm thrilled it worked!

      Thanks to Matt Lloyd, I have updated the coding (marked MDL) so we can use dimensions and measures with different names. Also, he gave me a trick for the decimals so the markers are placed more accurately. Compare the screenshot in VizPacker (original) with the one in Lumira (updated).

      The coding in GitHub has also been updated with these changes.

      Author's profile photo Ty Miller
      Ty Miller

      Cool. I know David Dalley has some feedback on how you might want to update to support multiple maps on one board. Let's see if he responds 😉

      Author's profile photo Former Member
      Former Member

      Looks great, Julien! I made a pull request in github with a couple of suggested changes, one of which allows multiple maps to coexist in a story.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Great! I'm happy I used GitHub,

      everybody will benefit from this new and improved version ... 😉

      Thanks, David!

      Author's profile photo Former Member
      Former Member

      Thank you Julien for sharing this step-by-step guide.

      Can this be done with on-premise GIS server, like ArcGIS? Thoughts, anyone?

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Hi Leonardi,

      I'm not an expert in ArcGIS, but from what I saw on their website, I believe you don't need Lumira to reproduce what I just did.

      What visualization are you trying to reproduce?

      Author's profile photo Former Member
      Former Member

      Awesome!!! Thanks for sharing. Just a disclaimer, google maps usage in a corporate environment might require licenses.

      I'd love to see a way to create "layers" of markers depending on a dimension, some way to hide/show etc. Do you think that's possible?

      Another question is, can we say it would also work in "Lumira Server" ?

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      You are absolutely right about the licenses. Here are the details:

      https://developers.google.com/maps/licensing

      Looks like the license fees are very reasonable (about 50¢ per 1,000 map loads):

      Google Geo Developers Blog: Lower pricing and simplified limits with the Google Maps API

      About the Lumira Server, I'm not 100% sure since I don't have access to one, but my guess would be yes. However, I believe extensions don't work on the Lumira Cloud. Can Matt Lloyd or Harleen Kaur or Ty Miller confirm?

      My plan is to use layers for my data geek entry in 2 weeks. Stay tuned ;o)

      Author's profile photo Ty Miller
      Ty Miller

      Yes, CVOM extensions, like this one, are supported with Lumira Server. Not on Lumira Cloud. Yet...

      Author's profile photo Former Member
      Former Member

      I'm dreaming about a world, in which the viz extensions would be automatically published with the stories, no IT involved at all 🙂

      Author's profile photo Ty Miller
      Ty Miller

      Agreed that we need a simpler deployment mechanism. Don't have an answer right now, but the need is noted.

      Author's profile photo Brian Thomas
      Brian Thomas

      Great post....
      Thanks!  I always wondered if this was possible! 🙂

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Now you know 😆

      Author's profile photo Robert Russell
      Robert Russell

      Hi Julien,

      I like it, thanks for sharing. It actually allows lat/lon mapping from HANA as well, which I found impossible with standard maps in the free version of Lumira.

      Thanks

      Robert

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Even better 🙂 Thanks for the feedback!

      Author's profile photo Former Member
      Former Member

      This is way too cool. Thanks for sharing Julien.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Appreciate your feedback ;o)

      Author's profile photo Former Member
      Former Member

      Very good post. Thanks for sharing.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Thanks

      Author's profile photo Hari Srinivasa Reddy
      Hari Srinivasa Reddy

      This is awesome Julien. Thanks for sharing.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Pleasure

      Author's profile photo Amit Gupta
      Amit Gupta

      Great job Julien! very nicely explained. I am going to try for sure.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Let us know what you were able to achieve.

      Author's profile photo Former Member
      Former Member

      Hello Julien

      Like it very much., i Just made one for the country of Honduras. But how can I make so i can graph information on top of the google map ? for example a pie chart in the latitude/longitude ?

      Regards

      Hector

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Thanks for your feedback.

      In order to show more information on your map, you need to adapt the javascript.

      Some examples can be found online, like this one:

      http://stackoverflow.com/questions/17502438/pie-chart-on-google-map

      Good luck

      Author's profile photo Former Member
      Former Member

      Julien,

      Awesome work !!!!

      Author's profile photo Former Member
      Former Member

      Hi Julien/Anyone,

      I have tried this step by step , but im getting only the barchart in the vizpacker... im new to sdk . could you please help me out...

      Author's profile photo Daniel Davis
      Daniel Davis

      Is this feature still working in 1.22 for everybody? I've recently upgraded, applied changes back to the ini file and the Google map is just black white in any new or existing visualisations 🙁

      Any ideas ?

      Thanks and regards Daniel

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      I'll upgrade, retest and let you know.

      Thanks for raised the issue.

      Julien

      Author's profile photo Imoette Akpan
      Imoette Akpan

      Hi Julien,

      Love the extension, but I'm also getting blank spaces when I attempt to use it on Lumira 1.22. Where could I find the upgraded extension?

      Thanks and Best Regards,

      Imoette

      Author's profile photo Daniel Davis
      Daniel Davis

      I can confirm - worked Pre 1.22 and White screen of White 🙂 from 1.22 onwards

      Author's profile photo Former Member
      Former Member

      Hi everyone

      Thanks a lot for this really interesting topic. We are just facing a problem : Doing your procedure works with a SAP Lumira 1.22 and windows 7 version. Point is it doesn't work with a SAP Lumira 1.23 and windows 7, nor a SAP Lumira 1.22 and windows 8 OS. So it is quite hard to tell whether it could be a js problem or a lumira compatibility.

      Did anyone ever face that problem too ?

      Regards

      Karim

      Author's profile photo Henry Banks
      Henry Banks

      Hi,

      i got a notification from GitHub on 5th March for all the published extensions. Here's 1 example:

      Update profile to be compatible with Lumira 1.23 by geogezw · Pull Request #7 · SAP/lumira-extension-viz · GitHub

      the info reads:

      From Lumira 1.23, VizPacker added a key "bindings" when calling createViz(), but this key does not exist in previous Lumira versions. It will cause the profile failing to load in Lumira 1.23. The fix is added a line of "var bindings = {}" in HTML section of profile

      Does that apply to this example?

      regards,

      H

      Author's profile photo Former Member
      Former Member

      Hi Henry,

      We tried that on the 1.23 version but unfortunately it didn't work. Nevertheless, we also got a problem on the SAP Lumira 1.22 version with a windows 8 system. Just a grey screen is displaying. The extension can be launch though (see below)/wp-content/uploads/2015/03/2015_03_18_17_40_46_667221.png

      Thanks for your reply

      Karim

      Author's profile photo Paul Ekeland
      Paul Ekeland

      I had this issue as well, but it turned out lat/long dimensions need to be of string type and not numbers. That solved it for me.

      Author's profile photo Robert Russell
      Robert Russell

      Hi,

      I think from my experience with 1.23 it is a clash of extensions with require.js or caching issue.

      When I load one of my own extensions first and then use Julien's google maps it does not open.

      notworking.PNG

      When I put back my options in the SAPLumira.ini file which 1.23 install had kindly removed.

      -Dhilo.cef.frame.debug=true

      -Dhilo.cef.cache.enabled=false

      Restarted and loaded the google maps extension FIRST thing it works.

      working.PNG

      Although I can no longer open my own extensions 🙁 .

      So I think the require.js only works with the first loaded extension or the cache is not clearing correctly.

      Anyway I would be interested if the above steps work for anyone else.

      Cheers

      Robert

      Author's profile photo Christoph Pahlke-Lerch
      Christoph Pahlke-Lerch

      Hi Julien,

      I'm trying out the Google Maps extension. Installation went smooth and the map shows up :-). However, I have a query view on HANA that provides latitude and longitude with reasonable values. Currently no pins with the locations are shown. Any idea why the locations are not showing up? I'm interested in the Google Maps extension since the ESRI map currently does not support locations with latitude and longitude when running with HANA.

      Best Regards, Christoph

      Author's profile photo Former Member
      Former Member

      Hello Jullien,

      Thanks for sharing your hard work and innovative approach with the communitiy.

      I was wondering if this can be utilized with Australian Map as even after providing correct longitudes /Latitude I couldn't get through to correct map.

      Appreciate your feedback ,thanks.

      Author's profile photo Former Member
      Former Member

      Hi Julian,

      Thanks you so much for sharing this information with us. It is very helpful.

      I am on version 1.25. When I am using the zip file which is there on github. I get blank screen.

      Lumira error 1.JPG

      So then I decided to follow step by step guide. When I am doing that I am getting below error.

      Lumia Error 2.JPG

      I have been trying to solve this issue from last three days. I am very new to this. Can you please help ?

      Thank,

      Happy

      Author's profile photo Pitiwat Bumrungkit
      Pitiwat Bumrungkit

      Hi Julien Delvat

      I have some problem after I composed google map extension in Lumira then I want to export to PDF but google map not show in file but another thing like cross tab table or Bar Chart are find.

      Please help,

      Thank in advance.

      Author's profile photo Jee Hye Yang
      Jee Hye Yang

      Hello,

      I’ve
      downloaded zip file from
      https://github.com/CostingGeek/LumiraGoogleMaps.

      and Lumira 1.27 from menu, click Extension, Click Manual installation, select LumiraGoogleMaps-master.zip.

      I got the error says “The extension is not
      valid and could not be installed”

      What's wrong with me ? Any advice would be very appreciated. Many Thanks. JH

      Author's profile photo Former Member
      Former Member

      Hi Jee,

      I have tried doing the same way and it wont work. The way it worked for me was. I had to extract the folder in extension folder.

      see attached snapshot for better understanding. Capture.JPG

      Author's profile photo Meng Wang
      Meng Wang

      Hi Julien,

      The component works fine with me on Lumira 1.27.

      One question, when i save the lumira document on BI Platform, how to make the customized component also be available on BI Platform?

      Now what i get is"Cannot display this chart, extention with id ..... is missing."

      Best Regards.

      Meng

      Author's profile photo Ty Miller
      Ty Miller

      Extensions aren't supported yet on Lumira Server for BI Platform. Coming soon.

      Author's profile photo Rahul Tiwari
      Rahul Tiwari

      It's available since 1.29 release on platform

      Author's profile photo Former Member
      Former Member

      One important note for using this extension (any google maps extension for that matter) is you will need some additional licensing for Google Maps for Work once you get past the development / testing phase.

      There is an officially supported Google Maps extension for SAP Lumira now with CMaps Analytics on the SAP extension gallery: https://analytics-extensions.enter.sap/sap/aed/ui/?keywords=CMaps%20Analytics


      In the extension library there are also non- Google Maps extensions too.