|
@@ -0,0 +1,531 @@
|
|
|
+function ExcelHelper () {
|
|
|
+ var WS = {}
|
|
|
+ var titleHeader = []
|
|
|
+ // 初始化数据格式
|
|
|
+ var iniData = (option) => {
|
|
|
+ const data = []
|
|
|
+ if (option && option.otherData && option.otherData.ExcelHead && option.data) {
|
|
|
+ for (var rowIndex = 0; rowIndex < option.data.length; rowIndex++) {
|
|
|
+ const dataItem = {}
|
|
|
+ // option.data[rowIndex]
|
|
|
+ for (var colIndex = 0; colIndex < option.otherData.ExcelHead.length; colIndex++) {
|
|
|
+ dataItem[option.otherData.ExcelHead[colIndex].text] = option.data[rowIndex][option.otherData.ExcelHead[colIndex].value]
|
|
|
+ // dataItem.push(option.data[rowIndex][option.otherData.ExcelHead[colIndex].value])
|
|
|
+ }
|
|
|
+ data.push(dataItem)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return data
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建excel表头
|
|
|
+ * @param revealList 列表页面展示的表头
|
|
|
+ * @returns {[]} excel表格展示的表头
|
|
|
+ */
|
|
|
+ var buildHeader = (revealList) => {
|
|
|
+ let excelHeader = [];
|
|
|
+ // 构建生成excel表头需要的数据结构
|
|
|
+ getHeader(revealList, excelHeader, 0, 0);
|
|
|
+ // 多行表头长短不一,短的向长的看齐,不够的补上行合并占位符
|
|
|
+ let max = Math.max(...(excelHeader.map(a => a.length)))
|
|
|
+ excelHeader.filter(e => e.length < max).forEach(
|
|
|
+ e => pushRowSpanPlaceHolder(e, max - e.length))
|
|
|
+ return excelHeader;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成头部
|
|
|
+ * @param headers 展示的头部
|
|
|
+ * @param excelHeader excel头部
|
|
|
+ * @param deep 深度
|
|
|
+ * @param perOffset 前置偏移量
|
|
|
+ * @returns {number} 后置偏移量
|
|
|
+ */
|
|
|
+ var getHeader = (headers, excelHeader, deep, perOffset) => {
|
|
|
+ let offset = 0
|
|
|
+ let cur = excelHeader[deep]
|
|
|
+ if (!cur) {
|
|
|
+ cur = excelHeader[deep] = []
|
|
|
+ }
|
|
|
+ // 填充行合并占位符
|
|
|
+ pushRowSpanPlaceHolder(cur, perOffset - cur.length)
|
|
|
+ for (let i = 0; i < headers.length; i++) {
|
|
|
+ let head = headers[i]
|
|
|
+ cur.push(head.text)
|
|
|
+ if (head.hasOwnProperty('childHead') && Array.isArray(head.childHead)
|
|
|
+ && head.childHead.length > 0) {
|
|
|
+ let childOffset = getHeader(head.childHead, excelHeader, deep + 1,
|
|
|
+ cur.length - 1)
|
|
|
+ // 填充列合并占位符
|
|
|
+ pushColSpanPlaceHolder(cur, childOffset - 1)
|
|
|
+ offset += childOffset
|
|
|
+ } else {
|
|
|
+ offset++
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return offset;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 填充行合并占位符
|
|
|
+ * */
|
|
|
+ var pushRowSpanPlaceHolder = (arr, count) => {
|
|
|
+ for (let i = 0; i < count; i++) {
|
|
|
+ arr.push('!$ROW_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 填充列合并占位符
|
|
|
+ var pushColSpanPlaceHolder = (arr, count) => {
|
|
|
+ for (let i = 0; i < count; i++) {
|
|
|
+ arr.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 合并头部单元格
|
|
|
+ **/
|
|
|
+ var doMerges = (arr) => {
|
|
|
+ // 要么横向合并 要么纵向合并
|
|
|
+ let deep = arr.length;
|
|
|
+ let merges = [];
|
|
|
+ for (let y = 0; y < deep; y++) {
|
|
|
+ // 先处理横向合并
|
|
|
+ let row = arr[y];
|
|
|
+ let colSpan = 0
|
|
|
+ for (let x = 0; x < row.length; x++) {
|
|
|
+ if (row[x] === '!$COL_SPAN_PLACEHOLDER') {
|
|
|
+ row[x] = undefined;
|
|
|
+ if (x + 1 === row.length) {
|
|
|
+ merges.push({ s: { r: y, c: x - colSpan - 1 }, e: { r: y, c: x } })
|
|
|
+ }
|
|
|
+ colSpan++
|
|
|
+ } else if (colSpan > 0 && x > colSpan) {
|
|
|
+ merges.push({ s: { r: y, c: x - colSpan - 1 }, e: { r: y, c: x - 1 } })
|
|
|
+ colSpan = 0
|
|
|
+ } else {
|
|
|
+ colSpan = 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 再处理纵向合并
|
|
|
+ let colLength = arr[0].length
|
|
|
+ for (let x = 0; x < colLength; x++) {
|
|
|
+ let rowSpan = 0
|
|
|
+ for (let y = 0; y < deep; y++) {
|
|
|
+ if (arr[y][x] === '!$ROW_SPAN_PLACEHOLDER') {
|
|
|
+ arr[y][x] = undefined;
|
|
|
+ if (y + 1 === deep) {
|
|
|
+ merges.push({ s: { r: y - rowSpan, c: x }, e: { r: y, c: x } })
|
|
|
+ }
|
|
|
+ rowSpan++;
|
|
|
+ } else if (rowSpan > 0 && y > rowSpan) {
|
|
|
+ merges.push({ s: { r: y - rowSpan - 1, c: x }, e: { r: y - 1, c: x } })
|
|
|
+ rowSpan = 0;
|
|
|
+ } else {
|
|
|
+ rowSpan = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return merges;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组织数据装载到sheet中
|
|
|
+ */
|
|
|
+ var aoa_to_sheet = (data, headerRows) => {
|
|
|
+ // const ws = {};
|
|
|
+ const range = { s: { c: 10000000, r: 10000000 }, e: { c: 0, r: 0 } };
|
|
|
+ for (let R = 0; R !== data.length; ++R) {
|
|
|
+ for (let C = 0; C !== data[R].length; ++C) {
|
|
|
+ if (range.s.r > R) {
|
|
|
+ range.s.r = R;
|
|
|
+ }
|
|
|
+ if (range.s.c > C) {
|
|
|
+ range.s.c = C;
|
|
|
+ }
|
|
|
+ if (range.e.r < R) {
|
|
|
+ range.e.r = R;
|
|
|
+ }
|
|
|
+ if (range.e.c < C) {
|
|
|
+ range.e.c = C;
|
|
|
+ }
|
|
|
+ /// 这里生成cell的时候,使用上面定义的默认样式
|
|
|
+
|
|
|
+ const cell = {
|
|
|
+ v: data[R][C] || '',
|
|
|
+ s: {
|
|
|
+ font: { name: "宋体", sz: 11, color: { auto: 1 } },
|
|
|
+ alignment: {
|
|
|
+ /// 自动换行
|
|
|
+ wrapText: 1,
|
|
|
+ // 居中
|
|
|
+ horizontal: "left",
|
|
|
+ vertical: "center",
|
|
|
+ indent: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (typeof cell.v === 'number') {
|
|
|
+ cell.t = 'n';
|
|
|
+ cell.s.alignment.horizontal = 'right'
|
|
|
+ } else if (typeof cell.v === 'boolean') {
|
|
|
+ cell.t = 'b';
|
|
|
+ } else {
|
|
|
+ cell.t = 's';
|
|
|
+ cell.s.alignment.horizontal = 'left'
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if(titleHeader.length > 0){
|
|
|
+ if (R === 0 ) {
|
|
|
+ // 生成主标题
|
|
|
+ cell.s.font.sz = 24
|
|
|
+ cell.s.font.bold = true
|
|
|
+ cell.s.alignment.horizontal = 'center'
|
|
|
+ } else if (R <= titleHeader.length - 1) {
|
|
|
+ // 生成副标题
|
|
|
+ cell.s.font.sz = 11
|
|
|
+ cell.s.font.bold = true
|
|
|
+ cell.s.alignment.horizontal = 'center'
|
|
|
+ }
|
|
|
+ }else if(R < headerRows){
|
|
|
+ cell.s.alignment.horizontal = 'center'
|
|
|
+ cell.s.font.color = { rgb: '606266' }
|
|
|
+ cell.s.font.bold = true
|
|
|
+ cell.s.border = {
|
|
|
+ top: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ left: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ bottom: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ right: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ };
|
|
|
+ cell.s.fill = {
|
|
|
+ patternType: 'solid',
|
|
|
+ fgColor: { tint: 0.3999755851924192, rgb: 'ebeef5' },
|
|
|
+ bgColor: { tint: 0.3999755851924192, rgb: 'D9D9D9' }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 头部列表加边框
|
|
|
+ if (R < titleHeader.length + headerRows - 1 && R >= titleHeader.length) {
|
|
|
+ cell.s.alignment.horizontal = 'center'
|
|
|
+ cell.s.font.color = { rgb: '606266' }
|
|
|
+ cell.s.font.bold = true
|
|
|
+ cell.s.border = {
|
|
|
+ top: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ left: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ bottom: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ right: { style: 'thin', color: { rgb: "000000" } },
|
|
|
+ };
|
|
|
+ cell.s.fill = {
|
|
|
+ patternType: 'solid',
|
|
|
+ fgColor: { tint: 0.3999755851924192, rgb: 'ebeef5' },
|
|
|
+ bgColor: { tint: 0.3999755851924192, rgb: 'D9D9D9' }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const cell_ref = XLSX.utils.encode_cell({ c: C, r: R });
|
|
|
+
|
|
|
+ WS[cell_ref] = cell
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (range.s.c < 10000000) {
|
|
|
+ WS['!ref'] = XLSX.utils.encode_range(range)
|
|
|
+ }
|
|
|
+ return WS
|
|
|
+ }
|
|
|
+
|
|
|
+ var s2ab = (s) => {
|
|
|
+ let buf = new ArrayBuffer(s.length);
|
|
|
+ let view = new Uint8Array(buf);
|
|
|
+ for (let i = 0; i !== s.length; ++i) {
|
|
|
+ view[i] = s.charCodeAt(i) & 0xFF;
|
|
|
+ }
|
|
|
+ return buf;
|
|
|
+ }
|
|
|
+
|
|
|
+ var openDownloadXLSXDialog = (url, saveName) => {
|
|
|
+ if (typeof url == 'object' && url instanceof Blob) {
|
|
|
+ url = URL.createObjectURL(url); // 创建blob地址
|
|
|
+ }
|
|
|
+ var aLink = document.createElement('a');
|
|
|
+ aLink.href = url;
|
|
|
+ aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
|
|
|
+ var event;
|
|
|
+ if (window.MouseEvent) {
|
|
|
+ event = new MouseEvent('click');
|
|
|
+ } else {
|
|
|
+ event = document.createEvent('MouseEvents');
|
|
|
+ event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false,
|
|
|
+ false, false, false, 0, null);
|
|
|
+ }
|
|
|
+ aLink.dispatchEvent(event);
|
|
|
+ this.success()
|
|
|
+ }
|
|
|
+
|
|
|
+ var extractData = (selectionData, revealList) => {
|
|
|
+ // 列
|
|
|
+ let headerList = flat(revealList);
|
|
|
+ // 导出的结果集
|
|
|
+ let excelRows = [];
|
|
|
+ if (!selectionData || selectionData.length < 1) {
|
|
|
+ return excelRows
|
|
|
+ }
|
|
|
+ // 如果有child集合的话会用到
|
|
|
+ let dataKeys = new Set(Object.keys(selectionData[0]));
|
|
|
+ selectionData.some(e => {
|
|
|
+ if (e.childHead && e.childHead.length > 0) {
|
|
|
+ let childKeys = Object.keys(e.childHead[0]);
|
|
|
+ for (let i = 0; i < childKeys.length; i++) {
|
|
|
+ dataKeys.delete(childKeys[i]);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ flatData(selectionData, (list) => {
|
|
|
+ excelRows.push(...buildExcelRow(dataKeys, headerList, list));
|
|
|
+ })
|
|
|
+ return excelRows;
|
|
|
+ }
|
|
|
+ var flatData = (list, eachDataCallBack) => {
|
|
|
+ let resultList = [];
|
|
|
+ for (let i = 0; i < list.length; i++) {
|
|
|
+ let data = list[i];
|
|
|
+ let rawDataList = [];
|
|
|
+ // 每个子元素都父元素合并成一条数据
|
|
|
+ if (data.childHead && data.childHead.length > 0) {
|
|
|
+ for (let j = 0; j < data.childHead.length; j++) {
|
|
|
+ delete data.childHead[j].bsm
|
|
|
+ let copy = Object.assign({}, data, data.childHead[j]);
|
|
|
+ rawDataList.push(copy);
|
|
|
+ copy['rowSpan'] = (j > 0 ? 0 : data.childHead.length);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ data['rowSpan'] = 1;
|
|
|
+ rawDataList.push(data);
|
|
|
+ }
|
|
|
+ resultList.push(...rawDataList);
|
|
|
+ if (typeof eachDataCallBack === 'function') {
|
|
|
+ eachDataCallBack(rawDataList)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ var buildExcelRow = (mainKeys, headers, rawDataList) => {
|
|
|
+ // 合计行
|
|
|
+ let sumCols = [];
|
|
|
+ // 数据行
|
|
|
+ let rows = [];
|
|
|
+ for (let i = 0; i < rawDataList.length; i++) {
|
|
|
+ let cols = []
|
|
|
+ let rawData = rawDataList[i];
|
|
|
+ // 提取数据
|
|
|
+ for (let j = 0; j < headers.length; j++) {
|
|
|
+ let header = headers[j];
|
|
|
+ // 父元素键需要行合并
|
|
|
+ if (rawData['rowSpan'] === 0 && mainKeys.has(header.value)) {
|
|
|
+ cols.push('!$ROW_SPAN_PLACEHOLDER')
|
|
|
+ } else {
|
|
|
+ let value;
|
|
|
+ if (typeof header.exeFun === 'function') {
|
|
|
+ value = header.exeFun(rawData);
|
|
|
+ } else {
|
|
|
+ value = rawData[header.value];
|
|
|
+ }
|
|
|
+ cols.push(value)
|
|
|
+ // 如果该列需要合计,并且是数字类型
|
|
|
+ if (header['summable'] && typeof value === 'number') {
|
|
|
+ sumCols[j] = (sumCols[j] ? sumCols[j] : 0) + value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rows.push(cols);
|
|
|
+ }
|
|
|
+ // 如果有合计行
|
|
|
+ if (sumCols.length > 0) {
|
|
|
+ rows.push(...sumRowHandle(sumCols));
|
|
|
+ }
|
|
|
+ return rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合计行
|
|
|
+ var sumRowHandle = (sumCols) => {
|
|
|
+ //TODO
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 扁平头部
|
|
|
+ var flat = (revealList) => {
|
|
|
+ let result = []
|
|
|
+ revealList.forEach(e => {
|
|
|
+ if (e.hasOwnProperty('childHead') && e.childHead.length > 0) {
|
|
|
+ result.push(...flat(e.childHead))
|
|
|
+ } else if (e.hasOwnProperty('exeFun')) {
|
|
|
+ result.push(e)
|
|
|
+ } else if (e.hasOwnProperty('text')) {
|
|
|
+ result.push(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化标题栏
|
|
|
+ var iniTitle = (option, headers) => {
|
|
|
+ var maxColumnSize = headers.length
|
|
|
+ titleHeader = []
|
|
|
+ // 主标题
|
|
|
+ if (option.otherData && option.otherData.ExcelTitle && option.otherData.ExcelTitle.t) {
|
|
|
+ var title = []
|
|
|
+ title.push(option.otherData.ExcelTitle.t)
|
|
|
+ for (var i = 1; i < maxColumnSize; i++) {
|
|
|
+ title.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ titleHeader.push(title)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 副标题
|
|
|
+ if (option.otherData && option.otherData.ExcelTitle && option.otherData.ExcelTitle.multiT) {
|
|
|
+ var t = option.otherData.ExcelTitle.multiT
|
|
|
+ var size = Math.floor(maxColumnSize / 3)
|
|
|
+ for (var i = 0; i < option.otherData.ExcelTitle.multiT.t0.length; i++) {
|
|
|
+ var t = []
|
|
|
+ var e = size
|
|
|
+ if (option.otherData.ExcelTitle.multiT.t0) {
|
|
|
+ t.push(option.otherData.ExcelTitle.multiT.t0[i])
|
|
|
+ for (let i = 1; i < e; i++) {
|
|
|
+ t.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (option.otherData.ExcelTitle.multiT.t1) {
|
|
|
+ t.push(option.otherData.ExcelTitle.multiT.t1[i])
|
|
|
+ for (let i = 1; i < e; i++) {
|
|
|
+ t.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (option.otherData.ExcelTitle.multiT.t2) {
|
|
|
+ t.push(option.otherData.ExcelTitle.multiT.t2[i])
|
|
|
+ e = maxColumnSize - t.length
|
|
|
+ for (let i = 0; i < e; i++) {
|
|
|
+ t.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ titleHeader.push(t)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return titleHeader
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化页脚
|
|
|
+ var iniFoot = (option, headers) =>{
|
|
|
+ var maxColumnSize = headers.length
|
|
|
+ var foot = []
|
|
|
+ if (option.otherData && option.otherData.ExcelFoot && option.otherData.ExcelFoot) {
|
|
|
+ var size = Math.floor(maxColumnSize / 3)
|
|
|
+
|
|
|
+ var t = []
|
|
|
+ var e = size
|
|
|
+ if (option.otherData.ExcelFoot.left) {
|
|
|
+ t.push(option.otherData.ExcelFoot.left)
|
|
|
+ for (let i = 1; i < e; i++) {
|
|
|
+ t.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (option.otherData.ExcelFoot.center) {
|
|
|
+ t.push(option.otherData.ExcelFoot.center)
|
|
|
+ for (let i = 1; i < e; i++) {
|
|
|
+ t.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (option.otherData.ExcelFoot.right) {
|
|
|
+ t.push(option.otherData.ExcelFoot.right)
|
|
|
+ e = maxColumnSize - t.length
|
|
|
+ for (let i = 0; i < e; i++) {
|
|
|
+ t.push('!$COL_SPAN_PLACEHOLDER')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ foot.push(t)
|
|
|
+ }
|
|
|
+ return foot
|
|
|
+ }
|
|
|
+
|
|
|
+ this.toExcel = function (option) {
|
|
|
+ if (!option.sheetName) {
|
|
|
+ option.sheetName = 'Sheet1'
|
|
|
+ }
|
|
|
+
|
|
|
+ iniData(option)
|
|
|
+
|
|
|
+ // excel表头
|
|
|
+ var excelHeader = buildHeader(option.otherData.ExcelHead)
|
|
|
+ var headers = flat(option.otherData.ExcelHead)
|
|
|
+ var foots = iniFoot(option, headers)
|
|
|
+ iniTitle(option, headers)
|
|
|
+ // 头部行数,用来固定表头
|
|
|
+ var headerRows = excelHeader.length
|
|
|
+ if (titleHeader.length > 0) {
|
|
|
+ headerRows++
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取数据
|
|
|
+ var dataList = extractData(option.data, option.otherData.ExcelHead)
|
|
|
+ // excelHeader.unshift(titleHeader)
|
|
|
+ excelHeader = titleHeader.concat(excelHeader)
|
|
|
+ if (dataList.length > 0) {
|
|
|
+ excelHeader.push(...dataList, [])
|
|
|
+ }
|
|
|
+ if (foots && foots.length>0){
|
|
|
+ excelHeader.push(foots[0])
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算合并
|
|
|
+ var merges = doMerges(excelHeader)
|
|
|
+ // 生成sheet
|
|
|
+ var ws = aoa_to_sheet(excelHeader, headerRows)
|
|
|
+ // 单元格合并
|
|
|
+ ws['!merges'] = merges
|
|
|
+ // 头部冻结
|
|
|
+ ws["!freeze"] = {
|
|
|
+ xSplit: "1",
|
|
|
+ ySplit: "" + headerRows,
|
|
|
+ topLeftCell: "B" + (headerRows + 1),
|
|
|
+ activePane: "bottomRight",
|
|
|
+ state: "frozen",
|
|
|
+ }
|
|
|
+ // 列宽
|
|
|
+ var columns = []
|
|
|
+ for (var i = 0; i < headers.length; i++) {
|
|
|
+ var n = (headers[i].width ? Number(headers[i].width) : 100)
|
|
|
+
|
|
|
+ columns.push({
|
|
|
+ wpx: Math.ceil(n)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ ws['!cols'] = columns
|
|
|
+ var workbook = {
|
|
|
+ SheetNames: [option.sheetName],
|
|
|
+ Sheets: {}
|
|
|
+ }
|
|
|
+ workbook.Sheets[option.sheetName] = ws
|
|
|
+ // excel样式
|
|
|
+ var wopts = {
|
|
|
+ bookType: 'xlsx',
|
|
|
+ bookSST: false,
|
|
|
+ type: 'binary',
|
|
|
+ cellStyles: true
|
|
|
+ }
|
|
|
+ var wbout = XLSX.write(workbook, wopts)
|
|
|
+ var blob = new Blob([s2ab(wbout)], { type: "application/octet-stream" })
|
|
|
+ openDownloadXLSXDialog(blob, option.fileName)
|
|
|
+ }
|
|
|
+
|
|
|
+ this.success = function(){}
|
|
|
+}
|
|
|
+
|
|
|
+export default ExcelHelper
|