點燈坊

失くすものさえない今が強くなるチャンスよ

如何將資料轉 CSV 並自動下載 ?

Sam Xiao's Avatar 2021-01-29

將資料以 CSV 下載為實務上常見功能,事實上並不需要套件幫助就可實現。

Version

Vue 2.6.11

Download CSV

csv000

自動下載 CSV。

<template>
  <div>Download CSV</div>
</template>

<script>
import { pipe, map, join, values, head, keys, concat, __, converge } from 'ramda'

let data = [
  { title: 'FP in JavaScript', price: 100 },
  { title: 'Programming Haskell', price: 200 },
  { title: 'Speaking JavaScript', price: 300 }
]

let header = pipe(
  head,
  keys,
  join(','),
  concat(__, '\n')
)

let objToStr = pipe(
  values,
  join(',')
)

let body = pipe(
  map(objToStr),
  join('\n')
)

let arrToCSV = converge(
  concat, [header, body]
)

let mounted = () => {
  let csv = arrToCSV(data)

  let anchor = document.createElement('a')
  anchor.href = `data:text/csv;charset=utf-8,${encodeURIComponent(csv)}`
  anchor.target = '_blank'
  anchor.download = 'data.csv'
  anchor.click()
}

export default {
  mounted
}
</script>

第 8 行

let data = [
  { title: 'FP in JavaScript', price: 100 },
  { title: 'Programming Haskell', price: 200 },
  { title: 'Speaking JavaScript', price: 300 }
]

資料為 Object Array,我們希望轉成 CSV 並自動下載。

14 行

let header = pipe(
  head,
  keys,
  join(','),
  concat(__, '\n')
)

首先處理 CSV 的 header 部分:

  • head():取得 Array 第一筆資料處理 header,為 Object
  • keys():將 Object 的 key 取出回傳 Array
  • join(','):將 Array 轉成 String,並以 , 分隔
  • concat(__, '\n'):在 String 結尾加上換行符號

26 行

let body = pipe(
  map(objToStr),
  join('\n')
)

處理 CSV 的 body 部分:

  • map(objToStr):將每筆資料 Object 轉成 String
  • join('\n'):將 Array 轉成 String,並以 \n 分隔

21 行

let objToStr = pipe(
  values,
  join(',')
)

將 Object 轉成以 , 分隔的 String,這也是最關鍵部分:

  • values():將 Object 的 value 取出回傳 Array
  • join(','):將 Array 轉成 String,並以 , 分隔

31 行

let arrToCSV = converge(
  concat, [header, body]
)

將 header 與 body 整合成完整 CSV:

  • concat():將 headerbody 合併
  • converge():整合 concat()header()body()

35 行

let mounted = () => {
  let csv = arrToCSV(data)

  let anchor = document.createElement('a')
anchor.href = `data:text/csv;charset=utf-8,${encodeURIComponent(csv)}`
  anchor.target = '_blank'
  anchor.download = 'data.csv'
  anchor.click()
}

產生 CSV 並自動下載:

  • 使用 arrToCSV() 將 Object Array 轉成 CSV
  • 動態建立 <a> 自動下載 CSV

Conclusion

  • Object Array 轉成 CSV 本質上就是一連串的轉換過程,特別適合使用 Ramda 實現
  • 自動下載可動態建立 <a> 並以 JavaScript 加以 click()