こんにちは、BOXIL開発に携わっている、新卒エンジニアの高砂と申します!
私はスマートキャンプにてこれまでインターンとして1年、新卒社員として1年ほど働いています。
皆さんは、普段の業務の中で「これって非効率だな」と感じた経験はありますか?
私はこれまで業務の中で非効率を見つけると、社内コミュニケーションツール「Slack」上で動くbotをGASで開発などして解決していました。
本記事では、開発した業務効率化botの内でお気に入りのものを3つほどご紹介し、その中でも特に注力した1つについて詳しくお話ししていきます!
業務効率化bot3選
来客対応サポートbot
スマートキャンプでは「RECEPTIONIST」という受付サービスを利用しています。
来客時にSlack通知する機能があり非常に便利なのですが、この通知には来客名しか表示されず、誰の来客か分からないという弱点があります。
なのでこれまでは、その日の受付担当者が来客名とマッチするGoogleカレンダー上の予定を目視で探し、来客先の社員に連絡するというフローで対応していました。
しかしそれが非効率だと思った私は、下記のように自動で対応する予定を探し、連絡してくれるbotを作りました。
詳しくはこちらの記事で説明しているので、良ければご覧ください。 tech.smartcamp.co.jp
質問精度向上bot
入社したての頃、新卒の私は「良い質問の仕方」を身につけるのに苦戦しました。
質問が曖昧だったり、過去に聞いた事があるのにまた質問してしまったりしていました。
かといってそれを質問する度に意識するのも非常に難しいです。
なので私が質問する度に、botが質問文かどうかを下記のようなロジックで判定した上で、質問文の場合は「良い質問の仕方」を意識させるような問いかけをするにしました。
var questionWords = ['ですか?', 'ますか?'] if (receivedMessage.indexOf(questionWord) !== -1) { postMessage(message) }
これにより私は、質問の度に「良い質問の仕方」を毎回意識することができ、自然と良い質問ができるようになりました。
日報半自動生成bot
スマートキャンプには「毎日退勤時に日報を書く」という文化があります。
その文化自体はとても良いものだと思うのですが、「日報の作成作業」にも非効率が潜んでいました。
それを解決する為に下記のようなbotを作成しました。
詳しくは次のセクションでお話ししていこうと思います。
日報半自動生成botの詳細
背景
先述した通り、スマートキャンプには「毎日退勤時に日報を書く」という文化があります。
その目的は2つあり、1つは業務報告、1つはコミュニケーション活性化です。
日報には下記のように「本日のタスク」と「雑感(ひとことコメントのようなもの)」を記載するので、2つの目的を達成できるようになっています。
なので日報を書くこと自体は重要なのですが、日報の前半の「本日のタスク」については、各自がGoogleカレンダーを見ながら手打ちで入力するという作業が発生していました。
「その作業は効率化し、雑感に時間をかけるべき」だと考えた私は、Googleカレンダーから自動で「本日のタスク」を抽出できるのでは考えました。
要件定義
前述の課題を解決するにあたって、下記要件が必要と考えました。
- Googleカレンダーから予定名を抽出して一覧化してくれる事
- 一覧を日報の定形フォーマットに挿入してくれる事
- 上記を特定の時間に共有してくれる事
これらを実現してくれるbotをGASで開発してみました。
実際の実装内容
実装は下記のように行いました。6つのセクションに分けて解説していきます。
①ーーーーーーーーーーーーーー function main() { var sheetId = PropertiesService.getScriptProperties().getProperties().sheetId var spreadsheet = SpreadsheetApp.openById(sheetId) var formSheet = spreadsheet.getSheetByName('form') var formSheetValues = formSheet.getDataRange().getValues() var idTableSheet = spreadsheet.getSheetByName('idTable') var idTableSheetValues = idTableSheet.getDataRange().getValues() ②ーーーーーーーーーーーーーー formSheetValues.slice(1).forEach(function (formSheetRow) { var calendarId = formSheetRow[1] var calendar = CalendarApp.getCalendarById(calendarId) if (calendar !== null) { var events = calendar.getEventsForDay(new Date()) var eventMessage = '' ③ーーーーーーーーーーーーーー events.forEach(function (event) { var title = event.getTitle() var status = event.getMyStatus() if (title !== '' && status != 'NO') { eventMessage += '・' + title + '\n' } }) var mention = makeMention(calendarId, idTableSheetValues) var message = makeDailyReport(eventMessage, mention) postMessage(message) } }) } ④ーーーーーーーーーーーーーー function makeMention(calendarId, idTableSheetValues) { var SLACK_ID_COLUMN = 2 var EMAIL_COLUMN = 3 var mention = ‘’ idTableSheetValues.forEach(function (idRow) { if (idRow[EMAIL_COLUMN] === calendarId) { mention = ‘<@‘ + idRow[SLACK_ID_COLUMN] + ‘> ‘ } }) return mention } ⑤ーーーーーーーーーーーーーー function makeDailyReport(message, mention) { return ‘今日の日報フォーマットを持ってきたわん!\n\n’ + mention + ‘*【日報】’ + Moment.moment().format(‘YYYY年MM月DD日(dddd)’) + ‘*’ + ‘\n```本日のタスク```\n’ + message + ‘\n```雑感```’ } ⑥ーーーーーーーーーーーーーー function postMessage(message) { (中略) }
まず①では、スプレッドシートから利用者情報を抽出しています。
アンケートで集めた日報半自動生成botの利用希望者一覧が記載されているスプレッドシートから、それぞれのメールアドレスおよびSlackのメンバーIDを引っ張ってきています。
①ーーーーーーーーーーーーーー function main() { var sheetId = PropertiesService.getScriptProperties().getProperties().sheetId var spreadsheet = SpreadsheetApp.openById(sheetId) var formSheet = spreadsheet.getSheetByName('form') var formSheetValues = formSheet.getDataRange().getValues() var idTableSheet = spreadsheet.getSheetByName('idTable') var idTableSheetValues = idTableSheet.getDataRange().getValues()
次に②では、①のメールアドレスをもとに対応するGoogleカレンダー、およびそこに記載されている今日の全予定を取得しています。
②ーーーーーーーーーーーーーー formSheetValues.slice(1).forEach(function (formSheetRow) { var calendarId = formSheetRow[1] var calendar = CalendarApp.getCalendarById(calendarId) if (calendar !== null) { var events = calendar.getEventsForDay(new Date()) var eventMessage = ‘’
そして③では、②の全予定の中で「不参加」以外の予定の予定名を取得し、変数に代入しています。
③ーーーーーーーーーーーーーー events.forEach(function (event) { var title = event.getTitle() var status = event.getMyStatus() if (title !== '' && status != 'NO') { eventMessage += '・' + title + '\n' } }) var mention = makeMention(calendarId, idTableSheetValues) var message = makeDailyReport(eventMessage, mention) postMessage(message) } }) }
④では、①のメンバーIDからSlackでのメンション文言を生成しています。
④ーーーーーーーーーーーーーー function makeMention(calendarId, idTableSheetValues) { var SLACK_ID_COLUMN = 2 var EMAIL_COLUMN = 3 var mention = ‘’ idTableSheetValues.forEach(function (idRow) { if (idRow[EMAIL_COLUMN] === calendarId) { mention = ‘<@‘ + idRow[SLACK_ID_COLUMN] + ‘> ‘ } }) return mention }
そして⑤では、③の予定名情報および④のメンション文言を用いて、botが実際に送るメッセージ内容を生成しています。
⑤ーーーーーーーーーーーーーー function makeDailyReport(message, mention) { return ‘今日の日報フォーマットを持ってきたわん!\n\n’ + mention + ‘*【日報】’ + Moment.moment().format(‘YYYY年MM月DD日(dddd)’) + ‘*’ + ‘\n```本日のタスク```\n’ + message + ‘\n```雑感```’ }
最後に⑥では、⑤で生成したメッセージを実際に送信する処理を行っています(良くある処理なのでこちらは省略させて頂きました)。
⑥ーーーーーーーーーーーーーー function postMessage(message) { (中略) }
以上の6つのセクションによって、今回の日報半自動生成botを実装しました。
実際の利用状況
最初は自分の為に作り始めたbotでしたが、社内公開してからクチコミで色んな方に利用して頂き、今ではなんと30人以上が利用しています!(全正社員の4割ほどにあたります)
また、利用者から寄せられた声をもとに定期的にアップデートもしており、好評をいただいています。
まとめ
最近の業務ツールはAPI連携が盛んであり、特にGASでSlack用のbotを作るのは自由度が高いです。
業務ツールの移り変わりと共に非効率な作業も発生しがちなものなので、皆さんもそれをbotで解決してみてはいかがでしょうか?
スマートキャンプのミッションである「テクノロジーで社会の非効率を無くす」を、引き続き社内でも体現していこうと思います!