セルの内容を取得して計算する


■Q&A

■Question

javascriptで表計算 2004.4.12.Mon No.3219

javascript 超初心者です。宜しくお願いします。
javascript を使用して簡単な表計算をしたいのですが、出来ますでしょうか?
内容は Table タグで作った表に 1.0 や 5.0 などの文字列が入っていて、その行や列の合計を一番端に表示さたいだけなのです。input タグは使用しません。純粋に <td>1.0</td> の値を数値として計算したいのです。
計算する値は残業時間の計算なので 5.0 の様な形になります。

どうかご指導お願いします。

■Answer

Re: javascriptで表計算 ぴろあき 2004.4.14.Wed No.3220

※ここの部分のソースは■横計算バージョンに書いてあります。

教科書的に作るとこんな感じかな?
処理のステップとしては

  1. <td> の内容を取得する
  2. 計算する
  3. 結果を <td> へ表示する

と、たったこれだけです。
問題は JavaScript からHTMLへアクセスする方法なんですが、前時代の方法ではそれができず、<input type="text"> などで代用するしかありません。古いブラウザでも動くのはメリットですが、もはやそれだけがメリットです。

そこで、新しい方法として JavaScript とHTMLを橋渡しする「DOMインターフェイス」というのがあります。身近なメジャーブラウザではIE5以降・Netscape6以降・Opera7以降(Opera6は中途半端)・Safariなどが実装してます。
このサンプルでは、いくつかのノードインターフェイスを使ってますが、個々の詳細は検索とかで調べてみてください。(解説サイトも無数にあります)

http://jt.mozilla.gr.jp/docs/dom/technote/tn-dom-table/
http://www.parkcity.ne.jp/~chaichan/src/javascdom01.htm

DOMを使うことで JavaScript からHTMLへ自由にアクセスでき、document.write() さえも過去の遺産にすることができます。また、DOMには仕様書があるので、ブラウザごとに処理を振り分けなくていいのも大きな魅力でしょう。(すべてのブラウザが完全に同じ動作をする…ともいかないのが現状ですけど)

■Res

Re: javascriptで表計算 2004.4.20.Tue No.3229

いろいろご丁寧に有り難うございます<(__)>
ご説明の内容で実施してみたいと思います。

また何かありましたら宜しくお力添えください。
有り難うございました。

■Question

Re: javascriptで表計算 2004.4.20.Tue No.3231

先日は大変助かりました。有り難うございました。

たびたび申し訳ありません。。。もう1点教えてください。

ご教授いただいた方法の応用で、たての合計をするにはどのように記述したら宜しいのでしょうか?
計算としては複数列のうち特定の列のみ計算する方法が知りたいのですが。
また空白のセルも混在していた場合についても教えて頂きたいのですが。(空白の場合は0を代入したい)

宜しくお願い致します。

■Answer

Re: javascriptで表計算 ぴろあき 2004.4.22.Thu No.3234

横に計算するのは簡単なんですが、縦はちょっと難しくなります。(なのでサンプルは横で作ったのですけど)

<table>
  <tr> <td1><td2><td3> </tr>
  <tr> <td1><td2><td3> </tr>
  <tr> <td1><td2><td3> </tr>
</table>

要するに、<tr> ごとに <td1> <td2> <td3> と個別に足していけばいいわけです。
まぁこれで充分なヒントになると思いますが、より高度なサンプルを作ってみたので興味があったら見てみてください。
http://faq.creasus.net/04/0422/

■Res

Re: javascriptで表計算 2004.4.23.Fri No.3237

ぴろあき様

ご回答、本当に本当に有り難うございます<(__)>
初心者故いろいろ質問させて頂く機会が多い中、ここまで親切丁寧にご回答頂いたことはありません。感謝感激しております。
自分の無知度合いをとても恥ずかしく思う一方、もっと勉強して行かねばと自分に活を入れ直しました。
作成して頂いたサンプルを参考に活用し、大切に保管致します。

次回質問させて頂く機会がありましたら、もう少しまともな内容で書けるよう頑張りますので、今後とも宜しくお願い致します。

ありがとうございました。

■Res

Re: javascriptで表計算 ぴろあき 2004.4.24.Sat No.3238

知りたいという興味を忘れずにいれば、人は成長するようにできてるものです。
JavaScript は簡単といっても、始めたてのうちは憶えることが山ほどありますから、ぷちぷちやってくのが良いですよ。
JavaScript に限らず、プログラムなんて一通りの構文さえマスターすれば、後は想像力と応用の世界ですしね。
頑張ってください。


縦計算バージョン

■縦計算:スクリプトの概要

メイン関数である tatecalc() には、2種類の動作モードがあります。

  1. セルを縦に計算して、最後の行に合計値を入れる
  2. 指定されたセルを縦に計算して、合計値を返す(複数同時指定可)

動作モードは渡す引数の数で自動で切り替わります。(引数を2つ以上渡すと 2. になる)


■縦計算:実行結果

非対応ブラウザでは実行されません。

1.セルを縦に計算して、最後の行に合計値を入れる

window.onload で実行され、結果をテーブルへ挿入します。出力にはDOMを使っています。
このサンプルでは、ついでにHTMLを作って表の下に列の個別結果を表示しています。

tr[0] td[0] td[1] td[2] td[3] td[4]
tr[1] 1.00 5.5 文字は無視 0000.4
tr[2] 3.0 5.4 100.
tr[3] 4.134 3.3 0.2 9.1
tr[4] 0.00 0.1 9.25 3混じっても無視

2.指定されたセルの合計値を返す

取得したい列を引数で渡すと、結果を返します。表への結果挿入はしません。
出力には document.write() を使っています。


■縦計算:ソース

■メイン関数

■1.セルを縦に計算して、最後の行に合計値を入れる

function loadComplete() {

  //引数をID名だけにすると結果をセルへ挿入する
  //tdsum = 各列ごとの合計値(配列)
  var tdsum = tatecalc("table1"); //<table id="table1">を対象にする

  //表示するHTMLを作る
  //数値は *1000 されたままなので小数に戻す
  var allsum = 0; //すべての<td>の合計値
  var text = "";
  var d = document; //記述の省略用
  var p = d.createElement("p"); //<p>を作る

  for (var i = 0; i < tdsum.length; i++) {
    allsum += tdsum[i];
    text = "td[" + i + "] の合計は " + (tdsum[i] /1000)+ "。";

    p.appendChild(d.createTextNode(text)); //text をノードに変換して<p>の最後に挿入
    p.appendChild(d.createElement("br")); //<br>を作って<p>の最後に挿入
  }

  text = d.createTextNode("全部のセルの合計は " + (allsum /1000) + "。")
  var strong = d.createElement("strong"); //<strong>を作る
  strong.appendChild(text); //<strong>の最後に text を入れる
  p.appendChild(strong); //<p>の最後に<strong>を入れる

  var table = d.getElementById("table1"); //<table id="table1">を取得する
  table.parentNode.insertBefore(p, table.nextSibling); //</table>の直後に<p>を挿入する
}

window.onload = loadComplete; //オンロードで loadComplete() が実行されるようにする

■2.指定されたセルの合計値を取得する

var sum = tatecalc("table1", 0, 1, 4); //td[0], td[1], td[4] の合計値が配列で返ってくる

if (sum) { //非対応ブラウザの時は false が返ってくるので確認
    var s = "<p><strong>";
    //数値は *1000 されたままなので元に戻す
    s += "<code>td[0]<\/code> の合計は " + (sum[0] /1000) + "。<br>";
    s += "<code>td[1]<\/code> の合計は " + (sum[1] /1000) + "。<br>";
    s += "<code>td[4]<\/code> の合計は " + (sum[2] /1000) + "。<br>";
    s += "<code>td[0,1,4]<\/code> の合計は " + ((sum[0] + sum[1] + sum[2]) /1000) + "。<br>";
    s += "<\/strong><\/p>";
    document.write(s);
}


■縦計算:対応ブラウザ

IE5.5以降・Netscape6以降・Opera7以降
まともなDOMを実装してるので万事OKです。
IE5.0
DOMは弱いとこが多いですが、とりあえずこのサンプルは動きます。
MacとかUNIXとか
環境がないのでわかんないですが、Netscape6以降のようにきちんとしたDOMを実装していれば、動くことが期待されます。
Winのそれ以外のブラウザ
動かないです。Opera6はDOMを実装してますが、質が悪いので超ダメです。

横計算バージョン

■横計算:ソース

セルを横に計算するバージョン。
横に計算する時は <tr> ごとに <td> を計算すればいいだけなので簡単です。

function yokocalc(tableID) {
  if (!document.getElementById || !document.getElementsByTagName || (window.opera && !document.createEvent))
    return; //非対応ブラウザはなにもしない

  var table = document.getElementById(tableID); //<table id="ID名">を取得:DOM
  var tr = table.getElementsByTagName("tr"); //<table>内の<tr>を全部取得(配列):DOM

  var td, sum, num;

  for (var i = 1; i < tr.length; i++) { //<tr>の数だけ繰り返し(最初の1列目はスキップ)

    td = tr[i].getElementsByTagName("td"); //i番目の<tr>内にある<td>を全部取得(配列):DOM
    sum = 0; //<td>の合計値
    num = 0; //計算用の一時変数

    for (var j = 0; j < td.length -1; j++) { //<td>の数-1 だけ繰り返し(最後の<td>は結果表示用)
      if (td[j].firstChild) { //<td>内に文字が入ってるか
        num = td[j].firstChild.data; //<td>内の文字を取得:DOM
        num = parseFloat(num); //数値に変換
        num = num *1000; //小数点問題を回避するために適当な整数にする
      } else {
        num = 0; //セルの中身がない時は0として扱う
      }
      sum = sum + num;
    }

    sum = sum /1000; //整数を小数に戻す
    sum = document.createTextNode(sum); //sumをテキストノードに変換する:DOM
    td[j].appendChild(sum); //sumを最後の<td>に挿入:DOM
  }
}


■横計算:実行結果

1 2 3
1.0 2.29 3.4
3.0 4.2 5.8
2.0 5.1

■DOMについて個人的に思うこと

勘違いされることが多いのですが、DOMはインターフェイス(橋渡し)であり、JavaScript ではないです。JavaScript にDOMとアクセスする機能が備わってるだけです。

DOMはプログラム言語とファイルの中間に立ち、相互間の橋渡しをしたりジェットストリームアタックをかけたりします。アタックがきたら上手くよけるなり踏み台にするなりしないといけません。
もちろん「プログラム」は JavaScript だけではないし、「ファイル」はHTMLだけではないです。VBScript でも使えるし、XHTMLやXMLも扱えます。(ただ、HTMLはすでに「終わった言語」なので、XHTMLやXMLの方に主眼が置かれてます)

そして、DOMを使い始めるとこれまでのようにルーズなHTMLは通用しなくなります。従来はHTMLと JavaScript が分離してたので、HTMLにミスがあってもたいした問題にはなりませんでしたが、これからはスクリプトエラーに直結します。

納得のいかないエラーが起きる場合は W3C Validation ServiceAnother HTML lint といったHTMLチェックサービスを活用してみるといいかも。

今は過渡期でAからZまでDOM…というわけにもいかないですが、これまでみたいなブラウザ独自拡張機能とは違うので、近い将来に大きな地位を占めるようになるんじゃないかと思います。(個人的にはXHTMLの普及が鍵だと思ってるんですが)
とりあえず、憶えて得することはあっても、損することはありません。欠点としては…難しいとこでしょうか。


■蛇足

…と、こんな感じになります。多少の汎用性は考えたけど、その分だけ小難しくなってます。その気になれば縦横を同時に計算することもできますが、ちょっと複雑になりすぎるのでやめました。
JavaScript を始めたてだと気が遠くなると思いますが、頑張って解析してみてください。

足りない部分はあるものの、その辺はサンプルスクリプトごときがサポートできる範囲ではないので、ご自由に編集したりHDの肥やしにしたりすると良いでしょう。

あと、セルに colspanrowspan が入ると難度ランクが跳ね上がるのでご注意を。(こんな一朝一夕スクリプトでは無理)


■ このページについて

このページは、質疑応答掲示板で使用した回答の残骸です。検索エンジンに捕まったりリサイクルしたりすることもあろうので、なんとなく残してあります。広く公開しているページではありませんが、第3者の閲覧を禁止するものでもありません。
恒久的なURIは保証できないものの、よほどのことがない限り削除されることはないでしょう。心配性な人はページの保存をおすすめします。(IEは mht 形式でないと保存できないかも)