Ateam Brides Inc. Advent Calendar 2021の23日目は
株式会社エイチームブライズ の馬渕 @MAB_cx が担当します!
私の所属するチーム「DX推進部」
- 私は、ビジネス職種でプログラミング未経験のよわよわ会社員です。
- そんな会社員が紆余曲折あり、DX推進部に所属する事になりました。
- DXって…!と思いながら早3年。このあたりの紆余曲折は、またどこかで記事にしたいと思います。
- 当社は、デザイナやエンジニアとの距離が近く、企画や事業活動に対して一緒に取り組む事が多く、
DX推進部も例外ではありません。- 企画・PM担当が50%、エンジニアが50%で構成されており、システムについて一緒に考える日々。
- 勉強しながら、私自身も、Saasを用いたノーコード開発やGASでの効率化に夢中な今日この頃です。
今回のアドベントカレンダーは…
- DX推進に携わり、システムについて思いを馳せる事も多くなった3年前から、
アドベントカレンダーには毎年参加しています。 - 今年は、この機会に、コードの開発を疑似体験しようと思います!
DX推進部が抱える由々しき事態
-
突然ですが、リモートだと、本の貸し借りって難しいですよね。
-
DX推進部は、リモートワークが主流になる前は「DX文庫」と称して
本を持ち寄って、紹介や貸し借りを頻繁に行っていました。- ※DX推進部に限らず、会社全体でその文化は根強いです。
-
DX文庫の一部 ↓(カバーを外す癖のある私)
-
リモートワークが主流になってしまい、貸し借りも難しい今、
誰かのおすすめ、やこの本よかった、というような
良本のインプットが困難になってしまったと思いませんか? -
テキストで、この本よかったよ~とお勧めする事はあっても、たいてい共有はURLです!
- 後から本のタイトルを思い出せない…検索もできない…
- これは由々しき事態です。
- そこで決めました。
仮想本棚bot「DXな本棚」を作ろう!
- 目指す姿は4段階です。
レベル1
- 定期でSlackでおすすめの本がレコメンドされるようにしたい
- 目指すは部署内コミュニケーション活性化!インプット促進!
- 当社はコミュニケーションにSlackを活用し始めたところで、色々と機能を試したいタイミングでもあります。
- GASと組み合わせたbotも手軽に作れそうです。楽しそうです。
- 目指すは部署内コミュニケーション活性化!インプット促進!
レベル2
- Slackからおすすめの本を登録できるようにしたい
- アウトプット促進!
- コミュニケーションチャネルで投稿が出来る、というのは
URLで共有する=後から検索できない、を防ぐ良い手立てのように思えました。
- 私がSlackのワークフローを使ってみたい!という下心もあります。
今回目指す姿
- レベル2までを図示すると、こんな感じになります。
ここまで行けたら嬉しい姿
レベル3
- 気になるキーワードをつぶやいたら、メンバーが登録した本がレコメンドされるようにしたい
レベル4
- できれば登録ランキングを毎月流して登録&読書を促進したい
- ここまで行きつけば、DX推進部をはじめとする当社の読書習慣は強固なものになる事でしょう。
- ただし、ここまで作りこむには私には相当な時間とスキルの上達が必要と想定されるため、
また別の機会にしたいと思います。
- ただし、ここまで作りこむには私には相当な時間とスキルの上達が必要と想定されるため、
前提
-
この記事は、初心者の私がGASやSlackの理解促進のため、
インプットと同時にアウトプットをすることによる定着を目指す記事となっています。- アドバイスやご指摘等お待ちしています
-
そのため、回りくどいやり方をしていたり、参考にならない部分も多々あるかと思います。
-
何卒ご容赦ください。
-
また、今回、先輩(@rf_p)に意味などを教えていただきながら作成しました。
- 先輩は、かつて1人アドベントカレンダーなる修行を実践し、
「GoogleAppScript」にまつわる記事で埋め尽くした私の師匠です。
- 先輩は、かつて1人アドベントカレンダーなる修行を実践し、
- 今回は自分が学ぶ用に作っているため、
コードの中に師匠にヒアリングした意味などが入っている事があります。- ※メモを取り除いたコードも添えておきます。
今日はレベル1に挑戦!
- まずはデータが集まる所の構築を先に進めます。
- Slackで集める代わりに、
何も設定しなくてもスプレッドシートにデータを蓄積してくれるGoogleフォームを代用します。
- Slackで集める代わりに、
GoogleBooksAPIでISBNコードから書式情報を取得する
- 登録を促進したいので、登録する情報は少なければ少ないほどいい という事を突き詰めた結果、
「ISBN」だけ入力してもらう、という方法を採用することに。- タイトル、著者名などは、GoogleBooksApiから取ってくる、という手法です。
- タイトル、著者名などは、GoogleBooksApiから取ってくる、という手法です。
- こちらの記事を参考にさせていただきました。
最終的にはこのようなテーブルになります。
薄い青色の部分が、APIによって入力してもらう部分です。
const ISBN_COLUMN = 5;
//ISBNが入っているセルは5列目に位置する
//constは定数。再代入はできない。
//letは変数。代入も可能。
//varも変数だが、古い。
function onEdit2(e){ //eに編集されたデータが入っている
// 編集カラムが5列目であればsetBookInfo関数を呼び出す
const range = e.range;
for (let row = range.getRow(); row <= range.getLastRow(); row++) {
// for文は繰り返しを意味する構文。forは1行で書くのが良い。
// getRowで初めの行をとり、getLastRowで最終の行をとる、row++はループを回すごとに+1を足す
for (let column = range.getColumn(); column <= range.getLastColumn(); column++) {
// getColumnで初めの行をとり、getLastColumnで最終の行をとる、column++はループを回すごとに+1を足す
if (column == ISBN_COLUMN) {
setBookInfo(row); //setBookInfoのなかに、rowの値を渡す
}
}
}
}
function setBookInfo(row){
Logger.log(row);
const sheet = SpreadsheetApp.getActiveSheet(); // 開いているシートのオブジェクトを取得
const isbn = sheet.getRange(row, ISBN_COLUMN).getValue(); // 更新した行の5列目(ISBNが入っているセル)の値を取得し、変数isbnに代入
// Google Books APIを叩いてレスポンスを取得
const response = UrlFetchApp.fetch('https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn + '&country=JP');
const data = JSON.parse(response.getContentText()); //JSON形式のレスポンスをオブジェクトとしてパース
const bookInfo = data.items[0].volumeInfo; //本の情報を取得
sheet.getRange(row,6).setValue(bookInfo.title); // 8列目にタイトルを挿入
sheet.getRange(row,7).setValue(bookInfo.canonicalVolumeLink); // 9列目にリンクを挿入
sheet.getRange(row,8).setValue(bookInfo.authors.join()); // 10列目に著者を挿入
sheet.getRange(row,9).setValue(bookInfo.publishedDate); //11列目に発行日を挿入
}
トリガー設定はこちら
メモがないバージョン
こちらをクリック
const ISBN_COLUMN = 5;
function onEdit2(e){
const range = e.range;
for (let row = range.getRow(); row <= range.getLastRow(); row++) {
for (let column = range.getColumn(); column <= range.getLastColumn(); column++) {
if (column == ISBN_COLUMN) {
setBookInfo(row);
}
}
}
}
function setBookInfo(row){
Logger.log(row);
const sheet = SpreadsheetApp.getActiveSheet();
const isbn = sheet.getRange(row, ISBN_COLUMN).getValue();
const response = UrlFetchApp.fetch('https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn + '&country=JP');
const data = JSON.parse(response.getContentText());
const bookInfo = data.items[0].volumeInfo;
sheet.getRange(row,6).setValue(bookInfo.title);
sheet.getRange(row,7).setValue(bookInfo.canonicalVolumeLink);
sheet.getRange(row,8).setValue(bookInfo.authors.join());
sheet.getRange(row,9).setValue(bookInfo.publishedDate);
}
詰まったところ
Rangeの感覚がつかめないなど、苦戦したところもありますが、
特に難しかったのは↓のエラーです。
エラー Exception: UrlFetchApp.fetch を呼び出す権限がありません。
必要な権限: https://www.googleapis.com/auth/script.external_request
この記事で原因は特定できたものの
標準のイベントをトリガーにしていたため、なかなかエラーから抜け出す事ができませんでした。
結局、onEditからonEdit2に変更しました。
(上記コードがonEdit2になっているのはその理由です)
onOpen , onEdit など 標準のイベント から UrlFetchApp.fetch が呼びされている場合は何をしてもエラーとなる。この場合は ソースで onEdit2 など別名に変更し,「トリガー」に登録させる。onEditのままトリガーに登録させることもできるが,この場合2回実行されてしまい片方がエラーとなる。
師匠(@rf_p)からフィードバック頂いた、残り考慮すべき部分
- エラーが出たとき(responseの中身が欠けている時)の回避が定義できていない。
- レベル2でバージョンアップできれば挑戦!
- functionの中に詰め込みすぎると、メンテがしづらいので分割したほうが良い。
- sheet.getRange(row,6).setValue(bookInfo.title) は通信数が多い。
- 重くなる可能性があるので、setValuesでまとめて処理する方が良い。
- (初心者がそこまでやってたらビビる)
- 今回はリアルタイム性を求めていない&処理数も多くないので妥協とします。
- 重くなる可能性があるので、setValuesでまとめて処理する方が良い。
レベル1、終了!
まさか動くとは…という感動もさておき、ここから折り返しです!
レベル2は追って追記します!
①Slackから投稿
②Slackへ通知 にチャレンジします!
Ateam Brides Inc. Advent Calendar 2021の24日目は、
我らが代表が聖夜にふさわしいスペシャルな記事をお送りします!!