9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【JavaScript】CSV 書き出しの際に必要なエスケープ処理と二次元配列→文字列変換の方法

Last updated at Posted at 2020-11-15

CSV 書き出しの際に必要なエスケープ処理と二次元配列→文字列変換の方法

こんにちは、ndj です。
二次元配列から変換した CSV(カンマと改行コードで区切ってあるアレです)をファイルなどに書き出す際に値にエスケープ処理を施す必要があったので、そのときの方法を記録しておきます。
また、合わせて二次元配列を CSV 形式の文字列へ変換する方法についても記録しておきます。

なぜエスケープ処理が必要なのか

CSV 形式のファイルを作成する際、なぜエスケープ処理が必要なのかといいますと、値の中に**,(カンマ)や\n**(改行)が含まれてしまっていると、Excel や他のアプリケーションなんかで CSV を読み込んだときに値中に含まれている**,(カンマ)や\n**(改行)と区切り文字である**,(カンマ)や\n**(改行)を区別できないわけです。
なので、値は「""(ダブルクォーテーション)」で囲んで値であるということを明示する必要があります。

エスケープ処理を行う方法

escape.js
// エスケープ処理
const escapeForCSV = (s) => {
    return `"${s.replace(/\"/g, '\"\"')}"`
}

正規表現を用いて、引数として与えられた文字列をダブルクォーテーションで囲っています。
引数として与えられた文字列中に、「"」が含まれていると CSV に変換した際に値がずれてしまうため、「""」としてエスケープします。

二次元配列から CSV 文字列へ変換する方法

convert.js
const arrToString = (arr, colDelimeter=',', rowDelimeter='\n') => {
    return arr.map((row) => row.map((cell) => escapeForCSV(cell)).join(colDelimeter)).join(rowDelimeter);
}

まず、二次元配列を map() メソッドで行(row)を取り出す。
row は一次元配列になっているので、さらに map() メソッドを用いてセル(cell)を取り出す。
このとき、各値にエスケープ処理を施す。
そして、row を区切り文字で連結(この場合は「,」)する。
最後に行区切り(この場合の区切り文字は「\n」)を行い、完了。

サンプルコード

先述したように、arrToString() 内で各セルに対して escapeForCSV() を実行して、エスケープ処理を施しています。
TSV 形式にしたい場合は、arrToString() に引数を渡せばOK。

sample.js
// エスケープ処理
const escapeForCSV = (s) => {
    return `"${s.replace(/\"/g, '\"\"')}"`
}
//二次元配列 -> CSV形式の文字列に変換
const arrToString = (arr, colDelimeter=',', rowDelimeter = '\n') => {
    return arr.map((row) => row.map((cell) => escapeForCSV(cell)).join(colDelimeter)).join(rowDelimeter);
}

// CSV 形式文字列に変換
let sample = [['a', 'b', 'c'], ['"a"', '"b"', '"c"']];
console.log(arrToString(sample));
// "a","b","c"
// """a""","""b""","""c"""

// TSV 形式にしたい場合
console.log(arrToString(sample, colDelimeter='\t'));
// "a"	"b"	"c"
// """a"""	"""b"""	"""c"""

最後に

どちらも汎用的な処理なので、おそらくライブラリがあると思いますが、手法を知っておくのは必要だと思ったので、残しておきます。
誤字脱字やアドバイス、ご指摘などございましたらコメントや編集リクエストなどくださると幸いです。
以上です。
ここまで読んでくださりありがとうございました。

Twitter(@teqndj)

参考

CSV について

CodeZine: CSVファイルフォーマットの解説

正規表現について

Qiita: JavaScript 正規表現まとめ @iLLviA 様

非常に参考になりました。ありがとうございました。

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?