CSVファイルの加工を自動化したい?JavaScriptでやりましょう。
2018/06/25
こんにちは!
今回はちょっとエンジニア向けの記事になります。
JavaScriptのお話なので、JSとCSVはよく使う!という方、是非読んでいってください。
CSVの編集が面倒!
CEサイトへの商品の登録や、その他のデータのやり取りで頻繁に使われるCSVですが、ちょっとフォーマットがズレているだけでサービスは受け付けてくれません。
例えば、商品の一覧CSVがあったとして、それをECの販売サイトへ登録したいとします。
その時、CEサイト側では
[ID,商品名,販売価格,在庫数]
というフォーマットで登録しなければならないとしましょう。この時IDの欄は空欄にする必要がある、とします。
しかし、手元に送られてくる商品情報のフォーマットが
[商品名,メーカー名,販売価格,在庫数]
というCSVであった場合、通常はExcelか何かを開いて、
[空欄,商品名,販売価格,在庫数]
というフォーマットの票に1つ1つ貼り付けていく、という作業が発生します。
もちろん、1列は丸っとコピー出来るので、1つのCSVに対して列の数と同じ回数コピペすれば良いという話ではあるのですが、毎回フォーマットが決まっているのに手動で変換するのも馬鹿馬鹿しいですよね。
Excelのマクロを使っても良いのですが、複数枚のシートに跨った編集は若干面倒ですし、マクロを社内の皆で共有するのは結構難しかったりします。
そこで、JavaScriptを使って変換用のwebページを作ってしまえば良いのでは?と思って、ちょっとやってみました。
JavaScriptでCSVを扱うには?
JavaScriptでCSVを扱うためには、5つのステップを経る必要があります。
1.ブラウザにCSVを読み込ませる
2.CSVをJavaScriptで扱える形式(配列)に変換する
3.配列を操作する
4.配列をCSVに戻す
5.ダウンロードする
1.ブラウザにCSVを読み込ませる
ブラウザにCSVを読み込ませるには、input要素のtype="file"を利用します。
こんなボタンが表示されます。
そして、この要素に対して
document.getElementById('files').addEventListener('change', handleFileSelect, false);
このようにイベントリスナをセットします。
そして、このhandeFileSelectの内容を書いていきます。
function handleFileSelect(evt) { var file = evt.target.files[0]; var reader = new FileReader(); // Closure to capture the file information. reader.onload = (function (e) { var n = CSV.parse(Encoding.convert(e.target.result, 'UNICODE', 'AUTO')); var csv = fillCsv(n); SaveToFile('product.csv', csv); }); reader.readAsBinaryString(file); }
さて、ここで2つ便利なライブラリを利用しています。
1つは
CSV.js
https://github.com/knrz/CSV.js
もう一つは圧縮電子どうのこうの様のencoding.jsです。
http://polygon-planet-log.blogspot.jp/2012/04/javascript.html
var file = evt.target.files[0];
の部分で、ファイルを読み取っています。
multipleを指定しているのでファイルが複数選択される可能性があるのですが、今回はその1つ目のファイルだけを扱います。
つまり複数選択しても反映されません。複数選択を反映させたい場合には各自で改良してください。
そして、FileReader()をインスタンス化し、reader.onloadに、ファイルの読み込みが終わった時に実行したい関数として、読み込んだCSVをユニコードにエンコード→CSVをパースして配列に変換する
という内容を指定しています。
var n = CSV.parse(Encoding.convert(e.target.result, 'UNICODE', 'AUTO')); var csv = fillCsv(n); SaveToFile('product.csv', csv);
そして、evt.target.files[0]によって取得されたファイルを、readerのreadAsBinaryString関数を使ってreaderオブジェクトに読み込ませます。
読み込みが終わると同時に、その読み込まれたファイルを使って上記のencodingと配列変換が行われ、その配列がfillCsvという関数に渡されます。
fillCsvは、普通に配列を操作するための関数です。
function fillCsv(_csv) { var csv = _csv; for (var i = 1; i < csv.length; i++) { csv[i][1] = 1; csv[i][8] = 0; csv[i][11] = 1; csv[i][3] = csv[i][3] + ',' + csv[i][23]; csv[i][3] = csv[i][3] + ',' + csv[i][24]; csv[i][3] = csv[i][3] + ',' + csv[i][25]; csv[i].splice(23, 8); } csv[0].splice(23, 8); var csvFile = csvSimple.toCSV(csv); return csvFile; }
内容は例ですが、こんな風に普通の配列としてcsvの内容を操作出来てしまいます!
最後に
var csvFile = csvSimple.toCSV(csv);
の部分で、配列をcsvファイルに直しています。
ここでは
Azisava様の
http://azisava.sakura.ne.jp/js/lib/#csv
このライブラリを使わせて頂きました。
csvSimple.toCSV(2次配列)
とするだけでcsv形式のオブジェクトが生成され、すこぶる便利です。
さて最後に、返ってきたCSVファイルをダウンロードする処理をします。
function SaveToFile(FileName, Stream) { if (window.navigator.msSaveBlob) { window.navigator.msSaveBlob(new Blob([Stream], {type: "text/csv"}), FileName); } else { var a = document.createElement("a"); a.href = URL.createObjectURL(new Blob([Stream], {type: "text/csv"})); //a.target = '_blank'; a.download = FileName; document.body.appendChild(a);//FireFox a.click(); document.body.removeChild(a);//FireFox } }
SaveToFileという関数を作っています。
ファイル名とさっきのCSVオブジェクトを渡せばOKです。
最後に、aという名前のhtml要素を作り、それに生成したCSVファイルを渡し、さらにそれをクリックした事にしてファイルをダウンロードさせています。
FireFoxだけちょっと別の挙動が必要なのでその処理もしています。
さて、長くなりましたが全体像を最後に掲載しておきます。
もちろんそれぞれのライブラリは予め読み込んでおく必要があります。
まとめ
さて、ちょっと長く、そして難しくなってしまいましたが、これでJavaScriptでのCSVの操作はバッチリです。
このスクリプトを利用したHTMLを適当な場所にアップしておけば共有も簡単ですし、アップデートする場合にはそのスクリプトを書き換えるだけで済みます。
3種類のライブラリをダウンロードして予め読み込み、
CSV.js
https://github.com/knrz/CSV.js
encoding.js
http://polygon-planet-log.blogspot.jp/2012/04/javascript.html
csvSimple.js
http://azisava.sakura.ne.jp/js/lib/#csv
HTMLに
を書いて(もちろん<>で全体を囲んでくださいね。)、後は配列をいじっている場所を書き換えればそのまま使うことも出来るはずです。
function handleFileSelect(evt) { console.log(evt); var file = evt.target.files[0]; var reader = new FileReader(); // Closure to capture the file information. reader.onload = (function (e) { console.log(Encoding.detect(e.target.result)); var n = CSV.parse(Encoding.convert(e.target.result, 'UNICODE', 'AUTO')); console.log(n); var csv = fillCsv(n); SaveToFile('product.csv', csv); }); reader.readAsBinaryString(file); } function fillCsv(_csv) { var csv = _csv; for (var i = 0; i < csv.length; i++) { csv[i][1] = 1; csv[i][8] = 0; var n = ''; csv[i][3] = csv[i][3] + ',' + csv[i][23]; csv[i][3] = csv[i][3] + ',' + csv[i][24]; csv[i][3] = csv[i][3] + ',' + csv[i][25]; csv[i].splice(23, 8); } var csvFile = csvSimple.toCSV(csv); return csvFile; } function SaveToFile(FileName, Stream) { if (window.navigator.msSaveBlob) { window.navigator.msSaveBlob(new Blob([Stream], {type: "text/csv"}), FileName); } else { var a = document.createElement("a"); a.href = URL.createObjectURL(new Blob([Stream], {type: "text/csv"})); //a.target = '_blank'; a.download = FileName; documen[code lang="javascript"] t.body.appendChild(a);// FireFox specification a.click(); document.body.removeChild(a);// FireFox specification } } document.getElementById('files').addEventListener('change', handleFileSelect, false);
関連記事
静的なwebサイトなら、WordPressを使わずにphpのincludeでテンプレートエンジン化しちゃおう
今回はweb制作の話です。 こんにちは、基本的にWordpressでweb制作を ...
あれ?もう容量がいっぱい?何にそんなにSSDやHDDを使ってるんだ…!?GrandPerspectiveで可視化しよう!
こんにちは、MacBookAir略してMBAをメインに使っている僕です。 最近の ...
紙VSiPAD!iPadでノートを取るメリットとデメリット
こんにちは!今回はノートアプリのお話で、特にiPadに向けたアプリの紹介です。 ...
人前で口に出来ない…そんなWordPress用アクセス解析プラグイン
その名もstatistics!!! 言いづらい。 今回は、噛むこと必至の超高機能 ...
【2016年版】ブログで収入!副業としてブログを始める基本のき。
こんにちは、僕です。 僕に別に専業ブロガーという訳ではないのですが、最近友人など ...