Google App Scriptでカレンダーからスプレッドシートに予定と時間を出力

 タイトルのまんまです。ちょっと仕事でラクしたいなと思ってGASにて準備しましたが、もう少し考えないといけない部分とかあったけど、基本部分は応用で使えそうなので置いておきます。

カレンダーに登録されている当日の予定をすべて引っこ抜いてきて日付名のシートをつけて出力するという内容です。シート出力済みの制御とか考えてなくて、1日1回スケジューラで実行する予定でしたが、ほかにも考えないといけないことが出てきたので少し考え直し中

ほとんど参考サイトのコピペですけどね。


■ソースコード

//カレンダーIDとスプレッドシートのURLを指定
const CALENDAR_ID = 'XXX';
const SHEET_URL = "https://docs.google.com/spreadsheets/d/XXXXX/edit#gid=X";

function main() {
    //カレンダー取得用日付設定
    const n = 1;
    const d = new Date();
    const todayStartTime = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0);
    const nd = d.setDate(d.getDate() + n, d.setHours(0), d.setMinutes(0), d.setSeconds(0));
    const todayEndTime = new Date(nd);
    const nextdayEndTime = new Date(n2d);
    //カレンダーからタスク取得
    const todayTasks = getCalendarEvents(todayStartTime, todayEndTime);
    const nextdayTasks = getCalendarEvents(todayEndTime, nextdayEndTime);
    //スプレッドシート書き出し            
    const sheetname = todayStartTime.getFullYear() + '-' + toDoubleDigits(todayStartTime.getMonth() + 1) + '-' +
        toDoubleDigits(todayStartTime.getDate());
    const labels = ["作業日", "作業項目", "開始時間", "終了時間", "作業時間"]
    writeSheet(todayTasks, sheetname, labels);
}

function getCalendarEvents(startTime, endTime) {
    /* カレンダーからイベントを取得 */
    const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
    try {
        const events = calendar.getEvents(startTime, endTime);
        const values = [];
        for (const event of events) {
            const wt = getWorkerTime(event.getStartTime(), event.getEndTime());
            const workTime = getJIFUNFormat(wt);
            const wd = splitDayandTime(event.getStartTime())[0];
            const st = splitDayandTime(event.getStartTime())[1];
            const et = splitDayandTime(event.getEndTime())[1];
            const record = [
                wd,
                event.getTitle(),
                st,
                et,
                workTime
            ];
            values.push(record);
        }
        return values;
    } catch (e) {
        result = "error:" + e;
        Logger.log(result);
    }
}

function writeSheet(values, sheetname, labels) {
    /* スプレッドシートに書き出し */
    try {
        if (values.length > 0) {
            // シートを追加する
            var spreadSheet = SpreadsheetApp.openByUrl(SHEET_URL);
            var sheet = set_sheet(sheetname);
            // 1行目だけヘッダ追加
            var headerCheck = sheet.getLastRow();
            if (headerCheck == 0) {
                sheet.appendRow(labels);
            }
            var lastRow = sheet.getLastRow();
            // 追加したシートに書き出し
            values.forEach(function (value) {
                sheet.appendRow(value);
            });
            const n = labels.length;
            const lr = sheet.getLastRow();
            // カラム整形
            for (let i = 1; i <= n; i++) {
                //sheet.autoResizeColumns(i,1);
                sheet.setColumnWidth(i, 80);
            }
            if (headerCheck > 0) {
                sheet.insertRows(headerCheck + 1);
            }
        }
    } catch (e) {
        result = "error:" + e;
        Logger.log(result);
    }
}

function getWorkerTime(startTime, endTime) {
    /* 開始時刻と終了時刻から稼働時間算出 */
    try {
        const st = new Date(startTime);
        const et = new Date(endTime);
        const wt = (et - st) / (1000 * 60 * 60);
        return wt;
    } catch (e) {
        result = "error:" + e;
        Logger.log(result);
    }
}

function getJIFUNFormat(target) {
    /* 小数点以下をN時間N分フォーマットに修正して返す */
    try {
        const h = String(target).split(".")[0];
        const b = String(target).split(".")[1];
        const m = 60 * target //小数点表記の分を通常に変換
        if (Number(h) == 0 && Number(b) < 100) {
            return String(m) + "分";
        } else if (Number(h) > 1 && m < 60) {
            return h + "時間" + String(m) + "分";
        } else if (Number(h) > 1 && m > 60) {
            return h + "時間" + String(m % 60) + "分";
        } else {
            return h + "時間";
        }
    } catch (e) {
        result = "error:" + e;
        Logger.log(result);
    }
}

function splitDayandTime(target) {
    /* 日付と時刻に分割して返す */
    try {
        const t = new Date(target);
        const retDay = t.getFullYear() + '-' + toDoubleDigits(t.getMonth() + 1) + '-' + toDoubleDigits(t.getDate());
        const retTime = toDoubleDigits(t.getHours()) + ':' + toDoubleDigits(t.getMinutes());
        r = [retDay, retTime]
        return r;
    } catch (e) {
        result = "error:" + e;
        Logger.log(result);
    }
}

function toDoubleDigits(num) {
    /* 月と日付パディング */
    num += "";
    if (num.length === 1) {
        num = "0" + num;
    }
    return num;
}

function set_sheet(name) {
    /* 同じ名前のシートがなければ作成 
       https://qiita.com/crawd4274/items/13120429cb3328e8ace2
    */
    var sheet = SpreadsheetApp.getActive().getSheetByName(name)
    if (sheet) return sheet
    sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet();
    sheet.setName(name);
    return sheet;
}




■参考サイト

https://tonari-it.com/gas-setvalue/

https://tonari-it.com/gas-calendar-location-description/

https://hakuhin.jp/js/date.html

コメント

このブログの人気の投稿

証券外務員1種勉強(計算式暗記用メモ)

GASでGoogleDriveのサブフォルダとファイル一覧を出力する

マクロ経済学(IS-LM分析)