スプレッドシートのデータをGoogle Apps Scriptで圧縮してみた

#はじめに
2019年12月3日に``Google Fusion Tables``の提供が終了するらしく、Google Apps ScriptのWebアプリケーションで使っている**無料のデータベース**が使えなくなる。
インフラコスト0でデータベースを運用したいので``Googleスプレッドシート``に移行することを考えたが、**~~200万~~500万セル以上書き込めない問題**があり、**データを圧縮**できないかと考えた。
[Google Fusion Tables のご提供終了のお知らせ](https://gsuiteupdates-ja.googleblog.com/2018/12/google-fusion-tables-2019-12-3.html)

#問題点
<img width="723" alt="スクリーンショット 2019-06-03 14.24.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/49038123-0870-4f09-bafc-36f7598d97d1.png">

例としてこのような上記画像のような日報兼退勤記録がある
このまま数年間複数ユーザが使うと200万セルの壁にぶつかりアプリケーションが正しく動作しなくなると想定される。
``※1つのセルに格納できる最大文字数は50000文字``

#JSON文字列として1つのセルにまとめてみる

<img width="181" alt="スクリーンショット 2019-06-03 14.30.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/b9aebfec-d26f-dcb0-4fc4-a26bb3787bc3.png">

json文字列を格納するために``json``シートを作成
##コード
スクリプトエディタは[ツール]→[スクリプトエディタ]から立ち上げる
<img width="278" alt="スクリーンショット 2019-06-03 14.34.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/4696be25-fb19-6d1f-023e-f7d3a398fd38.png">

コード.gsに以下のソースを貼り付ける

```javascript:コード.gs
function setJSON(){
  var sheet = SpreadsheetApp.getActive().getSheetByName('json');
  //jsonシートの1,1（A1）にシート1のデータをJSON文字列として書き込む
  sheet.getRange(1,1).setValue(JSON.stringify(getData()));
}

//src https://qiita.com/takatama/items/7aa1097aac453fff1d53
//戻り値 シート1のJSONデータ
function getData() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
  var rows = sheet.getDataRange().getValues();
  var keys = rows.splice(0, 1)[0];
  return rows.map(function(row) {
    var obj = {};
    row.map(function(item, index) {
      obj[String(keys[index])] = String(item);
    });
    return obj;
  });
}
```

##出力
<img width="254" alt="スクリーンショット 2019-06-03 14.37.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/4c40ed02-20ae-5c31-d320-7fefe8d7a3f0.png">
``setJSON()``を実行

<img width="352" alt="スクリーンショット 2019-06-03 14.40.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/c041fdbd-9ff4-2c6f-7828-5f88e940e755.png">

JSON文字列として20セルのデータが1つのセルに入りました！！

#JSON文字列をgzipで通常用いられている圧縮ルーチンを使って圧縮、複合
**※1つのセルに50000文字を超える場合に使用**
>http://www.onicos.com/staff/iz/amuse/javascript/expert/
今回使うコードはこちらから引用

http://www.onicos.com/staff/iz/amuse/javascript/expert/deflate.txt
圧縮の処理を行いたいので、
上記のコードをコピーして``deflate.gs``を作成後、貼り付ける
<img width="510" alt="スクリーンショット 2019-06-03 14.44.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/9088608b-03c6-eaf2-6eaf-9d91bdfa9916.png">

http://www.onicos.com/staff/iz/amuse/javascript/expert/inflate.txt
複合の処理を行いたいので、
上記のコードをコピーして``inflate.gs``を作成後、貼り付ける
<img width="715" alt="スクリーンショット 2019-06-03 14.48.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/1da84706-146e-fef7-1560-557643c29cbf.png">

コード.gsを以下のように変更する

```javascript:コード.gs
function setJSON(){
  var sheet = SpreadsheetApp.getActive().getSheetByName('json');
  //jsonシートの1,1（A1）にシート1のデータをJSON文字列を圧縮して書き込む
  sheet.getRange(1,1).setValue(deflate(JSON.stringify(getData())));
}

function getJSON(){
  var sheet = SpreadsheetApp.getActive().getSheetByName('json');
  var data = sheet.getRange(1,1).getValue();
  
  Logger.log('文字列の長さ ' + data.length);
  //複合関数を呼び出し複合する
  Logger.log(inflate(data));
}

//src https://qiita.com/takatama/items/7aa1097aac453fff1d53
//戻り値 シート1のJSONデータ
function getData() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
  var rows = sheet.getDataRange().getValues();
  var keys = rows.splice(0, 1)[0];
  return rows.map(function(row) {
    var obj = {};
    row.map(function(item, index) {
      obj[String(keys[index])] = String(item);
    });
    return obj;
  });
}

// 圧縮関数
function deflate(val) {
    val = encodeURIComponent(val); // UTF16 → UTF8
    val = zip_deflate(val); // 圧縮
    return val;
}

// 復号関数
function inflate(val) {
    val = zip_inflate(val); // 復号
    val = decodeURIComponent(val); // UTF8 → UTF16
    return val;
}
```

#圧縮してみた
コード.gsの``setJSON()``を実行後、jsonシートを確認すると、
以下のように圧縮されていてますね！
<img width="355" alt="スクリーンショット 2019-06-03 14.57.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/731a4f15-fc5e-ad57-df52-dd84e37fe088.png">

#複合してみた
コード.gsの``getJSON()``を実行後、スクリプトエディタの[表示]→[ログ]から確認すると
以下のように複合されていますね！
<img width="624" alt="スクリーンショット 2019-06-03 14.58.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252959/fb15be84-d200-9b2e-a3ce-8d6968340a9d.png">

#最後に
ここまでしてスプレッドシートを使う人多くはないだろう
筆者の環境で圧縮したい``実際のデータを``入れてみると、**圧縮、複合に数分要する**ことがわかったので、Webアプリケーションのデータベースとしてはこの手法は向いていないことがわかった。

小規模の場合は計算にそこまで時間がかからないので、問題はなさそう
``小規模の場合は圧縮する必要がない...``