TsuyoshiKusakaの日々思うこと その2

(株)クエステトラに所属、ITエンジニア、テニス好き、地域のお手伝いをいろいろ、@tsuyoshikusaka

JavascriptからGoogle Apps Scriptにアクセスする方法

JavascriptからGoogle Spreadsheet上のデータを取得したい場合など、JavascriptからGoogle Apps Scriptにアクセスする方法を調べていて、結構いろいろあったのでメモ。


JavascriptからGoogle Apps Scriptへのアクセスには、httpリクエストを使ったので、クロスドメインの問題を考慮する必要があった。
クロスドメインの回避方法はいくつかあるが、結論としてはJSONPを使えば問題ない。
以下サンプルコード。

Javascript

var script = document.createElement('script');
script.src = "https://script.google.com/macros/s/xxxxx/exec?callback=callbackFunction";

window.callbackFunction = function(data) {
//(コールバックされた後の処理)
}

document.body.appendChild(script);

Google Apps Script側

var SHEET_ID = "xxxxx";
var SHEET_NAME = "シート1";

function doGet(e) {
return receive_(e);
}

function doPost(e) {
return receive_(e);
}

function receive_(e) {
var out = ContentService.createTextOutput(e.parameter['callback'] + '(' + getData() + ')');
return out;
}

function getData() {
var sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(SHEET_NAME)
var out_string;
//(Google Spreadsheet等からデータを取得して、出力データを作成する処理)
return out_string;
}

ただ、実際に試行錯誤していたときには、はじめブラウザの設定変更でクロスドメインを回避していたため、めんどうなことに突き当たった。
対象環境がIE8だったので、インターネットオプションでJavascriptのあるサイトに対して「ドメイン間でのデータソースのアクセス」を許容するよう設定することで、
 JavascriptGoogle Apps Script
へのhttpリクエスト送信は問題なく行われた。
ただ、
 JavascriptGoogle Apps Script
にhttpレスポンスを返すところで問題が出た。

具体的にいうと、以下のようなコードを書いていたが、httpレスポンスが返ってきたところ(★部分)で responseText が空になった。
※以下の質問と全く同じ事象に突き当たった。
http://stackoverflow.com/questions/11481222/how-do-i-make-xhr-ajax-requests-against-google-apps-script-contentservice-work

Javascript

try {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("error");
return;
}

xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
alert("xmlHttp.status 200 responseText:" + xmlHttp.responseText); //★
}
}
}

if (xmlHttp) {
try {
var url = "https://script.google.com/macros/s/xxxxx/exec";
xmlHttp.open("POST", url, true);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.send("xxxxx=" + xxxxx);
} catch (e) {
alert(e.message);
}
}

ということで、JSONPを使うことで問題を回避。
結果からみると、はじめからJSONPを使っていれば、それほどややこしい話にはならなかったとはいえる。

※各サンプルコードのxxxxxの部分にはそれぞれの環境にあわせた値が入る


※2014/7/12追記 サンプルコードで修正すべき点があったので追記
Javascript から Google Apps Script にアクセスする方法 補足 - TsuyoshiKusakaの日々思うこと その2