雛形から作成しようにも、「前回結論をペンディングした議題を反映しておきたい」など、前回の議事録からコピーしてくるケースも多いかもしれません。
ぼくの職場では少なくともそうでした。
毎週何も考えずに前回の議事録をコピーして、日付等必要な部分だけ書き換えたあとに
メンバーに共有するという作業を行っていました。
さすがに面倒になったので、Google Apps Scriptを使って自動化することにしました。
0.Google Apps Script(以下GAS)を使う
1.議事録のコピー
→前回の議事録をコピーし、次回用にファイル名や日付をリネームする
また、3ヶ月おきに自動的にフォルダを作成する
2.短縮URLの取得
→生成された次回用のアジェンダの短縮URLを取得
(slackで共有する際、ほんの少しスマートになる程度)
3.slackにて通知
→slackの任意の部屋へ次回アジェンダのURLをポストする
(slackのincoming-webhookをつかう)
4.GAS側でトリガーを設定
→毎週、MTGの前日にスクリプトが動くように設定
5.正常に動くことを祈る
→ただ祈る…
// ドキュメントをコピーする
/**
* copyDocument() をGASのトリガーにセットする
* 例:MTG前日の午前9時に実行されるようにする, etc.
**/
function copyDocument() {
var date = new Date();
date.setDate(date.getDate() + 1); // MTG日をセットする(MTG前日通知を想定しているため、 +1 日)
var previous_file = getPreviousFile(date); // 前回のMTG議事録を取得する
var file_name = previous_file.getName();
var folder = toFolder(date); // 保存先フォルダを指定
// 以下で生成するアジェンダのファイル名を生成するための準備
var append_date = Utilities.formatDate(date, 'JST', 'yyyyMMdd');
var replace_date = Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');
var lastweek = date.setDate(date.getDate() - 7);
var file_prefix = Utilities.formatDate(date, 'JST', 'yyyyMMdd');
// 前回の議事録をコピーし、次回用にリネームする
// ファイル名が「20170512_ほげMTGアジェンダ」となる。形式を変えたい場合は要調整
var new_file = previous_file.makeCopy(file_name.replace(file_prefix, append_date), folder);
folder.addFile(new_file); // 指定したフォルダにいま生成したアジェンダを追加
// Update date in the document
// ファイル内に前回のMTG開催日が記入されている場合は、次回の日付に置換する
updateContent(new_file, replace_date);
// slack 通知用のメッセージを生成
var body_slack = '@here\n *アジェンダ生成通知* ' + '\n> _アジェンダが生成されました。_\n' + '> ' + shortenUrl(new_file.getUrl()) + '\n\n';
body_slack += '各自アップデートをお願いします。'
// set channel name
// 通知先チャンネルをセット
var channel = 'xxxx';
postToSlack(channel, body_slack); // slackで通知
}
// 先週の議事録を取得する
function getPreviousFile(date) {
var lastweek = date.setDate(date.getDate() - 7); //前回のMTG日。 date には次回開催日が入っているので、単純に一週間(7日)分引く。
var file_prefix = Utilities.formatDate(date, 'JST', 'yyyyMMdd');
var folder_name = getFolderNameForCore(date); // 日付にマッチしたフォルダ名を取得
var base_folder = DriveApp.getFolderById('xxxxxxxxxxxxxx'); // 保存先の親フォルダを取得
var folder = base_folder.getFoldersByName(folder_name).next();
var condition = "title contains '" + file_prefix + "'";
date.setDate(date.getDate() + 7); // 日付を一週間後に戻す
return folder.searchFiles(condition).next(); // 指定フォルダ内にある検索条件にマッチするファイルを返す
}
// 日付を最新のものに置換
function updateContent(file, date) {
var document = DocumentApp.openById(file.getId());
var content = document.getBody();
// 日付を正規表現で置換
// 対象期間: 2010/01/01 - 2026/12/31
return content.replaceText("20[1-2][0-6]/[0-1][0-9]/[0-3][0-9]", date);
}
// コピー先のフォルダオブジェクトを取得
function toFolder(date) {
var folder_name = getFolderNameForCore(date);
var base_folder = DriveApp.getFolderById('xxxxxxxxxxxxx');
var folders = base_folder.getFoldersByName(folder_name);
return folders.hasNext() ? folders.next() : base_folder.createFolder(folder_name);
}
// フォルダ名を取得
/**
* 3ヶ月毎にフォルダを分ける
* 「2017_04_to_06」のようなフォルダ名
**/
function getFolderNameForCore(date) {
var current_month = Utilities.formatDate(date, 'JST', 'M');
var year = Utilities.formatDate(date, 'JST', 'yyyy');
var month = {};
var val = current_month % 3;
switch (val) {
case 0:
month.start = current_month - 2;
break;
case 1:
month.start = current_month;
break;
case 2:
month.start = current_month - 1;
break;
default:
month.start = 1;
break;
}
month.end = parseInt(month.start) + 2;
var folder_name = year + '_' + zeroPadding(month.start) + '_to_' + zeroPadding(month.end);
return folder_name;
}
// ゼロパディング
function zeroPadding(num) {
return ('0' + num).slice(-2);
}
// slackで通知する際に短縮URLを使う
function shortenUrl(long_url) {
var url = UrlShortener.Url.insert({
longUrl: long_url
});
return url.id;
}
// slackに投稿する
function postToSlack(channel, content, sender, icon) {
if (!sender) var sender = 'wkm-bot';
if (!icon) var icon = ':information_source:';
var hook_url = ''; // slack のincoming webhook
var params = {};
var slack_content = {
"channel": channel,
"username": sender,
"text": content,
"icon_emoji": icon,
"link_names": 1 // @mention を有効にする。デフォルトでは無効
};
var payload = JSON.stringify(slack_content);
params = {"method": "POST", "payload": payload};
return UrlFetchApp.fetch(hook_url, params);
}
大きなことをGASでやろうとするとしんどいイメージですが、簡単な通知や
docs, spreadsheetと連携した便利系ツールを作るのにGASはおすすめです。
実際に前案件ではアジェンダ自動生成に加えて、WBSから各機能のタスク進捗を
毎日2回(朝・夕)slackに自動でポストしたりもしていました。
それでは素敵なGASライフを!
新しい記事へ
[Django] Google Search Console などでサイトのドキュメントルートにHTMLファイルを設置する方法
mac に pip をインストールする
mac は標準で python が入っていますが、パッケージ管理の pip がインストールされていないので入れてみました。
2017/05/26 09:00
[GAS] Google Drive の特定フォルダ配下のフォルダ・ファイルの権限を一括で移譲する
Google Drive の特定フォルダ配下のファイル・フォルダの権限を一括で移譲するツールを Google Apps Script で作りました。
2018/11/10 15:54
[Windows] Ophcrack を使ってユーザーパスワードを解析する方法
家族で使っていた Windows7 のログインパスワードを忘れたため、Ophcrack を使って解析したときの記録です。
2017/09/30 21:00
[shell] フォルダ内にある大量の ZIP ファイルをまとめて解凍する
とある ZIP を解凍すると中に大量の ZIP が居たときに幸せになれるコマンドを紹介します
2018/06/19 23:45
[MySQL] データファイルから DB を復元する
先日 MySQL が再起動できなくなる問題が発生し、急遽データファイル(.frm, .ibd)から復元しました
2018/11/25 12:44