Help us understand the problem. What is going on with this article?

Googleカレンダーからスプレッドシートにイベントを出力する

はじめに

仕事で1週間の作業内容を記録したい!という要望を受け作成しました。
Googleカレンダーに登録されているイベントから以下のような表とグラフが作れます。
myFunction.png

プログラミングが全くわからない人でも作業ができるように丁寧に書いているつもりです。
分かる人は適当に改良して使ってください。

JS, GAS共に初心者が作ったものなので粗があるのは勘弁してください:bow_tone1:
それではどうぞ。

設定方法

  1. Googleカレンダーを読み取りたいユーザでログインします。

  2. 以下のGoogleスプレッドシートにアクセスします。
    https://docs.google.com/spreadsheets/

  3. 「新しいスプレッドシートを作成」から「空白」を選びます。
    スプレッドシート作成

  4. 「ツール」 > 「スクリプトエディタ」 を押します。
    ツール

  5. 以下のようなエディタが出てくるので中身を消して後ほど出てくるコードをコピペします。
    スクリプトエディタ
    スクリプトエディタ2

  6. 三角の実行ボタンを押します。
    スクリプトエディタ2

  7. プロジェクト(スクリプト)を保存するか聞かれるので「はい」を押します。
    保存

  8. 適当なプロジェクト名をつけて「OK」を押します。
    Edit Project Name

  9. コードに権限を与えていいか聞かれるので「許可を確認」を押します。
    Authorization required

  10. アカウントを選択します。
    アカウント選択.png

  11. 「このアプリは確認されていません」が出たら「詳細」を押します。
    このアプリは確認されていません.png

  12. なんか出るので「作業記録(安全ではないページ)に移動」を押します。(安全です。)
    このアプリは確認されていません2.png

  13. アカウントへのリクエストを要求してくるので「許可」を押します。
    アクセスリクエスト.png

  14. そしたらエディタに戻るとこんなのが出るのでもう一度6の実行ボタンを押しましょう。
    myFunction.png

  15. 3で開いたスプレッドシートに戻ると…
    myFunction.png
    やったね!
    いい感じに表とグラフができてます。

場合によってはアプリの確認とかは出ないかもしれませんがそこは適当にやってください。

作ったもの

詳細はコード内に書いてありますが、集計する期間を設定できたりします。

/*
!!注意!! 1日を超えるイベントが正しく取得できません!!

実行ボタンを押すことでログインしているユーザのカレンダーから
現在の週(日〜土)のイベントの時間を足し上げ新しいシートに出力します。
同じ週で実行すると結果を上書きします。

以下の値を設定することで集計する期間を設定することができます。(形式: YYYY/MM/DD, YYYY/MM/DD HH:mm:ss)
start: 開始日時
end: 終了日時
例: var start = "2019/11/20";
例: var end = "2020/1/2 9:30:00";
*/
var start = "";
var end = "";

function CalendarToSpreadSheet() {
  // 所要時間を整形するクラス
  var DurationToStr = function(duration) {
    this.duration = duration;
    this.culc = function() {
      var dur_h = Math.floor(this.duration / 60);  // 時
      var dur_m = this.duration - (dur_h * 60);    // 分
      // スプレッドシートの表示形式で経過時数01、経過分数01にすると桁がそろって見栄えが良い
      var dur_h_str = ('00' + dur_h).slice(-2);
      var dur_m_str = ('00' + dur_m).slice(-2);
      return dur_h_str + ':' + dur_m_str;
    }
  }

  // カレンダーから取得したイベントを整形して保存しておくクラス
  var SimpleEvent = function(title, duration) {
    this.title = title;
    this.duration = duration;
    this.getDurationStr = function() {
      return new DurationToStr(this.duration).culc();
    };
  };

  // ログインしているユーザのカレンダーを取得
  var calendar = CalendarApp.getCalendarById(Session.getActiveUser().getEmail());

  // 現在の週を取得
  var today = new Date();
  var thisYear = today.getFullYear();
  var thisMonth = today.getMonth();
  var thisDate = today.getDate();
  var thisDay = today.getDay();
  var thisSunday = thisDate - thisDay;
  var nextSunday = thisSunday + 7;
  // 日曜日の年月日
  if (start === "") {
    var startDate = new Date(thisYear, thisMonth, thisSunday);
  } else {
    var startDate = new Date(start);
  }
  // 次の日曜日の年月日
  if (end === "") {
    var endDate = new Date(thisYear, thisMonth, nextSunday);
  } else {
    var endDate = new Date(end);
    endDate.setDate(endDate.getDate() + 1);
  }
  // シート名を作成
  var startDateStr = startDate.getFullYear() + "/" + (startDate.getMonth() + 1) + "/" + startDate.getDate();
  var endDateStr = endDate.getFullYear() + "/" + (endDate.getMonth() + 1) + "/" + (endDate.getDate() - 1);
  var week = startDateStr + " - " + endDateStr;

  // アクティブなスプレッドシートを取得
  var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  // 今週のシートが既にあれば消す
  var oldSheet = spreadSheet.getSheetByName(week);
  if (oldSheet) {
    spreadSheet.deleteSheet(oldSheet);
  }
  // 新しいシートを作成
  spreadSheet.insertSheet(week);  
  // シートを取得
  var sheet = SpreadsheetApp.getActiveSheet();

  // イベントを取得
  var events = calendar.getEvents(startDate, endDate);
  // 読み出したイベントを登録しておく配列
  var readEvent = [];
  // イベントの読み出し
  for (var i = 0; i < events.length; i++) {
    var title = events[i].getTitle();         // 予定のタイトル
    var startTime = events[i].getStartTime(); // 開始時刻
    var endTime = events[i].getEndTime();     // 終了時刻
    // 所要時間の計算
    var duration = (endTime - startTime) / (1000 * 60);
    // SimpleEvent クラスを生成
    var simpleEvent = new SimpleEvent(title, duration);

    // 配列に追加済みか判定するフラグ
    var added = false;
    // 所要時間を足し上げ
    for (var j = 0; j < readEvent.length; j++) {
      if (title == readEvent[j].title) {
        readEvent[j].duration = readEvent[j].duration + duration;
        added = true;
        break;
      }
    }
    if (!added) {
      readEvent.push(simpleEvent);
    }
  }

  // 各行のタイトルを指定
  sheet.getRange('A'+(1)).setValue('予定名');
  sheet.getRange('B'+(1)).setValue('所要時間');
  // シートに出力
  for (var i = 0; i < readEvent.length; i++) {
    sheet.getRange('A'+(i+2)).setValue(readEvent[i].title);
    sheet.getRange('B'+(i+2)).setValue(readEvent[i].getDurationStr());
  }

  // 合計を出力
  var sumDuration = 0;
  for (var i = 0; i < readEvent.length; i++) {
    sumDuration = sumDuration + readEvent[i].duration;
  }
  sheet.getRange('A'+(readEvent.length+2)).setValue("合計");
  sheet.getRange('B'+(readEvent.length+2)).setValue(new DurationToStr(sumDuration).culc());

  // 円グラフを作成
  var range=sheet.getRange("A1:B" + String(readEvent.length+1));
  var chart=sheet.newChart()
    .addRange(range)
    .setChartType(Charts.ChartType.PIE)
    .setOption("pieSliceText", "value")
    .setPosition(1,4,0,0)
    .build()
  sheet.insertChart(chart);
}

参考

https://tonari-it.com/gas-calendar-spreadsheet/
https://yokonoji.work/google-apps-script-650
https://kiyotatsu.com/gas-script_get-calender/

2355
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away