index.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <template>
  2. <el-button type="primary" @click="exportToExcel">
  3. <img src="@/assets/imgs/OA/open.png" class="mr-8px" alt="" />
  4. 导出
  5. </el-button>
  6. </template>
  7. <script setup lang="ts">
  8. /**
  9. * @description 导出为excel
  10. */
  11. import * as XLSX from 'xlsx'
  12. import { saveAs } from 'file-saver'
  13. interface IProp {
  14. data: any[][] // 数据 [[表头,表头,表头],[数据,数据,数据]]
  15. fileName?: string // 文件名
  16. mergeRanges?: {
  17. s: { r: number; c: number } // 合并的起始单元格
  18. e: { r: number; c: number } // 合并的结束单元格
  19. }[] // 合并单元格列表
  20. colsWidth?: { wch: number }[] // 列宽
  21. title?: string // 标题
  22. }
  23. // 定义组件props
  24. const props = defineProps<IProp>()
  25. const titleStyle = {
  26. font: {
  27. bold: true,
  28. size: 20,
  29. color: { rgb: '#000000' }, // 设置颜色
  30. name: 'Arial' // 设置字体为Arial
  31. },
  32. alignment: {
  33. horizontal: 'center', // 水平居中
  34. vertical: 'middle' // 垂直居中
  35. },
  36. '!important': true // 添加 !important 规则
  37. }
  38. // 导出Excel函数
  39. const exportToExcel = () => {
  40. // 从props获取数据
  41. const data = props.data
  42. // 如果有标题,添加标题
  43. if (props.title) {
  44. // 创建一个包含样式信息的单元格对象(样式未生效,不知道是什么原因)
  45. const titleCell = { v: props.title, s: titleStyle }
  46. // 将单元格对象添加到数据中
  47. data.unshift([titleCell])
  48. }
  49. // 创建一个工作簿
  50. const wb = XLSX.utils.book_new()
  51. // 创建一个工作表
  52. const ws = XLSX.utils.aoa_to_sheet(data)
  53. // 如果有标题, 则在第一行插入标题
  54. if (props.title) {
  55. // 添加标题并合并单元格
  56. const mergeRange = { s: { r: 0, c: 0 }, e: { r: 0, c: data[1].length - 1 } } // 合并单元格范围
  57. ws['!merges'] = [mergeRange] // 合并单元格
  58. }
  59. // 多个合并范围 合并单元格
  60. if (props.mergeRanges) {
  61. ws['!merges'] = props.mergeRanges
  62. }
  63. // 设置列宽,定义多个列宽
  64. if (props.colsWidth) {
  65. ws['!cols'] = props.colsWidth ?? []
  66. }
  67. // 将工作表添加到工作簿中
  68. XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
  69. // 生成Excel文件
  70. const wbout = XLSX.write(wb, { type: 'binary', bookType: 'xlsx' })
  71. // 下载Excel文件
  72. saveAs(
  73. new Blob([s2ab(wbout)], { type: 'application/octet-stream' }),
  74. props.fileName || 'exported_data.xlsx'
  75. )
  76. }
  77. // 将二进制字符串转换为字节数组
  78. const s2ab = (s: string) => {
  79. const buf = new ArrayBuffer(s.length)
  80. const view = new Uint8Array(buf)
  81. for (let i = 0; i < s.length; i++) view[i] = s.charCodeAt(i) & 0xff
  82. return buf
  83. }
  84. </script>
  85. <style scoped></style>