Edited at

HTML5のtableタグをCSV出力(ダウンロード)してみる

More than 1 year has passed since last update.


はじめに

・今回は友人に頼まれ、WEBブラウザ(HTML)で表示されている表(tableタグ)をCSV出力させるHTML & java scriptのコードを書いてみました。あんまり需要があるかわかりませんが、優しい目で見ていただけると幸いです。

・WEBサーバを立てるのは面倒だったのでクライアント側(WEBブラウザ側)のみで処理させています。Chrome、IE、Firefoxにて動作を確認しています。

・ほぼ個人用のメモ&日記的なものですが、よろしければご参照ださい。


完成物

・入力フィールドの「店舗コード」、「品目」、「金額」に文字、数字を入力し、行を追加ボタンを押すと表に行が追加されます。「CSVファイルダウンロード」のリンクをクリックすると現時点で表示されている表をCSV形式でダウンロードされます。

Screenshot 2018-05-01 at 12.29.54.png


コード全文

・本来は、CSSとjava scriptは別ファイルに書いておくべきですが、都合上htmlに直書きしました。

・半分以上がCSS(HTMLの見てくれ)ですので、本投稿では、後半のbody属性の中身について解説していきます。

・以下コードは丸コピしてhtmlファイルで保存後、ブラウザで開けば使える状態になっています。


index.html

<!DOCTYPE html>

<html lang="ja">
<head>
<meta charset="UTF-8">
<style type="text/css">
@charset "UTF-8";
/* ========BASIC======== */
html {
overflow-y:scroll;
}

body {
margin:0;
padding:0;
line-height:1.6;
letter-spacing:1px;
font-family:Verdana, Helvetica, sans-serif;
font-size:12px;
color:#333;
background:#fff;
}

br {
letter-spacing:normal;
}

a {
color:#0089a1;
text-decoration:none;
}

a:hover {
color:#0089a1;
text-decoration:underline;
}

img {
border:0;
vertical-align:bottom;
}

h1,h2,h3,h4,h5,h6 {
margin:0;
}

/* ========TEMPLATE LAYOUT======== */
#top {
width:780px;
margin:10px auto;
border:1px solid #333;
}

#header {
width:780px;
}

#contents {
clear:both;
}

#main {
float:left;
width:540px;
padding:10px;
}

/* ========HEADER CUSTOMIZE======== */
#header h1 {
margin:0;
padding:10px;
font-size:24px;
}

#header h1 a {
color:#333;
}

/* ========MAIN CONTENTS CUSTOMIZE======== */
#main h2 {
margin-bottom:5px;
padding:5px 0;
font-size:16px;
border-bottom:3px double #ccc;
}

#main h3 {
margin-bottom:5px;
padding:5px;
font-size:14px;
border-left:5px solid #0089a1;
border-bottom:1px dotted #ccc;
}

#main h4 {
margin-bottom:5px;
padding:5px;
font-size:13px;
color:#fff;
background:#0089a1;
}

#main h5 {
margin-bottom:5px;
font-size:13px;
border-bottom:1px dotted #ccc;
}

#main h6 {
margin-bottom:5px;
font-size:13px;
}

#main p {
margin:0 0 1em 0;
}

/* INFORMATION CUSTOMIZE */
* html body #main dl.information dd div {
display:inline-block;
}

#main table {
width:100%;
border-collapse:collapse;
}

#main table th {
padding:5px;
font-size:12px;
text-align:left;
border:1px solid #aaa;
background:#f0f7fc;
}

#main table td {
padding:5px;
font-size:12px;
text-align:left;
border:1px solid #aaa;
}
</style>

<title>デモ用アプリ</title>
</head>
<body>
<div id="top">
<div id="header">
<h1>hogehoge株式会社</h1>
</div>
<div id="contents">
<div id="main" style="width: 760px;">
<h2>デモ用アプリ</h2>
<p>ここにこのサンプルコードの説明を記載してださい。</p>
<h4>店舗売上データ一覧</h4>
<table id="table1" border="1" cellpadding="10">
<tr>
<th>店舗コード</th>
<th>品目</th>
<th>金額(円)</th>
</tr>
</table>
<div style="padding-top: 10px;">
<h5>↓入力フィールド</h5>
<input name="table1_cell_value" id="th_value1" type="text" placeholder="店舗コード">
<input name="table1_cell_value" id="th_value2" type="text" placeholder="品目">
<input name="table1_cell_value" id="th_value3" type="text" placeholder="金額(円)">
<input type="button" value="行を追加" onclick="add_line()">
<b><a id="download" href="#" download="test.csv" onclick="handleDownload()">csvファイルダウンロード</a></b>
</div>
</div>
</div>

<script>
//ここから表の行追加のコード
function add_line() {
for(var i = 0; i < document.getElementsByName("table1_cell_value").length; i++){
if(document.getElementsByName("table1_cell_value")[i].value ==""){
alert("未入力項目があります。");
return false;
}
}

var table = document.getElementById('table1');//id=table1という要素を取得
var row = table.insertRow(-1);//id=table1の中にtrタグを最後の子要素として追加
var cells = new Array();
for(var i = 0; i < table.rows[0].cells.length; i++){
cells[i] = row.insertCell(-1);//新しく作ったrowの中にtrタグを最後の子要素として追加
cells[i].innerText=document.getElementsByName("table1_cell_value")[i].value;
document.getElementsByName("table1_cell_value")[i].value="";//入力フィールドの初期化
}
}
//ここまで表の列追加のコード

//ここからCSV出力&ダウンロード
function handleDownload() {
var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);//文字コードをBOM付きUTF-8に指定
var table = document.getElementById('table1');//id=table1という要素を取得
var data_csv="";//ここに文字データとして値を格納していく

for(var i = 0; i < table.rows.length; i++){
for(var j = 0; j < table.rows[i].cells.length; j++){
data_csv += table.rows[i].cells[j].innerText;//HTML中の表のセル値をdata_csvに格納
if(j == table.rows[i].cells.length-1) data_csv += "\n";//行終わりに改行コードを追加
else data_csv += ",";//セル値の区切り文字として,を追加
}
}

var blob = new Blob([ bom, data_csv], { "type" : "text/csv" });//data_csvのデータをcsvとしてダウンロードする関数
if (window.navigator.msSaveBlob) { //IEの場合の処理
window.navigator.msSaveBlob(blob, "test.csv");
//window.navigator.msSaveOrOpenBlob(blob, "test.csv");// msSaveOrOpenBlobの場合はファイルを保存せずに開ける
} else {
document.getElementById("download").href = window.URL.createObjectURL(blob);
}

delete data_csv;//data_csvオブジェクトはもういらないので消去してメモリを開放
}
//ここまでCSV出力&ダウンロード
</script>
</body>
</html>



bodyタグ内のHTMLの解説(tableタグ編)

・HTMLで表示されている表は以下コードで作成されています。後述のjava scriptによって行を追加ボタンを押されたタイミングでtrタグ、thタグを新たに足していきます。


index.html

<table id="table1"  border="1" cellpadding="10">

 <tr>
 <th>店舗コード</th>
<th>品目</th>
<th>金額(円)</th>
</tr>
</table>


bodyタグ内のHTMLの解説(入力フィールド編)

・2〜4行目では「店舗コード」、「品目」、「金額」用の入力フィールドを5,6行目では追加ボタン、CSVダウンロード用リンクを生成しています。

・name属性、id属性は後述のjava scriptで利用するために設定しています。

・add_line()関数、handleDownload()はそれぞれ表の行追加、csvファイルダウンロードを実行するための関数です。解説は後述の「java script scriptタグ内の解説(add_line()関数編)」、「java script scriptタグ内の解説(handleDownload()関数編)」で記載します。


index.html

<h5>↓入力フィールド</h5>

<input name="table1_cell_value" id="th_value1" type="text" placeholder="店舗コード">
<input name="table1_cell_value" id="th_value2" type="text" placeholder="品目">
<input name="table1_cell_value" id="th_value3" type="text" placeholder="金額(円)">
<input type="button" value="行を追加" onclick="add_line()">
<b><a id="download" href="#" download="test.csv" onclick="handleDownload()" align="right">csvファイルダウンロード</a></b>


scriptタグ内のjava scriptの解説(add_line()関数編)

・add_line()関数は入力フィールドに入力された文字・数字を表に列を追加する関数です。

・はじめのforループは入力フィールドが空白を防ぐためのコードです。空白の場合はアラートが出ます。

・9行〜17行目以降は、getElementById()関数でtableタブオブジェクトを取得しからinsertRow()関数、insertCell()を実行し行とセルを追加しています。引数に「-1」を指定することで最後尾に行とセルが追加されます。

・2つ目のforループでは新しくセルを追加したあとそのオブジェクトをcell配列に格納しています。格納後はinnerText属性に入力フィールドの入力値(value属性)を代入させています。


//ここから表の行追加のコード
function add_line() {
for(var i = 0; i < document.getElementsByName("table1_cell_value").length; i++){
if(document.getElementsByName("table1_cell_value")[i].value ==""){
alert("未入力項目があります。");
return false;
}
}

var table = document.getElementById('table1');//id=table1という要素を取得
var row = table.insertRow(-1);//id=table1の中にtrタグを最後の子要素として追加
var cells = new Array();
for(var i = 0; i < table.rows[0].cells.length; i++){
cells[i] = row.insertCell(-1);//新しく作ったrowの中にtrタグを最後の子要素として追加
cells[i].innerText=document.getElementsByName("table1_cell_value")[i].value;
document.getElementsByName("table1_cell_value")[i].value="";//入力フィールドの初期化
}
}
//ここまで表の列追加のコード


scriptタグ内のjava scriptの解説(handleDownload()関数編)

・詳細はソースコードのコメントアウトに書いてありますが、File APIの元となったBolb関数を用いてcsvファイルをBom付きUTF-8で出力させています、※エクセルで開ける用にするためBom付きにしています。

・forループ内はかなり原始的な処理をさせています。単純にdata_csvにtableタグ中のセルの値(thタグのinnerText属性値)を文字列として加算しています。if else文で「,」や改行コードを挟ませ、結果的にdata_csvに格納される文字列をcsv形式にしています。

※もっとうまい方法を思いつけば良かったのですが。。。。:weary:

    //ここからCSV出力&ダウンロード

function handleDownload() {
var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);//文字コードをBOM付きUTF-8に指定
var table = document.getElementById('table1');//id=table1という要素を取得
var data_csv="";//ここに文字データとして値を格納していく

for(var i = 0; i < table.rows.length; i++){
for(var j = 0; j < table.rows[i].cells.length; j++){
data_csv += table.rows[i].cells[j].innerText;//HTML中の表のセル値をdata_csvに格納
if(j == table.rows[i].cells.length-1) data_csv += "\n";//行終わりに改行コードを追加
else data_csv += ",";//セル値の区切り文字として,を追加
}
}

var blob = new Blob([ bom, data_csv], { "type" : "text/csv" });//data_csvのデータをcsvとしてダウンロードする関数
if (window.navigator.msSaveBlob) { //IEの場合の処理
window.navigator.msSaveBlob(blob, "test.csv");
//window.navigator.msSaveOrOpenBlob(blob, "test.csv");// msSaveOrOpenBlobの場合はファイルを保存せずに開ける
} else {
document.getElementById("download").href = window.URL.createObjectURL(blob);
}

delete data_csv;//data_csvオブジェクトはもういらないので消去してメモリを開放
}
//ここまでCSV出力&ダウンロード


参考サイト

・JavaScript のデータを CSV で保存する

・JavaScriptからtable要素を制御する方法

・javascript で作成したCSVファイルをエクセルで表示可能にする

・Blob と File クラスについて

・シンプルCSSテンプレート


あとがき

今回初めてQiitaに投稿してみましたが、書き方がわからず文字だらけに。。。:sweat_smile:

これからもちょこちょこ書き、ちょこちょこ見やすく分かりやすくしていきます!