1 Reply Latest reply on Dec 8, 2016 11:41 AM by Patrick A Van Der Hyde

    Feed Tableau data using getData() into D3 chart

    Stephen Harle

      Does anyone have any suggestions for formatting and feeding underlying data using Tableau's getData() function into this D3 Doughnut Chart?

      The underlying data is in this JSON format:

       

       

      [
        
      {
        
      "value":"Thais Sissman",
        
      "formattedValue":"Thais Sissman"
        
      },
        
      {
        
      "value":"-0.6860335195530726",
        
      "formattedValue":"-68.6%"
        
      },
        
      {
        
      "value":"-3.3156",
        
      "formattedValue":"($3)"
        
      },
        
      {
        
      "value":"793",
        
      "formattedValue":"793"
        
      },
        
      {
        
      "value":"4.833000000000001",
        
      "formattedValue":"$5"
        
      }
      ]

       

       

      I would like to use the first Name value column and an additional numerical value from the array to place into the pie.  Below is my JavaScript:

       

       

      $(document).ready(function initViz() {
      var containerDiv = document.getElementById("vizContainer"),
        url
      = "https://SERVER-NAME/t/gfm/views/Superstore/Customers?:embed=y&:showShareOptions=true&:display_count=no&:showVizHome=no",
        options
      = {
        hideTabs
      : true,
        hideToolbar
      : true,
        onFirstInteractive
      : function () {
        document
      .getElementById('getData').disabled = false; // Enable our button
        
      }
        
      };
        viz
      = new tableau.Viz(containerDiv, url, options);
        
      });

      //when viz is loaded (onFirstInteractive), request data
      function getSummaryData() {
        options
      = {
        maxRows
      : 0, // Max rows to return. Use 0 to return all rows
        ignoreAliases
      : false,
        ignoreSelection
      : true,
        includeAllColumns
      : false
      };

      sheet
      = viz.getWorkbook().getActiveSheet();

      //if active tab is a worksheet, get data from that sheet
      if (sheet.getSheetType() === 'worksheet') {
        sheet
      .getSummaryDataAsync(options).then(function (t) {
        buildMenu
      (t);
      });

      //if active sheet is a dashboard get data from a specified sheet
      }   else {
        worksheetArray
      = viz.getWorkbook().getActiveSheet().getWorksheets();
        
      for (var i = 0; i < worksheetArray.length; i++) {
        worksheet
      = worksheetArray[i];
        sheetName
      = worksheet.getName();
        
      if (sheetName == 'CustomerRank') {
        worksheetArray
      [i].getSummaryDataAsync(options).then(function (t) {
        
      var data = t.getData(); 
        
      var columns = t.getColumns();
        table
      = t;
        
      var tgt = document.getElementById("dataTarget");
        tgt
      .innerHTML = "<h4>Underlying Data:</h4><p>" + JSON.stringify(table.getData()) + "</p>";
        buildVisual
      (t);
        
      });
        
      }
        
      }
        
      }
      }

      function buildVisual(table) {

      //the data returned from the tableau API
      var columns = table.getColumns();
      var data = table.getData();

      //convert to field:values convention
      function reduceToObjects(cols,data) {
        
      var fieldNameMap = $.map(cols, function(col) { return col.getFieldName(); });
        
      var dataToReturn = $.map(data, function(d) {
        
      return d.reduce(function(memo, value, idx) {
        memo
      [fieldNameMap[idx]] = value.value; return memo;
        
      }, {});
        
      });

        
      return dataToReturn;
      }

      var niceData = reduceToObjects(columns, data);

      var svg = d3.select('body')
       
      .append('svg')
       
      .attr('width', 400)
       
      .attr('height', 200)
       
      .attr('id', 'chart');

      // add an SVG group element for each user
      var series = svg.selectAll('g.series')
       
      .data(d3.keys(dataTarget))
       
      .enter()
       
      .append('g')
       
      .attr('class', 'series');

      var width = 300,
        height
      = 300,
        radius
      = Math.min(width, height) / 2;

      var color = d3.scale.category20();

      var pie = d3.layout.pie()
        
      .sort(null);

      var piedata = pie(niceData.data);

      var arc = d3.svg.arc()
        
      .innerRadius(radius - 100)
        
      .outerRadius(radius - 50);

      var svg = d3.select("body").append("svg")
        
      .attr("width", width)
        
      .attr("height", height)
        
      .append("g")
        
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

      var path = svg.selectAll("path")
        
      .data(piedata)
        
      .enter().append("path")
        
      .attr("fill", function(d, i) { return color(i); })
        
      .attr("d", arc);

      svg
      .selectAll("text").data(piedata)
        
      .enter()
        
      .append("text")
        
      .attr("text-anchor", "middle")
        
      .attr("x", function(d) {
        
      var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
        d
      .cx = Math.cos(a) * (radius - 75);
        
      return d.x = Math.cos(a) * (radius - 20);
        
      })
        
      .attr("y", function(d) {
        
      var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
        d
      .cy = Math.sin(a) * (radius - 75);
        
      return d.y = Math.sin(a) * (radius - 20);
        
      })
        
      .text(function(d) { return d.value; })
        
      .each(function(d) {
        
      var bbox = this.getBBox();
        d
      .sx = d.x - bbox.width/2 - 2;
        d
      .ox = d.x + bbox.width/2 + 2;
        d
      .sy = d.oy = d.y + 5;
        
      });

      svg
      .append("defs").append("marker")
        
      .attr("id", "circ")
        
      .attr("markerWidth", 6)
        
      .attr("markerHeight", 6)
        
      .attr("refX", 3)
        
      .attr("refY", 3)
        
      .append("circle")
        
      .attr("cx", 3)
        
      .attr("cy", 3)
        
      .attr("r", 3);

      svg
      .selectAll("path.pointer").data(piedata).enter()
        
      .append("path")
        
      .attr("class", "pointer")
        
      .style("fill", "none")
        
      .style("stroke", "black")
        
      .attr("marker-end", "url(#circ)")
        
      .attr("d", function(d) {
        
      if(d.cx > d.ox) {
        
      return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy;
        
      } else {
        
      return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy;
        
      }
        
      });
      }