こんにちは、ふちがみです。
前回の記事でHTMLのテーブルをCSVにしてダウンロードするJavascriptを作ってみましたが、
クロスブラウザ対応と、文字コード変換を後まわしにしていました。
今回は、その2つの対応を行いましたので、ご紹介したいと思います。
まずは完成版のコードとサンプルを先に示し、今回追加した処理を後で説明します。
完成版サンプル
完成版コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<style>
table, th, td {
border: 1px solid;
}
</style>
<script src="./encoding.min.js"></script>
<script>
var tableToCSV = {
export: function(elm /*, delimiter */) {
var table = elm;
var rows = this.getRows(table);
var lines = [];
var delimiter = delimiter || ',';
for (var i = 0, numOfRows = rows.length; i < numOfRows; i++) {
var cols = this.getCols(rows[i]);
var line = [];
for (var j = 0, numOfCols = cols.length; j < numOfCols; j++) {
var text = cols[j].textContent || cols[j].innerText;
text = '"'+text.replace(/"/g, '""')+'"';
line.push(text);
}
lines.push(line.join(delimiter));
}
return lines.join("\r\n");
},
getRows: function(elm){
return Util.getNodesByName(elm, 'tr');
},
getCols: function(elm){
return Util.getNodesByName(elm, ['td', 'th']);
}
}
var Util = {
getNodesByName: function(elm /*, string or array*/) {
var children = elm.childNodes;
var nodeNames = ('string' === typeof arguments[1]) ? [arguments[1]] : arguments[1] ;
nodeNames = nodeNames.map(function(str){ return str.toLowerCase() });
var results = [];
for (var i = 0, max = children.length; i < max; i++ ) {
if (nodeNames.indexOf(children[i].nodeName.toLowerCase()) !== -1)
{
results.push(children[i]);
}
else
{
results = results.concat(this.getNodesByName(children[i], nodeNames));
}
}
return results;
}
}
window.onload = function(){
document.getElementById('download').addEventListener('click', function (e){
var csv = tableToCSV.export(document.getElementById('tbl'));
var sjisArray = Encoding.convert(Encoding.stringToCode(csv), {to: 'SJIS'});
var blob = new Blob([new Uint8Array(sjisArray)], {type: 'text/csv'});
if (window.navigator.msSaveBlob) {
e.preventDefault();
window.navigator.msSaveBlob(blob, this.getAttribute('download'));
}
else {
this.href = URL.createObjectURL(blob);
}
});
}
</script>
</head>
<body>
<table id="tbl">
<thead>
<tr>
<th><strong>店舗名</strong></th>
<th>メールアドレス</th>
<th>電話番号</th>
<th>FAX番号</th>
<th>所在地</th>
</tr>
</thead>
<tbody>
<tr>
<td>A店</td>
<td>a@example.com</td>
<td>01-1111-1111</td>
<td>01-1111-0000</td>
<td>東京都新宿区</td>
</tr>
<tr>
<td>"B"店</td>
<td>a@example.com</td>
<td>02-2222-2222,02-2222-2220(採用担当)</td>
<td>02-2222-0000</td>
<td>東京都中野区</td>
</tr>
</tbody>
</table>
<a href="#" id="download" download="test.csv">CSVダウンロード</a>
</body>
</html>
クロスブラウザ対応
IEではmsSaveBlobという関数を使ってファイルの保存ができるそうです。
window.navigator.msSaveBlob の存在をチェックして、
存在する場合はこの関数でファイル保存するようにしてみました。
msSaveBlobは第2引数に保存するファイル名を取ることができるので、
aタグのダウンロード属性から値を取得してきています。
if (window.navigator.msSaveBlob) {
e.preventDefault();
window.navigator.msSaveBlob(blob, this.getAttribute('download'));
}
else {
this.href = URL.createObjectURL(blob);
}
文字コードの変換
CSVファイルはExcelで取りまわすことが多いため、文字コードをSJISに変換しました。
Encoding.jsを利用する
今回はencoding.jsというライブラリを使って、
UTF8 -> SJIS 変換を試みました。
var csv = tableToCSV.export(document.getElementById('tbl'));
var sjisArray = Encoding.convert(Encoding.stringToCode(csv), {to: 'SJIS'});
var blob = new Blob([new Uint8Array(sjisArray)], {type: 'text/csv'});
このとき、変換結果を配列で受け取ることと、文字列で受け取ることができるのですが、
文字列で受け取ると、どうしてもうまくいかなかったため、配列で受け取る方法を選択しました。
コメントを残す