- ベストアンサー
jquery.csv2table.jsのテーブルを使ってCSVデータを表示したい
- jquery.csv2table.jsを使って、CSVの会員名簿をWEB上で表示したいと思っています。
- 表示されるテーブルが横長になってしまうため、一行をセルの結合で2段にまとめて表示したいです。
- しかし、セルの場所を任意に変更することはできないため、難しいかもしれません。詳しい方に教えていただきたいです。
- みんなの回答 (11)
- 専門家の回答
質問者が選んだベストアンサー
return rec.split (/\t/g); を return rec.split (/,/g); にでもしましょうか? ^^; いい加減な回答で申し訳ない。以下を理解しないと私は先に進めません。そろそろ忙しくなってもきましたし・・・。 http://www.ietf.org/rfc/rfc4180.txt
その他の回答 (10)
- babu_baboo
- ベストアンサー率51% (268/525)
またも連投! アルゴリズムを見直しました。 あくまでもcsvファイルの読み込みは簡易的なもの。 信用してはいけません。 テーブルヘッドとフッタはどこへ行った? <!DOCTYPE html> <meta charset="utf-8"> <title>テーブルをn行に?</title> <style> th { color: green; width: 6em;} td { width:4em;} tbody th { background: #efe;} </style> <body> <table border="1" id="hoge"></table> <script> (function () { var reg_separator = /^\s*(\d+)(?:@([hd]?)(?:([Rr])([1-9][0-9]*)?)?(?:([Cc])([1-9][0-9]*)?)?)?\s*$/; //_____ function Ary2table (table, order, template) { this.table = table; this.order = order; this.template = template; } function setTbody (ary) { if (1 > arguments.length) throw new Error (); for (var i = 0, rec; rec = ary[i++]; ) { for (var j = 0, e, J = rec.length; j < J; j++) if (e = this.order[j]) e.textContent = rec[j] || ''; this.table .appendChild (this.table.ownerDocument.createElement ('tbody')) .appendChild (this.template.cloneNode (true)); } return this; } function load (name) { var req = new XMLHttpRequest; req.open ( 'GET', name, false); req.send (null); if (200 !== req.status ) throw new Error; this.setTbody ( req.responseText.trim () .split (/\r\n|\n|\r/g).map ( function (rec) { return rec.split (/\t/g); } ) ) } function createMap (format) { var doc = this; var fgm = doc.createDocumentFragment (); var tr = doc.createElement ('tr'); var order = [ ]; var i, j, J, buf, a, e, tr_; var rowMax = format.length; for (i = 0; buf = format[i++]; ) { fgm.appendChild (tr_ = tr.cloneNode (false)); for (j = 0, J = buf.length; j < J; j++) { if (! (a = reg_separator.exec (String (buf[j])))) throw new Error ('Syntax error: ['+ i+ ','+ j+ ']='+ buf[j]); tr_.appendChild (order[+a[1]] = e = doc.createElement ((a[2] === 'h') ? 'TH': 'TD')); if (a[3]) e.setAttribute ('rowSpan', a[4] || rowMax); if (a[5]) e.setAttribute ('colSpan', a[6] || J); // J? } } return { order: order, template: fgm }; } function create (table, format) { if (2 > arguments.length) throw new Error (); var map = createMap.call (table.ownerDocument, format); var obj = new Ary2table (table, map.order, map.template) return obj; } //_____ Ary2table.create = create; Ary2table.prototype.setTbody = setTbody; Ary2table.prototype.load = load; this.Ary2table = Ary2table; }) (); //____ var format = [ // セルNo @ h r[rowspan] c[colspan] ['0@hr', 1, 4, 7], [ 2, 5, 8], [ 3, 6, 9] ]; Ary2table.create (document.getElementById ('hoge'), format).load ('test.csv'); </script>
補足
babu_baboo様 何度もお付き合いくださりありがとうございます。 上記スクリプトですが、私のせいか<TH>にCSV1行が入ってしまい、<TD>は空っぽとなってしまいました。。。 自分でもbabu_baboo様のように、ここまで書ければ良いのですが( p_q)
- babu_baboo
- ベストアンサー率51% (268/525)
いつもより、”やっつけ” で書きました。 テーブルを置き換えるのではなく、CSVを配列にした状態からテーブルを作成します。 正規表現が何を意味するのか理解できれば好いのですが。 まぁこれは書いた本人も微妙ですし…。 ろくに確かめてもいないし…。 <!DOCTYPE html> <meta charset="utf-8"> <title>テーブルをn行に?</title> <style> th { color: green; width: 6em;} thead, tfoot { background: #8c8;} tbody th { background: #efe;} .num { text-align : right; } </style> <body> <table border="1" id="hoge"></table> <script> var D = /^(?:(?:(#)(?:\[(?:(\d+)(?:,(\d+)?)?)?\])?))?(.*)$/;//#[rowSpan,colspan]text function C (a) { var b = D.exec (a), c; if (b[1]) { c = document.createElement ('th'); c.textContent = b[4] || ''; if (b[2]) c.setAttribute ('rowSpan', b[2]); if (b[3]) c.setAttribute ('colSpan', b[3]); } else { c = document.createElement ('td'); c.textContent = a; if (! isNaN(a)) c.className = ('num'); } return c; } function B (a, b) { var c = document.createDocumentFragment (); var d = b.map (C); var i = 0, j, J, tr, m; for (i = 0; m = a[i++]; ) { tr = c.appendChild (document.createElement ('tr')); for (j = 0, J = m.length; j < J; j++) { tr.appendChild (d[m[j]]) } } return c; } function A (a, b, c, d, e) { if (3 > arguments.length) throw new Error; var f = document, g; while (g = a.firstChild) a.removeChild (g); if (d) a.appendChild (f.createElement ('thead')) .appendChild (B (b, d)); if (e) a.appendChild (f.createElement ('tfoot')) .appendChild (B (b, e)); if (c) c.forEach (function (h) { a.appendChild (f.createElement ('tbody')) .appendChild (B (b, h)); }) } //______________ var body = [ ['#[3]abcd',1,2,3,4,5,6,7,8,9], ['#[3]efgg',9,8,7,6,5,4,3,2,1] ]; var format = [ [0, 1, 4, 7], [ 2, 5, 8], [ 3, 6, 9] ]; var head = ['#[3]Name', '#a', 'b', 'c', '#d', 'e', 'f', '#g', 'h', 'i']; var foot = head; A (document.getElementById ('hoge'), format, body, head, foot); </script>
補足
babu_baboo様 何回もご回答頂き、本当にありがとうございます。 上に書いて下さったscriptは綺麗に表になっておりました! ですが、私の頭が追いついておりません・・少し整理して理解しましたら改めてお礼をさせて下さい。 取り急ぎありがとうございます。
- fujillin
- ベストアンサー率61% (1594/2576)
こんにちは。ANo3です。 「お薦めしない」といいながらも再度の投稿です(笑) csv2tableがどのような処理をしているか把握していないので、データはもちろん文書の構造もいじらない方が無難かなと思った次第です。 そうすると、どうしても表示のレイアウトでなんとかしようということに… HTMLが表示のためだけに利用されているなら、ANo4様の回答のように書き直しても問題は出ないでしょう。 >CSSで表示を変える方法は思案したのですが、やはりブラウザの差もあるので >不安定と思い避ける事といたしました。 ご意見ごもっともと思いますし、回答にも懸念を記載した通りです。 と言いながら・・・ いっそのこと、各セルをabsoluteで個々に指定してしまえば、ブラウザの差異も少ないのではないかと想像します。(せいぜい20項目程度?) 決してお薦めするつもりではありません(笑)
お礼
fujillin様 再度ご回答頂きありがとうございます。 absoluteでの方法もあると言う事、参考にさせて頂きます。 ありがとうございました。
- babu_baboo
- ベストアンサー率51% (268/525)
連投すみません。 目が覚めて気がつきました。 プロの人達から指摘が入る前に自分で指摘しておきます。 このプログラムは、マークアップする側から見ればダメです。 1レコードをN行にするので、行数はN倍に増えます。 そこである適当な行に注目します。 その行には、1レコードの何行目かをしるすものがありません。 せめて、class を指定して1レコードの何行目か(もしくは1レコードの何番目)を付加するべきでした。 やはりこの場合、1レコードを1つのtbodyにして表を作成すべきです。 見た目は変わりませんが、スクリプトで単純に置き換えたダメな例ですね。 また見た目が近いとして hr で置き換えしているものも、マークアップとしては間違いです。 rowSpanで2行にしてグループにしておきながら、間に<hr>文脈がまったく関係なくなる区切りのタグを使うのは、やってはいけないことです。
- babu_baboo
- ベストアンサー率51% (268/525)
テーブルが表示された後に、実行する もしくは、3秒後に実行されるようにする。 A(document.querySelector ('table'), [-1, 0, 0, 0, 1, 1, 1, 0, 1]); を、 // function AA () { A(document.querySelector ('table'), [-1, 0, 0, 0, 1, 1, 1, 0, 1]); } setTimeout (AA, 3000); // にする。 もちろん知っていると思うけど、2行以上でもOKだよ! もしくは誰かに再度聞く。 もしくは・・・、指をくわえて諦める。
- babu_baboo
- ベストアンサー率51% (268/525)
間違えた。 trs = [tr].concat (trs.reverse ()); を trs = [tr].concat (trs); に! (またも)すみません。
- babu_baboo
- ベストアンサー率51% (268/525)
ななめ下&横から ながめて、使えますかね? <!DOCTYPE html> <meta charset="utf-8"> <title>テーブルをn行に?</title> <body> <table border="1"> <tr> <th>A <th>B <th>C <th>D <th>E <th>F <th>G <th>H <th>I <tr> <td>1 <td>2 <td>3 <td>4 <td>5 <td>6 <td>7 <td>8 <td>9 </table> <script> function insertAfter (a) { this.parentNode.insertBefore (a, this.nextElementSibling); } function toAry (n) { return Array.prototype.slice.call (n, 0); } function B (tr) { var fmt = this; var thd = toAry (tr.children); var max = Math.max.apply (null, fmt); var trs = []; var e, i, n; for (i = 0; i < max; i++) trs.push (tr.cloneNode (false)); trs.forEach (insertAfter, tr); trs = [tr].concat (trs.reverse ()); max++; for (i = 0; e = thd[i]; i++) { switch (n = fmt[i]) { case 0 : case undefined : break; case -1: e.setAttribute ('rowSpan', max); break; default: trs[n].appendChild (e);break; } } } function A (table, format) { toAry (table.querySelectorAll ('tr')).forEach (B, format); } alert("Change!!"); A(document.querySelector ('table'), [-1, 0, 0, 0, 1, 1, 1, 0, 1]); </script> もっとコンパクトに書けそうだけれども…。
補足
babu_baboo様 ご回答ありがとうございます。 まさにやりたい表になっております! ですが、私の知識不足の為jquery.csv2table.jsにどう組み込めばよいのか全く解りません。。 ためしに、babu_baboo様が書いて下さったスクリプトをHTMLに埋め込んでみたのですが csv2tableで表が表示される前(ボタンで表示されます)にチェンジのアラートが出てしまい、結果何も起こらずじまいとなってしまいました。 わざわざここまで書いて下さったのに本当にすみません。 もっと勉強しないとダメですね( p_q)...
- fujillin
- ベストアンサー率61% (1594/2576)
少々無理やり感があるので、お薦めではありませんが… tdをinline-blockなどにしておいて、trの中でレイアウトし直してしまえばデータはそのままで、表示のレイアウトだけを変えることができるようです。 CSSで細かに指定してあげる必要がありますが、これならデータのtable構成はそのままなので、ソートしても同じレイアウトを保つことが可能です。 とはいうものの、もともとがtable要素として作成されているものを、本来のtableでなくしてしまうところが問題かもしれませんが… ブラウザによって同じ挙動をするかどうかまでは確認していませんが、Fxで簡単に試してみたところ可能なようです。 例えば、ANo1の補足のようなレイアウトなら、 trをposition:relativeにしておく tdをfloat:leftにして高さと幅を指定 項目B、Cだけ高さを半分に指定 項目Cをposition:absoluteで項目Bの下に来るように位置指定 といった要領で、一応それらしき表示にすることが可能です。 nth-childで指定する必要がありそうですが、これが使えないブラウザを対象にするのであれば、csv2tableにonloadのオプションがありますので、そちらで対象とするセルにクラス名を設定しておいてそれを利用するなどの工夫が必要かもしれません。 先に書きましたようにお薦めの方法とは言えませんので、どうしようもない時のアイデアとして…
お礼
fujillin様 ご回答ありがとうございます。 CSSで表示を変える方法は思案したのですが、やはりブラウザの差もあるので不安定と思い避ける事といたしました。 わざわざ試して頂いて大変申し訳ございません。 ありがとうございます。
- ONEONE
- ベストアンサー率48% (279/575)
なるほど、、、 そのようになると例示の場合にCSVの時点で項目Bと項目Cの間のカンマを<hr>にするのが一番簡単かと思います。 次点で、CSVを一行一行読み込む時に、○個目のカンマを<hr>にするという処理を加える方法です。 例えば2個目のカンマを<hr>に変えるにはstr_replaceと下記の正規表現で可能です。 ^([^,]+(,)){2} この方法はプラグインに直接手を加えなくてはならないのであまりよろしくないかもしれません。
お礼
ONEONEさま ご回答ありがとうございます。 <hr>を入れる案、とても希望する形には近くはなるのですが、項目が1つに集約されてしまうのでソート機能もどちらかが機能しなくなってしまいます・・・ やはり、これは難しいのですね。別の方法も考えてみようと思います。 ご回答ありがとうございました。
- ONEONE
- ベストアンサー率48% (279/575)
>出来れば一行をセルの結合で2段にまとめて表示したいと思っています。 ><td colspan="2"><td rowspan="2">を使って >[1]はココに表示[2]はココに表示するみたいにテンプレ化して表示できればと思っていますが >セルの背景色は変更できてもセルの場所を任意に変更できません 私にはここの意味がわかりません。 具体的なcsvの一行と、こう表示したいっていうのを例示してもらえますか? ソート機能ついてるし、ちょっと難しいのでは?と予想しますが、、、
補足
質問時に画像を添付するべきでした、、、解りづらい文章ですみません。 【CSV】 項目A/項目B/項目C/項目D/項目E あ,い,う,え,お 【HTML表示の表】 ------------------------------ 項目A|項目B|項目D|項目E| |-----| | | |項目C| | | ------------------------------ あ | い | え | お | |-----| | | | う | | | ------------------------------ ずれて見えてしまうかもしれませんが やりたい事は上のような項目Bと項目Cを二段で表示した表の表示です。 (実際にはもっと横長に項目量が多いです) やはり難しいですかね・・・
お礼
babu_baboo様 何度もお答え頂きありがとうございました。 上記部分を修正しましたらちゃんとTDに入りました! お忙しい中教えて頂きまして本当にありがとうございます。ペコリ ((-ω-('ω'〃)