※当エントリはQiita個人アカウントのエントリに転載いたします。
なお当アカウントとエントリはそのうち消えるかもしれません。
ユビレジマーケティングチームのごんどうです。
先日、Glideを使って社内向けにアプリを作ったので、そのときのことをつらつら書いてみようと思います。
(このエントリはUbiregi Advent Calendar 16日目の記事として時を越えて投稿されたものです。)
これは何か
タイトルのとおりノンプログラマーの、開発知識のない人でもGlideで簡単にアプリっぽいものが作れたし、楽しかったよ、というお話です。
#なぜつくったか
ユビレジのメインオフィスは原宿にあります。
ただ手狭になった昨今は徒歩圏内の北参道にもオフィスが増床されており、私は北参道オフィスに生息してます。
さて原宿・北参道エリアはイメージどおりというか何というか、外食するとけっこう高くつくことが多いです。
原宿はほぼ観光地ですし、北参道はダガヤサンドウなどと呼ばれるお洒落スポットでいらっしゃいます。
なので必然的に、お手軽なキッチンカーもランチ候補として挙がってくるのです。
このあたりは、キッチンカーがそこかしこにあります。
しかし。
「じゃあ今日のランチはキッチンカーにしよう!」と思っても
- どこに出店されているのか、改めて考えるとよくわからない(裏道とかにある)
- 曜日によって違うから、今日は何の店なのか行かないとわからない
- 知られざる名店とかもありそう
などの理由から、なかなか決めかねたりします。
暑かったり寒かったりすると、見切り発車で突撃するのもなかなか億劫ですし。
これが普通の店舗なら食べログやらを調べればそれでなんとかなります。しかしキッチンカーは自分や身近な人の情報しか頼りにならない。
でも、そういう情報って案外共有できていない……。
じゃあ作るしかないな、というところで情報共有のデータベースを作ろう、と思い至りました。
#どうやってつくったか
まあタイトルに書いてあるとおり、Glideでつくりました。
社内情報はQiita Teamで共有できるし、slackチャンネルを作って情報交換する、などの手もあったのですが。
やはりツールとして利用できるものがいいなーと思い、かねてより興味だけはあったGlideを使ってみることにしました。
みんな大好きGlide。
Googleスプレッドシートを使って、誰でも簡単にPWAが作れるというアレですね。
この手のものって「かんたん」とか言いつつ実際はそこそこ難しかったりすることがあるのですが。
ノンプログラマーの私が触ってみても「誰でも簡単に」というのはマジだな、という印象でした。
しゅごい。
英語だけのサービスですが、UIがわかりやすくシンプルなので、単語をなんとなく調べさえすれば大体わかる。
英語が苦手でもほぼ問題ありません。
#まずは何がやりたいか整理した
どう手をつけていいかよくわかりませんでしたが、まずは何がやりたいかをぼんやり考えてみました。
必須要件としては
- ユーザーが情報を自分で入力する
- 当日の曜日の情報が見られる
- 地図で見られる
- ジャンルでも分類して見られる
このあたりかなーと考えました。
どういうことかもう少し詳しく説明していきます。
##【ユーザーが情報を自分で入力する】
やっぱり私がひとりでコツコツ入れるのは限界があるし。
何よりポケモンGO的な感じで、新しいキッチンカーをみんなで探して盛り上がってくれたらうれしいな、と思いました。
##【当日の曜日の情報が見られる】
何より「使える」ツールである必要があります。
利用シーンとしては「今日はどこに行こうかな」という時がメインだと考えたので、その日にやっているお店がすぐにわかることが必須です。
##【地図で見られる】
「使える」という観点では「どこにあるか」という情報もすごく重要です。
それにポケモンGOを目指すならやっぱりマップで視覚的にわからないと。
さらにここでポイントなのは、Glideが地図表示可能ってことですね。
なんでもできるGlideさん最高にCool!
##【ジャンルでも分類して見られる】
地図で見られれば基本的にはいいのですが、必要に迫られて見るだけでなく「この辺ってどんなキッチンカーがあるんだろ」とちょっと眺めたりもできたらいいなあ、と考えました。
#何はともあれ作ってみた
この手のものは、とりあえず触りながら知るタイプなので、とりあえずつくってみました。
ひとまず、スプレッドシートに必要になりそうな情報をいれてみます。
ヘッダーに「店名」「住所」「曜日」「ジャンル」などなど。
試しにダミーデータも入れておきました。
で、Glideで新規Appを作成。登録して紐づけてみます。
あとはほとんどクリックで選んでいくだけで、どんどんそれらしくなっていきます。
なんとなく触っただけで構造もすぐ理解できました。
ひととおり組んでみましたが、考えていた要件はほぼクリアしました。
##【ユーザーが情報を自分で入力する】
問題なくできました。
しゅごい。
##【当日の曜日の情報が見られる】
リストをフィルタリングした状態で表示できます。
複数のタブに分けられるので
「月」「火」「水」「木」「金」それぞれでフィルタリングしたタブをつくることで実現しました。
##【地図で見られる】
問題なくできました。住所を入力するだけで自動的に位置を検出してピンを立ててくれます。
ユーザーがボタン一つでリスト表示にも切り替えられる。
さらに「詳細画面で住所をクリックしたらGoogleMapを開く」という挙動にもできるので、ナビゲートも簡単。
Cool!
(が、後に問題が起きる。後段。)
##【ジャンルでも分類して見られる】
同じデータベースを違うビューで表示できます。
なので「All」というタブをつくりジャンル別にリスト表示させるようにしました。
#プロトタイプで公開するも、課題が噴出
とりあえず完成しましたが、いったん周りの人だけにこっそり公開しました。
データが全然集まっていなかったので、ご協力をいただく必要があったのです。
親切な皆さんのおかげでデータがたまり、さらに使い勝手についてのご意見をいただけました。
しかしそこで、割と大き目な課題にぶつかってしまいました。
##【地図がなんかおかしい】
地図表示を眺めていたら、何かおかしいことに気づきました。
原宿・北参道周辺だけのはずなのに何かずいぶん北の方にピンが立ってる……???
連携しているGoogleMapから開くと、本来あるべき場所にちゃんとピンが立っている。
ということは、Glideのほうがおかしいってことだよなー?
と思い調べると、やはり。
どうもGlideはMapBoxという地図ツールと連携しており、それが問題の元になっている様子。
そのまんまのエントリがありました。
【Glide】マップ表示にMapBoxが使われるようになったので位置が不正確です。住所から緯度経度を調べる【Spread Sheet】
住所だけだとずれることがあるとのこと。。
###住所を関数で緯度経度に置き換える
ともかく、住所の表示がおかしい表記の解決方法は参考ページからわかったので、もうそのまんま解決させます。
CSISシンプルジオコーディング実験のAPIを使って、住所から緯度経度を割り出します。
①住所を記入しているセル(ここではD2)を使ってAPI対応のURLを生成する
= "http://geocode.csis.u-tokyo.ac.jp/cgi-bin/simple_geocode.cgi?charset=UTF8&addr=" & D2
②そのURL(ここではE2)に対してIMPORTXML関数を走らせる
= IMPORTXML(E2,"/")
③IMPORTXMLの結果(ここではF2)に対してSPLIT関数をかけ、空白で分割する
= SPLIT(F2," ",true,true)
④緯度と経度が吐き出されるセル(ここではJ2とI2)を使って、緯度経度がコンマと半角スペースでつながれたセルを作る
= J2&", "&I2
これでうまくいった!
……はずでした。
###便利だけどネックになったIMPORTXML関数
しかし、何回か見ていると、緯度経度がうまく書き出されず、地図がアメリカにまでぶっ飛んでしまうという現象が頻発してしまいました。
原因は、IMPORTXML関数。
最初はきちんと書き出されていたIMPORTXMLが、ときどきエラーになってしまい、緯度経度が吐き出されないことがあるのです。
前回見たときは問題なかったセルが、次に見たときはエラーになっていたりするので、どうも読み込みにいくときに何か問題が発生している模様。
Glideがしょっちゅう読み込みにいくため、何か制限に引っかかったのかもしれません。(詳しい原因は結局よくわかりませんでした。)
とにかく、IMPORTXMLはときどきエラーになってしまう。
解決方法が見つからないのであれば、別の方法を探すしかありません。
###データの持ち方を変えた
しかし、うまい解決方法はなかなか見つかりません。
なんとかGoogleマップとデータをつなぎこむ方法がないか考えてみたりしたのですが、うまくいかず…。
ということで、根本的に考え方を変える方法がありました。
で結局、住所を変換させることをやめました。
緯度経度がうまく書き出せないのであれば、ユーザーが登録する際に緯度経度を入力してもらえばよい、としたのです。
ユーザーがちょっと面倒ですが、住所を調べる手間と大して変わらないはず。
ですが、面倒は面倒です。
そのため、住所に関するデータの入力シーンを少しでも減らす必要があります。
これまでは、店舗ごとに住所を登録してもらっていました。
しかし、キッチンカーは基本的に出る場所が決まっていて、その場所を曜日でローテーションしているわけです。
なので、場所のデータベースを別で持ち、それを選択するようにすればよい。
というわけで、スプレッドシート側のタブを一つ増やし、そちらで住所のデータを管理。
店舗側からは場所を選択するという方式をとることにしました。
苦肉の策ではありましたが、データがすっきりして、住所が微妙にずれるようなこともなくなったので、結果的にこのほうがよかったように思います。
緯度経度での登録にしたのも正解でした。
キッチンカーは「このマンションの駐車場」などの微妙な場所に出店されます。
しかし住所で登録してしまうとどうしても建物の位置で検出されてしまっていたので、緯度経度登録になったことで正確な場所が出るようになりました。
##【データベースを関数で処理する必要が出てきてしまった】
さて、ノンプログラマーが今回のアプリを作成するうえで一番ネックになった課題がこれでした。
データベースを複数持つとvlookupを活用する必要が出てきますし、ちょっとした工夫をしようとすると上記のようにIMPORTXML関数だったりSPLIT関数を使ったり、とにかく行中にいわゆるexcel関数を使うケースが出てきます。
ここで問題になってくるのが、ユーザーが情報を新規追加した場合です。
Glideではユーザーが情報を追加すると、自動で行が追加されてデータが入ってきます。
しかし当然関数は手動で入れているので、新しい行には関数の列が反映されていません。
毎回手作業で関数をコピペするわけにもいかないので、情報が新規追加されたら、その行に関数が自動で関数が追加されなければなりません。
###手持ちの技術でなんとかならないか
最初は、「まだ何も書かれていない列に、あらかじめ関数だけコピーしておく」という手を使ってみました。
しかし、新規データは「最終行の次の行」に追加されるという仕様らしく、コピーされている次の行にデータが追加されてしまいました…。
↓
何か関数でうまいこと処理できないか調べてみましたがやはり難しいらしく。
どうもGoogle App Scriptを使わなければ解決しなそうだぞ、というところがわかりました。
###GASで新規行に自動追加させた
全く触ったことがないわけではないのですが、やはりスクリプトを書くとなると、ノンプログラマーには敷居が高い。
恐る恐る調べつつ、何とか以下のようなスクリプトを書き、事なきを得ました。
データが行にあったら、関数の入るべきセルは上の行からコピペしてくる、というスクリプトです。
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
var addressCellCol = 2; //住所列
var importXmlCellCol = 3; //IMPORTXML列
var copyColNum = 9; //コピーするべき列数
//3行目以降で住所列に値があってIMPORTXML列に値がなかったらIMPORTXML列から9行を上の行のセルからコピーする
for(var i = 3; i <= lastRow; i++) {
if(sheet.getRange(i, addressCellCol).getValue() && !sheet.getRange(i, importXmlCellCol).getValue()){
sheet.getRange(i-1, importXmlCellCol, 1, copyColNum).copyTo(sheet.getRange(i, importXmlCellCol));
}
}
}
(掲載用に一部書き換えたりしたので、間違ってたらすみません…。)
これをシートの編集をトリガーとして走らせました。
他にもコピーが必要なシーンがいくつかありましたが、この応用で何とか乗り切っています。
というか、Glide以外でもふだん起こりがちな処理なので普通に便利ですね。このスクリプト。
##【開くと最初は必ず「月曜」のマップが開かれちゃう】
Glideの場合、どうもホームのタブが自動的に決まっているらしく、最初に開いたときに表示されるタブが決まっています。
今回はそれが「月曜」のタブらしく、アプリを立ち上げると必ず月曜タブが開かれます。
しかしプロトタイプを利用してくれた方から、「他の曜日に利用する場合、いちいちタップするのは煩わしい」という意見をいただいた。
そりゃそうだよなー、と思うので、これも改善させる必要が出てきました。
###タブの設定でなんとかならないものか→ならない
この開かれるタブを何とかいじれないか見てみましたが、そんな設定は見当たりませんでした。
なのでタブをいじることは断念しました。
###そもそものアプリの在り方を再検討
しかし、そもそも月曜から金曜まで、すべての曜日の地図が見られる必要があるのでしょうか?
もちろん、あるに越したことはないのですが。
実際に必要なのは「その日に行ける場所の地図」です。他の日はジャンルや場所別で見られれば十分なはずです。
そこで思い切って、曜日で分けることをやめました。
次に、「今日行けるところ」をどう出すかの工夫が必要です。以下のようなセルを作ることでこれを解決しました。
=if(text(WeeKDAY(TODAY()), "DDD")=H2, 1,"")
H列に、「月」「火」「水」「木」「金」と曜日の記載があるので、TODAY()つまり今日の曜日が同じであれば「1」とフラグを立てる…というやりかたです。
Glide側で「曜日フラグが立っている行のみ」というフィルタリングをかければ、当日のリストだけが表示されます。
この改善でかなりアプリがスッキリして、使いやすくなりました。
#ひとまずの完成形
結局今はこうなっています。
ホームタブ。開いた曜日にやっているキッチンカーが地図表示されます。
カテゴリタブ。クリックするとカテゴリに属した店舗が一覧表示されます。 (ただ、カテゴリは自由記入なのでほとんど1ジャンル1店舗になってしまっている) 出没地点タブ。 ここから地点登録をするとともに、各地点ごとに全曜日の店舗が見られます。 店舗詳細画面。 店舗名やカテゴリなどの情報のほか、ユーザーが写真を投稿できます。 また、ボタンクリックでGoogle Mapも開けます。 店舗詳細の下部。 メニュー写真を投稿できるほか、ユーザーコメントも投稿できます。 (まだほとんど使われていませんが)#いろいろやってみて
ほかにも、親子関係を持たせるためのやり方をいろいろ調べたり、細かい工夫をしたところは細かくありますが、長くなってきたのでまたの機会にします。
とにかく、最初は「めちゃ簡単!」ってとこだったのですが、課題を解決するところからちょっとだけ難易度が上がりました。
とはいえ、課題をひとつずつつぶしていくのはゲーム的な要素があってなかなか面白かったです。
また、仕様を考え、整理し不要な要素を切ったり、データの組み方を見直し、やっては失敗し、チャレンジして成功し…といった過程はアプリ開発の流れを疑似体験できたような気がして、新鮮な体験でした。
「こういうのもあったら便利だよな」という機能があっても、時にはバッサリ捨てることも必要。
って、外から見るといくらでも言えますが、当事者になるとなかなか勇気が要りますね。
でも、やってみるとそれを解決するための新しいアイデアが出て、結果的にうまくいったというのは、特に面白い体験でした。
しかし楽しかったと同時に、めちゃくちゃ疲れました……。
開発の皆さんはこんなことをもっとずっと高度な次元で日々試行錯誤しているんだなーと感じられて、改めて頭が下がります。
何はともあれ、楽しいのでノンプログラマーも臆せずGlideで遊んでみるとよいと思います。
楽しいよ!