JavaScript/table2csv のバックアップの現在との差分(No.9)
TITLE:JavaScriptでHtmlのtable要素をCSVに変換する
Posted by aterai at 2012-07-25
JavaScriptでHtmlのtable要素をCSVに変換する
- title: JavaScriptでHtmlのtable要素をCSVに変換する keywords: [JavaScript, Bookmarklet, HTML, table, CSV, TSV] author: aterai pubdate: 2012-07-25 description: Htmlのtable要素をCSV、TSVに変換するBookmarklet
概要
Html の table 要素を CSV に変換する Bookmarklet です。colspan、rowspan で結合するセルがある場合は、同文字列を挿入しています。概要
Html
の<table>
要素をCSV
(character-separated values
)に変換するBookmarklet
です。colspan
、rowspan
で結合するセルがある場合は、同文字列を挿入しています。
- ブックマークレットなどに登録して表のあるページで実行
- table要素をダブルクリックすると、tableがtextareaに置換されて、内容がCSVになりコピー可能
- 子要素にtableが存在する場合は、ダブルクリックに反応しない
- textareaをダブルクリックすると、元のtableに戻る
- <thead><tfoot>は気にしていない(例えば、tbodyの前にあるtfootが、そのまま先の行としてCSVになる)
- <capthion>は無視
- <colgroup>のspan属性には未対応
- 区切り文字はタブ(
TSV
) - ブックマークレットなどに登録して表(
<table>
要素)のあるページで実行 -
<table>
要素をダブルクリックすると、その内容をCSV
に変換して<textarea>
に文字列として挿入- 子要素に
<table>
が存在する場合は、ダブルクリックに反応しない -
<table role="presentation">
や<table border="0">
のような、レイアウト目的の<table>
は無視する
- 子要素に
-
<textarea>
をダブルクリックすると、元の<table>
に戻る -
<thead>
や<tfoot>
の扱いは適当(例えば、<tbody>
の前にある<tfoot>
が、そのまま先の行としてCSV
になる) -
<capthion>
は無視 -
<colgroup>
のspan
属性には未対応
ソースコード
#spanend
#spandel
// ==UserScript==
#spanend
#spandel
// @name <table> to CSV
#spanend
#spandel
// @namespace http://terai.xrea.jp/
#spanend
#spandel
// @include http://*
#spanend
#spandel
// @description Html table -> CSV(textarea)
#spanend
#spandel
// @version 1.0.2
#spanend
#spandel
// ==/UserScript==
#spanend
#spandel
(function() {
#spanend
function table2csv(table) {
var tr = table.getElementsByTagName("tr"),
csv = "",i,j,k,l,xoff, text, csvRow, cells, td, array = [], lenr = tr.length, lenc;
for(i=0; i<lenr; i++) {
//前行のセルのcolspanで、すでにこの行は初期化されている場合がある
if(array[i] == null) array[i] = [];
cells = tr.item(i).cells;
lenc = cells.length;
for (j=0; j<lenc; j++) {
td = cells.item(j);
//タグの削除、タブをスペースに置換、両側trim、ダブルクオートの二重化
text = td.innerHTML.replace(/<.*?>/mg, "").replace(/\t/g," ").replace(/(^\s+)|(\s+$)/g, "").replace(/\"/, '""');
//前の行のrowspanですでにこのセルが使用されている場合はxoffだけ移動
xoff = 0;
while(array[i][j+xoff] != null) {
xoff++;
}
for(k=0; k<td.colSpan; k++) {
array[i][j+xoff+k] = text;
for(l=0; l<td.rowSpan; l++) {
if(array[i+l] == null) array[i+l] = [];
array[i+l][j+xoff+k] = text;
}
}
}
}
lenr = array.length;
lenc = array[0].length;
for(k=0; k<lenr; k++) {
csvRow = "";
for(l=0; l<lenc; l++) {
//内容をダブルクオートで囲んでタブ区切りで追加
csvRow += "\t\""+array[k][l]+"\"";
}
if(csvRow != "") {
csvRow = csvRow.substring(1,csvRow.length);
}
csv += csvRow+"\n";
}
return csv;
}
var listener = function(e) {
var tx = document.createElement("textarea");
tx.value = table2csv(this);
//textareaのサイズは適当
tx.style.width = '80%';
tx.style.height = "240px";
tx.originalTable = this;
this.tx = tx;
this.parentNode.replaceChild(this.tx, this);
tx.addEventListener("dblclick", function(e) {
this.parentNode.replaceChild(this.originalTable, this);
}, false);
},
table = document.getElementsByTagName("table"), i = 0, len = table.length;
for(; i<len; i++) {
//tableがネストしている(子tableが存在する)場合は、クリックしても無視する
if(table[i].getElementsByTagName("table").length>0) continue;
table[i].addEventListener("dblclick", listener, false);
}
#spandel
}());
#spanend
#spandel
ソースコード
Bookmarklet
Bookmarklet
- 名前(任意)
- table2csv
- アドレス(YUI Compressor で圧縮)
javascript:(function(){function e(x){var t=x.getElementsByTagName("tr"),o="",p,n,m,h,v,u,s,w,g,r=[],q=t.length,f;for(p=0;p<q;p++){if(r[p]==null){r[p]=[]}w=t.item(p).cells;f=w.length;for(n=0;n<f;n++){g=w.item(n);u=g.innerHTML.replace(/<.*?>/mg,"").replace(/\t/g," ").replace(/(^\s+)|(\s+$)/g,"").replace(/\"/,'""');v=0;while(r[p][n+v]!=null){v++}for(m=0;m<g.colSpan;m++){r[p][n+v+m]=u;for(h=0;h<g.rowSpan;h++){if(r[p+h]==null){r[p+h]=[]}r[p+h][n+v+m]=u}}}}q=r.length;f=r[0].length;for(m=0;m<q;m++){s="";for(h=0;h<f;h++){s+='\t"'+r[m][h]+'"'}if(s!=""){s=s.substring(1,s.length)}o+=s+"\n"}return o}var d=function(g){var f=document.createElement("textarea");f.value=e(this);f.style.width="80%";f.style.height="240px";f.originalTable=this;this.tx=f;this.parentNode.replaceChild(this.tx,this);f.addEventListener("dblclick",function(h){this.parentNode.replaceChild(this.originalTable,this)},false)},c=document.getElementsByTagName("table"),b=0,a=c.length;for(;b<a;b++){if(c[b].getElementsByTagName("table").length>0){continue}c[b].addEventListener("dblclick",d,false)}}());
-
table2csv
-
- アドレス(
YUI Compressor
で圧縮)javascript:(function(){function f(w){var s=w.getElementsByTagName("tr"),p,o,n,m,u,t,v,h,r=[],q=s.length,g;for(p=0;p<q;p++){r[p]=r[p]||[];v=s.item(p).cells;g=v.length;for(o=0;o<g;o++){h=v.item(o);t=h.innerHTML.replace(/<.*?>/mg,"").replace(/\t/g," ").replace(/(^\s+)|(\s+$)/g,"").replace(/\"/,'""');u=0;while(r[p][o+u]!=null){u++}r[p][o+u]=t;for(n=1;n<h.colSpan;n++){r[p][o+u+n]=t}for(m=1;m<h.rowSpan;m++){r[p+m]=r[p+m]||[];for(n=0;n<h.colSpan;n++){r[p+m][o+u+n]=t}}}}return e(r)}function e(o){var m=o.length,n=o[0].length,h="",j,i,g;for(i=0;i<m;i++){j="";for(g=0;g<n;g++){j+='\t"'+o[i][g]+'"'}if(j!=""){j=j.substring(1,j.length)}h+=j+"\n"}return h}var d=function(h){var g=document.createElement("textarea");g.value=f(this);g.style.width="80%";g.style.height="240px";g.originalTable=this;this.tx=g;this.parentNode.replaceChild(this.tx,this);g.addEventListener("dblclick",function(i){this.parentNode.replaceChild(this.originalTable,this)},false)},c=document.getElementsByTagName("table"),b=0,a=c.length;for(;b<a;b++){if(c[b].getElementsByTagName("table").length>0){continue}if(c[b].getAttribute("role")==="presentation"||(c[b].getAttribute("border")==="0")){continue}c[b].addEventListener("dblclick",d,false)}}());
- アドレス(テスト用にtable2csv.jsを読み込む)
javascript:(function(){var s=document.createElement("script");s.charset="UTF-8";s.src="http://terai.xrea.jp/data/javascript/table2csv.min.js?"+(new Date()).getTime();document.body.appendChild(s)}());
- アドレス(テスト用にtable2csv.user.jsを読み込む)
javascript:(function(){var s=document.createElement('script');s.charset='UTF-8';s.src='https://ateraimemo.com/data/javascript/table2csv.user.js?'+(new Date()).getTime();document.body.appendChild(s)}());
テスト用table
- アドレス(テスト用にtable2csv.min.jsを読み込む)
javascript:(function(){var s=document.createElement('script');s.charset='UTF-8';s.src='https://ateraimemo.com/data/javascript/table2csv.min.js?'+(new Date()).getTime();document.body.appendChild(s)}());
- rowspan, colspan
ユーザースクリプト、拡張機能
-
FireFox
-
Greasmonkey
などのユーザースクリプトとしてtable2csv.user.js
をドロップして追加
-
-
Chorme
など-
dev
版などで拡張機能タブにtable2csv.user.js
をドロップして追加
-
テスト用table
-
rowspan
,colspan
-
Bookmarklet
を実行、または拡張機能として追加した後、以下の表をダブルクリックするとCSV
文字列に変換A B C D 1 2 3 4 5 6 7
-
"A" "B" "C" "D" "1" "2" "3" "3" "4" "5" "5" "6" "7" "5" "5" "6"
- footer
ファイル数 サイズ 総行数 コメント行 実行数 空行数 コメント率 footer 合計 169 5291916 174370 77045 84804 12521 平均 31313 1031 455 501 74 44.13%
参考リンク
参考リンク
- CSV from HTML tables Bookmarklet | Bookmarklet Search Engine
- CodeKeep Snippet : Convert html table to csv (JavaScript)
コメント
- 表計算ソフトなどの場合は、tableタグをコピペするだけでspanを考慮した表の取込みが出来るので、このスクリプトを使って CSV, TSV に変換して読み込む意味はあまりないかも。ただ、自分の使いたいソフトには、Htmlでのtable取り込み機能がなく、csvを読み込んで表にする機能と、連続する同文字列セルの結合が可能なので作成してみました。取り込み作業は終わったのでもう必要ないけど、せっかくなので公開しておきます。 -- aterai
- innerTextではなく innerHTML.replace(/<.*?>/mg, "") を使用して、FireFoxでも動作するように修正。 -- aterai
コメント
- 表計算ソフトなどの場合は、
<table>
タグをコピペするだけでspan
を考慮した表の取込みが出来るので、このスクリプトを使ってCSV
,TSV
に変換して読み込む意味はあまりないかも。ただ、自分の使いたいソフトには、Html
での<table>
取り込み機能がないが、csv
を読み込んで表にする機能があり、また連続する同文字列セルの結合が可能なので作成してみました。取り込み作業は終わったのでもう必要ないけど、せっかくなので公開しておきます。 -- aterai -
innerText
ではなくinnerHTML.replace(/<.*?>/mg, "")
を使用して、FireFox
でも動作するように修正。 -- aterai -
@version 1.0.3
: セル中改行などに対応。 -- aterai - 非常に有用そうなものを公開していただき有難う御座います。
Firefox20
で本ブックマークレットの実行を試みた所、「アドレス(YUI Compressor
で圧縮) 」のコードをコピーしてブックマークに登録しようとしたら、登録自体ができませんでした。「アドレス(テスト用にtable2csv.js
を読み込む) 」はブックマークに登録出来ましたが、本ページで実行しても何も起こりませんでした。使用方法が間違っているでしょうか? -- ななしさん- 報告どうもありがとうございます。「アドレス(
YUI Compressor
で圧縮) 」は、先頭にjavascript:
が必要なのに書き忘れていました(修正しました)。「アドレス(テスト用にtable2csv.js
を読み込む) 」はFireFox21.0
などでは正常に動作しているようです。ブックマークレットを実行したあとで、表をダブルクリックしても何も起こらないのでしょうか? -- aterai
- 報告どうもありがとうございます。「アドレス(
- すみません、間違って二重投稿してしまいました。表をダブルクリックしなければ動かない、ということが理解出来ていませんでした。。。今動作確認しました所、どちらも動作しました。このブックマークレットを使い、銀行の使用履歴を簡単にコピペ出来ればと思っていましたが、実現出来そうです。ありがとうございました。 -- ななしさん
- 何度も再送信してしまい、大変失礼しました。失礼を承知でもう1つご教示頂きたいのですが、現在のスクリプトではブラウザ画面に""で括られたCSV形式で出力になっていますが、表に貼り付ける様にクリップボードへデータをコピーするようにカスタマイズするには、どのような変更を加えればよいでしょうか?もしよろしければご教示頂けると幸いです。 -- ななしさん
- 重複と思われるコメントを削除しました。カスタマイズですが、""で括らない形式にしたいということでしょうか?大抵の表計算ソフトならテキストの区切り記号を自動認識して除去してくれると思います。「アドレス(YUI Compressor で圧縮) 」を変更するなら、
'\t"'+o[i][g]+'"'
を'\t'+o[i][g]
に変更すればとりあえずは動作するような気がします。 -- aterai
- 重複と思われるコメントを削除しました。カスタマイズですが、""で括らない形式にしたいということでしょうか?大抵の表計算ソフトならテキストの区切り記号を自動認識して除去してくれると思います。「アドレス(YUI Compressor で圧縮) 」を変更するなら、
- 説明が悪くて申し訳ありません。表をダブルクリックするだけで、表示されている表の中のデータをクリップボードへコピーするようにしたいのです。もしよろしければご教示お願いします。 -- ななしさん
- おはようございます。セキュリティの問題で、最近のブラウザではスクリプトからのクリップボードアクセスは許可されていないようです。ブラウザの設定で変更できるのかもしれませんが(未調査)、あまりオススメできません。 -- aterai
- そうだったのですか。。。承知しました。素晴らしいスクリプトを公開していただいた上、ご説明まで頂きありがとうございました。 -- ななしさん
-
<table role="presentation">
や<table border="0">
のようなレイアウト目的の<table>
要素の場合は、クリックしても無視するように変更。 -- aterai