#73 Google スプレッドシートでカスタム関数を作る
今回の記事は、一風変わった GAS のプログラムです。
Facebook で見つけた、中学生が Google スプレッドシートを用いて、エビングハウスの忘却曲線をもとに、復習する日を算出している様子。
いろんな意味で「すごいな!」と思うものの、こんなに長い数式を設定しなくてもいい方法がないか?を考えてみました。
カスタム関数を作成する
以下のヘルプ記事に以下のような記述がありました。
ヘルプ記事を「カスタム関数」をキーワードに検索しても、これ以上の情報を見つけられませんでしたが、以下 URL で説明されているのを見つけました。
要約すると、GAS でプログラミングした関数を、Google スプレッドシートで用意されている関数と同じように呼び出して、関数の戻り値を結果として得られる、ということみたいです。
(1)エビングハウスの忘却曲線とは?
ちなみに、「エビングハウスの忘却曲線」については以下 URL でも説明されていますが、ドイツの心理学者である「ヘルマン・エビングハウス」が考案したもので、効果的に復習するタイミングを求めるために今回は使われています。
この理論をもとにして、冒頭の写真のように 5回の復習を行うことで学習内容の定着を狙っているようです。
覚えた直後に、復習する。
1日後に、再度復習する。(半分の時間)
7日後に復習する。 (更に半分)
14日後に復習する。 (さらに半分!)
1ヵ月後に復習する。 (1分以下!!)
(2)作成したプログラム
これまでの前提条件で、以下のようにプログラムを作成しました。
/**
* 参考:
* スプレッドシートのカスタム関数でお手軽処理しましょう
* https://qiita.com/yoh_n/items/0104984f1d3bdae81e82
*/
/**
* エビングハウスの忘却曲線に基づいて、効果的な再学習の日付を返します。
*
* @param {date} date - 学習した日
* @param {number} times - 何回目の復習か?(1~5)
* @return 効果的な再学習の日付
* @customfunction
*/
function EbbinghausCurve(date, times) {
let d = new Date(date);
switch (Number(times)) {
default:
case 1: // 1、覚えた直後に、復習する。
break;
case 2: // 2、1日後に、再度復習する。(半分の時間)
d.setDate(d.getDate() + 1);
break;
case 3: // 3、7日後に復習する。 (更に半分)
d.setDate(d.getDate() + 7);
break;
case 4: // 4、14日後に復習する。 (さらに半分!)
d.setDate(d.getDate() + 14);
break;
case 5: // 5、1ヵ月後に復習する。 (1分以下!!)
d.setDate(d.getDate() + 30);
break;
}
return d;
}
36行のプログラムですが、参考にさせていただいた ↑ の URL もコメントに記載してありと、空行やコメントで半分くらいを占めています。
関数名は、「エビングハウスの忘却曲線」によるものなので、エビングハウス(Ebbinghaus)と 曲線(Curve)から EbbinghausCurve としました。
1つ目の引数に基準となる学習日 date を、2つ目の引数に何回目の復習か?、を指定します。関数の結果として、前述の基準によって算出された日付を戻します。
今回の関数は、API などを使用していないこともあって、実行時に権限の確認が必要ありません。 と言うよりも、権限の確認を求めるような処理を行えません。
冒頭の写真では「年」「月」「日」をそれぞれ別のセルに入力していましたが、この関数では日付として入力させ、当日、翌日、7日後(一週間)、14日後(二週間)、30日後(一か月)、の日付を戻しています。
Date 型の変数で処理しているため、年や月をまたいだり、うるう年の判定なども意識しなくて済みます。
(3)スプレッドシートでの利用方法
サンプルとして作成した Googleスプレッドシートは、以下の URL にアクセスすることで、自身の Google ドライブにコピーを作成できます。
https://docs.google.com/spreadsheets/d/1zO7D-Pz_z0YALahvXlf7IETNQj01rrvXlMBOPHvrINM/copy
セル C2 に学習した日付を入力することで、セル C3:C7 に 1~ 5回目の復習のタイミングを算出しています。
セル C3 には、以下のように記述してカスタム関数を呼び出しています。1つ目の引数にはセル C2 に入力された日付を、2つ目の引数にはセル B1 の見出し文字列の末尾から何回目の復習であるかを、RIGHT 関数で取得しています。
=EbbinghausCurve(C$2,right($B3,1))
それぞれの引数には C$2 や $B3 と $ を付けて固定してあるので、C4 ~ C7 にはオートフィル機能で数式を設定します。
(4)JsDoc による説明文
今回のプログラムでは、EbbinghausCurve 関数の前に JsDoc のルールに沿ってコメントを記述したことで、下図のように Google スプレッドシートに用意されている組み込み関数のように説明文が表示されます。
上図の「カスタム関数の詳細」というリンクをクリックすると、以下のカスタム関数についての詳細を説明したページにアクセスできます。カスタム関数のより詳しい情報については、こちらをご覧ください。
まとめ
冒頭の中学生が IF 文を駆使して、多くの判定によって実現していた機能が、コメントなどを含んで 36行で実現できました。
これまでに GAS でプログラミングしていない人にとっては異質な感じかもしれませんが、冒頭の写真のような難解な IF 文と比べると、今回作成したプログラムはとてもシンプルな感じになっていると思いませんか?
頻繁に使うものではないかもしれませんが、Google スプレッドシートの組み込み関数として用意されていない関数(処理)であっても、カスタム関数を用いれば解決できることがあるかもしれません。
こんなテクニックがあることを、どこかに覚えておいてください。👍