
Q.Man
Google Spread Sheetで作成したツールを販売したい。けど、スプレッドシートを複製されて、無料配布されてしまう…。どうにか対策できないかな?

P.Man
あ、その悩みなら解決できると思うよ?
Google Spread SheetにGAS(Google Apps Script)を埋め込んで、汎用性の高いツールを作ったから販売したい!と考えている方にとって、スプレッドシートの複製・再配布は天敵ですね。これを防止する方法を紹介します。
スプレッドシート複製の対策
スプレッドシートには「スプレッドシートID」というものが存在します。このシートIDで複製シートを見分ける仕組みをプログラムに実装します。
実装方法
それでは、具体的な実装方法を解説していきます。
1:スプレッドシートID管理用のスプレッドシートを準備
まず、スプレッドシートID管理用にスプレッドシートを準備しましょう。公開設定は「リンクを知っている人全員」にします。シートの中身はこんな感じです。

赤線部分がスプレッドシートIDです。※購入日や購入者識別IDは不要
2:GASにスプレッドシートID比較処理を挿入
続いて、GASにスプレッドシートIDの比較処理を実装します。利用する情報は以下。
- スプレッドシートID管理用スプレッドシートのシートID
- GAS実行シートのシートID
次のような関数を実装します。
//スプレッドシートID管理用スプレッドシートのシートID
const LICENCESHEETID = 'スプレッドシートID管理用スプレッドシートのシートID';
//スプレッドシートID管理用スプレッドシートのシート名
const SHEETNAME = 'license';
//スプレッドシートID管理用スプレッドシート上の参照する列
const COL_SHEETID = 4;
//関 数:checkLicense
//引 数:sheetId > GASが実行されるシートID
//戻り値:0:スプレッドシートIDが正しい、-1:スプレッドシートIDが正しくない
function checkLicence_(sheetId){
//スプレッドシートID管理用スプレッドシートを取得
let ss = SpreadsheetApp.openById(LICENCESHEETID);
let sheet = ss.getSheetByName(SHEETNAME);
//登録されている最大行を特定
let mxR = sheet.getRange(sheet.getMaxRows(), COL_SHEETID).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
if(mxR < 1 ){mxR = sheet.getMaxRows()};
//シートIDを配列valuesに格納
let values = sheet.getRange(2,COL_SHEETID,mxR,COL_SHEETID).getValues().flat();
//valuesの値を引数「sheetId」と比較
for(value of values){
if(value === sheetId){
return 0;
}
}
return -1;
}
この「checkLicence_」を販売したいGASのスクリプト先頭に挿入しましょう。実装例は以下です。
function main(){
//GAS実行シートのシートIDを取得
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(WSNAME);
let sheetId = ss.getId();
//checkLicenceで複製シートか確認「-1」は複製シート
if(checkLicence_(sheetId) === -1){
Browser.msgBox('本スプレッドシートは不正にコピーされているため利用権限がありません。');
return 0; //強制終了
}
//↓↓ココから下が本来の処理
}
3:お客さんに配布するシートIDを追加する
最後に、お客さんに配布するスプレッドシートのシートIDを、スプレッドシートID管理用スプレッドシートに追記します。
最後に
GASプログラムの実行シートを固定し、複製を防止する方法を紹介しました。ただ、このままプログラムを配布すると、GASを読めてしまう人には簡単に仕掛けを解除されてしまいますので、プログラムの隠蔽も必要です。
隠蔽方法について、また別の記事で紹介します。不明点があればコメントにお願いします!


コメント