Search code examples
javascriptgoogle-visualizationgooglevis

Google Charts bar/column chart getColumnRange() unexpected value from DataView


I'm trying to get the min and max value of a Dataview with the help of getColumnRange(). Unfortunately the values I get are not the ones I'd expect. Can someone advise me how I can get the correct values? The value I'd expect as max is 331M (the highest bar on the bar chart), but I get 8,5M. I tried to better my understanding of the DataView object with console.log(), however that didn't quite help me (line 65-71)

https://jsfiddle.net/zhp5rny6/3/

  var data = new google.visualization.DataTable({
cols: [
{id:"","label":"Products","pattern":"","type":"string"},
{id:"","label":"Manila","pattern":"","type":"number"},
{id:"","label":"Bangkok","pattern":"","type":"number"},
{id:"","label":"New York","pattern":"","type":"number"},
{id:"","label":"Sydney","pattern":"","type":"number"}],

rows:[
{c:[{v:"Glasses"},{v:-1270.7287},{v:-4486.0961},{v:-1019.4662},{v:3763827.8335}]},
{c:[{v:"Joysticks"},{v:145543.985},{v:2108039.5802},{v:266392.5277},{v:6006566.18690001}]},
{c:[{v:"Laptops"},{v:1723781.2686},{v:4435404.56789999},{v:7060065.3164},{v:17514581.1763}]},
{c:[{v:"PS4"},{v:78002243.0557997},{v:47591320.6768999},{v:43832560.9528002},{v:161580254.021496}]},
{c:[{v:"XBOX One"},{v:10507117.0145001},{v:8059953.41120002},{v:14103816.4604002},{v:34676509.4036004}]},
{c:[{v:"Smartphones"},{v:2373067.7893},{v:-53954.2187},{v:30783391.8722},{v:37288122.5537999}]},
{c:[{v:"Chairs"},{v:86583.2876},{v:71082.0195},{v:79813.2918},{v:22959813.0499999}]},
{c:[{v:"CPU"},{v:12479599.4709999},{v:22650137.9890997},{v:17562381.7794999},{v:25589299.8099997}]},
{c:[{v:"RAM"},{v:null},{v:-59.1},{v:282.7517},{v:1461239.6186}]},
{c:[{v:"Table"},{v:-566.5377},{v:-217.3444},{v:-865.114},{v:356870.886599999}]},
{c:[{v:"Water"},{v:870883.521900001},{v:1128581.9856},{v:1177332.008},{v:3922057.50240001}]}]
});

  var formatter = new google.visualization.NumberFormat({
    pattern: 'short'
  });

    for (var i = 1; i < data.getNumberOfColumns(); i++) {
    formatter.format(data, i);
    }

    var view = getDataView(data);

  function getDataView(dataTable) {
    var dataView;
    var viewColumns = [];

    for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
      addViewColumn(i);
    }

    function addViewColumn(index) {
        viewColumns.push(index);
        if(index == (dataTable.getNumberOfColumns() - 1)) {
            viewColumns.push({
            calc: function (dt, row) {
                for(var e = 0; e < dt.getNumberOfRows(); e++) {
                    var value = 0;
                    for(var u = 1; u < dt.getNumberOfColumns(); u++) {
                        value += dt.getValue(row, u);
                    }
                    return formatter.formatValue(value).toString();
                }
                },
            type: 'string',
            role: 'annotation',
            });
        }
    }

    dataView = new google.visualization.DataView(dataTable);
    dataView.setColumns(viewColumns);
    for(var z = 0; z < dataView.getNumberOfColumns(); z++) {
        console.log(JSON.stringify(dataView.getColumnRange(z)));
    }

    console.log(JSON.stringify(dataView.getViewColumns()));
    console.log(JSON.stringify(viewColumns));
    return dataView;
  }

Solution

  • the reason you get "8.5M" instead of "331M" is because the column type = 'string'

    alphabetically, "8.5M" is greater than "331M"

    to correct this issue, use a column type of 'number'.
    when building the data view annotation column,
    and return an object with both the value (v:) and formatted value (f:).

      viewColumns.push({
        calc: function (dt, row) {
          for(var e = 0; e < dt.getNumberOfRows(); e++) {
            var value = 0;
            for(var u = 1; u < dt.getNumberOfColumns(); u++) {
              value += dt.getValue(row, u);
            }
            return {  // <-- return object here
              v: value,
              f: formatter.formatValue(value)
            };
          }
          },
        type: 'number',  // <-- change to number
        role: 'annotation',
      });
    

    see following working snippet...

    google.charts.load("44", {packages:['corechart']});
    google.charts.setOnLoadCallback(drawChart);
    
    function drawChart() {
      var data = new google.visualization.DataTable({
    cols: [
    {id:"","label":"Products","pattern":"","type":"string"},
    {id:"","label":"Manila","pattern":"","type":"number"},
    {id:"","label":"Bangkok","pattern":"","type":"number"},
    {id:"","label":"New York","pattern":"","type":"number"},
    {id:"","label":"Sydney","pattern":"","type":"number"}],
    
    rows:[
    {c:[{v:"Glasses"},{v:-1270.7287},{v:-4486.0961},{v:-1019.4662},{v:3763827.8335}]},
    {c:[{v:"Joysticks"},{v:145543.985},{v:2108039.5802},{v:266392.5277},{v:6006566.18690001}]},
    {c:[{v:"Laptops"},{v:1723781.2686},{v:4435404.56789999},{v:7060065.3164},{v:17514581.1763}]},
    {c:[{v:"PS4"},{v:78002243.0557997},{v:47591320.6768999},{v:43832560.9528002},{v:161580254.021496}]},
    {c:[{v:"XBOX One"},{v:10507117.0145001},{v:8059953.41120002},{v:14103816.4604002},{v:34676509.4036004}]},
    {c:[{v:"Smartphones"},{v:2373067.7893},{v:-53954.2187},{v:30783391.8722},{v:37288122.5537999}]},
    {c:[{v:"Chairs"},{v:86583.2876},{v:71082.0195},{v:79813.2918},{v:22959813.0499999}]},
    {c:[{v:"CPU"},{v:12479599.4709999},{v:22650137.9890997},{v:17562381.7794999},{v:25589299.8099997}]},
    {c:[{v:"RAM"},{v:null},{v:-59.1},{v:282.7517},{v:1461239.6186}]},
    {c:[{v:"Table"},{v:-566.5377},{v:-217.3444},{v:-865.114},{v:356870.886599999}]},
    {c:[{v:"Water"},{v:870883.521900001},{v:1128581.9856},{v:1177332.008},{v:3922057.50240001}]}]
    });
    
      var formatter = new google.visualization.NumberFormat({
        pattern: 'short'
      });
    
      for (var i = 1; i < data.getNumberOfColumns(); i++) {
      formatter.format(data, i);
      }
    
      var view = getDataView(data);
    
      function getDataView(dataTable) {
        var dataView;
        var viewColumns = [];
    
        for (var i = 0; i < dataTable.getNumberOfColumns(); i++) {
          addViewColumn(i);
        }
    
        function addViewColumn(index) {
        viewColumns.push(index);
        if(index == (dataTable.getNumberOfColumns() - 1)) {
          viewColumns.push({
            calc: function (dt, row) {
              for(var e = 0; e < dt.getNumberOfRows(); e++) {
                var value = 0;
                for(var u = 1; u < dt.getNumberOfColumns(); u++) {
                  value += dt.getValue(row, u);
                }
                return {
                  v: value,
                  f: formatter.formatValue(value)
                };
              }
              },
            type: 'number',
            role: 'annotation',
          });
        }
        }
    
        dataView = new google.visualization.DataView(dataTable);
        dataView.setColumns(viewColumns);
        for(var z = 0; z < dataView.getNumberOfColumns(); z++) {
          console.log(JSON.stringify(dataView.getColumnRange(z)));
        }
        console.log(JSON.stringify(dataView.getViewColumns()));
        console.log(JSON.stringify(viewColumns));
    
        return dataView;
      }
    
      var options = {
    
        annotations: {
        alwaysOutside: true,
        textStyle: {
          fontSize: 10
        }
      },
        height: 400,
        isStacked: true
      };
    
      var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
      chart.draw(view, options);
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="columnchart_values"></div>