exportFile.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import html2canvas from "html2canvas";
  2. import JSPDF from "jspdf";
  3. import * as XLSX from 'xlsx'
  4. /**
  5. * 导出PDF
  6. * @param domID 需要输出PDF的页面id
  7. * @param fileName 文件名
  8. * @param type 默认A4分页
  9. * @param wMultiple 宽倍数
  10. * @param hMultiple 高倍数
  11. * @returns
  12. */
  13. export const exp2pdf = async (domID: string, fileName: string, type = 'A4', wMultiple = null, hMultiple = null) => {
  14. const dom = document.getElementById(domID)
  15. if (!dom) return
  16. // loading
  17. const domHeight = dom.offsetHeight // 获取DOM高度
  18. const domWidth = dom.offsetWidth // 获取DOM宽度
  19. const canvas = await html2canvas(dom, {
  20. logging: false,
  21. useCORS: true, // 允许图片跨域
  22. scale: 1.5,
  23. width: wMultiple ? wMultiple * domWidth : undefined,
  24. height: hMultiple ? hMultiple * domHeight : undefined
  25. })
  26. if (type === 'A4') {
  27. // A4分页
  28. const pdf = new JSPDF("p", "mm", "a4") // A4纸,纵向
  29. const ctx = canvas.getContext("2d") as any
  30. const a4w = 200;
  31. const a4h = 277 // A4大小,210mm x 297mm,四边各保留20mm的边距
  32. const imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
  33. let renderedHeight = 0
  34. while (renderedHeight < canvas.height) {
  35. const page = document.createElement("canvas")
  36. page.width = canvas.width
  37. page.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
  38. // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
  39. page.getContext("2d")?.putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)
  40. pdf.addImage(page.toDataURL("image/jpeg", 1.0), "JPEG", 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) // 添加图像到页面,保留10mm边距
  41. renderedHeight += imgHeight
  42. if (renderedHeight < canvas.height) { pdf.addPage() } // 如果后面还有内容,添加一个空页
  43. // delete page;
  44. }
  45. pdf.save(fileName)
  46. } else {
  47. // 整张
  48. const pdf = new JSPDF('p', 'px', [domWidth, domHeight])
  49. pdf.addImage(canvas.toDataURL("image/jpeg", 1.0), "JPEG", 10, 10, domWidth, domHeight)
  50. pdf.save(fileName)
  51. }
  52. // loading
  53. }
  54. /**
  55. * 导出PNG
  56. * @param domID 需要输出PDF的页面id
  57. * @param fileName 文件名
  58. * @param bkcolor 背景色
  59. */
  60. export const exp2png = async (domID: string, fileName: string, bkcolor: string) => {
  61. // loading
  62. window.scroll(0, 0) // 首先先顶部
  63. const design = document.getElementById(domID) as HTMLElement
  64. if (!design) return
  65. const imgHeight = design.offsetHeight // 获取DOM高度
  66. const imgWidth = design.offsetWidth // 获取DOM宽度
  67. const scale = window.devicePixelRatio <= 3 ? 3 : window.devicePixelRatio // 获取设备像素比
  68. const canvas = await html2canvas(design, {
  69. backgroundColor: bkcolor, // 设置背景颜色
  70. useCORS: true, // 允许图片跨域
  71. scale: scale, // 缩放3倍,使得图片更加清晰=>越清晰图片越大
  72. width: imgWidth,
  73. height: imgHeight,
  74. imageTimeout: 5000 // 设置图片的超时,设置0为禁用
  75. })
  76. const imgURL = canvas.toDataURL('image/png')
  77. return imgURL
  78. // loading
  79. }
  80. /**
  81. * 解析excel表格
  82. * @param file 文件
  83. * @returns
  84. */
  85. export const exp2json = async (file: File) => {
  86. return await new Promise((resolve, reject) => {
  87. try {
  88. const reader = new FileReader()
  89. reader.onload = (e) => {
  90. const wb = XLSX.read(e.target?.result, {
  91. type: 'binary'
  92. }) // 读取完成的数据
  93. // 转成json header解析第一行标题
  94. const data = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { header: 1 })
  95. resolve(data)
  96. }
  97. reader.readAsBinaryString(file)
  98. } catch (error) {
  99. console.log('解析错误')
  100. reject(error)
  101. }
  102. })
  103. }
  104. /**
  105. * dom导出excel
  106. * @param domID domID
  107. * @param fileName 文件名
  108. */
  109. export const dom2excel = (domID: string, fileName: string) => {
  110. const dom = document.getElementsByTagName(domID)
  111. if (!dom) return
  112. const wb = XLSX.utils.table_to_book(dom[0])
  113. const baty = XLSX.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' })
  114. // 字符串转ArrayBuffer
  115. const s2ab = (s: any) => {
  116. const buf = new ArrayBuffer(s.length)
  117. const view = new Uint8Array(buf)
  118. for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
  119. return buf
  120. }
  121. const blob = new Blob([s2ab(baty)], { type: 'application/octet-stream' })
  122. return blob
  123. }
  124. /**
  125. * array导出excel表格
  126. * @param arr 数据是数组包含的对象
  127. * @param fileName 名字
  128. */
  129. export const exp2excel = (arr: object[], fileName: string, cellMerges?: Array<any>) => {
  130. const sheet = XLSX.utils.json_to_sheet(arr);
  131. // excel宽高设置
  132. sheet["!cols"] = arr.map(() => {
  133. return { wch: 30 }
  134. })
  135. if (cellMerges) {
  136. sheet['!merges'] = cellMerges; // <====合并单元格
  137. }
  138. // 转blob
  139. const sheet2blob = (sheet: any, sheetName = 'sheet1') => {
  140. const workbook = {
  141. SheetNames: [sheetName],
  142. Sheets: {} as any
  143. };
  144. workbook.Sheets[sheetName] = sheet;
  145. // 生成excel的配置项
  146. const wopts = {
  147. bookType: 'xlsx', // 要生成的文件类型
  148. bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
  149. type: 'binary'
  150. } as any
  151. const wbout = XLSX.write(workbook, wopts);
  152. // 字符串转ArrayBuffer
  153. const s2ab = (s: string) => {
  154. let buf = new ArrayBuffer(s.length);
  155. let view = new Uint8Array(buf);
  156. for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
  157. return buf;
  158. }
  159. const blob = new Blob([s2ab(wbout)], { type: "application/octet-stream" });
  160. return blob;
  161. }
  162. return sheet2blob(sheet)
  163. }