Help us understand the problem. What is going on with this article?

Google Apps Scriptで議事録テンプレ作成を楽にした

【移行のお知らせ】プライバシー上の懸念により、Qiitaアカウントの削除を検討しています。
各投稿は個人blog( https://gateau.hatenablog.com/archive/category/Qiita )に移行しました。
今後も参照される方は、ブックマークなど移行をお願い致します。


DroidKaigiでは月に1回、スタッフが集まってMTGをしています。
Google Documentに各々事前に議題を書き、当日議論した結果を書き残して議事録とする運用です。
そのテンプレを挿入するGoogle Apps Script(以下、GAS)を作りました。

ヘルプの右にあるボタンを押すと…
gas_template_1_public.png

別ファイルから取得したテンプレートが一番上に挿入されました!

gas_template_2.png

この記事の目的

  • スタッフ向け(自分含む)
    • スクリプトの内容を理解し、メンテナンス出来るようになる
  • それ以外の方向け
    • 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プログラミング入門 を参考に読みつつ、まずはまっさらな状態からスタートしてみましょう。

  1. テスト用のdocumentを作成して保存する
  2. ツール->スクリプトエディタ でGAS用エディタを開く
  3. 左上で適当なプロジェクト名を入力し、保存すると実行できるようになる
  4. 再生ボタン▶のマークをクリック、もしくは「実行」から関数を選択し実行する GAS_test1.png

「関数myFunctionを実行中」と表示され、まだ関数の中身は何も無いので何も起きずに終了します。

補足:スクリプトエディタを開けない場合

Googleアカウントを複数ログインしている状態だと、エラーで開けないことがあります。
その場合は、ブラウザを変えてアカウント1つだけログインした状態にすると開けました。

gas_error_1.png

ログを出力する

デバッグしやすいようにログ出力の方法を学びましょう。
Logger.log(); でログ出力が可能です。

function myFunction() {
  Logger.log("Google Apps Scriptに挑戦しています");
}

実行し、「表示」->「ログ」 で内容を確認できます。
GAS_test2.png

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());

}

実行結果
スクリーンショット 2018-06-10 15.31.36.png

ただし、こちらのコードは初回実行時にデータへのアクセス権限を承認する必要があります。

アクセス権限を承認する

GASはデータアクセスが発生する際、このような承認ダイアログを表示します。
スクリーンショット 2018-06-10 15.37.00.png
許可を確認し、アカウントを選択
スクリーンショット_2018-06-10_15_17_58.png
左下の「詳細を表示」で下に増える部分から、「(安全ではないページ)に移動」をクリック
スクリーンショット_2018-06-10_15_18_09.png
「許可」でGASを実行可能になります。
スクリーンショット_2018-06-10_15_18_15.png

文字を挿入する

function myFunction() {
  var this_doc = DocumentApp.getActiveDocument();
  this_doc.getBody().insertParagraph(0, "一番上に文字を挿入したい!") // 0は挿入する位置
}

getBody()でDocumentから本文(Body)を取得できます。
Bodyに appendXXX, insertXXXX をすると任意の要素を追加できます。

スクリーンショット 2018-06-10 20.20.00.png

実行して追加された文字は通常の操作と同じく「編集」->「元に戻す」で戻せます。

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で「ヘルプ」の横に追加したメニューが表示されるので実行します。
スクリーンショット 2018-06-10 18.49.16.png

完了すると「スクリプトが終了しました」という表示され、先ほどと同じように一番上に挿入されました。

スクリーンショット 2018-06-10 18.50.49.png

箇条書きを挿入する

箇条書きの挿入は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();` を入れてましたが省略
}

スクリーンショット 2018-06-10 20.32.20.png

繰り返し処理をする

for文やforEach文の利用が可能です。
forEachを使って、予め作成しておいたテンプレートドキュメントの内容をログに出力してみましょう。

function myFunction() {
  var template_doc = DocumentApp.openById("XXXXXXXXXXXXXXXXXXXXXX");

  template_doc.getBody().getParagraphs().forEach(function(value, i) {
    Logger.log(value.getText());
  })
}

スクリーンショット 2018-06-10 20.14.36.png

それっぽくなりました。あとはここまでの内容を駆使すれば、最初のスクリプトの内容が理解出来るはずです。

まとめ

やっていることは単なるコピペですが、元のテンプレがどこにあるかなどを知らないと出来ないですし、スタッフの人数が増えると全員に周知するのは困難です。
そこで、目につくところにメニューがあれば新しく入った人でも実行出来ると思い作りました。
calendarやslack連携といった拡張なんかも考えられるので、みんなで推進していきたいと思います!

wiroha
mercari
フリマアプリ「メルカリ」を、グローバルで開発しています。
https://tech.mercari.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした