Sunday, September 24, 2017

User-Generated Batch Printing in Tableau with JavaScript

I love using Tableau to publish interactive data visuals, but if you publish Tableau visuals in a workplace, sooner or later you're going to get a request for batch-printing.

If you have Tableau server, this can be done using tabcmd, but it requires work by the BI team for each request. It's okay for a few one-off requests, but if you have hundreds of users who want on-demand or customizable batch-printing, it's not a great solution. Instead, we can allow the user to do their own batch printing using JavaScript.

The basic plan is:
  1. Make a URL that generates Tableau dashboard PDFs
  2. Make a dashboard that can be filtered to a list of the URLs
  3. Use the JavaScript API to get the list of URLs
  4. Use JavaScript to batch-download the dashboard PDFs
If you'd like to skip the tutorial, here's a working html file that contains the code and you can skip to the bottom for a demonstration. Even if you read the tutorial, the html file is useful to see all the code in the right order, and the JavaScript libraries used.

Step 1: Make a URL that generates Tableau dashboard PDFs

Tableau will generate a pdf of a dashboard view if you include ".pdf" at the end of the workbook name in the url. Tableau can also receive filter values as url parameters, which will allow the user to customize the view. Andy Kriebel has a nice blog post on url parameters here. Andy's post generates PNG files, but PDF is the same concept.

In my case, I created a one-page of home price data by major US city, using Zillow data. Here's an example using my city:

The url to create this pdf is:

https://public.tableau.com/views/HomePriceOneSheet_0/HomePriceProfile.pdf?:showVizHome=no&CityState=AtlantaGA

To switch to a pdf of Chicago, and change the time comparison to five years:

https://public.tableau.com/views/HomePriceOneSheet_0/HomePriceProfile.pdf?:showVizHome=no&CityState=ChicagoIL&TimeComparison=FiveYear

Once you have your URL, make a calculated field in Tableau that generates the URL, given the user selection. In my case:

Step 2: Make a dashboard that can be filtered to a list of URLs

Make a worksheet that contains only the URL variable and your filter variables:

"Time Comparison" doesn't appear in my filter list because it's a parameter. Next, make this pretty by putting the worksheet on a small dashboard with filters showing and the URL list hidden.



Step 3: Use the JavaScript API to get the list of URLs

I adapted this code from Tableau's github page on the getData() functions. First, we initialize the visual:
var viz, sheet, table;  
function initViz() {  
     var containerDiv = document.getElementById("vizContainer"),  
          url = "https://public.tableau.com/views/HomePriceOneSheet_0/BatchPrint", 
          //replace with your tableau url  
          options = {  
               hideTabs: true,  
               hideToolbar: true,  
               onFirstInteractive: function() {  
                    document.getElementById('getData').disabled = false;  
          }};  
     viz = new tableau.Viz(containerDiv, url, options);  
 }  
Next, we use the getSummaryData() function to get the urls and reshape the data array. This command will be called in our html from a button click (below), after the user has made their selection in the Tableau visual.
function getSummaryData() {  
      sheet = viz.getWorkbook().getActiveSheet().getWorksheets().get("URLs");   
      //replace "URLs" with the name of your worksheet containing the URLs  
      options = {  
           maxRows: 0, // Max rows to return. Use 0 to return all rows  
           ignoreAliases: false,  
           ignoreSelection: true,  
      };  
      sheet.getSummaryDataAsync(options).then(function(t) {  
           table = t;  
           var tgt = document.getElementById("dataTarget");                      
           var data = table.getData()  
           var value_array = new Array();  
           //reshape array to fit download code  
           for (var i=0;i<data.length;i++){  
           value_array[i] = new Array (data[i][0].value);  
           }  
           //call download function from above  
           downloadAll( value_array )  
      });}  
Step 4: Use JavaScript to batch-download the dashboard PDFs

The last function in the above code, downloadAll() has not been defined. This function loops through the urls and downloads each pdf. I adapted downloadAll() from this code. Unfortunately this code only works in Chrome; other browsers will just show a single PDF.
function downloadAll(files){  
      if(files.length == 0) return;  
      file = files.pop();  
      var theAnchor = $('<a />')  
           .attr('href', file[0])  
           .attr('download',file[0])  
           .appendTo('body');  
      theAnchor[0].click();   
      theAnchor.remove();  
      downloadAll(files);  
      }  
Last, we use html to call our JavaScript functions:
<body onload="initViz();">  
      <div id="vizContainer" style="width:100%; height:300px;"></div>  
   <div class="page-header">  
     <button id="getData" onclick="getSummaryData()" class="btn" disabled>Get Reports</button>  
   </div>  
      <div id="dataTarget"></div>  
 </body>  
Here's the code in action below. The files might take a few seconds to download because the Tableau Public server has to generate each one.

Home Price Profile by City: Batch Printing


A great next step for this project is to get the multiple file download to work in browsers other than Chrome. 

It would also be helpful to rename the PDF after the city instead of the dashboard name. However, JavaScript can't rename an external file, so this would require downloading the PDF to a web server, renaming, and then downloading to the client.

Another next step is to stitch together the pdfs. This also can't be done in JavaScript and would require an intermediate download to a web server.

Let me know in the comments if you use this code, or let me know on twitter.

22 comments:

  1. This plan will be only work if you read the tutorial, the html file is useful to see all the code in the right order, and the JavaScript libraries used.
    http://www.typingservice.org/convert-image-text-to-word-file-or-excel-file/

    ReplyDelete
  2. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a Front end developer learn from Javascript Training in Chennai . or learn thru JavaScript Online Training India. Nowadays JavaScript has tons of job opportunities on various vertical industry.

    ReplyDelete
  3. A visual originator should set up the format and illustrations for the first information sheet layout.Vslprint.com

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. I found so many interesting stuff in your blog especially its discussion. Really its great article. Keep it up. 55printed

    ReplyDelete
  6. Thanks for the great tutorial, I can't wait to get home and try it out! Perhaps this will make my life with reviews of online proofreading service which is http://essayguard.com/services/editing a bit better. Cuz you know it's getting boring.

    ReplyDelete
  7. Nice post! This is a very nice blog that I will definitively come back to more times this year! Thanks for informative post.
    box file

    ReplyDelete
  8. Often with tee shirt transfers there is a a yellowish hue around the printing. This is caused by the coating on the transfer paper that bonds the ink to the shirt. gifts for companies

    ReplyDelete
  9. I'm impressed, I must say. Very rarely do I come across a blog thats both informative and entertaining, and let me tell you, you ve hit the nail on the head. Your blog is important.. drukowanie 3d

    ReplyDelete
  10. Despite the sort or innovation that is utilized, the most vital thing to search for in a photograph printer is photorealistic quality. Everything else is optional.wydruki 3d

    ReplyDelete
  11. Apple has released iOS 12 beta for developers. You can download latest iOS 12 beta for your iPhone and iPad right now, using our direct links service. Get your device a working iOS 12 beta right now.

    ReplyDelete
  12. It can likewise be fundamentally more affordable for people or little runs on account of the low set cost for ink, paper and expert printing.3d printer reviews guide

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete
  14. nice blog thank for posting such useful information
    broadcast printinghope you will share more post in future.

    ReplyDelete
  15. Some pro printing firms are likewise ready to offer additional wide printing administrations for vast scale outside applications, for example, promoting announcements, hoardings and building wraps.postcards printing

    ReplyDelete
  16. Business card printing can say a thousand words about who you are. A well-designed business card has the capability to attract customers to your business with minimal expenses attached. You can add style by selecting a great layout for your business card and in return, you can expect additional customers. The best part is it's quite easy to design an aesthetically pleasing business card. Leeds Printing

    ReplyDelete
  17. "One of the first producers of exaggerated postcards was William H. Martin, of Ottawa, Kansas. Martin's photography studio began experimenting with trick photography around 1908. His work featured huge ears of corn and peaches, a giant rabbit being tracked by a car, and pumpkins uprooting a farmstead. He was so successful that he established the Martin Post Card Company in 1909, and reportedly produced seven million exaggerated postcards the next year."
    postcards printing

    ReplyDelete
  18. I admire this article for the well-researched content and excellent wording. I got so involved in this material that I couldn’t stop reading. I am impressed with your work and skill. Thank you so much.
    HTML Training in Chennai

    ReplyDelete
  19. It is imperative that we read blog post very carefully. I am already done it and find that this post is really amazing. cheap every door direct mail flyer printing

    ReplyDelete
  20. https://public.tableau.com/views/BatchPrint/BatchPrint

    this is my tableau public url
    but i'm enable to get pdf links

    i got the error in getSummaryData()

    ReplyDelete
  21. With advanced designing softwares, the art of graphic designing evolved into a new. Since decades t-shirt printers have depended on printing for creating fabulous styles and trends that lived over generations. cheap 3d printer

    ReplyDelete
  22. Video is almost instantly perceived as content. As a result people are more likely to think it's more valuable to pay attention to than simple text is. Letter Printing Direct Mail Service

    ReplyDelete