【移行のお知らせ】プライバシー上の懸念により、Qiitaアカウントの削除を検討しています。
各投稿は個人blog( https://gateau.hatenablog.com/archive/category/Qiita )に移行しました。
今後も参照される方は、ブックマークなど移行をお願い致します。
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を実行可能になります。
文字を挿入する
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連携といった拡張なんかも考えられるので、みんなで推進していきたいと思います!