【TypeScript】Shift_JISの文字コードでCSVを生成しダウンロードする

フロント側だけで完結させます。
CSVデータをstringで生成し、encoding-japaneseでコンバートしたものを出力します。

目次

インストール&読み込み

encoding-japaneseパッケージをインストールします。

npm install --save encoding-japanese

importで読み込む。

import Encoding from 'encoding-japanese';

そのほかの参考はGitHubを参照してください。

https://github.com/polygonplanet/encoding.js/blob/master/README_ja.md#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

CSV生成

ObjectからStringのCSVデータへ変換します。
第一引数のdataには Key Valueの配列でわたし、map()メソッドで配列の要素ごとに処理をします。
処理後に、headerString、rowItemsのオブジェクトを改行区切りで、stringとして生成します。

/**
 * Object to Csv
 * @param data
 * @param headerOrder
 * @param headerGridDisplay 表示ヘッダー切り替え
 * @returns
 */
export const objectToCsv = (
  data: Record<string, any>[],
  headerOrder: string[],
  headerGridDisplay: string[] = []
): string => {
  let headerString: string = headerOrder.join(',')
  const replacer = (_: string, value: any): any => value ?? ''
  const rowItems: string[] = data.map((row: Record<string, any>) =>
    headerOrder.map((fieldName: string) => JSON.stringify(row[fieldName], replacer)).join(',')
  )

  if (headerGridDisplay) {
    headerString = headerGridDisplay.join(',')
  }

  const csv: string = [headerString, ...rowItems].join('\r\n')

  return csv
}

ブラウザからファイルダウンロード

第一引数にわたされたdataをtypeを指定してBlobで生成します。
createObjectURLでurlを作成後に、aタグエレメントのclick()メソッドを発火します。

/**
 * ファイルダウンロード
 * @param data
 * @param name
 */
export const download = (data: string | Uint8Array, name: string) => {
  const blob = new Blob([data], { type: 'text/csv' })
  const url = window.URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.setAttribute('href', url)
  a.setAttribute('download', `${name}.csv`)
  a.click()
}

Shift_JISの文字コードに変換し、CSVダウンロード

objectToCsvでCSVデータを生成し、Encoding.convertでShift_JISに変換したデータを、downlodに渡すことで、Shift_JISに変換されたCSVをダウンロードさせます。

Encoding.convertは、IntArrayTypeを渡す必要があるため、TextEncoder().encodeしてUint8Array型をわたします。
Encoding.convertの第二引数でShift_JISを指定します。

const csvdata = objectToCsv(exportData, keys, headerGridDisplay)

download(
  new Uint8Array(
    Encoding.convert(new TextEncoder().encode(csvdata), {
      to: 'SJIS',
      from: 'AUTO'
    })
  ),
  `shift_jis`
)
よかったらシェアしてね!
目次