2月に入って1回も更新していなかったことに気づきました。
良くないですね。
さて、今回は久々に社内ツールを作ってみたのでご紹介したいと思います。
タイトルの通り、採寸をデータ化しようという試みです。
予め断っておくと、以前ご紹介したゾゾタウンのボディースーツは採寸を自動化するもの。
今回作ったのは、そんな大層なものではありません(笑)
あくまで、これまで手書きだった採寸結果をデータ化しようというものです。
完成イメージ
- 採寸結果をフォームに記入し、送信するとスプレッドシートに保存される。
- 3回の検算は自動で行い、誤差が大きい時には再測定を促す。
- 身長・体重・性別から基準値を判定し、表示する。
- 女性のみの3項目は、性別の選択に応じて表示/非表示。
- 各採寸場所の測り方を表示。
- ↑非表示にも出来るようにする。
メリット
フードベストや重器材の購入時、適切なサイズを判断するために採寸表を引っ張り出す手間が減るのでは、と思っています。
また、3回の検算や身長・体重・性別に応じた基準値を自動で表示することで、採寸ミスを減らす効果も見込めると思います。
サクッとGoogleフォーム+スプレッドシート?
では出来ないんですよね、今回のテーマ。
シンプルな一問一答形式であれば、Googleフォームで作ってしまえば即スプレッドシートに保存されるので楽チンです。
しかし、今回のテーマ、ラジオボタン(単一回答)の選択肢によってリアルタイムに表示非表示を切り替えたり、フォームの入力値をその場で計算したり、『イメージ』の①以外、どれもGoogleフォームでは実現できません。
ということで、以下の構造で考えてみました。
- フォームはHTMLで構築
- 計算や表示非表示の切り替えはJavascriptで
- スプレッドシートに保存するのはGoogleAppsScriptで
実現したい事を紐解く
HTML
HTMLで用意されているフォームに関するタグを使ってフォームを成形する。
入力値のバリデーション(検証)はHTML5標準の機能で。
Javascript
表示/非表示の切り替え
- ラジオボタンが押されたら関数発火
- 選択肢に応じた要素を表示、または非表示
身長・体重・性別から基準値を表示
- 身長と体重を入力したときに関数発火
- 全ての項目が記入されていることをチェック
- 性別から、性別ごとに基準値をまとめたCSVファイルを読み込む
- 身長・体重に応じた基準値ごとにループ
- 入力された身長との差をとる
- 入力された体重との差をとる
- それぞれの絶対値を足したものを、用意しておいた配列に格納
- 身長、体重の差の合計値が格納された配列の要素のうち、最少のものの配列番号を取得
- 配列番号に応じた基準値を、それぞれの採寸場所入力欄の隣に表示
検算
- 検算に用いる採寸場所を入力したときに関数発火
- 検算に必要な全ての項目が記入されていることをチェック
- 検算
- 検算結果の絶対値が2.5以下であれば、次に進むという表示
- 誤差が大きい場合には再測定を赤文字で表示
GoogleAppsScript
- POSTを受け取る
- 受け取ったデータの要素名がタイトル行を一致したところに記入
完成品
この様に記入した結果が、おなじみスプレッドシートに保存される様に作ってあります。
それぞれの画像は、一番上のボタンで表示非表示を切り替えられるので、採寸場所が頭に入っている場合にはスクロールの手間を省くことが出来ます。
ひとまず挙動を完成させただけなので、見栄えに一切華が無い点はご容赦ください(笑)
もし、欲しいと言う方がいらっしゃれば、お声がけ頂ければと思います。
結構な時間をかけたので、さすがに差し上げるという訳には行かないですが…
また、お気づきの方も多いとは思いますが、画像は日本ウエットスーツ工業会のものです。
社内ツールとして作ったので、まぁ、、、多めに見てください、中の人…
ただ、このまま販売してしまっては、確実に著作権絡みでエライことになるので、もし販売という形になった場合は、ちゃんと写真撮るなりイラスト作るなりします。
見栄えももう少し良くします。(笑)
実装(参考)
今回は、自分の覚書程度になるかと思うので、最後に回させてもらいました。
実際のコードなどは以下の通りです。
HTML
<form>を使ってPOST。
ラジオボタンは<input type=”radio”>
名前などは<input type=”text”>
採寸値は<input type=”number”>
各inputにrequiredをつけることで必須回答にすることが出来ます。
JavaScript
表示/非表示の切り替え
- ラジオボタンが押されたら関数発火
→HTMLの<input>タグに<input onclick=”関数名()” >と書く - 選択肢に応じた要素を表示、または非表示
document.getElementById("非表示にしたい要素のID").style.display="none";
で非表示。
document.getElementById("表示にしたい要素のID").style.display="";
で表示。
複数の要素を一気に切り替える時には予め
var element = document.getElementsByClassName("表示にしたい要素のClass");
とした上で
for (var i=0;i<element.length;i++) {
element[i].style.display = "";
}
とすれば、一気に表示出来る。
身長・体重・性別から基準値を表示
- 性別を選択した時に、性別に応じたCSVファイルを読み込む
性別を選択するラジオボタンにonclickをつけておく。
飛び先の関数の最初で、最終行と最終列を指定しておく(男女で異なるので)
var req = new XMLHttpRequest();
req.open("get", "ファイル名", true);
req.send(null);
req.onload = function(){
convertCSVtoArray(req.responseText);
}
上記でCSV読み込み。
function convertCSVtoArray(str){
var tmp = str.split("\n");
for(var i=0;i<tmp.length;++i){
result[i] = tmp[i].split(',');
}
}
上記でCSVのデータを配列に格納。 - 身長と体重を入力したときに関数発火
→ラジオボタン同様。 - 全ての項目が記入されていることをチェック
例えば身長なら
var tall = document.getElementById("身長のID").value;
の様に取得し
if(tall != "" && weight != ""){
で記入されているかのチェック。 - 身長・体重に応じた基準値ごとにループ
var dif= [];
差の合計を格納する配列を予め準備。
最終列までループ
for(var i=0;i<lastCol;++i){
- 入力された身長との差をとる
var tallDif = Math.abs(Number(result[0][i]) - tall);
- 入力された体重との差をとる
var weightDif = Math.abs(Number(result[1][i]) - weight);
- それぞれの絶対値を足したものを、用意しておいた配列に格納
var difsum = tallDif + weightDif;
dif.push(difsum);
}
- 入力された身長との差をとる
- 身長、体重の差の合計値が格納された配列の要素のうち、最少のものの配列番号を取得
var difIndex = dif.indexOf(Math.min.apply(null,dif));
}
- 配列番号に応じた基準値を、それぞれの採寸場所入力欄の隣に表示
document.getElementById("身長の要素のID").innerHTML = result[0][difIndex];
上記を全項目で行う。
検算
- 検算に用いる採寸場所を入力したときに関数発火
検算に用いる採寸場所にonclickをつけておく - 検算に必要な全ての項目が記入されていることをチェック
身長、体重、と同様 - 検算
シンプルに計算。
res_1 = Math.abs(res_1);
で絶対値をとる
- 検算結果の絶対値が2.5以下であれば、次に進むという表示
計算結果で条件分岐して予めメッセージや文字色を指定。
if文の外で
restext_1.innerHTML = text_1;
- 誤差が大きい場合には再測定を赤文字で表示
restext_1.style.color = text_1_col;
GoogleAppsScript
やりたいことはシンプルながら、なかなかハマりました…
正しいはずのコードでも全く動いてくれず…
ということで、1回全て無かったことにして、こちらのサイトを参考に構築しました。