はじめに
本シリーズでは、GASの始め方や便利な使い方、ビジネス活用まで幅広く解説します。シリーズをひと通り読んでいただければ、あなたもきっとGASマスターになれるはずです。
シリーズの対象者
- そもそもGASってなんだかわからない方
- GASを学びたいけど何から始めればいいかわからない方
- GASはわかり始めたけど、もっと活用ができないかと模索している方
- とにかくGoogleが好き! という方
前回記事
スプレッドシートで遊ぶ
では早速始めていきましょう。【0からGASを学ぶ】シリーズの第8回は「GASを用いてGoogleカレンダー+メール送信で翌日の予定を通知しよう」です。前回に引き続きPDFエクスポートを使った操作をやってみようと思います。これまで、Googleカレンダー
やGmail
をGASから操作しました。また第5回では、スプレッドシートのデータを評価し、メールを自動送信しました。これらを組み合わせてみましょう。
今回やること
- Googleカレンダーの翌日のイベントをすべての取得する。
- イベントをスプレッドシートに一覧でまとめる。
- スプレッドシートをPDF変換する。
- 変換したPDF(翌日の予定一覧)を添付ファイルとして自分自身にメールを送信する。
- 毎日、翌日の予定一覧が届くようにトリガー登録する。
事前準備
カレンダーに予定を作成
すでに予定がびっしりな方は不要ですが、今回やることではイベントが取得できないと面白くないので、何かしら作っておきましょう。
カレンダーテンプレートの準備
スプレッドシートでカレンダーテンプレートを適当に作成しましょう。私は以下のような様式を作成しました。
PDF出力場所の作成
「今回やること」にも記載しましたが、途中でスプレッドシートをPDF変換するため、その出力先を作成しておきましょう。
IDの取得
スプレッドシートはコンテナバインド型で開くためIDは不要ですが、PDF出力先
のIDは事前に取得しておきましょう。
プログラム開始
GASエディタを開く
準備したカレンダーテンプレートからコンテナバインド型でGASプログラムを記述していきましょう。こちらを参考にGASエディタを起動してください。では、どんどんいきますよ、ついてきてください。
STEP.1 Googleカレンダーの翌日のイベントをすべての取得する
function Qiita008_SpreadSheet() {
// カレンダークラスを用いて、IDを指定してGoogleカレンダーにアクセスする
const wCalendar = CalendarApp.getCalendarById('*******************@gmail.com');
let wToday = new Date()
, wTriggerDate = new Date();
// 対象日付を翌日にセットする
wTriggerDate.setDate(wToday.getDate()+1);
// 対象日付のイベントを取得する
const wTomorrowEvent = wCalendar.getEventsForDay(wTriggerDate);
// 各イベントの開始・終了時間等の詳細をログに出力する
wTomorrowEvent.forEach(function(wEvent){
console.log(Utilities.formatDate(wEvent.getStartTime(), 'JST', 'HH:mm:ss'));
if (wEvent.isAllDayEvent()) {
console.log('23:59:59')
} else {
console.log(Utilities.formatDate(wEvent.getEndTime(), 'JST', 'HH:mm:ss'));
}
console.log(wEvent.getTitle());
console.log(wEvent.getLocation());
console.log(wEvent.getDescription());
});
}
23:09:27 お知らせ 実行開始
23:09:28 情報 00:00:00
23:09:28 情報 23:59:59
23:09:28 情報 終日の予定1
23:09:28 情報 お台場, 日本、東京都 お台場
23:09:28 情報
23:09:28 情報 08:30:00
…
23:09:28 お知らせ 実行完了
まずは翌日の予定をすべて取得できました。CalendarEvent
クラスは非常に扱いやすいクラスです。詳しくは以下をご覧ください。
STEP.2 イベントをスプレッドシートに一覧でまとめる
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
function Qiita008_SpreadSheet() {
// カレンダークラスを用いて、IDを指定してGoogleカレンダーにアクセスする
const wCalendar = CalendarApp.getCalendarById('*******************@gmail.com');
// スプレッドシートクラスを用いて、バインドしているスプレッドシートにアクセスする
const wSpread = SpreadsheetApp.getActiveSpreadsheet();
const wSheet = wSpread.getSheets()[0];
let wToday = new Date()
, wTriggerDate = new Date();
// 対象日付を翌日にセットする
wTriggerDate.setDate(wToday.getDate()+1);
let wPasteLst = new Array();
// スプレッドシート内の既存データをクリアする
let wLstRow = wSheet.getLastRow();
if (wLstRow>1) wSheet.getRange(2, COL.NUM, wLstRow-1, COL.DETAIL).clearContent();
// 対象日付のイベントを取得する
const wTomorrowEvent = wCalendar.getEventsForDay(wTriggerDate);
// 各イベントの開始・終了時間等の詳細を貼り付け用のリストに設定する
wTomorrowEvent.forEach(function(wEvent, eIdx){
wPasteLst.push([
eIdx+1
, Utilities.formatDate(wEvent.getStartTime(), 'JST', 'HH:mm:ss')
, wEvent.isAllDayEvent() ? '23:59:59' : Utilities.formatDate(wEvent.getEndTime(), 'JST', 'HH:mm:ss')
, wEvent.getTitle()
, wEvent.getLocation()
, wEvent.getDescription()
]);
});
wSheet.getRange(2, COL.NUM, wPasteLst.length, wPasteLst[0].length).setValues(wPasteLst);
}
こちらを実行すると、先ほどまではログに出力したカレンダーの内容がスプレッドシートに書き込まれます。
ゴールは近いですね。
wEvent.isAllDayEvent() ? '23:59:59' : Utilities.formatDate(wEvent.getEndTime(), 'JST', 'HH:mm:ss')
この箇所、少しだけテクニックを入れてあります。
isAllDayEvent
つまり終日予定の場合かそうでないかで配列に設定する値を変えたいんです。しかしながら、配列の値をセットしている途中にif文を記載することはできません(1要素ずつのpushなら別ですが)。
そこで三項演算子を使って、isAllDayEvent
の返却値によって値をセットしています。三項演算子は
条件式 ? 条件式がtrueの場合に評価される式 : 条件式がfalseの場合に評価される式;
といった構文となっており、配列の中だとしても柔軟に設定を行うことができます。
STEP.3 スプレッドシートをPDF変換する
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
const PDF_OUTDIR = DriveApp.getFolderById('1rwVxGOY14fcQcJEwTFV-_IDXsaBSVy5A');
function Qiita008_SpreadSheet() {
// カレンダークラスを用いて、IDを指定してGoogleカレンダーにアクセスする
const wCalendar = CalendarApp.getCalendarById('*******************@gmail.com');
// スプレッドシートクラスを用いて、バインドしているスプレッドシートにアクセスする
const wSpread = SpreadsheetApp.getActiveSpreadsheet();
const wSheet = wSpread.getSheets()[0];
let wToday = new Date()
, wTriggerDate = new Date();
// 対象日付を翌日にセットする
wTriggerDate.setDate(wToday.getDate()+1);
let wPasteLst = new Array();
// スプレッドシート内の既存データをクリアする
let wLstRow = wSheet.getLastRow();
if (wLstRow>1) wSheet.getRange(2, COL.NUM, wLstRow-1, COL.DETAIL).clearContent();
// 対象日付のイベントを取得する
const wTomorrowEvent = wCalendar.getEventsForDay(wTriggerDate);
// 各イベントの開始・終了時間等の詳細を貼り付け用のリストに設定する
wTomorrowEvent.forEach(function(wEvent, eIdx){
wPasteLst.push([
eIdx+1
, Utilities.formatDate(wEvent.getStartTime(), 'JST', 'HH:mm:ss')
, wEvent.isAllDayEvent() ? '23:59:59' : Utilities.formatDate(wEvent.getEndTime(), 'JST', 'HH:mm:ss')
, wEvent.getTitle()
, wEvent.getLocation()
, wEvent.getDescription()
]);
});
wSheet.getRange(2, COL.NUM, wPasteLst.length, wPasteLst[0].length).setValues(wPasteLst);
let wPdfId = createPdf(wSpread.getId()
, wSheet.getSheetId()
, 'A1%3AF'+(wPasteLst.length+1)
, Utilities.formatDate(wTriggerDate, 'JST', 'yyyyMMdd')+'の予定');
}
function createPdf(spreadId, sheetId, rangeStr, fileName){
// PDF変換するためのベースURLを作成する
let wUrl = `https://docs.google.com/spreadsheets/d/${spreadId}/export?gid=${sheetId}&exportFormat=pdf`;
let wPdfOpt = '&size=A4' // 用紙サイズ
+ '&portrait=true' // 用紙の向き true:縦向き / false:横向き
+ '&fitw=true' // ページ幅を用紙にフィットさせるか true:フィットさせる / false:原寸大
+ '&top_margin=0.50' // 上の余白
+ '&right_margin=0.50' // 右の余白
+ '&bottom_margin=0.50' // 下の余白
+ '&left_margin=0.50' // 左の余白
+ '&horizontal_alignment=CENTER' // 水平方向の位置
+ '&vertical_alignment=TOP' // 垂直方向の位置
+ '&range='+rangeStr; // 変換範囲
// headersにアクセストークンを格納する
let wOtions = {
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
}
};
// PDFを作成する
let wBlob = UrlFetchApp.fetch(wUrl+wPdfOpt, wOtions).getBlob().setName(fileName + '.pdf');
//PDFを指定したフォルダに保存する
return PDF_OUTDIR.createFile(wBlob).getId();
}
実行すると、事前準備で作成したPDF出力先
に以下のようなPDFが作成されます。
ここでポイントとなるのは、前回と同様にPDF変換用のURL部https://docs.google.com/spreadsheets/d/${spreadId}/export?gid=${sheetId}&exportFormat=pdf
およびその他変換オプションとなります。
コード内でも一部は使用しましたが、変換オプションには以下のパラメタを使用することができます。
パラメタ | 役割 | 設定例 |
---|---|---|
size | 用紙サイズ | A3, A4 など |
portrait | 用紙の向き | true:縦向き / false:横向き |
fitw | ページ幅を用紙にフィットさせるか | true:フィットさせる / false:原寸大 |
top_margin | 上の余白 | 0, 0.5, 1.0など |
right_margin | 右の余白 | 0, 0.5, 1.0など |
bottom_margin | 下の余白 | 0, 0.5, 1.0など |
left_margin | 左の余白 | 0, 0.5, 1.0など |
horizontal_alignment | 水平方向の位置 | LEFT, CENTER, RIGHT |
vertical_alignment | 垂直方向の位置 | TOP, MIDDLE, BOTTOM |
range | セル範囲 | A1%3AF5 %3Aは:を意味します。つまり例はA1:F5をURIencodingしているということです
|
scale | 表示スケール | 1:標準100% / 2:幅に合わせる / 3:高さに合わせる / 4:ページに合わせる |
printtitle | スプレッドシート名をPDFに表示するか | true:表示する / false:表示しない |
sheetnames | シート名をPDFに表示するか | true:表示する / false:表示しない |
pagenum | ページ番号を表示するか | true:表示する / false:表示しない |
gridlines | グリッドラインを表示するか | true:表示する / false:表示しない |
fzr | 固定行を表示するか | true:表示する / false:表示しない |
fzc | 固定列を表示するか | true:表示する / false:表示しない |
STEP.4 変換したPDF(翌日の予定一覧)を添付ファイルとして自分自身にメールを送信する
これは簡単です。STEP.3まででPDFはできているので、それを添付するだけです。
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
const PDF_OUTDIR = DriveApp.getFolderById('1rwVxGOY14fcQcJEwTFV-_IDXsaBSVy5A');
function Qiita008_SpreadSheet() {
// カレンダークラスを用いて、IDを指定してGoogleカレンダーにアクセスする
const wCalendar = CalendarApp.getCalendarById('*******************@gmail.com');
// スプレッドシートクラスを用いて、バインドしているスプレッドシートにアクセスする
const wSpread = SpreadsheetApp.getActiveSpreadsheet();
const wSheet = wSpread.getSheets()[0];
let wToday = new Date()
, wTriggerDate = new Date();
// 対象日付を翌日にセットする
wTriggerDate.setDate(wToday.getDate()+1);
let wPasteLst = new Array();
// スプレッドシート内の既存データをクリアする
let wLstRow = wSheet.getLastRow();
if (wLstRow>1) wSheet.getRange(2, COL.NUM, wLstRow-1, COL.DETAIL).clearContent();
// 対象日付のイベントを取得する
const wTomorrowEvent = wCalendar.getEventsForDay(wTriggerDate);
// 各イベントの開始・終了時間等の詳細を貼り付け用のリストに設定する
wTomorrowEvent.forEach(function(wEvent, eIdx){
wPasteLst.push([
eIdx+1
, Utilities.formatDate(wEvent.getStartTime(), 'JST', 'HH:mm:ss')
, wEvent.isAllDayEvent() ? '23:59:59' : Utilities.formatDate(wEvent.getEndTime(), 'JST', 'HH:mm:ss')
, wEvent.getTitle()
, wEvent.getLocation()
, wEvent.getDescription()
]);
});
wSheet.getRange(2, COL.NUM, wPasteLst.length, wPasteLst[0].length).setValues(wPasteLst);
// スプレッドシートをPDFにエクスポートする
let wPdfId = createPdf(wSpread.getId()
, wSheet.getSheetId()
, 'A1%3AF'+(wPasteLst.length+1)
, Utilities.formatDate(wTriggerDate, 'JST', 'yyyyMMdd')+'の予定');
// 自分自身のメールアドレス宛にPDFを送信する
GmailApp.sendEmail(
'*******************@gmail.com'
, '【自動送信メール】明日の予定'
, '' // 自分あてなので本文はなくても笑
, {attachments: DriveApp.getFileById(wPdfId).getBlob()}
);
}
function createPdf(spreadId, sheetId, rangeStr, fileName){
// PDF変換するためのベースURLを作成する
let wUrl = `https://docs.google.com/spreadsheets/d/${spreadId}/export?gid=${sheetId}&exportFormat=pdf`;
let wPdfOpt = '&size=A4' // 用紙サイズ
+ '&portrait=true' // 用紙の向き true:縦向き / false:横向き
+ '&fitw=true' // ページ幅を用紙にフィットさせるか true:フィットさせる / false:原寸大
+ '&top_margin=0.50' // 上の余白
+ '&right_margin=0.50' // 右の余白
+ '&bottom_margin=0.50' // 下の余白
+ '&left_margin=0.50' // 左の余白
+ '&horizontal_alignment=CENTER' // 水平方向の位置
+ '&vertical_alignment=TOP' // 垂直方向の位置
+ '&range='+rangeStr; // 変換範囲
// headersにアクセストークンを格納する
let wOtions = {
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
}
};
// PDFを作成する
let wBlob = UrlFetchApp.fetch(wUrl+wPdfOpt, wOtions).getBlob().setName(fileName + '.pdf');
//PDFを指定したフォルダに保存する
return PDF_OUTDIR.createFile(wBlob).getId();
}
こちらを実行するとメールにて予定が送られてきましたよね。これでひとまずは完成です。
が!!!! 翌日の予定一覧が欲しいときにGASエディタを開いていちいち実行というのはめんどくさいですよね。そこで、今回つくったメソッドが毎日定時に実行されるようスケジュール登録していきましょう。
STEP.5 毎日、翌日の予定一覧が届くようにトリガー登録する
これで毎日上記で登録した時刻にメソッドが動き出し、翌日の予定を自身に送信してくれるようになりました。
このやり方の場合、[時刻を選択]で選択できる時間には幅があり、例えば22:00きっかりにという指定ができません。でも、スケジュール実行ならそうしたいですよね。安心してください、できます。次回、そういった小技をお伝えしていきます。
おわりに
お疲れ様でした。
第8回は「GASを用いてGoogleカレンダー+メール送信で翌日の予定を通知しよう」ということで、前回に引き続きPDF変換およびメール送信、さらにはトリガー登録と、より実業務で活用できそうなことをちりばめてみました。次回は、私がこれまで習得してきたGASのちょっとした小技をいくつか紹介します。あえて言っておきます、神回です。
記事を読んで、「良いな」や「今後に期待できる!」と感じて頂けたらいいねやフォロー、コメントいただけると幸いです。それではまた次回をお楽しみに!