Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

JavaScriptでCSVエクスポートを実装してみた。

More than 3 years have passed since last update.

前書き

CSVのエクスポートは、WEBアプリでは結構利用する機能だと思います。
できる限り、フロント側で完結したい内容ではありますので、JavaScriptで実装してみました。

実装

利用するのは以下二つのライブラリです。

# JsonをCSV文字列に変換してくれるライブラリ
$ npm install papaparse
$ yarn add papaparse

# 文字コード変換をしてくれるライブラリ
$ npm install encoding-japanese
$ yarn add encoding-japanese

Papaparseは、他にもできることが多く、ドキュメントが素晴らしいのでぜひご覧ください。

Papaparse

JSONをCSV形式に変換する処理

Papaparseにオブジェクト配列を渡すことで、簡単にCSV文字列(区切り文字列)に変換してくれます。

import Papa from 'papaparse';
import encoding from 'encoding-japanese';

...

// configの初期値
const config = {
  delimiter: ',', // 区切り文字
  header: true, // キーをヘッダーとして扱う
  newline: '\r\n', // 改行
};

// 区切り文字へ変換
const delimiterString = Papa.unparse(json, config);

// blobUrlへの変換
const strArray = encoding.stringToCode(delimiterString);
const convertedArray = encoding.convert(strArray,'SJIS', 'UNICODE');
const UintArray = new Uint8Array(convertedArray);
const blobUrl = new Blob([UintArray], {type: 'text/csv'});

ソースとしては以上です。
のちにダウンロードを行うため、blobへ変換しています。
その変換過程でencoding(encoding-japanese)のconvertで第2引数の文字コードに変換しています。

ダウンロード処理

ダウンロードでは、擬似的にaタグを利用して、blobを叩いてダウンロードさせるようにします。

const blob = blobUrl;
const aTag = document.createElement('a');

aTag.download = fileName;

// 各ブラウザに合わせ、CSVをダウンロード
if (window.navigator.msSaveBlob) {
  // for IE
  window.navigator.msSaveBlob(blob, aTag.download);
} else if (window.URL && window.URL.createObjectURL) {
  // for Firefox
  aTag.href = window.URL.createObjectURL(blob);

  document.body.appendChild(aTag);

  aTag.click();

  document.body.removeChild(aTag);
} else if (window.webkitURL && window.webkitURL.createObject) {
  // for Chrome
  aTag.href = (window.URL || window.webkitURL).createObjectURL(blob);

  aTag.click();
} else {
  // for Safari
  window.open(
    `data:type/csv;base64,${window.Base64.encode(this.state.content)}`,
    '_blank'
  );
}

ダウンロードの処理には、ほとんどPapaparseもencoding-japaneseも利用しません。
各ブラウザで保存方法が違うので、制御式を書いています。
(aタグ使わずにもっといい書き方あるのかな。。。)

まとめ

まとめとして、一連のソースを記述します。

const config = {
  delimiter: ',', // 区切り文字
  header: true, // キーをヘッダーとして扱う
  newline: '\r\n', // 改行
};

// 区切り文字へ変換
const delimiterString = Papa.unparse(json, config);

// blobUrlへの変換
const strArray = encoding.stringToCode(delimiterString);
const convertedArray = encoding.convert(strArray,'SJIS', 'UNICODE');
const UintArray = new Uint8Array(convertedArray);
const blobUrl = new Blob([UintArray], {type: 'text/csv'});
const blob = blobUrl;
const aTag = document.createElement('a');

aTag.download = fileName;

// 各ブラウザに合わせ、CSVをダウンロード
if (window.navigator.msSaveBlob) {
  // for IE
  window.navigator.msSaveBlob(blob, aTag.download);
} else if (window.URL && window.URL.createObjectURL) {
  // for Firefox
  aTag.href = window.URL.createObjectURL(blob);

  document.body.appendChild(aTag);

  aTag.click();

  document.body.removeChild(aTag);
} else if (window.webkitURL && window.webkitURL.createObject) {
  // for Chrome
  aTag.href = (window.URL || window.webkitURL).createObjectURL(blob);

  aTag.click();
} else {
  // for Safari
  window.open(
    `data:type/csv;base64,${window.Base64.encode(this.state.content)}`,
    '_blank'
  );
}

後書き

フロント側でも簡単にCSVエクスポートが実装できました。
Papaparseを使えば、インポート処理も実装できるので、なかなか重宝します。

maecho
大阪のエンジニアです。 最近は、ReactNativeやFlutterでアプリ作ってます。 他、AWSや、GoでAPI作ってます。 インフラが好きです。
https://as-rule.io
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away