GAS

Google Spreadsheetの時系列データから散布図を自動生成してGoogle Driveに保存するGASスクリプト

thumbnail
n-mukineer
えぬ
えぬ

こんにちは、えぬ(@nmukineer)です!

Google SpreadSheetで管理している体重データを、定期的にグラフ化して画像付きツイートしたいなーと思って作ってみました。

今回はGoogle SpreadSheetの時系列データから任意の日時範囲で散布図を作成し、Google Driveに画像として保存するGASスクリプトを書いてみました。

処理の流れ

処理の流れを簡単に書くと以下のようになります。

グラフを自動生成する処理の流れ
  1. データ参照
    • 時系列データを保管しているシートを参照します。ここでは範囲を絞らず、シート内の全データを取得します
    • 全データを取得したら、指定した範囲にデータを切り取ります。
  2. 一時シート作成
    • ①で切り出したデータを、同一スプレッドシートの別シートに記録します。このシートはグラフ作成のために一時的に作成されるものであり、⑤で削除されます。
  3. グラフ作成
    • ②で作成したデータに対してグラフを作成します。
  4. グラフ画像保存
    • ③で作成したグラフを画像として所定のGoogle Driveのフォルダに保存します。
  5. 一時シート削除
    • ④で画像として保存したため②で作成したシートは不要になりました。削除します。

スプレッドシートの準備

Google Drive上にスプレッドシートを新規作成します。

今回は、体重や体脂肪率をスプレッドシート上で管理しているという想定で、「体重」と「体脂肪率」というシートを作成しておきます。

また、「体重」シートには、こちらのように適当にダミーで日時と体重データを入れておきます。上から日時が古い順に並んでいます。

スプレッドシートを準備する

GASスクリプトの作成

プロジェクトを作成

プロジェクトの作成方法についてはこちらの記事を参考にしてください。

あわせて読みたい
【無料】GASを使い始めるための3ステップ【簡単】
【無料】GASを使い始めるための3ステップ【簡単】

スクリプトを作成

こちらが今回作成したスクリプトです。参考までにスクリプト内にコメントしております。

//スクリプトプロパティに事前に登録しておく
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const SPREADSHEET_ID = PropertiesService.getScriptProperties().getProperty('SPREADSHEET_ID');

//スプレッドシートのシート名
const SHEET_NAME = {
  weight: "体重",
  fat: "体脂肪率",
  temp: "temp"
}

//Date型を日付文字列に変換する関数
const dateText = date => `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`;

//配列を転置する関数
const transpose = a => a[0].map((_, c) => a.map(r => r[c]));

//グラフを作成する関数
//期間(from, to): Date
//key: シート名(キー)
function createGraph(from, to, key) {
  const sheetName = SHEET_NAME[key];
  const activeSheet = SpreadsheetApp.openById(SPREADSHEET_ID);
  const sheet = activeSheet.getSheetByName(sheetName);
  const values = sheet.getDataRange().getValues();
  const tValues = transpose(values);

  //from, toのそれぞれのIndexを探す
  const fromIndex = tValues[0].findIndex(elem => elem >= from);
  const toIndex = tValues[0].findIndex(elem => elem >= to);

  //取得したfrom, toの範囲にデータを限定する
  const tempArray = values.slice(fromIndex, toIndex + 1)
  
  //ヘッダー追加
  tempArray.unshift(["日時", SHEET_NAME[key]])

  //一時シート作成(重複しないようにシート名にタイムスタンプをつける)
  let newSheet = activeSheet.insertSheet();
  const tempName = `${SHEET_NAME.temp}${Date.parse(new Date())}`
  newSheet.setName(tempName);

  //一時シートに記録
  tempArray.forEach(function(row) {
    newSheet.appendRow(row);
  });
  
  //散布図作成
  const range = newSheet.getRange(1, 1, values.length, values[0].length);
  let chart = newSheet.newChart()
                .addRange(range)
                .asScatterChart()
                .setNumHeaders(1)
                .setYAxisRange(60, 80)
                .setPosition(1,4,0,0)
                .setOption("title", `${SHEET_NAME[key]}推移: ${dateText(from)}~${dateText(to)}`)
                .build();
  newSheet.insertChart(chart);

  //折れ線グラフをドライブに保存
  const graph = newSheet.getCharts();
  const graphImg = graph[0].getBlob();
  const folder = DriveApp.getFolderById(FOLDER_ID);
  const file = folder.createFile(graphImg.setName(tempName));
  const fileId = file.getId();

  //シートの削除
  const sheet2 = activeSheet.getSheetByName(tempName);
  activeSheet.deleteSheet(sheet2);
  return fileId;
}

//テスト用関数。こっちを実行する。
function test() {
  const endDate = "2022/10/20";
  const dateRange = 7;
  const to = new Date(endDate);
  let from = new Date(endDate);
  from.setDate(from.getDate() - dateRange);
  const graphId = createGraph(from, to, 'weight');
  console.log(graphId);
}

実行してみる

テスト実行用に用意したtestを実行してみます。成功したら、生成されたグラフのファイルIDがログに表示されるはずです!

じゃん!

きました!Google DriveはファイルIDがわかれば、

https://drive.google.com/file/d/<ファイルID>

とすることでアクセスすることが可能です(アクセス権限があるGoogleアカウントのみ)。

これをGoogle Driveで開いてみます!

どん!

自動的に生成された体重推移グラフ

見事にできてました。Google Drive上のどこにあるかは、スクリプト上で「FOLDER_ID」というスクリプトプロパティに登録したフォルダに生成されています。

今回は「マイドライブ⇒GAS用⇒graphs」というフォルダのIDをFOLDER_IDに設定したため、ちゃんとフォルダ内に画像が保存されていました。

設定したフォルダに画像が保存されていた

まとめ

今回はGASを使ってスプレッドシートの時系列データから任意の範囲をグラフ化し画像として保存するスクリプトを書いてみました!

えぬ
えぬ

決まった日時に画像を生成してTwitterに投稿するようにしておけば自動的に日々の変化を発信していけますね!

お読みいただきありがとうございました!

このブログを書いている人
えぬ
えぬ
N日後にムキムキになるエンジニア
WebアプリエンジニアとしてIoTシステムを開発中。30代折り返し。 趣味(モノづくり、プログラミング、筋トレ)や子育てのことを主に記事にします。 TOEIC: 900点/第一級陸上無線技術士/第3種電気主任技術者/技術士一次試験合格/基本情報技術者/第2種電気工事士/デジタル技術検定2級(情報・制御)
記事URLをコピーしました