Googleマップの場所の情報を取得ツールを作成しました（Googleマップ＋Googleスプレッドシート＋Google Places API）

# 目的
Google Apps Scriptと[Google Maps Platform](https://cloud.google.com/maps-platform/?authuser=1)の勉強のため、Googleスプレッドシートと[Google Maps Platform](https://cloud.google.com/maps-platform/?authuser=1)の[Places API](https://developers.google.com/places/web-service/intro?hl=ja)を用いて、検索施設名から場所の情報（Googleマップの住所や座標、施設名称等）を取得するツールを作成してみました。

### [Places API](https://developers.google.com/maps/documentation/geocoding/start?authuser=1)
- 今回は、Google Maps Platformの中でも「[プレイス](https://developers.google.com/maps/documentation/?hl=ja)」に分類される「[Places API](https://developers.google.com/places/web-service/intro?hl=ja)」を使用しています。
- Places APIは、HTTP リクエストを使用して、多くの場所の最新情報を取得できます。

### Google Apps Script
- Google Apps Scriptは、Google社が提供するJavaScriptベースのプログラミング言語であり、クラウドサーバ上で動作します。
- Gmail、Googleスプレッドシート、Googleカレンダー、Googleドライブ、Google翻訳などのGoogleが提供する数々のアプリケーション群をプログラミングにより操作可能です。

# 実行環境
この記事ではGoogle Apps Scriptを使っています。
コードを実行するためにはGoogle Maps PlatformのAPIキーが必要です。

>※Google Maps Platform APIキーの取得・発行についてはこちらを参照してください。
https://www.zenrin-datacom.net/business/gmapsapi/api_key/index.html

# 前提条件

### 道の駅のリスト
- 場所の情報（住所や座標、施設名称等）を取得する対象は、「道の駅の駅名（全国1,160駅）」を対象としました。
- 道の駅のリストは、以下よりエクセル形式がダウンロードできます。
- [「道の駅」一覧](https://www.mlit.go.jp/road/Michi-no-Eki/list.html)
- 上記のリストには、所在地が記載されていますが、市町村までの記載のため、場所の特定が困難です。
- そこで、道の駅の駅名をもとに、[Places API](https://developers.google.com/places/web-service/intro?hl=ja)を用いて、場所の情報（住所や座標、施設名称等）を取得します。

# 実行方法

### 入力設定

- Googleスプレッドシートに駅名を入力します。
- 駅名は、A列に入力してください。
- 駅名は、場所の情報の取得を上手く行うために、もとの駅名に「道の駅」という文字を付加し、余計なスペースを削除しています。
- シート名は「List」に変更してください。
 
<img width="320" alt="list.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/98c69141-c561-f0dc-55e3-eb8981eee467.png">

### 実行
- Googleスプレッドシートのツール＞スクリプトエディタを開いて、下記のソースを貼り付けます。
- "APIキーを入力してください"のところに、APIキーを入力してください。
- 「関数を選択」を「Main」にしてスクリプトを実行してください。
- Googleスプレッドシートへのアクセス権の確認画面が出ますので許可してください。

```javascript:gas1.gs
//基本的な設定
//**********************************************************************************************
// APIKEYを設定する
var APIKEY = "APIキーを入力してください" // APIキー
//**********************************************************************************************

var InputText;      // インプットテキスト
var ArrInputList;   // インプットリスト
var LastRow;        // 最終行

//**********************************************************************************************
// Main関数
//**********************************************************************************************
function Main() {  
  // インプットリストを設定する
  SetInputList();
  
  // 戻り値を格納する配列
  var ArrRes = [];
  for (var i = 0; i <= LastRow-2; i++) {
    
    // PlacesAPI関数によるname,formatted_address,lat,lngの取得
    var data = PlacesAPI(ArrInputList[i][0], APIKEY);
    
    // 戻り値を配列に格納する
    ArrRes[i] = [];
    ArrRes[i][0] = data[0]; // name
    ArrRes[i][1] = data[1]; // formatted_address
    ArrRes[i][2] = data[2]; // lat
    ArrRes[i][3] = data[3]; // lng
  }
  // 結果をスプレッドシートに出力する
  var bk = SpreadsheetApp.getActiveSpreadsheet();  // アクティブなスプレッドシートを取得する
  var sh = bk.getSheetByName('List');         　　　// Listシートを取得する
  
  for (var i = 0; i <= LastRow-2; i++) {
    // 値をセルに入力する
    sh.getRange(i + 2, 2).setValue(ArrRes[i][0]);  // name
    sh.getRange(i + 2, 3).setValue(ArrRes[i][1]);  // formatted_address
    sh.getRange(i + 2, 4).setValue(ArrRes[i][2]);  // lat
    sh.getRange(i + 2, 5).setValue(ArrRes[i][3]);  // lng
  }  
}

//**********************************************************************************************
// インプットリストを作成する関数
//**********************************************************************************************
function SetInputList() {
  // addressシートの内容を配列に格納する
  var bk = SpreadsheetApp.getActiveSpreadsheet();             // アクティブなスプレッドシートを取得する
  var sh = bk.getSheetByName('List');　　　                    // Listシートを取得する
  LastRow = sh.getLastRow();                                  // 最終行を取得する
  // var colLst = sh.getLastColumn();                         // 最終列を取得する
  
  Logger.log(LastRow);
  
  // データを配列に格納する
  // Sheetオブジェクト.getRange(行番号, 列番号, 行数, 列数)
  ArrInputList = sh.getRange(2, 1, LastRow-1, 1).getValues();

  Logger.log(ArrInputList);
}

//**********************************************************************************************
// PlacesAPIを実行する関数
//**********************************************************************************************
function PlacesAPI(InputText, APIKEY){
  // URLを作成する
  var url = "https://maps.googleapis.com/maps/api/place/findplacefromtext/json?language=ja" +
            "&input=" + InputText +　　　　　　　　　　　　 // for example, a name, address, or phone number
            "&inputtype=textquery" +                    // textquery or phonenumber
            "&fields=formatted_address,geometry,name" + // fields
            "&key=" + APIKEY;                           // API key
  
  Logger.log(url);
  
  // HTTPリクエストを行う
  var res  = UrlFetchApp.fetch(url,{muteHttpExceptions:true});
  Logger.log(res); 
  
  // HTTPレスポンスを文字列として取得、JSON形式の文字列を解析してオブジェクトとして返す
  var json = JSON.parse(res.getContentText()); 
  Logger.log(json);
  
  if (json["status"] == "OK") {
    var json_formatted_address = json["candidates"][0]["formatted_address"];
    var json_lat = json["candidates"][0]["geometry"]["location"]["lat"];
    var json_lng = json["candidates"][0]["geometry"]["location"]["lng"];    
    var json_name = json["candidates"][0]["name"];
    
    // 「日本、」「郵便番号」を除外
    var formatted_address = json_formatted_address.split(' ');
    
    return [json_name,formatted_address[1],json_lat,json_lng];
    
  } else {
    //"status"が"OK"以外は空白として返却する
    return ["","","",""]
  }
}
```

# 実行結果
- 実行結果は、B列にname（施設名称）、C列にformatted_address（住所）、D列にlat（緯度）、E列にlng（経度）が出力されます。
- formatted_addressに含まれる「日本」や「郵便番号」は除外しています。

<img width="900" alt="list2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205045/21739311-b731-8218-ca16-65c66b05c2bd.png">

# 留意事項
- [PlacesAPIは、取得する場所の情報の種類に応じて、利用料金が細かく設定されています。](https://cloud.google.com/maps-platform/pricing/sheet/?hl=ja)
- 料金体系は、下記の記事が参考になるかと思います。
- [(2018/9) Google Mapsの料金体系について](https://qiita.com/wf9a5m75/items/87fad6c484378c0519ec)
- **※無料枠を超えてAPIを使用すると課金されますのでご注意ください(>_<)**
- 大量の住所データ

# 参考書
[詳解! GoogleAppsScript完全入門 ~GoogleApps & G Suiteの最新プログラミングガイド~](https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-GoogleAppsScript%E5%AE%8C%E5%85%A8%E5%85%A5%E9%96%80-GoogleApps-G-Suite%E3%81%AE%E6%9C%80%E6%96%B0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%AC%E3%82%A4%E3%83%89/dp/4798053767)
[Developer Guide（Geocoding API）](https://developers.google.com/maps/documentation/geocoding/start?authuser=1)