大田区から発信するゆるゆる日記

主にITエンジニアに関する備忘録日記。たまに趣味も。何か不備があればコメント頂けると幸いです。Twitterアカウント https://twitter.com/ryuzan03

【HTML/Javascript】フロントエンドでCSVデータを出力する方法

※下記の内容に不備がありましたら、コメント頂けると幸いです。また、下記の内容をご使用頂ける場合は自己責任でお願いします。

【目次】

【20/6/26 追記】
この記事の内容だとExcelcsvを開くと文字化けする可能性があります。

この記事の内容+以下のサイトを参考にすると、Excelで開いても文字化けしないcsv(tav)ファイルを作ることができます(サイトのコメント欄も要チェックです)。まあExcel2016以降はUTF-8に対応されたみたいなので、この記事の内容でも問題ないかもですが...
javascript で作成したCSVファイルをエクセルで表示可能にする - Qiita

概要

Angular(フロントエンド)からCSVデータを出力したかったのですが、HTMLとJavascriptだけで簡単に出力ができたので、その備忘録を書きます。

今回のブログのコードはAngular(Typescript)で記述しますが、使用している技術はHTMLとJavascriptの技術になります。ですので、Javascriptを使用されている方も参考にできる記事になっていると思います。

CSVデータ出力方法

処理の流れ

  1. ユーザ(画面)がクリックイベントを発火する
  2. 多次元(2次元)配列でデータを作成
  3. 多次元(2次元)配列のデータをJSON形式に変換し、さらにCSV出力方法を追加
  4. HTMLでa要素を作成
  5. 4のa要素に3のJSON形式のデータとdownload属性を追加する
  6. HTMLドキュメントに5のa要素を追加する
  7. a要素でクリックイベントを発火させる
  8. a要素を破棄する

最終的にJSON形式に変換できればCSV出力はできるので、多次元(2次元)配列ではなくても、オブジェクトデータなどでもCSV出力は可能です。

多次元(2次元)配列を使った理由

2次元配列の構造は以下のような感じです。

var a = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
]


上記のデータのうち1つの要素がCSVの1行になるわけですが、上記データの構造と以下のCSVデータ構造(分かりやすいようにスプレッドシートの画像を載せています)を見比べてみるとどうですか?構造が似ていていませんか? spreadsheet
私は似ているなと思い、データ構造のイメージがしやすかったので、2次元配列を使うことにしました。

多次元(2次元)配列とは?

2つ以上のインデックスが組み合わさっている配列で、配列の中に配列があるイメージです。JavaScriptでは多次元配列という構文は用意されていませんが、多次元配列のように配列を組み合わせても使うことはできます。

詳しくはこちらをご覧ください。


画面とメソッドを作成

component.html

<button (click)="downloadCsv()">CSVダウンロード</button>

component.ts

export class TestComponent {
  downloadCsv() {
    // 以下で記述
  }
}



2次元配列データを作成し、JSON形式に変換

component.ts

downloadCsv() {
  const array: stirng[][] = [
    ['1', '2', '3'],
    ['4', '5', '6'],
    ['7', '8', '9'],
  ]
  // 本来であれば、foerEachやmapなどを使って2次元配列を作ることになるかと思います。その場合は、pushやconcat、new Arrayなどを使うことが多いと思います。
  const csvData: string = this.arrToCSV(array)
}

arrToCSV(array: string[][]): string {
  let csvData = 'data:text/csv;charset=utf-8,'; /// 最初にcsvDataに出力方法を追加しておく
  arr.forEach(a => {
    const row = a.join(',');
    csvData += row + '\r\n';
  });
  return csvData;
}



a要素を作成して、csvを出力

component.ts

downloadCsv() {
...
  const csvData: string = this.arrToCSV(array)

  const encodedUri = encodeURI(csvData); // csvDataをエンコード化する
  const ele = document.createElement('a'); // a要素を作成する

  ele.setAttribute('href', encodedUri);  // a要素に出力データを追加
  ele.setAttribute('download', 'test' + '.csv'); // a要素に出力情報を追加。「'test'」部分は変数を入れることも可能。
  ele.style.visibility = 'hidden';
  document.body.appendChild(ele);
  ele.click(); // HTMLドキュメントに追加したa要素を実行(clickイベント発火)
  document.body.removeChild(ele);
}



今後に向けて

知らないことが無限に出てくる。

参考

素晴らしい記事に感謝致します。
多次元配列 - 配列 - JavaScript入門
クライアント側でCSV生成してダウンロードさせる - ryotah’s blog
【JavaScript】配列データをCSVファイルとして保存できるようにする | あれは魔法だろうか?
Export JSON to CSV file in Angular - GeeksforGeeks