4
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【GAS】住所から緯度経度を取得してスプレッドシートに書き込む

Last updated at Posted at 2017-11-12

住所から緯度経度を取得してスプレッドシートに書き込む

https://qiita.com/OUIEA/items/bcbeacd0fff53d5a4d2b
をまるっと引用しています。

追加情報として

  • APIキーが必要だった
  • 無料の範囲で、大量にリクエストを投げるときはスリープが必要
  • ついでにモジュールパターンを採用
  • ついでにスプレッドシートに書き込む実装

あとはコードで語ります。


/*
 * 住所変換スクリプト
 */
function convert() {
  const COLUMN = {
    ADDRESS: 5,
    LAT: 37,
    LON: 38,
  }
  const sheetName = 'フォームの回答 1'
  const sheet = SpreadsheetApp.getActive().getSheetByName(sheetName)
  const startRow = 2
  const lastRow = sheet.getLastRow() - 1
  const lastCol = sheet.getLastColumn()

  const dataRange = sheet.getRange(startRow, 1, lastRow, lastCol);
  const data = dataRange.getValues();

  for (var i = 0; i < data.length; ++i) {
    var row = data[i]

    var latitude = row[COLUMN.LAT]
    var longitude = row[COLUMN.LON]
    // 既に変換済みの場合は何もしない
    if (latitude != "" || longitude != "") {
      continue
    }

    var location = APP.util.common.convertAddress(row[COLUMN.ADDRESS])
    Logger.log(location)
    if (typeof location === 'undefined') {
      continue
    }

    // 50回リクエストを送信したら1秒スリープする
    APP.util.common.sleepByCount(1000, 50)

    // スプレッドシートに出力
    sheet.getRange(startRow + i, COLUMN.LAT + 1).setValue(location['lat'])
    sheet.getRange(startRow + i, COLUMN.LON + 1).setValue(location['lon'])

    // Make sure the cell is updated right away in case the script is interrupted
    SpreadsheetApp.flush()
    Logger.log(row)
  }
}

// namespace
var APP = APP || {
    util: {
      common: {}
    },
  }

APP.util.common = (function () {
  /*
   *一定の回数になると1秒スリープし、カウンタが0になる
   * sleepMS: sleepする時間(ms)
   * limit: スリープするタイミング
   */
  sleepByCount = function (sleepMS, limit) {
    if (typeof limit === 'undefined') {
      // limitが引数として指定されていなければカウントしない
      return
    }

    if (typeof sleepByCount.count === 'undefined') {
      // 関数内カウンタ初期化
      sleepByCount.count = 0
    }
    if (sleepByCount.count % limit === 0 && sleepByCount.count !== 0) {
      Utilities.sleep(sleepMS)
      Logger.log('おやすみ')
    }
    sleepByCount.count += 1

    Logger.log(sleepByCount.count)
  }

  /*
   * 住所から緯度、経度を変換する
   * Google Geocoding APIにはAPIキーが必要
   * https://developers.google.com/maps/documentation/geocoding/get-api-key?hl=ja
   * 制限について
   * 2500リクエスト/日
   * 50リクエスト/秒
   * 大量に取得したい場合は、50reqごとに1秒のwaitを入れるような実装が必要
   */
  convertFromAddressToLocation = function (address) {
    if (address === '') {
      return
    }

    var api_url = "https://maps.googleapis.com/maps/api/geocode/json?address=" + encodeURI(address);
    api_url += '&key=[見せられないよ!]'
    var response = UrlFetchApp.fetch(api_url);
    var result = JSON.parse(response);
    var location = result['results'][0]
    if (typeof location === 'undefined') {
      return
    }
    location = location['geometry']['location']
    return {lat: location['lat'], lon: location['lng']}
  }

  // Public API

    sleepByCount: sleepByCount,
    convertAddress: convertFromAddressToLocation
  }
}())

以上です。
コードが汚い!こう書いたほうがいい!編集リクエスト待っています。

実は、sleepByCountのところが納得いっていません。別途sleepByCountを読んだ場合に同じcountを参照してしまうので。

4
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?