普通の入力フォームをエクセルのように数式を登録して計算できるようにする方法

2019年10月20日

テクノロジー プログラミング

WEBページで色々なシステムやサービスを構築していると、「エクセルの数式登録って本当にいい仕組みだな」と考えさせられます。 任意のセルの値と別の値を足したり掛けたりして、自由に好きな式を登録して、作った人はなんとなく便利なシステムを自分で作った気分になれるし、実際に非常に便利に使い続けている人も多いことを考えると、世の中のシステムでもっとこうした仕組みを取り入れていかないといけないのでは・・・と考え始めました。 ただ、SQLなどに、数値以外の数式を入れる場合は、型が違うとかの理由でシステム構築する際の設計が非常に重要になってくるので、今回は入力フォームで出来るレベルの手軽な方法を簡単なプログラムと一緒にご紹介します。

サンプルコード

<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>EFO - Calcration</title> <link rel="stylesheet" href="calc.css"> <script src="calc.js"></script> </head> <body> <form name="form1" action="calc.php"> 数値(数式)登録 : <input type="text" name="calc" data-type="calc" value=""> <input type="submit" value="送信"> </form> </body> </html> input[type="text"]{ width:200px; height:30px; border:1px solid #ccc; border-radius:4px; padding:4px; font-size:14px; content:"hoge"; } input:before{ content:"test"; } ;(function(){ var __event = function(target, mode, func , flg){ flg = (flg) ? flg : false; if (target.addEventListener){target.addEventListener(mode, func, flg)} else{target.attachEvent('on' + mode, function(){func.call(target , window.event)})} }; var __construct = function(){ switch(document.readyState){ case "complete" : new $$;break; case "interactive" : __event(window , "DOMContentLoaded" , function(){new $$});break; default : __event(window , "load" , function(){new $$});break; } }; var $$ = function(){ this.setEvent_calc(); }; // data-type="calc"フォームに対して、イベントを設定 $$.prototype.setEvent_calc = function(){ var inputs = document.querySelectorAll("[data-type='calc']"); for(var i=0; i<inputs.length; i++){ __event(inputs[i] , "focus" , (function(e){this.calc_focus(e)}).bind(this)); __event(inputs[i] , "blur" , (function(e){this.calc_blur(e)}).bind(this)); } __event(document.forms.form1 , "submit" , (function(e){this.calc_submit(e)}).bind(this)); }; // focus : data-calcに式が入っている場合はvalueに設置 $$.prototype.calc_focus = function(e){ var input = e.currentTarget; if(!input){return;} var data_calc = input.getAttribute("data-calc"); if(!data_calc){return;} input.value = data_calc; }; // valueに"="から始まる計算式が書かれている場合は、data-calcに敷きを格納して計算結果をvalueに登録する。 $$.prototype.calc_blur = function(e){ var input = e.currentTarget; if(!input){return;} if(input.value.match(/^=(.*?)$/)){ var val = RegExp.$1; input.setAttribute("data-calc",input.value); input.value = eval(val); } else{ input.removeAttribute("data-calc",""); input.removeAttribute("data-calc-result",""); } }; // 送信時(form->post)に対象項目の値を計算結果から、計算式に置き換えてsubmitする $$.prototype.calc_submit = function(e){ var inputs = document.querySelectorAll("[data-type='calc']"); for(var i=0; i<inputs.length; i++){ var calc = inputs[i].getAttribute("data-calc"); if(calc === null || calc === ""){continue;} inputs[i].value = calc; } }; __construct(); })(); <?php echo $_REQUEST["calc"];

使い方

サンプルは全てのファイルをWEBサーバーの同じ場所に設置すると動作するようになっています。 index.htmlにアクセスすると、表示されるinput項目に数値または数式を入力するようになります。 数式はエクセルと同じく"="イコールから始まる文字列にすると、書かれた数式の結果数値が表示され、入力項目にアタッチし直すと、再度数式が現れて編集ができるようになります。 エクセルのようにサーバー登録後に何度も数式を編集し直す場合は、データ登録を数式で行う必要がありますが、そうではない場合は計算結果の数値のみサーバーに送る方法もアリです。 サンプルでは、送信時に入力フォームを数式の計算結果から数式に入れ替えてサーバーに送るようにしていますが、この辺はシステム全体の仕様に関わるので、サーバー構成で決めてもらえればと思います。

サンプル

See the Pen Excel-input by YugetaKoji (@geta1972) on CodePen.

サンプルではphpへのアクセスは出来ないので、「送信」ボタンを押すとエラーになりますが、今回はフロントエンドまでのご紹介という事で、それ以降はご使用に応じてお使いください。 ちなみに、この入力フォーム(inputタグ)は、普通に数値登録しても使えるので、アドオン機能として利用することも可能ですよ。