操作电子表格数据以进行可视化

时间:2015-08-25 14:30:39

标签: javascript google-apps-script google-sheets google-visualization

我刚刚开始学习Google Apps脚本/ JavaScript,并想知道如何重塑,操纵Google Spreadsheets中的多维数据。我读了一些像this one这样的帖子,说GAS对数据操作不灵活。但这篇文章有点过时了,所以我想知道GAS功能是否有任何新的变化/补充。

以下是功能代码。它可以成功绘制下面的图表。但我真正想要的是:

  1. 分组"工作日" (dayOfWeek(toDate(A)))和"项目" (column B
  2. 使用"项目"作为过滤器

    enter image description here

  3. 我尝试使用PIVOT BGROUP BY dayOfWeek(toDate(A)),,但它返回了One or more participants failed to draw()×错误消息或意外格式。

    <html>
      <head>
        <title>
          Test
        </title>
        <!--Load the AJAX API-->
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
        <script type="text/javascript">
          google.load('visualization', '1', {'packages': ['table', 'controls', 'corechart']});
          google.setOnLoadCallback(initialize);
    
          function initialize() {
    
                  var url = 'https://docs.google.com/spreadsheets/d/1_mSbT87MVWOiX2cfKX_x3dgTnToY5ulCWeGGCVn13iQ/gviz/tq?sheet=Sheet1&tq='   
    
                  var queryStringDaily = encodeURIComponent("SELECT dayOfWeek(toDate(A)), sum(C), sum(D), sum(E), sum(F), sum(G), sum(H) GROUP BY dayOfWeek(toDate(A)) LABEL dayOfWeek(toDate(A)) 'Weekday' " ); 
    
                  var queryDaily = new google.visualization.Query(url+ queryStringDaily);
                  queryDaily.send(drawDaily);
          }
    
          function drawDaily(dailyTicket) {
    
                    //prepare data
                    var dailyTicket_table = dailyTicket.getDataTable(firstRowIsHeader = true); 
    
                    // Create a dashboard.
                    var dashboard = new google.visualization.Dashboard(
                        document.getElementById('dashboard_div2'));
    
                    // Create a filter
                    var categoryFilter = new google.visualization.ControlWrapper({
                      'controlType': 'CategoryFilter',
                      'containerId': 'filter_div2',
                      'options': {
                        'filterColumnLabel': 'Weekday'
                      }
                    });
    
                    //create chart
                    var dailyChart = new google.visualization.ChartWrapper({
                      'chartType': 'LineChart',
                      'containerId': 'current_day',
                      'options': {
                        'title': 'Tickets by Rep, Item, and Weekday',
                        'legend': {position: 'right'},
                        //reformat x-axis tickmarks
                        'hAxis': {'viewWindow': {'min': 1.5, 'max': 6.5},
                                  'ticks': [//{v: 1, f: 'Sunday'}, 
                                            {v: 2, f: 'Monday'}, 
                                            {v: 3, f: 'Tuesday'}, 
                                            {v: 4, f: 'Wednesday'}, 
                                            {v: 5, f: 'Thursday'}, 
                                            {v: 6, f: 'Friday'}, 
                                            //{v: 7, f: 'Saturday'}
                                            ] 
                                },                    
                      }
                    });
    
                    // bind charts and controls to dashboard 
                    dashboard.bind(categoryFilter, dailyChart); 
    
                    // Draw the dashboard.
                    dashboard.draw(dailyTicket_table);
    
          }
    
    
        </script>
      </head>
    
      <body>
        <!--Div that will hold the dashboard-->
        <div id="dashboard_div2"></div>
        <!--Divs that will hold each control and chart-->
        <div id="filter_div2"></div>
        <div id="current_day" style="align: center; width: 500px; height: 250px;"></div>
    
      </body>
    </html>
    

2 个答案:

答案 0 :(得分:1)

您可以添加多个过滤器。要对源数据执行此操作:

  1. 您需要SELECT其他文本列B并将其包含在GROUP BYLABEL语句中。

    var queryStringDaily = encodeURIComponent("SELECT B, dayOfWeek(toDate(A)), sum(C),
              sum(D), sum(E), sum(F), sum(G), sum(H)
              GROUP BY dayOfWeek(toDate(A)), B
              LABEL dayOfWeek(toDate(A)) 'Weekday', B 'Issue' ");
    

    请注意,我们首先B。如果我们不这样做,我们会收到您提到的错误。这是因为LineChart期望标签列然后是相关序列的列。将文本列移动到SELECT侧的开头 - 处理错误。

  2. 为&#34;问题&#34;。

    添加过滤器
    var issueFilter = new google.visualization.ControlWrapper({
      'controlType': 'CategoryFilter',
      'containerId': 'issue-div',
      'options': {
        'filterColumnLabel': 'Issue'
      }
    });
    
  3. 将新过滤器绑定到信息中心。

    dashboard.bind(issueFilter, dailyChart);
    
  4. 那就是它!

    Results

    ......不,不是。由于Issue是我们的第一列,因此它被选为主轴,这不是很有用。

    此时您的挑战是选择与您的数据匹配的适当可视化 - 因为LineChart不会。

    注意:此代码段可以运行。

    &#13;
    &#13;
    google.load('visualization', '1', {
      'packages': ['table', 'controls', 'corechart']
    });
    google.setOnLoadCallback(initialize);
    
    function initialize() {
    
      var url = 'https://docs.google.com/spreadsheets/d/1_mSbT87MVWOiX2cfKX_x3dgTnToY5ulCWeGGCVn13iQ/gviz/tq?sheet=Sheet1&tq='
    
      var queryStringDaily = encodeURIComponent("SELECT B, dayOfWeek(toDate(A)), sum(C), sum(D), sum(E), sum(F), sum(G), sum(H) GROUP BY dayOfWeek(toDate(A)),B LABEL dayOfWeek(toDate(A)) 'Weekday', B 'Issue' ");
    
      var queryDaily = new google.visualization.Query(url + queryStringDaily);
      queryDaily.send(drawDaily);
    }
    
    function drawDaily(dailyTicket) {
    
      //prepare data
      var dailyTicket_table = dailyTicket.getDataTable(firstRowIsHeader = true);
      console.log(JSON.stringify(dailyTicket_table).replace(/\\"/g,"'").replace(/"/g,''));
    
      // Create a dashboard.
      var dashboard = new google.visualization.Dashboard(
        document.getElementById('dashboard-div'));
    
      // Create a filter
      var issueFilter = new google.visualization.ControlWrapper({
        'controlType': 'CategoryFilter',
        'containerId': 'issue-div',
        'options': {
          'filterColumnLabel': 'Issue'
        }
      });
    
      var categoryFilter = new google.visualization.ControlWrapper({
        'controlType': 'CategoryFilter',
        'containerId': 'weekday-div',
        'options': {
          'filterColumnLabel': 'Weekday'
        }
      });
    
      //create chart
      var dailyChart = new google.visualization.ChartWrapper({
        'chartType': 'LineChart',
        'containerId': 'linechart-div',
        'options': {
          'title': 'Tickets by Rep, Item, and Weekday',
          'legend': { position: 'right'},
          //reformat x-axis tickmarks
          'hAxis': {
            'viewWindow': { 'min': 1.5, 'max': 6.5},
            'ticks': [ 
              //{v: 1, f: 'Sunday'}, 
              { v: 2, f: 'Monday' },
              { v: 3, f: 'Tuesday' },
              { v: 4, f: 'Wednesday'},
              { v: 5, f: 'Thursday' },
              { v: 6, f: 'Friday' },
              //{v: 7, f: 'Saturday'}
            ]
          },
        }
      });
    
      // bind charts and controls to dashboard 
      dashboard.bind(issueFilter, dailyChart);
      dashboard.bind(categoryFilter, dailyChart);
    
      // Draw the dashboard.
      dashboard.draw(dailyTicket_table);
    
    }
    &#13;
    <html>
      <head>
        <title>
          Test
        </title>
        <!--Load the AJAX API-->
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    
      </head>
    
      <body>
        <!--Div that will hold the dashboard-->
        <div id="dashboard-div">
          <div id="control-div">
            <div id="issue-div">
            </div>
            <div id="weekday-div">
            </div>
          </div>
          <div id="charts-div">
            <div id="linechart-div" style="align: center; width: 500px; height: 250px;">
            </div>
          </div>
        </div>    
    
      </body>
    </html>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:0)

我想我今天早上有一个顿悟的时刻。在学习并借用其他帖子的代码后(在下面的脚本中提到),我能够生成我想要的图表。

  1. 正如@Mogsdad建议的那样,我将列B(问题)移到&#34; SELECT&#34;的开头。项目以及稍后使用此列进行注释和过滤。注释文本疯狂地出现在每个单独的栏上方,但我可以通过将annotated.textStyle的fontsize设置为0来隐藏它们。
  2. 我还自定义工具提示,因此工作日(数字格式)不会显示。
  3. 我认为这是我的问题的解决方法。如果您有更好的建议,我将不胜感激。

    &#13;
    &#13;
    <html>
      <head>
        <title>
          Test
        </title>
        <!--Load the AJAX API-->
        <script type="text/javascript" src="https://www.google.com/jsapi"></script>
        <script type="text/javascript">
          google.load('visualization', '1', {'packages': ['table', 'controls', 'corechart']});
          google.setOnLoadCallback(initialize);
    
          function initialize() {
    
                  var url = 'https://docs.google.com/spreadsheets/d/1_mSbT87MVWOiX2cfKX_x3dgTnToY5ulCWeGGCVn13iQ/gviz/tq?sheet=Sheet1&tq='   
                  
                  var queryStringDaily = encodeURIComponent("SELECT B, dayOfWeek(toDate(A)), sum(C), sum(D), sum(E), sum(F), sum(G), sum(H) GROUP BY dayOfWeek(toDate(A)), B LABEL dayOfWeek(toDate(A)) 'Weekday' , B '{role: \"annotation\"}' " ); 
    
                  var queryDaily = new google.visualization.Query(url+ queryStringDaily);
                  queryDaily.send(drawDaily);
          }
    
          function drawDaily(dailyTicket) {
    
                    //prepare data
                    var dailyTicket_table = dailyTicket.getDataTable(firstRowIsHeader = true); 
                    
                    //NEW!!! create tooltip
                    //inspired by http://stackoverflow.com/questions/17924826/add-tooltips-to-a-google-line-chart-with-multiple-data-series-with-simplified
                    var columns = [2]; // jump to the value columns
                    for (var i = 2; i < dailyTicket_table.getNumberOfColumns(); i++) { 
                        columns.push(i);
                        columns.push({
                            type: 'string',
                            properties: {
                                role: 'tooltip'
                            },
                            calc: (function (j) {
                                return function (dt, row) {
                                    return dt.getColumnLabel(j)  //+ ': Weekday:' + dt.getValue(row, 1) 
                                    + ' Tickets:' + dt.getValue(row, j)
                                } 
                            })(i) 
                        });
    
                        columns.push({sourceColumn: 0,
                            //calc: getValueAt.bind(undefined, 1)
                            type: "string",
                            role: "annotation",
                            label: "Issue"} );
                    }
                    columns = [1].concat(columns);
    
                    var view = new google.visualization.DataView(dailyTicket_table);
                    view.setColumns(columns)
    
                    // Create dashboard.
                    var dashboard = new google.visualization.Dashboard(
                        document.getElementById('dashboard_div2'));
    
                    // Create filter
                    var issueFilter = new google.visualization.ControlWrapper({
                      'controlType': 'CategoryFilter',
                      'containerId': 'issue-div',
                      'options': {
                        'filterColumnLabel': 'Issue',
                        'ui': {
                        'allowMultiple': false,
                        'allowNone': false, 
                        }
                      },
                      //Set default filter value
                      'state': {'selectedValues': [dailyTicket_table.getValue(1, 1)]}
                    });
    
                    //create chart
                    var dailyChart = new google.visualization.ChartWrapper({
                      'chartType': 'ColumnChart',
                      'containerId': 'current_day',
                      'options': {
                          'legend': {position: 'right'},
                          //Set the fontsize of labels so they don't show up crazily
                          'annotations': {textStyle: {'fontsize': 0},
                                         //use 'line' style so to remove the line pointer
                                          style: 'line'},
                          'hAxis': {'viewWindow': {'min': 1.5, 'max': 6.5},
                                    'ticks': [//{v: 1, f: 'Sunday'}, 
                                              {v: 2, f: 'Monday'}, 
                                              {v: 3, f: 'Tuesday'}, 
                                              {v: 4, f: 'Wednesday'}, 
                                              {v: 5, f: 'Thursday'}, 
                                              {v: 6, f: 'Friday'}, 
                                              //{v: 7, f: 'Saturday'}
                                              ] 
                                   },  
                      }
                    });
    
                    // bind charts and controls to dashboard 
                    dashboard.bind(issueFilter, dailyChart);
    
                    // Draw the dashboard.
                    dashboard.draw(view);
          }
    
        </script>
      </head>
    
      <body>
        <!--Div that will hold the dashboard-->
        <div id="dashboard_div2"></div>
        <!--Divs that will hold each control and chart-->
        <div id="filter_div2"></div>
        <div id="issue-div"></div>
        <div id="current_day" style="align: center; width: 1100px; height: 500px;"></div>
    
      </body>
    </html>
    &#13;
    &#13;
    &#13;