GASでスプレッドシートをダッシュボード化する意義
Googleスプレッドシートは手軽なデータ共有ツールですが、データが増えるにつれてチャートの更新作業が手間になります。Google Apps Scriptを使ってチャートを自動更新することで、常に最新データを反映したダッシュボードを維持できます。
活用シーン:
- EC売上の日次・月次ダッシュボード
- スクレイピングで収集した競合価格の推移グラフ
- 予約件数・キャンセル率のモニタリング
- 広告費・ROASのリアルタイム確認
スプレッドシートとGASの連携基本
// スプレッドシートのオブジェクトを取得
const ss = SpreadsheetApp.getActiveSpreadsheet();
// シートを名前で取得
const dataSheet = ss.getSheetByName('データ');
const dashSheet = ss.getSheetByName('ダッシュボード');
// データ範囲を取得
const data = dataSheet.getDataRange().getValues();
console.log(`行数: ${data.length}, 列数: ${data[0].length}`);
売上データの自動集計
/**
* 月別売上を集計してダッシュボードシートに書き込む
*/
function updateMonthlySummary() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const data = ss.getSheetByName('売上データ').getDataRange().getValues();
const dash = ss.getSheetByName('月別集計');
// ヘッダーをスキップしてデータを月別に集計
const monthlyMap = {};
for (let i = 1; i < data.length; i++) {
const date = new Date(data[i][0]);
const sales = parseFloat(data[i][2]) || 0;
const key = Utilities.formatDate(date, 'Asia/Tokyo', 'yyyy-MM');
if (!monthlyMap[key]) {
monthlyMap[key] = { month: key, total: 0, count: 0 };
}
monthlyMap[key].total += sales;
monthlyMap[key].count++;
}
// 月順にソートして書き出し
const sorted = Object.values(monthlyMap).sort((a, b) => a.month.localeCompare(b.month));
dash.clearContents();
dash.appendRow(['月', '売上合計', '件数', '平均単価']);
sorted.forEach(row => {
dash.appendRow([
row.month,
row.total,
row.count,
Math.round(row.total / row.count),
]);
});
// 数値列に書式設定
const lastRow = dash.getLastRow();
dash.getRange(2, 2, lastRow - 1, 1)
.setNumberFormat('#,##0');
dash.getRange(2, 4, lastRow - 1, 1)
.setNumberFormat('#,##0');
}
チャートの自動生成・更新
/**
* 月別売上の棒グラフを生成(または更新)
*/
function createOrUpdateSalesChart() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const dash = ss.getSheetByName('月別集計');
const board = ss.getSheetByName('ダッシュボード');
const lastRow = dash.getLastRow();
const dataRange = dash.getRange(1, 1, lastRow, 2); // 月・売上合計の2列
// 既存チャートを削除
board.getCharts().forEach(chart => board.removeChart(chart));
// 新しいチャートを作成
const chartBuilder = board.newChart()
.setChartType(Charts.ChartType.COLUMN)
.addRange(dataRange)
.setPosition(2, 1, 0, 0) // 行2・列A から配置
.setNumHeaders(1)
.setOption('title', '月別売上推移')
.setOption('titleTextStyle', { fontSize: 16, bold: true })
.setOption('width', 700)
.setOption('height', 400)
.setOption('colors', ['#1a73e8'])
.setOption('vAxis.format', '#,##0')
.setOption('legend.position', 'none');
board.insertChart(chartBuilder.build());
SpreadsheetApp.flush();
}
KPIカードの自動更新
/**
* ダッシュボードにKPIサマリーを更新する
*/
function updateKPICards() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const data = ss.getSheetByName('売上データ').getDataRange().getValues().slice(1);
const dash = ss.getSheetByName('ダッシュボード');
const today = new Date();
const thisMonth = Utilities.formatDate(today, 'Asia/Tokyo', 'yyyy-MM');
const lastMonth = Utilities.formatDate(
new Date(today.getFullYear(), today.getMonth() - 1, 1),
'Asia/Tokyo', 'yyyy-MM'
);
let thisMonthTotal = 0, lastMonthTotal = 0;
let thisMonthCount = 0, lastMonthCount = 0;
data.forEach(row => {
const month = Utilities.formatDate(new Date(row[0]), 'Asia/Tokyo', 'yyyy-MM');
const sales = parseFloat(row[2]) || 0;
if (month === thisMonth) { thisMonthTotal += sales; thisMonthCount++; }
if (month === lastMonth) { lastMonthTotal += sales; lastMonthCount++; }
});
const growthRate = lastMonthTotal > 0
? ((thisMonthTotal - lastMonthTotal) / lastMonthTotal * 100).toFixed(1)
: 'N/A';
// KPIをセルに書き込む
dash.getRange('B2').setValue(`¥${thisMonthTotal.toLocaleString()}`); // 今月売上
dash.getRange('B3').setValue(thisMonthCount); // 今月件数
dash.getRange('B4').setValue(`${growthRate}%`); // 前月比
dash.getRange('B5').setValue(new Date().toLocaleString('ja-JP')); // 最終更新
}
全処理をまとめて実行
/**
* ダッシュボードを一括更新するメイン関数
*/
function refreshDashboard() {
console.log('ダッシュボード更新開始:', new Date().toLocaleString('ja-JP'));
updateMonthlySummary();
createOrUpdateSalesChart();
updateKPICards();
console.log('ダッシュボード更新完了');
}
定期実行トリガーの設定
function setupDailyTrigger() {
// 既存トリガーをクリア
ScriptApp.getProjectTriggers()
.filter(t => t.getHandlerFunction() === 'refreshDashboard')
.forEach(t => ScriptApp.deleteTrigger(t));
// 毎朝7時に自動更新
ScriptApp.newTrigger('refreshDashboard')
.timeBased()
.atHour(7)
.everyDays(1)
.inTimezone('Asia/Tokyo')
.create();
}
まとめ
GASを使ったスプレッドシートのダッシュボード化は、Googleアカウントがあれば追加コストゼロで実装できます。弊社ではEC売上分析・スクレイピングデータの可視化・KPIモニタリングのダッシュボードをGASで構築してきました。
業務自動化・データ可視化ツールの開発についてはお気軽にご相談ください。