記事一覧
Topに戻る

GASで議事録のテンプレ作成と周知を自動化する

更新日:

by @Panda_Program

書類の山

Photo by Sharon McCutcheon on Unsplash

Google Apps Scriptで議事録作成を自動化する

この記事では、Google Apps Script(以下、GAS)を使って毎週の議事録作成を自動化する方法を紹介します。

Google Driveに保存されているGoogle Documentをコピーするコードを解説した後、祝日は実行をスキップするコードとSlackに通知するコードを掲載します。

関連記事

GASのコードを書く

GASでフォルダやファイルを扱うにはDriveAppオブジェクトを利用します。

今回はGoogle Document20200613_🐼チーム_議事録をコピーして、20200620_🐼チーム_議事録というファイルを自動作成するというシーンを想定します。

Google DriveのファイルをコピーするGASのコードは下記です。

main.js
const FOLDER_ID = 'XXXXXXXXXXXXXXXX'

function copy() {
  // 1. コピー元のファイルが存在するフォルダを指定する
  const folder = DriveApp.getFolderById(FOLDER_ID)

  // 2. ファイル名は数値の降順なので、
  // イテレーションの先頭のものが最新のファイルになる
  const files = folder.getFiles()
  const file = files.next()

  // 3. 新規ファイル名を組み立てる
  const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd')
  const name = `${date}_🐼チーム_議事録`

  return file.makeCopy(name, folder)
}

FOLDER_IDは、コピーしたいファイルが格納されているフォルダのIDです。https://drive.google.com/drive/folders/XXXXXXXXXXXXXXXXのように、フォルダのIDはURL内に記載されています。

以下、コメントを記載している箇所の解説をします。

コピー元のファイルが存在するフォルダを指定する

DriveAppオブジェクトのgetFolderById(id)メソッドでフォルダを取得します。

返り値はFolderオブジェクトです。次にFolderオブジェクトを使って、このフォルダに存在するファイルを全て取得します。

フォルダに存在するファイル群から目的のファイルを取得する

FolderオブジェクトのgetFiles()メソッドでファイルを取得します。

返り値はFileIteratorというイテレータです。このイテレータの中にはFileオブジェクトが入っています。

例えば、フォルダに格納されている全てのファイルのファイル名を取得するコードは以下のようになります。

const files = DriveApp.getFiles();
while (files.hasNext()) {
  const file = files.next();
  Logger.log(file.getName());
}

Fileイテレータ内のファイルは数値の降順になっているため、ファイル名の先頭に日付を入れておくとイテレータの先頭に前回の議事録のファイルが入ります。

このため、今回はfiles.next()を一度実行するだけで対象のファイルを取得できます。

新規ファイル名を組み立てて、ファイルをコピーする

新しいファイル名は20200620_🐼チーム_議事録にします。

会議当日の日付が入るため、GASの便利オブジェクトUtilitiesformatDateを使って日付を組み立てます。

そして、filemakeCopyでコピーを作成します。第二引数には、ファイルを格納したいフォルダを指定します。

実務で使えるようにブラッシュアップする

これでGoogle Driveのファイルをコピーできました。さらに作成した議事録をSlackに通知する機能と、祝日なら議事録を作成しないようにしましょう。

コピーした議事録のURLをSlackに通知する

作成した議事録のURLをSlackのチャンネルに投稿しましょう。

const SLACK_WEBHOOK_URL = PropertiesService
    .getScriptProperties()
    .getProperty('SLACK_WEBHOOK_URL')

function send(url) {
  const text = `今日の議事録予定地です
${url}`

  const data = {
    "username" : 'Panda User',
    "icon_emoji": ':panda_face:',
    text,
  };

  const params = {
    "method": "POST",
    "contentType": "application/json",
    "payload": JSON.stringify(data),
  };

  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, params)
}

Slackのチャンネルに対して発行されるWEBHOOK URLはGASのプロパティに格納しましょう。GASのプロパティは環境変数のようなものです。WEBHOOK URLは外に漏れないように管理しましょう。

GASで祝日の判定をして、祝日なら議事録を作成しない

祝日判定には、CalendarAppオブジェクトを使います。

function isHoliday() {
  const today = new Date();
  const calendars = CalendarApp.getCalendarsByName('日本の祝日');
  const count = calendars[0].getEventsForDay(today).length;
  return count > 0;
}

祝日を判定する仕組みは下記の記事で詳しく解説しています。

GASで日本の休日・祝日を判定する方法を解説します(Google Apps Script)

週次実行のトリガーを設定する

次は、議事録の作成を週次で実行する設定をしましょう。GASではトリガーを設定することで、毎週自動で関数を実行できます。

トリガーは関数単位で指定できるので、コード全文に記載しているmain関数を指定します。

GASのトリガーの設定方法は、「Google Apps ScriptからSlackとLINEと連携するbotを作る手順を紹介します」という記事で解説しています。

まとめ

これで議事録を自動でSlackに投稿できるようになりました!

Slackへの投稿

今回は日常に潜むルーティンワークの1つ、議事録の週次の作成を無くすためのGASを紹介しました。

「プログラマが知るべき97のこと」という本に「面倒でも自動化できることは自動化する」という章があります。

この章で説かれているようにルーティンワークはプログラムで自動化して、価値を生む活動のために時間を節約しましょう!

コード全文を記載します

今回使ったコードの全文を記載します。

main.js
const FOLDER_ID = 'XXXXXXXXXXXXXXXX'
const SLACK_WEBHOOK_URL = PropertiesService
  .getScriptProperties()
  .getProperty('SLACK_WEBHOOK_URL')

function main() {
  if (isHoliday()) {
    return
  }

  const file = copy()
  const url = file.getUrl()

  send(url)
}

function isHoliday() {
  const today = new Date();
  const calendars = CalendarApp.getCalendarsByName('日本の祝日');
  const count = calendars[0].getEventsForDay(today).length;
  return count > 0;
}

function copy() {
  const folder = DriveApp.getFolderById(FOLDER_ID)
  const files = folder.getFiles()
  const file = files.next()

  // 新規ファイル名を組み立てる
  const date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd')
  const name = `${date}_🐼チーム_議事録`

  return file.makeCopy(name, folder)
}

function send(url) {
  const data = {
    "username": 'panda user',
    "icon_emoji": ':panda-face:',
    "text": `今日の議事録予定地です
${url}`,
  };
  const params = {
    "method": "post",
    "contentType": "application/json",
    "payload": JSON.stringify(data),
  };

  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, params)
}

Happy Coding 🎉