なんか公式のやり方があるっぽいのでメモがてら書いておく。
Google Apps Script [GAS] ガチ勢3日目
Google Apps Scriptすげえ!楽しい!ってなって3日目です。
このScript便利だよ、自社のJavaScript書けるエンジニアさんの大切な時間を奪えばなんだっていろいろできるよって話をしていきます。
##内容
- 完成品の確認
- コピペ編
- コード編
以上3つで構成しようと思っています。
完成品の確認
マイカレンダー >> [ ◯◯株式会社 ] これを作ります。
POINT
Googleの[ 日本の祝日 ]を元として、自社だけの[ 創立記念日 ]とか[ △休日出勤 ]
とか追加したカレンダーが作れます。
作るだけならコピペで10分くらいで作れるかと思います。
一度このスクリプトに慣れれば[声優さんイベントカレンダー]とか[アイドルライブカレンダー]とか[◯◯イベントカレンダー]とかをすぐ作れるようになれます。私、某J系アイドルのコンサート日程をGoogleマイカレンダーに登録しているんですけど、普段は非表示(今日は◯でライブか…いきたい!!ってならないように。)必要なときに表示にしています。
使用するサイト・技術など
- Google Apps(スプレッドシート、カレンダー)を使うので、Googleアカウント
- Google Apps Script( ≒ JavaScript)
カレンダーを作成した後の発展先
後でQiita公開しようと思ってる記事
自社の営業日だけSlackに投稿したりするボット作成
これに似たのさっき公開しました最終営業日に月末の報告しっかりしろよってSlackに投げるやつ
CalendarApp.getCalendarById();
holidays = cal.getEvents();
return holidays.length != 0;
自社カレンダーがあるとこれくらいのコード量で、[ 自社が休みかどうか ]の営業日判定がすごくやりやすくなります。
詳しくはこちらGoogleAppsScriptで日本の祝日を取得する
スクレイピングしてせっせとカレンダー作りまくる
先程の[ ◯◯株式会社のカレンダー ]
実は一般公開も簡単で、趣味のイベント情報の管理人にもすぐなれます。画像右下の[ + Google Calendar ]からカレンダーの追加もすぐできます。趣味友のためにイベント情報ちょっとスクレイピングしてくるわ(どやっ)ってしてくれるといいですね。
コピペ編
スプレッドシート作成
Google Driveからスプレッドシートを作成してください。
表のスタイルをあわせる
1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|
Googleカレンダーからの取得 | 手動追加 | カレンダーの名前 | ||
日付 | タイトル | 日付 | タイトル | ◯◯株式会社 |
まずこちらをコピーして、[ 値のみ貼り付け ]をして、図のような形式にしてください。 |
スクリプトエディタを開く
スクリプトエディタにコードを貼り付ける
1. 左上の名前変更 1. コード.gsに以下のコードをコピペfunction createGoogleCalendar(){
var title, date;
// カレンダー名の取得
var sheet = SpreadsheetApp.getActiveSheet();
var calendarName = sheet.getRange(2, 5).getValue();
// カレンダーの作成と、オブジェクトcalの生成
var cal = CalendarApp.createCalendar(calendarName);
// Google[日本の祝日]の全日イベントの追加
for (var i = 3; i <= sheet.getLastRow(); i++) {
title = sheet.getRange(i, 2).getValue();
date = sheet.getRange(i, 1).getValue();
if (title=="" && date == "") break;
cal.createAllDayEvent(title, date);
}
// [手動追加]の全日イベントの追加
for (var i = 3; i <= sheet.getLastRow(); i++) {
title = sheet.getRange(i, 4).getValue();
date = sheet.getRange(i, 3).getValue();
if (title=="" && date == "") break;
cal.createAllDayEvent(title, date);
}
}
// Google[日本の祝日]の全日イベントからスプレッドシート作成
function createByGoogleHoliday() {
var start = new Date(2017, 0, 1, 0, 0, 0, 0);
var end = new Date(2019, 0, 1, 0, 0, 0, 0);
var sheet = SpreadsheetApp.getActiveSheet();
var holidays = getHoliday(start, end);
var startRow = 3;
var range = sheet.getRange(startRow, 1, holidays.length, holidays[0].length);
range.setValues(holidays);
range.sort([{column: 1, ascending: true}]); // 昇順ソート
}
/**
* startDate〜endDateまでの祝日をgoogleカレンダーの「日本の祝日」から取得
* [日付,祝日名]の多次元配列にした上で返す
*/
function getHoliday(start, end) {
var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
var holidays = cal.getEvents(start, end);
var values = [];
for(var i = 0; i < holidays.length; i++) {
values[i] = [holidays[i].getStartTime(), holidays[i].getTitle()];
}
/**
* 追加と削除機能あり
* values.push([new Date("2017/1/4"), "俺の日"]);
* values = deleteHoliday(values, "2017/1/4");
*/
return values;
}
function deleteHoliday(values, date){
var target = new Date(date);
values.some(function(v, i){
if (Date.parse(v[0]) == Date.parse(target)) values.splice(i,1);
});
return values;
}
今回は自動化はしていませんが、コードはこちらの記事[ google spread sheetに自動更新される日本の祝日シートを作る ]から3割くらいお借りしています。月に一度の自動更新で正確に祝日カレンダーをGoogleから同期させられる手法なのでぜひ読んでみてください。追加点はコード内でイベントの追加と削除機能を実装
とソート機能
とスプレッドシートからのカレンダー作成
です。
コードの実行
実行 >> createByGoogleHoliday
スプレッドシートに戻ってみる
こんな感じでGoogleカレンダーから取得できてると正解
手作業入力
- 手動追記 >> 日付とタイトル
- 一応どちらも入力してください
- 空白行があるとそこで終了
- カレンダーの名前 >> 私の会社
- 私の会社の部分がカレンダーのタイトルになります。
Script Edit
ツール >> スクリプトエディタ
からスクリプトエディタに戻って
実行 >> createGoogleCalendar
作成に時間はかかりますが、カレンダーができました!!!!
Google Calendarを見る
これでカレンダーができました!!無事[ △休日出勤 ]も春分の日も出力されてるので作成ができました。
共有とか削除はカレンダー設定からいろいろいじれます。
蛇足ボタンの追加
ここからボタン作成ができます。
図形右クリック >> 右上のボタン >> スクリプトの割り当て
ここで先程つくったスクリプトを割り当てられます。かっこいらない系。
[ createGoogleCalendar ]
[ createByGoogleHoliday ]
こうするとデータの更新とカレンダーの作成がワンクリックでできるようになります。
以上、10分でできる専用カレンダーの作成方法でした。
次はこの自社カレンダーを使って、営業日だけ動くSlackボットの作成がしたい~
あ、Google Apps Scriptだと、コード10行くらいで定期実行してくれるbotが簡単につくれます。コード編終わって落ち着いたら記事書きます。
コード編
簡単な解説とかいれていきます。私がGAS知ってからチュートリアル的なサンプル作りつつ、1日くらいで作れたので、ゆっくり丁寧にコードを読みといていけばすぐにGAS書けるようになると思います。
Googleカレンダーから日本の祝日の取得方法
// Google[日本の祝日]の全日イベントからスプレッドシート作成
function createByGoogleHoliday() {
var start = new Date(2017, 0, 1, 0, 0, 0, 0);
var end = new Date(2019, 0, 1, 0, 0, 0, 0);
var sheet = SpreadsheetApp.getActiveSheet();
var holidays = getHoliday(start, end);
var startRow = 3;
var range = sheet.getRange(startRow, 1, holidays.length, holidays[0].length);
range.setValues(holidays);
range.sort([{column: 1, ascending: true}]); // 昇順ソート
}
/**
* startDate〜endDateまでの祝日をgoogleカレンダーの「日本の祝日」から取得
* [日付,祝日名]の多次元配列にした上で返す
*/
function getHoliday(start, end) {
var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
var holidays = cal.getEvents(start, end);
var values = [];
for(var i = 0; i < holidays.length; i++) {
values[i] = [holidays[i].getStartTime(), holidays[i].getTitle()];
}
/**
* 追加と削除機能あり
* values.push([new Date("2017/1/4"), "俺の日"]);
* values = deleteHoliday(values, "2017/1/4");
*/
return values;
}
function deleteHoliday(values, date){
var target = new Date(date);
values.some(function(v, i){
if (Date.parse(v[0]) == Date.parse(target)) values.splice(i,1);
});
return values;
}
function createByGoogleHoliday()
var start = new Date(2017, 0, 1, 0, 0, 0, 0);
var end = new Date(2019, 0, 1, 0, 0, 0, 0);
Googleの日本の祝日だと2年分くらいしか取得することができないので、この期間で設定しています。
またミリ秒までセットしている理由は、deleteHoliday()
の部分でミリ秒まで同じなら削除をするみたいな判定しているからです。(ここ書き方わかんなくて適当に実装しました。アドバイスいただけたらうれしいです。)
var sheet = SpreadsheetApp.getActiveSheet();
こちらスプレッドシート上のGASから操作しているので簡単にシートのオブジェクトがとれます。
別のGASからでもSpreadsheetApp.openByUrl(SHEET_URL)
とかを使えばオブジェクトを取ってこれます。もしくはopenByIdとか。
var holidays = getHoliday(start, end);
後で書きますがgetHoliday関数で、ある期間の祝日を、日付とタイトルの配列として返します。[[日付, タイトル], [日付2, タイトル2]]
こんな感じ。
var startRow = 3;
今回は3行目からデータを挿入していくので。
var range = sheet.getRange(startRow, 1, holidays.length, holidays[0].length);
range.setValues(holidays);
range.sort([{column: 1, ascending: true}]); // 昇順ソート
まず範囲オブジェクトを作ります。配列の行列と範囲オブジェクトを対応させて、下の表の3行目(日付、タイトルの下)から、値をrange.setValues(holidays)で一気に入れます。
1 | 2 |
---|---|
Googleからの取得 | |
日付 | タイトル |
day1 | title1 |
day2 | title2 |
day3 | title3 |
day4 | title4 |
day5 | title5 |
day6 | title6 |
そしてrange.sort([{column: 1, ascending: true}])
でソートしてます。(実は削除も追加もしなかったらもともと昇順です)
column: で何列目を基準にするか
ascending: trueが昇順、falseが降順
function getHoliday(start, end) {}
function getHoliday(start, end) {
var cal = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
var holidays = cal.getEvents(start, end);
var values = [];
for(var i = 0; i < holidays.length; i++) {
values[i] = [holidays[i].getStartTime(), holidays[i].getTitle()];
}
/**
* 追加と削除機能あり
* values.push([new Date("2017/1/4"), "俺の日"]);
* values = deleteHoliday(values, "2017/1/4");
*/
return values;
}
- (start, end)で範囲指定する
- CalendarApp.getCalendarByIdで[日本の祝日]を取得
- cal.getEvents(start, end)で[ 日本の祝日 ]のイベント取得
- 単数データにすると
- .getStartTime()で始まる時間
- .getTitle()でタイトルを取得できるようになる
- ここで追加したい時は配列にプッシュするだけ
- deleteHolidayは関数として実装
function deleteHoliday(values, date){}
function deleteHoliday(values, date){
var target = new Date(date);
values.some(function(v, i){
if (Date.parse(v[0]) == Date.parse(target)) values.splice(i,1);
});
return values;
}
詳細はJavaScriptのsomeを。
targetに消したい日のDateオブジェクトを。
valuesには[ 日本の祝日 ]データが入っているので、それをすべて検索
[ Dateオブジェクト, title ]という形式なのでv[0]
Date.parse()でDate型を変換して比較できるようにしている(もっと良い書き方あるはず)
function createGoogleCalendar(){}
function createGoogleCalendar(){
var title, date;
// カレンダー名の取得
var sheet = SpreadsheetApp.getActiveSheet();
var calendarName = sheet.getRange(2, 5).getValue();
// カレンダーの作成と、オブジェクトcalの生成
var cal = CalendarApp.createCalendar(calendarName);
// Google[日本の祝日]の全日イベントの追加
for (var i = 3; i <= sheet.getLastRow(); i++) {
title = sheet.getRange(i, 2).getValue();
date = sheet.getRange(i, 1).getValue();
if (title=="" && date == "") break;
cal.createAllDayEvent(title, date);
}
// [手動追加]の全日イベントの追加
for (var i = 3; i <= sheet.getLastRow(); i++) {
title = sheet.getRange(i, 4).getValue();
date = sheet.getRange(i, 3).getValue();
if (title=="" && date == "") break;
cal.createAllDayEvent(title, date);
}
}
まずはこちら。
var sheet = SpreadsheetApp.getActiveSheet();
var calendarName = sheet.getRange(2, 5).getValue();
var cal = CalendarApp.createCalendar(calendarName);
現在のアクティブシートからシートオブジェクトを作成して
カレンダー名を2行5列のとこから取得して、カレンダーを作成
for (var i = 3; i <= sheet.getLastRow(); i++) {
title = sheet.getRange(i, 2).getValue();
date = sheet.getRange(i, 1).getValue();
if (title=="" && date == "") break;
cal.createAllDayEvent(title, date);
}
3行目からシートの最終行まで繰り返す処理
タイトルを2列目から
日付を1列目から所得して
もしどちらも空白ならfor文終了
タイトルと日付を使って全日イベントを作成。
Google Apps Script
GASはいかがでしたか。かなり便利でいろんな機能が使えそうだと思ってます。
シンタックスハイライト追加プルリクありがとうございます。追加しました!!
.