Getting Started

2020/03/05

Google Apps Script

どうも、こんにちは!JellyWareです。

Getting Started!! Riiiver tutorialの第10弾となります。

このシリーズは、Riiiverやプログラミングを学び、初心者の方でもEco-Drive Riiiverを活用したオリジナルアプリを理解して作れるようになることを目指します。

前回、前々回と学んだ「API通信」「JSON」を活用して天気情報をGoogle スプレッドシートで管理できるようにします。

そのために必要な「GAS」というのを今回は学びます。

後半ではglitchを使用します。glitchについては、第6弾をご参照ください。


目次


GAS

GAS とは何かということを説明し、簡単なサンプルコードを実行してもらいます。

GASとは?

GAS とは、Google Apps Script の略です。

Google が提供するプログラミングを行える環境で、JavaScripit をベースにした言語を使用します。(基本的に JavaScript と同じで、GAS 専用の関数を使うことができます。)

Googleが提供するスプレッドシートなどのサービスと紐づけて使用することができます。

スプレッドシートと連携

それでは実際にGAS を使ってみましょう。

事前準備として「Google スプレッドシート」を新規作成する必要があります。
作成するには「Google」アカウントが必要です。ここの一連の流れに関しては、知っていらっしゃる方がほとんどだと思われますので割愛させていただきます。
(調べるとすぐに作成方法を見つけることができると思います。)

作成できた方はツール > スクリプトエディタを選択していきます。

このような画面が立ち上がります。この画面にコードを書いていきます。その前に、少し設定を変更します。

実行 > Chrome V8 を搭載した新しい Apps Script ランタイムを有効にするをクリックするだけです。Chrome V8 を搭載した新しい Apps Script ランタイムを無効にするとなっている方は、既に有効なので不要です。

それでは現在書かれているコードを全部消して、下記のコードを記入してください。

const doGet = (e) => {
  // 現状Activeになっているsheetを取得
  const sheet = SpreadsheetApp.getActiveSheet();

  // 1を追記
  sheet.appendRow([1]);
}

次に、「保存」して実行します。「保存」はフロッピーディスクのアイコンをクリックするだけです。

赤枠のフロッピーディスクをクリックします。

「プロジェクト名の編集」というウィンドウが表示されるので、適当に「test」などの名前をつけてOKをクリックしましょう。

保存ができたら、この「GAS」を外部からも使用できるように設定していきます。

メニューの公開 > ウェブアプリケーションとして導入…を選択します。

選択するとこちらのようなウィンドウが表示されます。
New全員(匿名ユーザーを含む)を選択し導入ボタンを押します。これを選択すると、誰でもこのGASを実行できるようになります。後に支給されるURLの管理には注意しましょう。

「承認が必要です」というウィンドウが出たら、許可を確認ボタンを押します。

ボタンを押すと上記のようなウィンドウが表示されるので、自分のGoogle アカウントを選択します。

ボタンを押すと「警告画面」に移りますが、今回は気にしなくて大丈夫です。左下にある小さな詳細をクリックします。

ボタンを押すと、表示が広がります。左下の小さなtest(安全ではないページ)に移動をクリックします。

ボタンを押して上記の表示が出たら、下へスクロールして右下の許可ボタンをクリックします。

ボタンを押すと次のようなウィンドウが表示されます。

「URL」をコピーして、OKを押します。
(URLをコピーし忘れた方は、メニューの公開 > ウェブアプリケーションとして導入…から確認してください。)

次に、新しいタブを開いてコピーしたURLにアクセスして下さい。

アクセスしたページはエラーになりますが、スプレッドシートに「1」が追記されていれば成功です。ちなみに、新しく開いたページを更新すると「1」がどんどん追記されます。

このように簡単に外部からスプレッドシートを操作することができます。

それでは、使用したコードの解説を行います。

const doGet = (e) => {
  // 現状Activeになっているsheetを取得
  const sheet = SpreadsheetApp.getActiveSheet();
        
  // 1を追記
  sheet.appendRow([1]);
}

doGet()関数を作成しています。doGet()関数は特別な関数で、公開したWebアプリケーションのURLにアクセスがあった、もしくは、「GET通信」が行われた時に実行される関数です。

次に、関数内の処理について順に解説します。

// 現状Activeになっているsheetを取得
const sheet = SpreadsheetApp.getActiveSheet();

Activeなsheetは、スプレッドシートを開くと最初に表示される、または現在開いているsheetのことを指します。

SpreadsheetApp.getActiveSheet()を使用することで、Activeなsheetを取得できます。

特にシートを増やしたり名前を変更していなければ、シート1がActiveなsheetになります。

// 1を追記
sheet.appendRow([1]);

次に、取得したActiveなsheetに値を追記します。

appendRow()は、引数として受け取った配列をシートの最終行に追加する関数です。追加するシートは、appendRow()の前に.を使って連結します。

GAS(JavaScript)の配列は、第9弾で学んだJSONの配列と同じで、値を[ ]で囲み,で区切ります。

// 1,2を追記
sheet.appendRow([1,2]);

例えばこのようにすると、1の隣のセルに2と記入されます。

変更したGASを外部から実行できるようにするには、プロジェクトを更新する必要があります。

先程と同様にメニューの 公開 > ウェブアプリケーションとして導入... をクリックしてください。ここで"プロジェクトバージョン"を New にすることを忘れないようにして下さい。その他は前回の設定が保持されていると思います。

更新ボタン、OKボタンを押します。ちなみに、スクリプトの内容を変えてもURLに変化はありませんのでURLを再びコピーする必要はありません。

URLクエリパラメータを取得

先ほどのコードを少し変更し、URLクエリパラメータを活用して好きな値をスプレッドシートに送信できるようにします。

コード.gs内のコードを全て削除して、以下のコードと差し替えてください。

const doGet = (e) => { // URLクエリパラメータからデータを取得 const queryParameter = e.parameter.test; // 現状Activeになっているsheetを取得 const sheet = SpreadsheetApp.getActiveSheet(); // シートに取得したデータを追記 sheet.appendRow([queryParameter]); }

コードを差し替えたら、プロジェクトのバージョンを Newにして更新します。

また、実行する前に下記のようにURLクエリパラメータを追加してください。queryのところは好きな値に変えて大丈夫です。

https://script.google.com/macros/s/xxxxxx/exec?test=query

上記URLにアクセスすると、今度は「1」ではなくURLクエリパラメータに追加した値が記入されます。(上記URLの場合、queryが記入されます。)

次にコードの解説をします。変更した箇所は2点です。

// URLクエリパラメータからデータを取得     
const queryParameter = e.parameter.test;

2,3行目に追加しました。
e.parameter.URLクエリパラメータの変数名とすることで、URLクエリパラメータの変数に対応する値を取得できます。

今回はtestにしましたが、他の変数名でも問題ありません。

// シートに取得したデータを追記
sheet.appendRow([queryParameter]);

9行目のappendRow()の引数を変更しました。
3行目で宣言した、URLクエリパラメータの値が代入されているqueryParameterに変更しています。


Node.js で GAS

それではNode.js を使ってGASを実行してみましょう。と言っても、前回行ったAPI通信とほとんど同じです。

それでは、glitchでプロジェクトを作成して、requestrequest-promiseのモジュールを追加しましょう。
(前回作成したプロジェクトが残っている場合は、そちらを使用しても問題ありません。モジュールの追加方法については第8弾をご参照ください。また、プロジェクトは非公開にしましょう。)

GASとAPI通信

まずはURLクエリパラメータを使ってスプレッドシートに値を送信します。使用するGASは「URLクエリパラメータを取得」のコードで大丈夫です。

まずは、以下の3つを確認しましょう。

  • URL:GASから支給されるウェブアプリケーションのURL
  • 送信データ:任意
  • 通信方法:GET

URLは、そのままGASから支給されるURLを使用すれば大丈夫です。
通信方法は、doGet()関数を用いるためGETです。
送信データは、スプレッドシートに記入したい値となるため任意としています。

準備ができたら、以下の5行目のURLを差し替えて実行しましょう。

※GASのURLクエリパラメータをtestから変更されている方は、11行目のtestも変更する必要があります。

// request-promiseの読み込み const requestPromise = require("request-promise"); // URL let url = "https://script.google.com/macros/s/xxxxxx/exec"; // みなさんのGASのURLと差し替える // 送信データ const query = "今日の天気は晴れ"; // 最終URL作成 url = `${url}?test=${query}`; // 文字コードの変換 url = encodeURI(url) // API通信 const doApi = async () => { try { const result = await requestPromise({ uri: url, method: "GET" }); console.log(result); } catch (error) { console.log("Error message: " + error.message); } }; // 実行 doApi();

実行すると、このように8行目に設定した値がGoogle スプレッドシートに追加されます。

それでは、コードを解説してきます。と言っても、前回行ったAPI通信のコードとほとんど同じため、変更した点のみ解説します。

// URL
let url = "https://script.google.com/macros/s/xxxxxx/exec";

// 送信データ
const query = "今日の天気は晴れ";

// 最終URL作成
url = `${url}?test=${query}`;

4~11行目を変更しました。

上から順に、「URL」「送信データ」「URLクエリパラメータ」をGAS用に設定しています。

// 文字コードの変換
url = encodeURI(url)

13,14行目を追加しました。

プログラミングで「URLクエリパラメータ」を活用する場合、日本語のままだと文字コード(コンピュータが文字を扱うためのルール)の関係でエラーが発生します。

そのためencodeURI()関数を使って、文字コードの変換を行っています。

OpenWeatherと連携

次に前回活用したOpenWeatherとスプレッドシートを連携させます。
東京の気温と天気をスプレッドシートに送信します。

まずはGASのコードを修正します。

const doGet = (e) => { // URLクエリパラメータからデータを取得 const temp = e.parameter.temp const weather = e.parameter.weather // 現状Activeになっているsheetを取得 const sheet = SpreadsheetApp.getActiveSheet(); // 日時を取得 const date = new Date(); // シートに取得したデータを追記 sheet.appendRow([date, temp, weather]); }

先ほどのコードから、3点修正しました。

// URLクエリパラメータからデータを取得      
const temp = e.parameter.temp
const weather = e.parameter.weather

2~4行目を変更しました。

まずは、URLクエリパラメータの変数名を変更し、「気温(temp)」と「天気(weather)」の2つを取得するようにしました。

// 日時を取得  
const date = new Date();

9,10行目を追加しました。

次に日時を取得しています。
new Date()を使用することで、実行したタイミングの日時を取得できます。

// シートに取得したデータを追記
sheet.appendRow([date, temp, weather]);

最後に、取得したデータをそれぞれシートに追記するように修正しました。

次にNode.jsのコードを変更します。

追加したら、以下のコードの11行目をOpenWeatherのAPI Keyに、33行目をGASのURLに差し替えて実行しましょう。

// request-promiseの読み込み const requestPromise = require("request-promise"); // URL let url = "https://api.openweathermap.org/data/2.5/weather"; // 都市名 const cityName = "Tokyo"; // API Key const apikey = "xxxxxxx"; // みなさんのAPI Keyに差し替える // 最終URL url = `${url}?q=${cityName}&APPID=${apikey}&units=metric`; // OpenWeather const doOpenWeather = async () => { try { let result = await requestPromise({ uri: url, method: "GET" }); // 文字列からJSONに変換 result = JSON.parse(result); return result; } catch (error) { console.log(`Error message: ${error.message}`); } }; // GASのURL let gas = "https://script.google.com/macros/s/xxxxxxx/exec"; // みなさんのGASのURLに差し替える const doGAS = async () => { // OpenWeatherから気温と天気を取得 const openWeatherData = await doOpenWeather(); try { // JSONデータから必要なデータを取得 const temp = openWeatherData["main"]["temp"]; // 気温 const weather = openWeatherData["weather"][0]["main"]; // 天気 // 最終URLを作成 gas = `${gas}?temp=${temp}&weather=${weather}` await requestPromise({ uri: gas, method: "GET" }); } catch(error) { console.log(`Error message: ${error.message}`); } } // 実行 doGAS();

実行すると、このように日付とOpenWeatherから取得した値がGoogle スプレッドシートに追加されます。

それでは、コードを解説してきます。

// request-promiseの読み込み const requestPromise = require("request-promise"); // URL let url = "https://api.openweathermap.org/data/2.5/weather"; // 都市名 const cityName = "Tokyo"; // API Key const apikey = "xxxxxxx"; // みなさんのAPI Keyに差し替える // 最終URL url = `${url}?q=${cityName}&APPID=${apikey}&units=metric`; // OpenWeather const doOpenWeather = async () => { try { let result = await requestPromise({ uri: url, method: "GET" }); // 文字列からJSONに変換 result = JSON.parse(result); return result; } catch (error) { console.log(`Error message: ${error.message}`); } };

まずは、31行目までを解説します。OpenWeatherとAPI通信を行い、東京の情報を取得しています。コードは、第8弾のOpenWeatherとAPI通信をするコードから少し変更しています。

変更した箇所は、2点です。

// 最終URL
url = `${url}?q=${cityName}&APPID=${apikey}&units=metric`;

13,14行目を変更しました。

units=metricというURLクエリパラメータを追加しました。これを追加することで、取得する気温が ℃(摂氏) に変換されます。(追加しない場合は華氏となります。)

// 文字列からJSONに変換    
result = JSON.parse(result);
return result;

24~26行目を追加しました。

OpenWeatherから取得したデータは文字列となっているため、JSONに変換してデータを扱いやすくします。

JSON.parse()を使用することで変換できます。

そして、JSONに変換したresultを戻り値として返しています。

// GASのURL let gas = "https://script.google.com/macros/s/xxxxxxx/exec"; // みなさんのGASのURLに差し替える const doGAS = async () => { // OpenWeatherから気温と天気を取得 const openWeatherData = await doOpenWeather(); try { // JSONデータから必要なデータを取得 const temp = openWeatherData["main"]["temp"]; // 気温 const weather = openWeatherData["weather"][0]["main"]; // 天気 // 最終URLを作成 gas = `${gas}?temp=${temp}&weather=${weather}` await requestPromise({ uri: gas, method: "GET" }); } catch(error) { console.log(`Error message: ${error.message}`); } } // 実行 doGAS();

残りのコードで、取得した情報をスプレッドシートに送信しています。
基本的にはさきほどのコードと同じで、URLクエリパラメータを活用してデータを送信しています。

// OpenWeatherから気温と天気を取得
const openWeatherData = await doOpenWeather();

36,37行目に追加しました。

コード前半で作成した、doOpenWeather()を使用して東京のデータを取得しています。非同期処理のためawaitが必要です。

// JSONデータから必要なデータを取得   
const temp = openWeatherData["main"]["temp"]; // 気温
const weather = openWeatherData["weather"][0]["main"]; // 天気

40~42行目に追加しました。

OpenWeatherから受け取ったままだと、不要なデータが多いため「気温」と「天気」だけを抜き出しています(JSONの扱い方は第9弾で解説しています。)。

// 最終URLを作成
gas = `${gas}?temp=${temp}&weather=${weather}`

44,45行目に追加しました。

先ほど抜き出した「気温」と「天気」をURLクエリパラメータとしてURLに渡しています。このURLクエリパラメータ経由でスプレッドシートにデータが送信されます。

※glitchは、サイトを閉じてもプロジェクトが実行されます。スプレッドシートにデータが送信され続けるので、doGAS();// doGAS();とコメントにして実行されないようにしましょう。


以上がGASでした。

今回はAPIサービスとの連携を行いましたが、他にも様々なことができて便利です。

また、これで基礎編は一通り終了です。

次からは、今回行った最後の「天気情報取得」→「スプレッドシートに送信」の流れを「Eco-Drive Riiiver」で行えるようにします。

コードの内容で不明点があった方は適宜復習していただければと思います。

ご覧くださいましてありがとうございました。