【Javascript】Google Sheets APIを簡単に使うためのラッパーClassを作りました

Youtubeでもレブル250/グラディウス400/GN125の情報を発信してます! (登録してもらえると超喜びます!!)

はじめに

「Googleドライブ上のスプレッドシートをJavascriptで操作したいんじゃ!」
という要望がありました。
色々勉強して、一応JavascriptだけでSheetsAPIを操り、値の取得~更新はできるようになったのですが…これをいちいち手書きするのも大変だな、ということで、classにしておきました。

意外と日本語のSheetsAPI(Javascript)に関する情報が無くて…少しでも参考になれば幸いです。

ソース

ラッパークラス本体(SheetsManager)

下記のような感じにしました。
コメントでも書いていますが、認証の所を外出しして、他のAPIを使用する場合を考えてクラス分離しようとも思ったのですが、今回のターゲットはとりあえずSheetsAPIに限定しているので1クラスにしました。はい。

[javascript] // Wrapper Class for Google Sheets API
class SheetsManager {

// Constructor
// クライアントID, スプレッドシートIDを受け取りもろもろ初期化する(本クラスの仕様として、インスタンス化時に)
// cliend_id : your CLIENT ID
// sheet_id : SHEET ID (https://docs.google.com/spreadsheets/d/{HERE IS SHEET ID!!}/edit#gid=0)
// auto_sign_in: インスタンス化と同時にサインインする場合はtrue[OPTIONAL] constructor(client_id, sheet_id, auto_sign_in){
this.client_id = client_id;
this.sheet_id = sheet_id;
this.googleClient = {};

this.DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest"];
this.SCOPE = ‘https://www.googleapis.com/auth/spreadsheets’;

// 各種ライブラリの準備
this.loadLibraries()
.then(
()=>{
// ロード成功時処理
console.log("[constructor] in loadLibraries’s then");

// 自動サインインフラグがtrueで未サインインなら
if(auto_sign_in && !this.isSignedIn()){
this.signIn();
}
},
(error)=>{
console.log("loadLibraries Failure…");
console.log(error);
}
)
}

// ———- ここから認証関連 ———-
// loadLibraries
// 認証ライブラリ, とSheetsAPIライブラリのロードを行う.
// Promiseオブジェクトを返却するんで、thenすればsheets api使用可能になった直後に処理を繋げる
loadLibraries(){
console.log("[loadLibraries] driven");
return new Promise((resolve, reject)=>{
try{
// クライアント認証ライブラリをロード
gapi.load(‘client:auth2’,
()=>{
console.log("[loadLibraries] in gapi.load");
// クライアント情報のセット(初期化)
gapi.client.init({
discoveryDocs: this.DISCOVERY_DOCS,
clientId: this.client_id,
scope: this.SCOPE
}).then(()=> {
// 認証OK時に駆動する関数. SheetsAPIをロードする
var loadSheetsApi = ()=> {
gapi.client.load(‘https://sheets.googleapis.com/$discovery/rest?version=v4’)
.then(()=> {
console.log("[loadLibraries] sheets api loaded");

// 再利用するんで
this.googleClient = gapi.client;
});
};

// 認証状態を監視させる
gapi.auth2.getAuthInstance().isSignedIn.listen(function(is_signed_in){
if(is_signed_in){
console.log("[loadLibraries] signed in!!");
loadSheetsApi();
}
else{
console.log("[loadLibraries] signed out…");
}
});

// ここを通った時点でログイン済かを確認. 既に認証済なら早速sheets api をロードする
if(gapi.auth2.getAuthInstance().isSignedIn.get()){
loadSheetsApi();
}

resolve(gapi.auth2);
});
},
(error)=>{// gapi.load failure callback
console.log("[loadLibraries] gapi.load error…");
console.log(error)
}
);
}
catch(e){
console.log("[loadLibraries] loadLibraries rejected…");
reject(e);
}
});
}

// signIn
// サインインする
signIn(){
gapi.auth2.getAuthInstance().signIn();
}

// signOut
// サインアウトする
signOut(){
gapi.auth2.getAuthInstance().signOut();
}

// isSignedIn
// サインイン状態を返却する
isSignedIn(){
return gapi.auth2.getAuthInstance().isSignedIn.get();
}
// ———- ここまで認証関連 ———-
// 認証とspreadsheetの操作を分けろよ!とのコメントがありそうですが…ごもっともです
// 分けると、spreadsheetだけシンプルに使いたいんだけど、という人からすると分かりにくいかな、ということで、1クラスにしてますと言い訳しておきます。

// getValue
// SpreadSheetからrange_stringで指定された範囲の値を取得する. thenableなんで、値取得後に描画処理をしたい場合は、getValue.then(function(){})してください。
// range_string: シートから抽出する値の範囲. "シート1!B2:D24"のような文字列を与える
// 戻り値はgoogleのvalues.getの値まんま. 十分使い易かったんで
getValue(range_string){
// 呼出元でthenする
return this.googleClient.sheets.spreadsheets.values.get({
spreadsheetId: this.sheet_id,
range: range_string
});
}

// findValue
// SpreadSheetからrange_stringで与えられた範囲のなかにfind_valueと一致するデータが存在するかを検査する
// range_string: getValueと同様. シートから抽出する値の範囲
// find_value : 検索したい値. プリミティブ型を想定(文字列や数字など)
// search_all : 検索値にヒットする全ての値を取得したい場合にtrue
// 戻り値は配列. 1要素ごと{row, col, data}を持つ. row, colは、検索開始位置からの差分を表す. ヒットしなかった場合は配列長0
findValue(range_string, find_value, search_all){
return this.getValue(range_string)
.then(function(response){
console.log("[findvalue] getvalue’s callback");
return new Promise(function(resolve, reject){
if(!!(response && response.result && response.result.values && (response.result.values.length > 0))){
var result = [];
for(var i = 0; i < response.result.values.length; i++){
var r = response.result.values[i];
for(var j = 0; j < r.length; j++){
var c = r[j];
if(c == find_value){
result.push({ row: i, col: j, data: c });
if(!search_all) break;
}
}
}
console.log("[findvalue] getvalue callback-> resolve");
resolve(result);
}
else{
console.log("[findvalue] getvalue callback-> reject");

// nodata…
reject();
}
});
});
}

// updateValue
// 与えられたrange_string範囲を, update_valuesの値で更新する
// range_string : getValueと同様. 更新対象範囲を指定する
// update_values: 2次元配列を与える. range_stringで与えた範囲と一致するだけの行, 列を持った2次元配列をセットすること
updateValue(range_string, update_values){
return this.googleClient.sheets.spreadsheets.values.update({
spreadsheetId: this.sheet_id,
range: range_string,
valueInputOption: "USER_ENTERED",
values: update_values
});
}

// convAlpha2Number
// 与えられたアルファベットを数値に変換する(ex: A=0, D=3)
// s: 変換対象のアルファベット. 大文字想定
convAlpha2Number(s){
return s.charCodeAt(0) – 65;
}

// convNumber2Aplha
// 与えられた数値をアルファベットに変換する. convAlpha2Numberの反対
// n: 変換対象の数値
convNumber2Aplha(n){
return String.fromCharCode(65 + n);
}

}

[/javascript]

 

使う場合のコード例です

インスタンス化する際は、下記の様な3パラメータを与えて下さい。
第1引数にGoogleClientIDを(取得方法などは…一旦は割愛します)、
第2引数にスプレッドシートのIDを(こちらも割愛します)、
第3引数にインスタンス化時に認証まで行うか、のフラグを渡します。

[javascript] window.sheetsManager = new SheetsManager(
"youre-client-id.gprru.apps.googleusercontent.com",
"youre-sheets-id",
true
);
[/javascript]

実際に使う処理は下記のような感じになります。

[javascript] // findValue開始
window.sheetsManager.findValue("わたしのSheet!A2:A1024", $scope.currentId, false)
.then(
// findValue成功時処理
function(result){
// 検索値の、A2からの相対行を取得
var pos_r = result[0].row;

// 成功時、その行の値を欲しい範囲だけ取得するためにgetValueする
return window.sheetsManager.getValue("わたしのSheet!H" + (2 + pos_r) + ":K" + (2 + pos_r));
},
// failure…
function(error){
console.log("findvalue-> failure…");
console.log(error);
}
)
// getValueのthen(とりあえず失敗時は無視して)
.then(
function(response){
// getValue Success時処理
return new Promise(function(resolve, reject){
try{
if(!(response && response.result && response.result.range)){
console.log("response not filled…");
reject();
}

var values = [
["ここが", "私が", "更新したい", "範囲です。"],
["そういう", "感じ", "です", "。"] ];

// updateValueでシートを更新する
return window.sheetsManager.updateValue(response.result.range, values)
.then(function(response){
alert("シート更新まで無事に完了しましたよ…お疲れ様でした。");
})
}
catch(e){
console.log("fatal error occured… in get value success");
console.log(e);

reject();
}
});
}
);
[/javascript]

急いで書いたので、また後で色々補足などを追記していこうと思います…すみません。

今回は以上です。

Youtubeでもレブル250/グラディウス400/GN125の情報を発信してます! (登録してもらえると超喜びます!!)
最新情報をチェックしよう!