Google Apps Scriptで議事録テンプレ作成を楽にした
※本記事はQiitaに投稿していた記事のexportです(元投稿日: 2018/6/11)
DroidKaigiでは月に1回、スタッフが集まってMTGをしています。 Google Documentに各々事前に議題を書き、当日議論した結果を書き残して議事録とする運用です。 そのテンプレを挿入するGoogle Apps Script(以下、GAS)を作りました。
ヘルプの右にあるボタンを押すと…
別ファイルから取得したテンプレートが一番上に挿入されました!
この記事の目的
- スタッフ向け(自分含む)
- スクリプトの内容を理解し、メンテナンス出来るようになる
- それ以外の方向け
- DroidKaigiやそのスタッフに興味を持ってもらう
- GASに興味を持ってもらう(そしてノウハウをアウトプットしてほしい!情報が少ない!)
最終的なコードはこちらなので、これが書ける方はこの記事を読む必要はありません。(むしろレビュー歓迎です)
function onOpen() { var ui = DocumentApp.getUi(); ui.createMenu('★次回議事録テンプレ挿入') .addItem('最上部に挿入', 'insertTemplate') .addToUi(); } function insertTemplate() { var TEMPLATE_DOC_ID = "XXXXXXXXXXXXXXXXXXXXXX" // URLの一部がID https://docs.google.com/document/d/XXXXXXXXXXXXXXXXXXXXXX/edit var template_doc = DocumentApp.openById(TEMPLATE_DOC_ID); var this_doc = DocumentApp.getActiveDocument(); this_doc.getBody().insertHorizontalRule(0); template_doc.getBody().getParagraphs().forEach(function(value, i) { if (value.getType() == DocumentApp.ElementType.LIST_ITEM) { // 箇条書きの場合 this_doc.getBody().insertListItem(i, value.getText()).setGlyphType(DocumentApp.GlyphType.BULLET); } else { this_doc.getBody().insertParagraph(i, value.getText()); this_doc.getBody().getParagraphs()[i].setAttributes(value.getAttributes()); // 見出しなどの属性を設定 } }) }
GASを動かしてみる
公式ドキュメント と 初心者のためのGoogle Apps Scriptプログラミング入門 を参考に読みつつ、まずはまっさらな状態からスタートしてみましょう。
- テスト用のdocumentを作成して保存する
- ツール->スクリプトエディタ でGAS用エディタを開く
- 左上で適当なプロジェクト名を入力し、保存すると実行できるようになる
- 再生ボタン▶のマークをクリック、もしくは「実行」から関数を選択し実行する
「関数myFunctionを実行中」と表示され、まだ関数の中身は何も無いので何も起きずに終了します。
補足:スクリプトエディタを開けない場合
Googleアカウントを複数ログインしている状態だと、エラーで開けないことがあります。 その場合は、ブラウザを変えてアカウント1つだけログインした状態にすると開けました。
ログを出力する
デバッグしやすいようにログ出力の方法を学びましょう。
Logger.log();
でログ出力が可能です。
function myFunction() { Logger.log("Google Apps Scriptに挑戦しています"); }
実行し、「表示」->「ログ」 で内容を確認できます。
Documentの情報を取得する
DocumentApp.getActiveDocument();
で現在のDocumentを取得します。
this_docはDocument型で、 getName()
をするとドキュメント名を取得できます。
任意のDocument情報を取得するには DocumentApp.openById();
でID指定します。IDはURLの一部です。
function myFunction() { var this_doc = DocumentApp.getActiveDocument(); Logger.log(this_doc); Logger.log(this_doc.getName()); var template_doc = DocumentApp.openById("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") // https://docs.google.com/document/d/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/edit // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ この部分がID Logger.log(template_doc); Logger.log(template_doc.getName()); }
実行結果
ただし、こちらのコードは初回実行時にデータへのアクセス権限を承認する必要があります。
アクセス権限を承認する
GASはデータアクセスが発生する際、このような承認ダイアログを表示します。
許可を確認し、アカウントを選択
左下の「詳細を表示」で下に増える部分から、「<GAS名>(安全ではないページ)に移動」をクリック
「許可」でGASを実行可能になります。
文字を挿入する
function myFunction() { var this_doc = DocumentApp.getActiveDocument(); this_doc.getBody().insertParagraph(0, "一番上に文字を挿入したい!") // 0は挿入する位置 }
getBody()
でDocumentから本文(Body)を取得できます。
Bodyに appendXXX
, insertXXXX
をすると任意の要素を追加できます。
実行して追加された文字は通常の操作と同じく「編集」->「元に戻す」で戻せます。
Documentに実行メニューを追加する
実行がスクリプトエディタからだけでは不便なので、Document側に実行メニューを追加してみましょう。
function onOpen() { var ui = DocumentApp.getUi(); ui.createMenu('メニューに表示される名前') .addItem('myFunctionを実行する', 'myFunction') .addToUi(); } function myFunction() { var this_doc = DocumentApp.getActiveDocument(); this_doc.getBody().insertParagraph(0, "一番上に文字を挿入したい!") }
Documentを開いてすぐ実行する処理は onOpen()
内に記述します。
onOpen()
内で 'メニューに表示される名前' というメニューを作成し、そこに表示名と実行する関数を定義します。
Documentで「ヘルプ」の横に追加したメニューが表示されるので実行します。
完了すると「スクリプトが終了しました」という表示され、先ほどと同じように一番上に挿入されました。
箇条書きを挿入する
箇条書きの挿入はinsertListItem()
やappendListItem()
を使います。
デフォルトでは番号付きリストになり、 setGlyphType()
で丸や矢印などタイプの変更が可能です。
定数はこちらに定義されており、見た目を試した結果が下記の通りです。
function myFunction() { var body = DocumentApp.getActiveDocument().getBody(); body.appendListItem("default"); body.appendListItem("BULLET").setGlyphType(DocumentApp.GlyphType.BULLET); body.appendListItem("HOLLOW_BULLET").setGlyphType(DocumentApp.GlyphType.HOLLOW_BULLET); body.appendListItem("SQUARE_BULLET").setGlyphType(DocumentApp.GlyphType.SQUARE_BULLET); body.appendListItem("NUMBER").setGlyphType(DocumentApp.GlyphType.NUMBER); body.appendListItem("LATIN_UPPER").setGlyphType(DocumentApp.GlyphType.LATIN_UPPER); body.appendListItem("LATIN_LOWER").setGlyphType(DocumentApp.GlyphType.LATIN_LOWER); body.appendListItem("ROMAN_UPPER").setGlyphType(DocumentApp.GlyphType.ROMAN_UPPER); body.appendListItem("ROMAN_LOWER").setGlyphType(DocumentApp.GlyphType.ROMAN_LOWER); // 実際には 1つずつ `body.appendHorizontalRule();` を入れてましたが省略 }
繰り返し処理をする
for文やforEach文の利用が可能です。 forEachを使って、予め作成しておいたテンプレートドキュメントの内容をログに出力してみましょう。
function myFunction() { var template_doc = DocumentApp.openById("XXXXXXXXXXXXXXXXXXXXXX"); template_doc.getBody().getParagraphs().forEach(function(value, i) { Logger.log(value.getText()); }) }
それっぽくなりました。あとはここまでの内容を駆使すれば、最初のスクリプトの内容が理解出来るはずです。
まとめ
やっていることは単なるコピペですが、元のテンプレがどこにあるかなどを知らないと出来ないですし、スタッフの人数が増えると全員に周知するのは困難です。 そこで、目につくところにメニューがあれば新しく入った人でも実行出来ると思い作りました。 calendarやslack連携といった拡張なんかも考えられるので、みんなで推進していきたいと思います!