Googleカレンダーに登録された予定をうっかり忘れてしまうことってありませんか?
そこで、この記事では、Googleカレンダーの翌日の予定を取得し、それらの予定をスプレッドシートに一覧でまとめ、PDFに変換し、そのPDFをメールの添付ファイルとして自分自身に送信する方法について解説します!
この記事を読めば、Googleカレンダーの予定を自動的にまとめてメールで受け取る方法がすべて分かるようになります!
スケジュール管理を自動化して、業務効率化を図っちゃいましょう!
GAS(Google Apps Script)を活用して、手動での作業を自動化することで、時間と労力を節約できるようになります
GASを極めたい方や、業務の効率化を図りたい方は、ぜひこの記事を読んください!
難しいことはGASに任せて、我々人間は楽しちゃいましょう!
当ブログでは実際に仕事でGASを扱っている私が、GASの魅力について徹底的に取り上げていきます!
Googleカレンダーに登録された予定をPDF化してメール送信する
張り切って演習に取り組んでいきましょう!
【事前準備1】Googleカレンダーに予定を作成
今回の演習でイベントが取得できないと面白くないので、Googleカレンダー上で何かしらの予定を作っておきましょう!
Googleカレンダーにすでに予定が入力されている方は作成不要です!
Googleカレンダーでイベントを作成する際は、「予定」と「タスク」があります
しかしながら、これまでお伝えしたCalendarApp
では前者の「予定」しか取得することはできません
「タスク」の取得はまた今度!
【事前準備2】スプレッドシートにて、カレンダーテンプレートを準備
スプレッドシートでカレンダーテンプレートを適当に作成しましょう!
私は以下のような様式を作成しました
カレンダーテンプレートを作るのが面倒な方は
上記URLから「Ctrl+A」でコピペしちゃってください!
【事前準備3】Googleドライブ内にPDF出力先を作成
途中でスプレッドシートをPDF変換するため、Googleドライブ上に
出力先を作成しておきましょう
また、スプレッドシートはコンテナバインド型で開くためIDは不要ですが、PDF出力先
のIDは事前に取得しておきましょう
【STEP1】Googleカレンダーの翌日のイベントをすべての取得する
準備したカレンダーテンプレートからコンテナバインド型でGASプログラムを記述していきましょう!
こちらを参考にGASエディタを起動してください
では、どんどんいきますよ、ついてきてください!
function gaslog_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クラスについて
CalendarEvent
クラスは非常に扱いやすいクラスです
詳しくは以下をご覧ください!
クラス名をクリックすると公式リファレンスに飛べます!
【STEP1】の補足説明
分かる方はここをクリックして、【STEP2】へ進んでください!
let wToday = new Date()
, wTriggerDate = new Date();
// 対象日付を翌日にセットする
wTriggerDate.setDate(wToday.getDate()+1);
wToday
と wTriggerDate
という2つの Date
オブジェクトを作成します。wToday
には現在の日付が設定され、wTriggerDate
は wToday
の翌日の日付に設定されます
つまり、wTriggerDate
は明日の日付を表しています!
// 対象日付のイベントを取得する
const wTomorrowEvent = wCalendar.getEventsForDay(wTriggerDate);
wCalendar.getEventsForDay(wTriggerDate)
を使用して、wTriggerDate
(明日)の日付に予定されているイベントを取得します
取得したイベントは wTomorrowEvent
という変数に格納されます
// 各イベントの開始・終了時間等の詳細をログに出力する
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());
});
wTomorrowEvent
に含まれる各イベントに対してループを実行し、イベントの詳細情報をログに出力します。以下の情報が出力されます
指定したGoogleカレンダー内で翌日に予定されているイベント情報を取得し、その情報をコンソールログに表示しています!
【STEP2】カレンダーから取得したイベント情報をスプレッドシートに転記
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
function gaslog_SpreadsSheet() {
// カレンダークラスを用いて、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')
wEvent.isAllDayEvent()
は、wEvent
が、イベントが終日の予定であるかどうかを判定します
もし終日のイベントであれば、この条件式は真(true)を返します(条件が成立)
isAllDayEvent
つまり終日予定の場合かそうでないかで配列に設定する値を変えたい…!
しかしながら、配列の値をセットしている途中にif文を記載することはできません(1要素ずつのpushなら別ですが)
そこで三項演算子を使って、isAllDayEvent
の返却値によって値をセットしています
条件式 ? 条件式がtrueの場合に評価される式 : 条件式がfalseの場合に評価される式;
三項演算子 (?
) は、条件が真の場合(終日のイベントの場合)と偽の場合(通常のイベントの場合)に異なる式を評価する方法を提供します
終日のイベントの場合は、翌日の0:00を終了時刻として持っていますが、今回のプログラムの場合、時刻のみを取得しているため「開始:0:00、終了:0:00」という表記になるのが嫌なので、明示的に23:59:59とさせていただきました!
したがって、この三項演算子を使用することで、条件に応じて異なる値を選択的にセットでき、終日のイベントと通常のイベントの両方に対して適切な終了時刻を設定することができます!
【STEP2】の補足説明
分かる方はここをクリックして、【STEP3】へ進んでください
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
// スプレッドシートクラスを用いて、バインドしているスプレッドシートにアクセスする
const wSpread = SpreadsheetApp.getActiveSpreadsheet();
const wSheet = wSpread.getSheets()[0];
SpreadsheetApp.getActiveSpreadsheet()
を使用して、スクリプトが実行されているスプレッドシートにアクセスし、その最初のシート(wSpread
オブジェクト)を取得します
let wPasteLst = new Array();
// スプレッドシート内の既存データをクリアする
let wLstRow = wSheet.getLastRow();
if (wLstRow>1) wSheet.getRange(2, COL.NUM, wLstRow-1, COL.DETAIL).clearContent();
wPasteLst
という空の配列を作成します
これは、後でイベント情報を一時的に格納するためのリストです
既存のデータをクリアするために、スプレッドシート内の最終行の情報を取得し、最終行が1より大きい場合に clearContent()
を使用してデータをクリアします
// 対象日付のイベントを取得する
const wTomorrowEvent = wCalendar.getEventsForDay(wTriggerDate);
wCalendar.getEventsForDay(wTriggerDate)
を使用して、wTriggerDate
(明日)の日付に予定されているイベントを取得します
取得したイベントは wTomorrowEvent
という変数に格納されます
// 各イベントの開始・終了時間等の詳細を貼り付け用のリストに設定する
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()
]);
});
wTomorrowEvent
に含まれる各イベントに対してループを実行し、それぞれのイベントの情報を配列として wPasteLst
に追加します
この情報には、No、開始時刻、終了時刻、名称、場所、説明が含まれます
wSheet.getRange(2, COL.NUM, wPasteLst.length, wPasteLst[0].length).setValues(wPasteLst);
wSheet.getRange(2, COL.NUM, wPasteLst.length, wPasteLst[0].length).setValues(wPasteLst)
を使用して、wPasteLst
の内容を、setValues()
メソッドを使って、指定された範囲にデータを一括して書き込みます
【STEP3】スプレッドシートをPDF変換する
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇〇〇(自分のGoogleドライブのID)');
function gaslog_SpreadsSheet() {
// カレンダークラスを用いて、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
ここでポイントとなるのは、前回の記事と同様に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など |
bottom_margin | 下の余白 | 0, 0.5, 1.0など |
right_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:表示しない |
これらのオプションを適切に組み合わせることで、生成したPDFファイルのレイアウトや表示方法を調整することができます!
PDF化については、前回の記事を参考にしてください!
【STEP4】変換したPDFを添付ファイルとして自分宛にメールを送信する
const COL = {
NUM: 1
, START: 2
, END: 3
, TITLE: 4
, LOCATION: 5
, DETAIL: 6
}
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇〇〇(自分のGoogleドライブのID)');
function gaslog_SpreadsSheet() {
// カレンダークラスを用いて、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();
}
すごい!
僕のメールアドレス宛にPDF化された予定が
送信されてきたよ!
…でも、これイチイチやるの面倒じゃない??
そうだよね!
じゃあ、今回つくったメソッドが毎日定時に実行されるよう
スケジュール登録してみよう!
【STEP4】の補足説明
分かる方はここをクリックして、【STEP5】へ進んでください
// 自分自身のメールアドレス宛にPDFを送信する
GmailApp.sendEmail(
'*******************@gmail.com'
, '【自動送信メール】明日の予定'
, '' // 自分あてなので本文はなくても良し
, {attachments: DriveApp.getFileById(wPdfId).getBlob()}
);
このコードを実行することで、指定したメールアドレスに自動生成されたPDFファイルが添付されたメールが送信されます!
メールの件名や本文、添付ファイルの指定は、必要に応じてカスタマイズできますよ
options
は、メール送信に関連するオプションの情報を持つオブジェクトです!
以下に、一般的に使用されるいくつかの options
オプションを説明します。
オプション | 説明 |
---|---|
attachments(添付ファイル) | このオプションを使用して、メールに添付ファイルを追加できます |
name(送信者名) | このオプションを使用して、メールの送信者名を設定できます |
cc(CC 受信者) | メールの CC (Carbon Copy) 受信者のアドレスを指定できます |
bcc(BCC 受信者) | メールの BCC (Blind Carbon Copy) 受信者のアドレスを指定できます |
htmlBody(HTML 本文) | メールの本文を HTML 形式で設定できます |
replyTo(返信先アドレス) | メールの返信先アドレスを設定できます。 |
{attachments: ...}
は、メールに添付ファイルを指定するためのオプションです!
{attachments: DriveApp.getFileById(wPdfId).getBlob()}
では、メールに添付するファイルを指定しています
DriveApp.getFileById(wPdfId)
は、wPdfId
で指定されたGoogleドライブ上のファイルを取得しています
(wPdfId
は、PDFファイルのGoogleドライブ上のファイルIDです)
【STEP5】毎日、翌日の予定一覧が届くようにトリガー登録する
時刻はお好きな時間を選択してください!
許可すると、上記イメージのようにトリガーが追加されていることを確認できます!
これで毎日上記で登録した時刻にメソッドが動き出し、翌日の予定を自身に送信してくれるようになりました!
でも、スケジュール実行なら決まった時刻に設定したいですよね
安心してください、できます
次回、そういった小技をお伝えしていきます
まとめ
本記事では、Googleカレンダーを活用して、翌日の予定を自動的に取得し、PDFにまとめてメールで受け取る方法を解説しました
前回に引き続きPDF変換およびメール送信、さらにはトリガー登録と、より実業務で活用できそうなことをちりばめてみました
X(旧:Twieer)にて、ブログの更新やQiita記事の更新、GAS情報をお届けしますので、是非フォローしてください!
おかげさまで今年5月に起業しました!
GASやGoogleサービス、プログラミング全般のご相談承ります!
YouTubeでGoogleサービスをより
快適に使う方法をご紹介しています!
見て頂けたらうれしいです
コメント