建置Google表單

目前不論是問卷調查還是投票,甚至是婚禮統計親友要來與否,很多人都直接使用 Google 表單來進行統計。這裡我做了一個簡單的投票頁面,僅做 demo 用,並沒真的抽獎活動。

查看回應結果

我們可以在 Google 雲端硬碟中找到該試算表,詳實記錄了投票的時間與選項,但沒有統計出數據。 投票結果

Google APP Script API

我們可以透過 Google APP Script API 將該試算表發布為 API,供後續自己或他人二次開發使用。

操作步驟:

  • 雲端硬碟 > 新增 > 更多 > Google APP Script
  • 輸入以下 Code,本範例將該試算表讀取後轉換為 JSON 格式發佈。
function doGet(e) {
  var ss = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1GdGQn93xWgCT3xu31r3nDxHuVK9znTJGTKUIGxQePcY/edit#gid=1885393347');
  var sheet = ss.getSheetByName('表單回應 1');
  
  return getData(sheet);
}

function getData(sheet){
  var jo = {};
  var dataArray = [];
  var rows = sheet.getRange(2, 1, sheet.getLastRow(), sheet.getLastColumn()).getValues();
//  var target = "C" + sheet.getLastRow();
//  var rows = sheet.getRange("A2:"+target).getValues();
  
  Logger.log(rows);
  
  for(var i = 0, l = rows.length; i<l; i++){
    var dataRow = rows[i];
    var record = {};
    if(dataRow[0]!='' && dataRow[2]!=''){
      record['time'] = dataRow[0];
      record['phone'] = dataRow[1];
      record['product'] = dataRow[2];
    
      dataArray.push(record);    
    }
    
  }
  
  jo.data = dataArray;
  
  var result = JSON.stringify(jo);
  return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON);
}
  • 發佈 > 佈署為網路應用程式

佈署為網路應用程式

  • 請記得每次若有修改,重新發佈時,專案版本號碼都要 往上加一

佈署設定

  • 之後只要在網址列輸入 API 連結,就可以得到 JSON 格式的資料。

JSON格式的資料

  • 可使用圖表繪製套件繪製專屬圖表,這裡我使用 Google Chart,搭配 Vue 來實作。

HTML

<div id="app">
    <button id="getBtn" @click="getData" hidden>取得資料</button>
    <div id="barchart" style="width: 100%; height: 300px;border: 1px solid green;"></div>
    <div id="piechart_3d" style="width: 100%; height: 300px;border: 1px solid green;"></div>
    <pre></pre>
</div>

Javascript

$(function () {
    console.log("ready!");
    $('#getBtn').click();
});



var vm = new Vue({
    el: '#app',
    data: {
        result: []
    },
    computed: {
    },
    methods: {
        getData() {
            var self = this;
            $.ajax({
                url: "https://script.google.com/macros/s/AKfycbzgi7A8mvHKhvvwgAmZLdZGRzp67mYTwE_qHXCUmeoTQvJwOj7P/exec",
                success: function (data) {
                    console.log(data.data);

                    //取得所有產品名稱
                    var product_names = data.data.map(row => Object.values(row)[2])
                        .reduce((a, b) => a.concat(b), [])
                        .filter((data, index, arr) => arr.indexOf(data) == index)
                    console.log(product_names);

                    //inital items
                    var items = [];
                    product_names.map(ele => {
                        items.push({
                            name: ele, vote: 0
                        })
                    })

                    //計算得票數
                    data.data.map(data_ele => {
                        items.map(item => {
                            if (data_ele.product == item.name) {
                                item.vote++;
                            }
                        })
                    })

                    //轉換Google Chart所需格式
                    self.result = [];
                    self.result.push(['名稱', '得票數']);
                    items.map(ele => {
                        self.result.push([ele.name, ele.vote])
                    })
                    // console.log(self.result);
                    if (self.result.length > 2) {
                        self.startDraw();
                    }

                }
            });
        },
        startDraw() {
            google.charts.load('current', { 'packages': ['bar'] });
            google.charts.setOnLoadCallback(this.drawBarChart);

            google.charts.load("current", { packages: ["corechart"] });
            google.charts.setOnLoadCallback(this.drawPieChart);
        },
        drawBarChart() {
            console.log(this.result);
            var data = google.visualization.arrayToDataTable(this.result);

            var options = {
                legend: { position: 'none' },
                chart: {
                    title: '目前商品得票數統計',
                    subtitle: '統計時間:' + this.showTime(),
                },
                axes: {
                    x: {
                        0: { side: 'top', label: '得票數' } // Top x-axis.
                    }
                },
                bars: 'horizontal' // Required for Material Bar Charts.
            };

            var chart = new google.charts.Bar(document.getElementById('barchart'));
            chart.draw(data, google.charts.Bar.convertOptions(options));
        },
        drawPieChart() {
            console.log(this.result);
            var data = google.visualization.arrayToDataTable(this.result);

            var options = {
                title: '目前得票數統計',
                is3D: true,
            };

            var chart = new google.visualization.PieChart(document.getElementById('piechart_3d'));
            chart.draw(data, options);
        },
        showTime() {
            var timeDate = new Date();
            var tMonth = (timeDate.getMonth() + 1) > 9 ? (timeDate.getMonth() + 1) : '0' + (timeDate.getMonth() + 1);
            var tDate = timeDate.getDate() > 9 ? timeDate.getDate() : '0' + timeDate.getDate();
            var tHours = timeDate.getHours() > 9 ? timeDate.getHours() : '0' + timeDate.getHours();
            var tMinutes = timeDate.getMinutes() > 9 ? timeDate.getMinutes() : '0' + timeDate.getMinutes();
            var tSeconds = timeDate.getSeconds() > 9 ? timeDate.getSeconds() : '0' + timeDate.getSeconds();
            return timeDate = timeDate.getFullYear() + '/' + tMonth + '/' + tDate + ' ' + tHours + ':' + tMinutes + ':' + tSeconds;
        }
    }
})

CodePen

配額

雖然此服務是免費的,但其實是有些限制的,請參考配額說明連結。