export.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // import { createCellPos } from './translateNumToLetter'
  2. const Excel = require('exceljs')
  3. import FileSaver from 'file-saver'
  4. export var exportExcel = function (luckysheet, value) {
  5. // 参数为luckysheet.getluckysheetfile()获取的对象
  6. // 1.创建工作簿,可以为工作簿添加属性
  7. const workbook = new Excel.Workbook()
  8. // 2.创建表格,第二个参数可以配置创建什么样的工作表
  9. if (Object.prototype.toString.call(luckysheet) === '[object Object]') {
  10. luckysheet = [luckysheet]
  11. }
  12. luckysheet.forEach(function (table) {
  13. if (table.data.length === 0) return true
  14. // ws.getCell('B2').fill = fills.
  15. const worksheet = workbook.addWorksheet(table.name)
  16. const merge = (table.config && table.config.merge) || {}
  17. const borderInfo = (table.config && table.config.borderInfo) || {}
  18. // 3.设置单元格合并,设置单元格边框,设置单元格样式,设置值
  19. setStyleAndValue(table.data, worksheet)
  20. setMerge(merge, worksheet)
  21. setBorder(borderInfo, worksheet)
  22. return true
  23. })
  24. // return
  25. // 4.写入 buffer
  26. const buffer = workbook.xlsx.writeBuffer().then(data => {
  27. // console.log('data', data)
  28. const blob = new Blob([data], {
  29. type: 'application/vnd.ms-excel;charset=utf-8'
  30. })
  31. console.log("导出成功!")
  32. FileSaver.saveAs(blob, `${value}.xlsx`)
  33. })
  34. return buffer
  35. }
  36. var setMerge = function (luckyMerge = {}, worksheet) {
  37. const mergearr = Object.values(luckyMerge)
  38. mergearr.forEach(function (elem) {
  39. // elem格式:{r: 0, c: 0, rs: 1, cs: 2}
  40. // 按开始行,开始列,结束行,结束列合并(相当于 K10:M12)
  41. worksheet.mergeCells(
  42. elem.r + 1,
  43. elem.c + 1,
  44. elem.r + elem.rs,
  45. elem.c + elem.cs
  46. )
  47. })
  48. }
  49. var setBorder = function (luckyBorderInfo, worksheet) {
  50. if (!Array.isArray(luckyBorderInfo)) return
  51. // console.log('luckyBorderInfo', luckyBorderInfo)
  52. luckyBorderInfo.forEach(function (elem) {
  53. // 现在只兼容到borderType 为range的情况
  54. // console.log('ele', elem)
  55. if (elem.rangeType === 'range') {
  56. let border = borderConvert(elem.borderType, elem.style, elem.color)
  57. let rang = elem.range[0]
  58. // console.log('range', rang)
  59. let row = rang.row
  60. let column = rang.column
  61. for (let i = row[0] + 1; i < row[1] + 2; i++) {
  62. for (let y = column[0] + 1; y < column[1] + 2; y++) {
  63. worksheet.getCell(i, y).border = border
  64. }
  65. }
  66. }
  67. if (elem.rangeType === 'cell') {
  68. // col_index: 2
  69. // row_index: 1
  70. // b: {
  71. // color: '#d0d4e3'
  72. // style: 1
  73. // }
  74. const { col_index, row_index } = elem.value
  75. const borderData = Object.assign({}, elem.value)
  76. delete borderData.col_index
  77. delete borderData.row_index
  78. let border = addborderToCell(borderData, row_index, col_index)
  79. // console.log('bordre', border, borderData)
  80. worksheet.getCell(row_index + 1, col_index + 1).border = border
  81. }
  82. // console.log(rang.column_focus + 1, rang.row_focus + 1)
  83. // worksheet.getCell(rang.row_focus + 1, rang.column_focus + 1).border = border
  84. })
  85. }
  86. var setStyleAndValue = function (cellArr, worksheet) {
  87. if (!Array.isArray(cellArr)) return
  88. cellArr.forEach(function (row, rowid) {
  89. row.every(function (cell, columnid) {
  90. if (!cell) return true
  91. let fill = fillConvert(cell.bg)
  92. let font = fontConvert(
  93. cell.ff,
  94. cell.fc,
  95. cell.bl,
  96. cell.it,
  97. cell.fs,
  98. cell.cl,
  99. cell.ul
  100. )
  101. let alignment = alignmentConvert(cell.vt, cell.ht, cell.tb, cell.tr)
  102. let value = ''
  103. if (cell.f) {
  104. value = { formula: cell.f, result: cell.v }
  105. } else if (!cell.v && cell.ct && cell.ct.s) {
  106. // xls转为xlsx之后,内部存在不同的格式,都会进到富文本里,即值不存在与cell.v,而是存在于cell.ct.s之后
  107. // value = cell.ct.s[0].v
  108. cell.ct.s.forEach(arr => {
  109. value += arr.v
  110. })
  111. } else {
  112. console.log('0603')
  113. value = cell.m
  114. }
  115. // style 填入到_value中可以实现填充色
  116. let letter = createCellPos(columnid)
  117. let target = worksheet.getCell(letter + (rowid + 1))
  118. // console.log('1233', letter + (rowid + 1))
  119. for (const key in fill) {
  120. target.fill = fill
  121. break
  122. }
  123. target.font = font
  124. target.alignment = alignment
  125. target.value = value
  126. return true
  127. })
  128. })
  129. }
  130. var fillConvert = function (bg) {
  131. if (!bg) {
  132. return {}
  133. }
  134. // const bgc = bg.replace('#', '')
  135. let fill = {
  136. type: 'pattern',
  137. pattern: 'solid',
  138. fgColor: { argb: bg.replace('#', '') }
  139. }
  140. return fill
  141. }
  142. var fontConvert = function (
  143. ff = 0,
  144. fc = '#000000',
  145. bl = 0,
  146. it = 0,
  147. fs = 10,
  148. cl = 0,
  149. ul = 0
  150. ) {
  151. // luckysheet:ff(样式), fc(颜色), bl(粗体), it(斜体), fs(大小), cl(删除线), ul(下划线)
  152. const luckyToExcel = {
  153. 0: '微软雅黑',
  154. 1: '宋体(Song)',
  155. 2: '黑体(ST Heiti)',
  156. 3: '楷体(ST Kaiti)',
  157. 4: '仿宋(ST FangSong)',
  158. 5: '新宋体(ST Song)',
  159. 6: '华文新魏',
  160. 7: '华文行楷',
  161. 8: '华文隶书',
  162. 9: 'Arial',
  163. 10: 'Times New Roman ',
  164. 11: 'Tahoma ',
  165. 12: 'Verdana',
  166. num2bl: function (num) {
  167. return num === 0 ? false : true
  168. }
  169. }
  170. // 出现Bug,导入的时候ff为luckyToExcel的val
  171. let font = {
  172. name: typeof ff === 'number' ? luckyToExcel[ff] : ff,
  173. family: 1,
  174. size: fs,
  175. color: { argb: fc.replace('#', '') },
  176. bold: luckyToExcel.num2bl(bl),
  177. italic: luckyToExcel.num2bl(it),
  178. underline: luckyToExcel.num2bl(ul),
  179. strike: luckyToExcel.num2bl(cl)
  180. }
  181. return font
  182. }
  183. var alignmentConvert = function (
  184. vt = 'default',
  185. ht = 'default',
  186. tb = 'default',
  187. tr = 'default'
  188. ) {
  189. // luckysheet:vt(垂直), ht(水平), tb(换行), tr(旋转)
  190. const luckyToExcel = {
  191. vertical: {
  192. 0: 'middle',
  193. 1: 'top',
  194. 2: 'bottom',
  195. default: 'top'
  196. },
  197. horizontal: {
  198. 0: 'center',
  199. 1: 'left',
  200. 2: 'right',
  201. default: 'left'
  202. },
  203. wrapText: {
  204. 0: false,
  205. 1: false,
  206. 2: true,
  207. default: false
  208. },
  209. textRotation: {
  210. 0: 0,
  211. 1: 45,
  212. 2: -45,
  213. 3: 'vertical',
  214. 4: 90,
  215. 5: -90,
  216. default: 0
  217. }
  218. }
  219. let alignment = {
  220. vertical: luckyToExcel.vertical[vt],
  221. horizontal: luckyToExcel.horizontal[ht],
  222. wrapText: luckyToExcel.wrapText[tb],
  223. textRotation: luckyToExcel.textRotation[tr]
  224. }
  225. return alignment
  226. }
  227. var borderConvert = function (borderType, style = 1, color = '#000') {
  228. // 对应luckysheet的config中borderinfo的的参数
  229. if (!borderType) {
  230. return {}
  231. }
  232. const luckyToExcel = {
  233. type: {
  234. 'border-all': 'all',
  235. 'border-top': 'top',
  236. 'border-right': 'right',
  237. 'border-bottom': 'bottom',
  238. 'border-left': 'left'
  239. },
  240. style: {
  241. 0: 'none',
  242. 1: 'thin',
  243. 2: 'hair',
  244. 3: 'dotted',
  245. 4: 'dashDot', // 'Dashed',
  246. 5: 'dashDot',
  247. 6: 'dashDotDot',
  248. 7: 'double',
  249. 8: 'medium',
  250. 9: 'mediumDashed',
  251. 10: 'mediumDashDot',
  252. 11: 'mediumDashDotDot',
  253. 12: 'slantDashDot',
  254. 13: 'thick'
  255. }
  256. }
  257. let template = {
  258. style: luckyToExcel.style[style],
  259. color: { argb: color.replace('#', '') }
  260. }
  261. let border = {}
  262. if (luckyToExcel.type[borderType] === 'all') {
  263. border['top'] = template
  264. border['right'] = template
  265. border['bottom'] = template
  266. border['left'] = template
  267. } else {
  268. border[luckyToExcel.type[borderType]] = template
  269. }
  270. // console.log('border', border)
  271. return border
  272. }
  273. function addborderToCell(borders, row_index, col_index) {
  274. let border = {}
  275. const luckyExcel = {
  276. type: {
  277. l: 'left',
  278. r: 'right',
  279. b: 'bottom',
  280. t: 'top'
  281. },
  282. style: {
  283. 0: 'none',
  284. 1: 'thin',
  285. 2: 'hair',
  286. 3: 'dotted',
  287. 4: 'dashDot', // 'Dashed',
  288. 5: 'dashDot',
  289. 6: 'dashDotDot',
  290. 7: 'double',
  291. 8: 'medium',
  292. 9: 'mediumDashed',
  293. 10: 'mediumDashDot',
  294. 11: 'mediumDashDotDot',
  295. 12: 'slantDashDot',
  296. 13: 'thick'
  297. }
  298. }
  299. // console.log('borders', borders)
  300. for (const bor in borders) {
  301. // console.log(bor)
  302. if (borders[bor].color.indexOf('rgb') === -1) {
  303. border[luckyExcel.type[bor]] = {
  304. style: luckyExcel.style[borders[bor].style],
  305. color: { argb: borders[bor].color.replace('#', '') }
  306. }
  307. } else {
  308. border[luckyExcel.type[bor]] = {
  309. style: luckyExcel.style[borders[bor].style],
  310. color: { argb: borders[bor].color }
  311. }
  312. }
  313. }
  314. return border
  315. }
  316. function createCellPos(n) {
  317. let ordA = 'A'.charCodeAt(0)
  318. let ordZ = 'Z'.charCodeAt(0)
  319. let len = ordZ - ordA + 1
  320. let s = ''
  321. while (n >= 0) {
  322. s = String.fromCharCode((n % len) + ordA) + s
  323. n = Math.floor(n / len) - 1
  324. }
  325. return s
  326. }