iOSアプリからスプレッドシードのデータを読み込む

iOSアプリからスプレッドシートのデータを読み込みたい時が人生にはあります。その方法です。

# 大まかな流れ
iOSからスプレッドシートのデータを読むためには、スプレッドシート側にGAS（Google Apps Script）を実装する必要があります。GASでスプレッドシートをReadするGETを実装し、iOSからそこ目掛けて通信する実装をすれば完成です。

# GASの実装
スプレッドシートの「シート1」シートに下記のようなデータがあるものとします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/720a7621-4854-b8be-f1f7-cb89ba1a9680.png" width="400">

スプレッドシートメニューの`ツール＞スクリプトエディタ`を選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/adf98484-5f25-0e29-f13e-6758861d1903.png" width="500">

するとApps Scriptエディタが開きます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/4a04bc27-a773-c1c1-2a46-84ffe281543a.png" width="500">

ここに処理を実装していきます。

## Readする
スプレッドシートのデータを読み込む方法は以下の通りです。

```gs
function myFunction(){
    var targetFileID = DriveApp.getFileById("xxxxx")
    var targetFile = SpreadsheetApp.open(targetFileID)
    var targetSheet = targetFile.getSheetByName("シート1")

    var values = targetSheet.getRange(3, 1, 1, 4).getValues()
    console.log(values)
}

//出力結果
22:51:30	情報	[ [ '花子', 22, 15, 5 ] ]
```

1. `DriveApp.getFileById("xxxxx") `でGoogle Drive内にある対象ファイルのIDを取得します。※1
2. `SpreadsheetApp.open(targetFileID)`で対象ファイルを取得します。
3. `targetFile.getSheetByName("シート1")`で対象ファイル内の対象シートを取得します。
4. `targetSheet.getRange(3, 1, 1, 4).getValues()`で対象シート内の３行目１列目のセルを起点に、1行分4列目まで取得します。
5. デバッグするにはメニューバーにある`▷実行`を押します。
   * スプレッドシートの内容にアクセスする場合、[初回はアクセス権限に関する表示](https://qiita.com/kensuzuk/items/eae3396d3b9e29c439f6)が出るので対処します。

※1：ファイルIDはURLの https://docs.google.com/spreadsheets/d/xxxxx/edit#gid=0 の「xxxxx」にあたる部分です

## GETを実装する

GASでWebAPIを実装できます。GASの中で`GETならdoGet(e)`を定義し実装します。これをウェブアプリとして公開するとWebAPIが発行され外部からアクセスできるようになります。

### doGet(e)
スプレッドシートの内容をWebAPI経由で取得する方法は以下の通りです。

```
function doGet(e){
    var targetFileID = DriveApp.getFileById("xxxxx")
    var targetFile = SpreadsheetApp.open(targetFileID)
    var targetSheet = targetFile.getSheetByName("シート1")

    var values = targetSheet.getRange(3, 1, 1, 4).getValues()

    return ContentService.createTextOutput(JSON.stringify(values)).setMimeType(ContentService.MimeType.JSON)
}
```

1. `myFunction()`を`doGet(e)`に書き換えます。
2. データの取得までは`Readする`と同じです。
3. returnに `ContentService.createTextOutput(JSON.stringify(values)).setMimeType(ContentService.MimeType.JSON)` を書きます。スプレッドシートの情報をJSON形式で返します。
4. `デプロイ`を行い、WebAPIを発行します。
   * [こちらの手順](https://qiita.com/kensuzuk/items/486a8a63436b73aa148d)を参考にして下さい。

すると、このような形でWebAPIが取得できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/e5201252-7d48-9c4f-9042-dc5633f09ea8.png" width=500>

試しにブラウザにそのURLを入力すると`doGet(e)`内で取得された情報が返ってくるのが確認できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/f0a0584a-331e-1087-df63-f521c43fcb48.png" width=500>

# iOSの実装
ここではiOSからGASのWebAPIへのアクセスを容易にするために[Alamofire](https://github.com/Alamofire/Alamofire)と[SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON)を用います。適宜インストールして下さい。

```swift
import UIKit
import Alamofire
import SwiftyJSON

class ViewController: UIViewController {
    @IBOutlet weak var name: UILabel!
    @IBOutlet weak var count: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = "https://script.google.com/macros/s/xxx/exec" //上記で取得したWebAPI
        
        AF.request(url, method: .get).responseJSON{ (response) in
            
            switch response.result {
            case .success(let elm):
                let json = JSON(elm as Any)// [["花子", 22, 15, 5]]
                
                self.name.text = json[0][0].stringValue
                self.count.text = json[0][2].description
                
            case .failure(_):
                print("failure")
            }
        }
    }
}
```

1. `AF.request(_, method: .get)`で上で取得したWebAPIへGETで通信を行います
2. `response.result`にレスポンスが入るので、Switch文で分岐処理します
3. レスポンスをJSONオブジェクトに変換します
4. JSONオブジェクトインスタンスの各要素にアクセスし、型に応じて変換処理をかけます

これをシュミレータで実行するとこうなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143255/9d95716f-0c9d-a318-eb9b-e6d304919056.png" width=300>

# まとめ
iOSアプリからスプレッドシートのデータを読み込む方法をまとめました。

この様な流れでiOSからスプレッドシートのデータを読み込むことができます。
パラメータを付けて何行目のデータを取得する等、動的にすることも可能です。

[スプレッドシートにデータを書き込む方法](https://qiita.com/kensuzuk/items/efbfaed719932822f207)もまとめましたので、よろしければご覧ください。

## おまけ
`doGet()`を実装する際、デバッグする度iOS側からアクセスするのは面倒です。
下記のリンクに簡易デバッグの方法を記載しましたのでご参照ください。
[GoogleAppsScriptでdoGet()をdebugする](https://qiita.com/kensuzuk/items/3a3aa4b371675e70cbdd)