Excelからデータを読み込んで処理を行い、
結果をCSVファイルに書き出してExcelで開くといった要件を満たす必要がありました。
しかし、CSVファイルをExcelで開く際は出力時に文字コードをShift-JISにしないと文字化けが起こります。
(ファイル読み込み時にUTF-8を指定できますが、都度操作する必要があります。)
参考:Microsoft Excel で開ける CSV 関連のフォーマットまとめ
今回は、文字化けしないようにCSVファイルをShift-JISで出力し
Excelでスムーズに開けるようにする方法を共有します。
必要なモジュール
const fs = require('fs')
const csv = require('fast-csv')
const jconv = require( 'jconv' )
const xlsx = require('xlsx')
const utils = xlsx.util
Excelデータ読み込み
Excel内のデータを読み込みます。
読み込んだデータはCSV形式のままだと扱い難いのでお好みで配列にしてください。
// csv -> Array[Object]
function parseCSVtoArray(csv) {
let result = []
csv
.fromString(csv, {headers: true})
.on('data', function(data) {
result.push(data)
})
.on('end', function() {
console.log('end')
})
return result
}
var workbook = xlsx.readFile(importPath) // Excelファイルを読み込む
var sheetName = workbook.SheetNames[0] // Excelファイルの最初のシートの名前を取得
var worksheet = workbook.Sheets[sheetName] // Excelファイルの最初のシートを読み込む
var csv = xlsx.utils.sheet_to_csv(worksheet) // ExcelデータをCSV形式で取得
let array = yield parseCSVtoArray(csv) // データを使いやすくするために配列に変換
for (let arr of array ) {
console.log(arr['hoge'])
// 処理 …
}
CSV書き出し
jconv を使って処理結果をShift-JISに変換します。
ここでは処理結果を配列で拾っているので、
ヘッダーを付けてCSV(文字列)に変換したものを渡しています。
Bufferについてはこちらを参考にしてください。
// resultArray: 処理結果が入った配列
// Array[object] -> csv
csv.writeToString(resultArray, {headers: true}, (err, data) => {
var buffer = jconv.convert(data, 'UTF8', 'SJIS') // UTF-8からShift-JISへ文字コードを変換
fs.writeFileSync('result.csv', buffer) // ファイルを書き出し
})
これで文字コードがShift-JISのCSVファイルが書き出されたので、
Excelで開いてもウィザード無しで文字化けもせずスムーズに開けます。
おまけ:Excelデータで書き出し
このデータをExcelで書き出したい場合は、node-xlsxを使うと簡単に出力できます。
const nodeXlsx = require('node-xlsx').default
…
function convertCSVtoArray(str) {
var result = []
var tmp = str.split('\n')
for(var i = 0; i < tmp.length; ++i) {
result[i] = tmp[i].split(/(?:",|,"|,(?=(?:(?:[^\"]*\"){2})*[^\"]*$))/) // ※セル内の複数値に対応
}
return result
}
csv.writeToString(resultArray, {headers: true}, (err, data) => {
var arr = convertCSVtoArray(data)
var buffer = nodeXlsx.build([{name: sheetName, data: arr}])
fs.writeFileSync('result.xlsx', buffer)
})
これで .xlsx
ファイルで書き出されます。
ヘッダーを意識せずに付加する為に一度csvにしてからまた配列に戻す手間をしてますが、
必要がない場合や別途加工する場合は writeToString
を挟む必要は無いと思います。
終わりに
完全にモジュール頼りですが、これらの素晴らしいモジュールを知って
Excelで消耗する人が一人でも減ってくれれば嬉しいです。