Voiceflow夏休みAdvent Calendarの18日目です。
Googleスプレッドシート連携シリーズ第4回です。検索・登録機能まで実装した「ゼロカロリースキル」に「更新」機能を追加していきたいと思います。
前回のあらすじはこちら。
ではまずスキルの実行イメージから。
アレクサ、「ゼロカロリースキル」をひらいて
ゼロカロリースキルです。カロリーを知りたい食べ物の名前を言ってください
カツカレーを更新
カツカレーは、カツとカレーのカロリーが相殺されるから、という理由で、現在登録されています。更新する理由をお聞きします。最初に、理由、最後に、から、をつけていってください。例えば、理由、ほにゃほにゃだから、という感じで言ってください。
理由、カツとカレーのカロリー同士が喧嘩して相殺されるから
カツカレーは、カツとカレーのカロリー同士が喧嘩して相殺されるから、カロリーゼロ、で更新します。よろしいですか?
はい
カツカレーを更新しました。カロリーを知りたい食べ物の名前を言ってください・・・
さぁ、ではやってみましょう。
スキルの全体図
前回と同様に、更新用のフローを別に追加します。線が徐々にすごいことになってきてますね・・・こうならないように実際にはFlow Block使って処理ごとにフローを分けることをおすすめしますが、今回は全体のわかりやすさを優先してます。
Interactin Blockへ更新フローの追加
まずは、最初から更新を目的とする場合です。前回と同じように、更新用のフローを新たに作っていきますので、更新用のフローへの入口となるインテントを追加します。Home -> Speak の次にあるInteraction Blockをクリックします。
Interaction Blockの設定を順に見ていきます。Slotタブは今回も変更不要です。
Intentsタブに新たに更新用インテントのサンプル発話を登録していきます。"+ Add Intent"をクリックして、インテント名は"update_intent"、サンプル発話は以下のような感じで登録します。
Choicesタブに更新用のフローを追加します。"+ Add Choice"をクリック、ドロップダウンから先ほど作成した"update_intent"を選択、"+ Add Variable Map"をクリックして、他のインテントと同じように、スロット"[slot_recipe]"(食べ物名を受け取るスロット)と変数”varRecipe”(食べ物名を入れておくフロー変数)のマッピングを作成します。
これで、更新用フローができました。ここからブロックを繋げていきます。
更新フローの作成
更新の場合、すでに食べ物名が登録されていることが前提となります。が、万が一、登録されていない場合はどうなるでしょうか?ということで、一旦登録されているかどうかのチェックを行います。
Integration Blockを使って食べ物名の存在チェックをしましょう。Integration Blockをおいて、先程のInteraction Blockから線をつなげます。
Integration Blockの設定を行います。基本的にやっていることは「検索」と同じです。
- 存在するか?の検索なので"Retrive Data" を選択
- すでに連携済みのGoogleアカウントを選択
- スプレッドシート名「ゼロカロリースキル」、シート名「recipes」を選択
- スプレッドシートのカラム名"recipeName" が 変数"varRecipe" と一致するものを検索
で、スプレッドシート検索の結果と変数と紐付ける Mapping Output のところですが、後でやる「更新」の場合に備えて、少しだけ前のやり方と変わります。順にやっていきます。"+ Add Mapping"をクリックして、
カラムのところは"Row Number"を選択します。"Row Number"はスプレッドシートの何行目か?を取得するために予め用意されているビルトインの設定で、これを取得するようにします。で、これを保存しておく変数を作ります。変数を選択するドロップダウンの一番下に"Create variable"があるのでこれをクリックします。
左のメニューが変数のメニューに変わりますので、ここでフロー変数"varRowNum"を作成します。
再度、Integration BlockのMapping Outputの設定に戻って、カラム"Row Number"と変数"varRowNum"を紐付けます。
最後に、検索時と同じようにカラム"reason"と変数"varReason"を紐付けるマッピングを追加すればOKです。
最終的にはこんな感じです。
ちょっと見にくいので、Expandで表示したものも貼っておきます。
では、Test Integrationをクリックしてテストしてみます。
適当にすでに登録済みのものを入力してみてください。今回は「ラーメン」で検索してみました。
検索のときと結果は変わらないですよね。1点だけ補足しておくと、先程Mapping Outputで設定した"Row Number"はこの結果の"row"の値になります。
実際のスプレッドシートの方も見てみましょう。確かに行番号が取れているのがわかります。更新時は、この行番号をとっておくことが重要になります。
スプレッドシートの検索処理に失敗した場合のフローも用意しておきます。ただし、このフローは結果が0件の場合ではなく、あくまでもスプレッドシートへのアクセスで何か問題があった場合なのでご注意ください。
スプレッドシートの検索結果をチェックします。If Blockをおいて、以下のように、"varReason"の値が定義されていない、すなわち、検索結果が0件だったかどうかをチェックする条件を入力します。ここは expression を使ってください(expressionの使い方はTIPS #12の「⑤⑥⑦ If Blockで検索結果の判定」を参照してください)
ちょっと条件のところは見にくいのでいかに貼っておきます。変数のところはそのままコピペでは動かないので注意してくださいね。
equal({varReason},undefined)
"varReason"の値が定義されていない、すなわち、検索結果が0件だった場合は、更新ができないので、その旨を発話させて、
最初のInteraction Blockに戻してやります
ということで、お気づきになられた方がいらっしゃるかもしれませんが、これ、検索フローでやったこととほとんど同じです。
なので、こういう場合は、ブロックのコピペを使うと良いです。ということで、先程のIf BlockとSpeak Blockをコピペで作る手順もご紹介しましょう。
ブロックのコピー&ペースト
この状態から・・・
Shiftキーを押しながら、検索フローのIf Block と Speak Blockをクリックします。少しだけハイライトされているのがわかりますか?(違いが見えにくいですよね・・・これは既に開発元に修正要望上がってるのでそのうち治るかもしれません。)
この状態で、WindowsならCtrl+C、MacならCommand+Cを入力すると、以下のように選択したブロックがクリップボード上にコピーされたことがわかります。
ペーストしたい場所がだいたい中心になるようにCanvasを動かして、WindowsならCtrl+V、MacならCommand+Vを入力してみてください。すると、
あとは、位置を整えて、線を引いて、文言等修正しないといけないところは修正すればOKです!かんたんですね! If BlockでExpression使う場合とか、Code Blockで似たようなコードを書く場合などは、煩雑だしミスも起こりやすいと思うので、コピペもうまく活用してもらえればと思います。
少し脱線しましたが、続けましょう。If Blockで登録されていることが確認できたら、更新の準備ができたことになりますので、更新後の理由を取得していきます・・・ってこれも聞いたことありますよね?
これ、登録時のフローとほぼ同じですね!ということは、ここフローごとマルっとコピペして修正すればOKですね!
先程は、Shiftキーを押しながら、ブロックを順にコピーしましたが、Shiftキーを押しながら範囲選択してコピーすることもできます。
で、ちょっとCanvasを動かしてペーストします。
同じフローがまるっとコピーされました!範囲選択した範囲内に限り、線もコピーされていますね。あとは、更新フローからつなげて、修正していけばOKというわけですね。楽ちんです!順次修正していきます。
更新フローの作成(続き)
まず、最初のSpeak Block。ここは文言の修正だけです。登録時は理由の発話の仕方だけを説明していましたが、更新時は今登録されている理由の内容も聞いた上で、理由の発話について説明します。
次、実際に理由を取得するInteraction Block。ここは変更する必要なしです。理由を取得するだけなので、登録時も更新時もやることは全く変わりませんので、同じインテントをそのまま使えます。
更新の確認を発話するSpeak Block。ここも「登録」を「更新」に変えるだけです。
確認に対して「はい」「いいえ」を受け取るInteraction Block、ここも変更する必要はありません。
で、「いいえ」の場合、ここも「登録」を「更新」に変更するだけです。そして、最初の検索のInteraction Blockに戻します。
では、Integration Blockで更新処理です。
Integration Blockでスプレッドシートの更新
Integration Blockを登録フローからコピペしてきたので、現在はスプレッドシートへの(新規)登録になっています。
これを更新処理に変更していきます。まず最初の”I want to”のところ、更新なので"Update Data"を選択します。
アカウントは選択するだけです。
スプレッドシートの設定が消えているので、検索・登録と同じように設定してください。
次に、With Settingで条件を設定するのですが、設定項目が、検索の時とも登録の時から変わってますよね?
更新時は、「何行目("Row Number")のカラム("recipeName"と"reason")をどう更新するか?」という設定の仕方になります。したがって、スプレッドシートの「何行目」のデータなのか?ということが必要になります。更新フローの最初で「何行目」か?を事前に取得していたのはこのためなのです。
ということで、必要なデータは全て揃っていますよね?それぞれ入力しましょう。Row Numberは"{varRowNum}"、recipeNameは"{varRecipe}"、reasonは"{varReason}"というふうに、変数を設定します。終わったらNextをクリックします。
では、Test Integrationでテストしてみましょう。
更新の場合は、既存のデータを変更することになりますので、こういう警告が出ます。この辺の配慮は嬉しいですね。Confirmをクリックして進めましょう。
では更新します。既に登録されている食べ物名、かつ、その行番号を設定して、RUNをクリックします。
以下のように"Updated"となっていればOKです。
スプレッドシートの方も更新されていますね!
はい、これで今日のメインテーマであるスプレッドシートの更新処理は完了です!残りのフローも修正していきましょう。
スプレッドシート更新エラーの場合のメッセージも「登録」から「更新」に変えます。
スプレッドシート更新に成功した場合もメッセージも「登録」から「更新」に変えます。そして、最初の検索のInteraction Blockに戻すように線をつなげます。
はい、これで更新フローは完了です。おつかれさまでした!
更新フローのテスト
ではテストです。
うまく更新できていますね!登録されていないものを更新しようとした場合のテストもやっておきましょう。
うまくいきませんね・・・・なぜかスプレッドシート自体へのアクセスが失敗した流れになってしまいます・・・検索フローのときはきちんとできていたのに・・・
で、調べててみたんですが、更新の場合は更新対象となるレコードの行番号が必要なので、row numberを取得するようにしているんですが、どうもこれがあると、Integration Blockの時点でfailになってしまう様子。ここちょっと不具合な気もします。ということで暫定ですが、ここだけ少し線を変えておきましょう
はい、これでテストします。
とりあえず良しですかね。ここは開発元にも確認投げてますので、回答きたらまた修正したいと思います。
ということで、検索・登録・更新と完了しましたので、残りは削除ですね。これでGoogleスプレッドシートでできることは一通りご紹介できたことになると思います。よろしければ次回もご覧くださいませ。