アプリからサインイン無しでGoogleスプレットシートのデータを取得する方法
はじめに
以前、Googleサインインを組み込む方法をブログで書いたのですが、 今回はサインイン無しでアプリからGoogleスプレットシートのデータを取得する方法について記載します。
サインイン無しで利用するにはGoogle Apps Scriptを利用します。
※ イメージ図
注意事項
但し、今回の方法は公開権限を制限することが出来ません。後述で出てくるGoogle Apps ScriptのURLが流出すると、おそらく誰でもデータを取得/編集することが出来てしまいます。
セキュリティのリスクを把握したうえで、正しくご利用ください。
環境
今回実施している環境は下記の通りです。
XCode | 8.0 |
---|---|
Swift | 3.0 |
CocoaPods | 1.0.0 |
iOS SDK | 9.0 以上 |
※ 今回はiOSで試していますが、アプリ側の実装はAndroidでもXamarinでも何でもOKです。
準備
スプレットシートを用意する
データを読み書きする対象のスプレットシートを作成します。
今回は、サンプルとして会社に置いてあるボードゲームのリストを書いてみました。
ここでメモしておく必要があるのが、シートIDです。 シートIDはURLの
https://docs.google.com/spreadsheets/d/{ここの部分}/edit#gid=0
になります。
また、対象のシート名もスクリプトで使用するのでメモしておきましょう。
Google Apps Scriptの記述
スプレットシートのメニューの ツール > スクリプトエディタ をクリックします。
すると、スクリプトエディタが新規でひらきます。
タイトル部分をクリックするとプロジェクト名編集ダイアログが表示されるので、適宜名前を付けます。
また、コード.gsとなっているコードの名前も変更しましょう。
リストを取得するスクリプト
以下のスクリプトは対象のシートの1行目キーにしたJSONを返すスクリプトです。
"{シートID}"には準備の時に作成したスプレットシートのシートIDを、
"{シート名}"の部分にはスプレットシートのシート名を入力します。
function getList(id, sheetName) { var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName); var rows = sheet.getDataRange().getValues(); var keys = rows.splice(0, 1)[0]; return rows.map(function(row) { var obj = {}; row.map(function(item, index) { if (item != "") { obj[keys[index]] = item; } }); return obj; }); } function doGet() { var data = getList("{シートID}", "{シート名}"); return ContentService.createTextOutput(JSON.stringify(data, null, 3)).setMimeType(ContentService.MimeType.JSON) }
スクリプトの呼び出しについて
今回はこのスクリプトをWebアプリケーションとして公開します。
その際、GETで呼び出した時はdoGet()、POSTで呼び出した時はdoPost()が呼び出されます。
とりあえず、この doGet() or doPost() からスタートされると思っていて良いと思います。
[参考] Content Service | Google Apps Script
スクリプトの簡単な説明
SpreadsheetApp.openById(id)
指定したIDのスプレットシートを開きます。同じくURLからスプレットシートを開く、
openByUrl(url)もありますが、URLの中にIDが含まれているのでopenByIdの方が短く書けて良いと思います。
[参考] Class SpreadsheetApp | Google Apps Script
getSheetByName(name)
openByIdで開いたスプレットシートからシートを名前で取得します。
[参考] Class Spreadsheet | Google Apps Script
getDataRange()
getSheetByNameで取得したシートからデータが入力されている範囲を取得します。
[参考] Class Sheet | Google Apps Script
JSON.stringify()
JSON 文字列に変換します。
[参考] JSON.stringifyを改めて調べる。| Qiita
ContentService.createTextOutput()
テキストコンテンツを返します。
.setMimeType(ContentService.MimeType.JSON) をつけることでJSON形式として扱います。
[参考] Class ContentService| Google Apps Script
スクリプトの実行
スクリプトが書けたら実行します。メニューバーの▶ボタンをクリックします。
すると承認が必要でダイアログが表示されるので、許可を確認ボタンをクリックします。
別ウィンドウでスプレットシートの許可リクエストが表示されるので、スプレットシートに対しての許可をします。
ウェブアプリケーションとして導入
アプリでGoogle Apps Scriptを利用するにはウェブアプリケーションとして導入し、URLを発行?する必要があります。
公開 > ウェブアプリケーションとして導入 をクリックします。
次のダイアログが表示されます。
アプリケーションにアクセス出来るユーザーを全員(匿名ユーザーを含む)にして、導入ボタンをクリックします。
すると、URLが表示されるので、ここに表示されているURLをコピーします。
また、最新のコード部分をクリックすると、このスクリプトの挙動を確認することが出来るので、どんな値が返ってくるのか予め確認すると良いと思います。
このURLが発行されたらGoogle Apps Script側の作業は完了です。
アプリ側の実装
次にアプリ側の実装に入ります。今回はサンプルプロジェクトとして、TableViewで一覧が表示される簡単なものです。
プロジェクトの作成
XCodeでプロジェクトを新規に作成します。
今回はBoardGameListViewerというプロジェクトを作成しました。
そして、CocoaPodsで各種ライブラリをインストールします。
今回はAlamofireとJSONのパース用にArgoというライブラリを使ってますが、お好みにあわせて別のライブラリでも問題ありません。
use_frameworks! target 'BoardGameListViewer' pod 'Alamofire' pod 'Argo' pod 'Curry' post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |configuration| configuration.build_settings['SWIFT_VERSION'] = "3.0" end end end
サンプルコード
取得するスプレットシートにあったデータを定義します。今回はゲーム一覧なので表示する各項目を定義しています。
import Argo import Curry import Runes struct GameItem { let name: String let tag1: String? let tag2: String? let tag3: String? let playerMin: Int? let playerMax: Int? let timeMin: Int? let timeMax: Int? } extension GameItem: Decodable { public static func decode(_ json: JSON) -> Decoded<GameItem> { return curry(GameItem.init) <^> (json <|? "name").map { $0 ?? "***" } <*> (json <|? "tag1") <*> (json <|? "tag2") <*> (json <|? "tag3") <*> (json <|? "player_min") <*> (json <|? "player_max") <*> (json <|? "time_min") <*> (json <|? "time_max") } }
今回はサンプルなので簡単に、TableViewController側の処理です。 "https://script.google.com/macros/s/XXXXXXXXXX/exec"の部分にGoogle Apps Scriptで発行されたURLを入力します。
import UIKit import Alamofire import Argo class GameListTableViewController: UITableViewController { private var list: [GameItem] = [] override func viewDidLoad() { super.viewDidLoad() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) loadList() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // MARK: - Private private func loadList() { Alamofire.request("https://script.google.com/macros/s/XXXXXXXXXX/exec").responseJSON { response in if let json = response.result.value { guard let list: [JSON] = decode(json) else { return } self.list = [] for item in list { if let gameItem = GameItem.decode(item).value { self.list.append(gameItem) } } self.tableView.reloadData() } } } // TableViewの実装部分は省略 }
実行結果
Googleスプレットシートの内容がアプリに表示されました。
さいごに
個人で利用したり、開発中のAPIモックとして利用したりするのにちょうどいいと思いました。
Google Apps Scriptを使えばスプレットシート以外にも色々利用出来ます。
詳細は公式のhttps://developers.google.com/apps-script/をご覧ください。
参考
スプレッドシートとgoogle apps scriptで簡易APIを作ってalamofireからget/postする|Qiita