1.安装插件
npm install xlsx@0.16.9 xlsx-js-style@1.2.0
2.封装excel.js
import XLSX from 'xlsx';
import XLSXS from 'xlsx-js-style'
function auto_width(ws, data) {
/*set worksheet max width per col*/
const colWidth = data.map((row) =>
row.map((val) => {
/*if null/undefined*/
if (val == null) {
return { wch: 10 };
} else if (val.toString().charCodeAt(0) > 255) {
/*if chinese*/
return { wch: val.toString().length * 2 };
} else {
return { wch: val.toString().length };
}
})
);
/*start in the first row*/
let result = colWidth[0];
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j]['wch'] < colWidth[i][j]['wch']) {
result[j]['wch'] = colWidth[i][j]['wch'];
}
}
}
ws['!cols'] = result;
}
//获取合并单元格数据
function getRowsExcel(key, list, notes) {
console.log(key, list, notes);
// s 表示要合并的单元格范围的左上角单元格,r 表示该单元格的行号,c 表示该单元格的列号,行列号从 0 开始计数。所以 { r: 0, c: 0 } 表示第 1 行第 1 列的单元格,即 A1 单元格。
// e 表示要合并的单元格范围的右下角单元格,其含义与 s 相同。所以 { r: 0, c: 1 } 表示第 1 行第 2 列的单元格,即 B1 单元格。
let start = {}, end = "", data = "", mergeRules = notes ? [{ s: { r: 0, c: 0 }, e: { r: 0, c: list.length } }] : [];
let len = notes ? 2 : 1;
key.map((e, cIndex) => {
list.map((es, eIndex) => {
if (data) {
if (data != es[e]) {
data = es[e];
if(end){
mergeRules.push({
s: start,
e: end
})
}
end = "";
start = { r: eIndex + len, c: cIndex };
} else {
end = { r: eIndex + len, c: cIndex };
}
} else {
data = es[e];
start = { r: eIndex + len, c: cIndex };
}
})
})
return mergeRules;
}
//导出公共方法--设置单元格样式---单元格自动合并设置
//key 导出表头prop []
//title 导出表头label
//filename 导出表格名称
//data 导出数据 []
//widthList 导出列width集合[] , 例如 [200,100,200...]长度等于key.length; 默认200
//align 导出列对齐方式 , 例如 ['left','center'...]长度等于key.length; 默认cneter
//autoWidth 是否自动撑开
//styles 导出单元格样式
//notes 导出表格 title(显示在xls第一行)
//mergeRules 导出表格合并列集合 mergeRules类型数组 []=所有列合并 [prop]=指定列合并
export const export_array_to_STYLES = ({ key, data, widthList, align, autoWidth, title, filename, styles, notes, mergeRules }) => {
let workbook = XLSXS.utils.book_new(); // 工作簿
const arr = json_to_array(key, data);
if (notes) {
notes = title.map((e, index) => {
return index === 0 ? notes : '';
});
}
const excelData = notes ? [notes, title, ...arr] : [title, ...arr];
let worksheet = XLSXS.utils.aoa_to_sheet(excelData); // 数据表
if (autoWidth) {
auto_width(worksheet, arr);
}
let cols = []; // 设置每列的宽度
let rows = [];//行高
// wpx 字段表示以像素为单位,wch 字段表示以字符为单位
// if (!(align && align.length > 0)) { return false; }
for (let i = 0; i <= excelData[0].length; i++) {
let col = {};
col.wpx = widthList && widthList.length > 0 ? widthList[i] : 200;
cols.push(col);
}
for (let i = 1; i <= excelData.length; i++) {
rows.push({ hpx: 32 });
}
worksheet['!cols'] = cols; // 设置列宽信息到工作表
worksheet['!rows'] = rows;
//以下是样式设置,样式设置放在组织完数据之后,xlsx-js-style的核心API就是SheetJS的
const set = { "A": 0, "B": 1, "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7, "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13, "O": 14, "P": 15, "Q": 16, "R": 17, "S": 18, "T": 19, "U": 20, "V": 21, "W": 22, "X": 23, "Y": 24, "Z": 25 }
Object.keys(worksheet).forEach((key, i) => {
// 非!开头的属性都是单元格
if (!key.startsWith("!")) {
const len = title.length + (notes ? notes.length : 0);
if (i < len) {
//表头设置
worksheet[key].s = {
font: {
bold: true,
sz: 11,
name: '宋体',
},
// alignment 对齐方式
alignment: {
vertical: 'center', // 垂直居中
horizontal: notes ? (i < notes.length ? 'left' : 'center') : "center"
},
// border 边框属性
border: {
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
},
// fill 颜色填充属性
fill: {
fgColor: { rgb: 'FFFFFF' },
}
};
} else {
//默认样式
const styleCss = {
font: {
bold: false,
sz: 10,
name: '宋体',
},
// alignment 对齐方式
alignment: {
vertical: 'center', // 垂直居中
horizontal: align ? align[set[key.charAt(0)]] : "center" // 水平居中
},
// border 边框属性
border: {
top: { style: 'thin' },
bottom: { style: 'thin' },
left: { style: 'thin' },
right: { style: 'thin' }
},
// fill 颜色填充属性
fill: {
fgColor: { rgb: 'FFFFFF' },
}
};
if (styles && styles[key]) {
styles[key].alignment.horizontal = align ? align[set[key.charAt(0)]] : 'center';
}
worksheet[key].s = styles && styles[key] ? styles[key] : styleCss;
}
}
})
//以下是合并单元格
// 设置合并单元格规则
if (mergeRules && Array.isArray(mergeRules)) {
const keys = mergeRules && mergeRules.length == 0 ? key : mergeRules;
// s 表示要合并的单元格范围的左上角单元格,r 表示该单元格的行号,c 表示该单元格的列号,行列号从 0 开始计数。所以 { r: 0, c: 0 } 表示第 1 行第 1 列的单元格,即 A1 单元格。
// e 表示要合并的单元格范围的右下角单元格,其含义与 s 相同。所以 { r: 0, c: 1 } 表示第 1 行第 2 列的单元格,即 B1 单元格。
// 因此,{ s: { r: 0, c: 0 }, e: { r: 0, c: 1 } } 表示要合并第 1 行第 1 列和第 1 行第 3 列之间的元格。
// 注意,合并会以开始位置单元格中的内容为准,所以合并后的单元格中的内容为 A1 单元格中的内容。
const mergeList = getRowsExcel(keys, data, notes);
worksheet['!merges'] = mergeList.map((rule) => ({ ...rule })); // 保留之前设置的合并规则
// 设置合并后单元格内容
mergeList.forEach((mergeRule) => {
const { s, content } = mergeRule;
if (content) {
const cell = XLSX.utils.encode_cell({ r: s.r, c: s.c });
worksheet[cell] = { t: 's', v: content };
}
});
}
XLSXS.utils.book_append_sheet(workbook, worksheet, "Sheet1");
XLSXS.writeFile(workbook, filename + ".xlsx");
};
export default {
export_array_to_STYLES
};
3.使用
import { export_array_to_STYLES } from '@/utils/excel.js';
export default{
data(){
return {
column:[ {
prop: "INNER_NAME",
isProp: "INNER_NAME",
label: "账套名称",
minWidth: 180,
align: 'left',
fixed: false,
},
{
prop: "COMPANY_CODE_CN",
isProp: "COMPANY_CODE_CN",
label: "公司名称",
minWidth: 180,
align: 'left',
fixed: false,
},
{
prop: "TRADE_VARIETY_NAME",
isProp: "TRADE_VARIETY_NAME",
label: "交易类型",
minWidth: 100,
align: 'center',
fixed: false,
},]
}
},
methods:{
Excel(){
var data = [
{INNER_NAME:1,COMPANY_CODE_CN:1,TRADE_VARIETY_NAME:1},
{INNER_NAME:1,COMPANY_CODE_CN:1,TRADE_VARIETY_NAME:1},
{INNER_NAME:1,COMPANY_CODE_CN:2,TRADE_VARIETY_NAME:1},
{INNER_NAME:1,COMPANY_CODE_CN:2,TRADE_VARIETY_NAME:1},
{INNER_NAME:2,COMPANY_CODE_CN:3,TRADE_VARIETY_NAME:1},
{INNER_NAME:2,COMPANY_CODE_CN:3,TRADE_VARIETY_NAME:1},
{INNER_NAME:3,COMPANY_CODE_CN:3,TRADE_VARIETY_NAME:2},
{INNER_NAME:1,COMPANY_CODE_CN:5,TRADE_VARIETY_NAME:2},
{INNER_NAME:8,COMPANY_CODE_CN:3,TRADE_VARIETY_NAME:2}
];
var title = [];
var key = [];
column.map((e) => {
title.push(e.label);
key.push(e.prop);
});
var spanMethodList = ['INNER_NAME','COMPANY_CODE_CN'];//指定合并列
export_array_to_STYLES({
key: key,
title: title,
notes:"商品持仓数据确认",
data: data,
filename: '商品持仓数据确认',
autoWidth: true,
mergeRules:spanMethodList
});
}
}
}
效果图
1698223088510.png
网友评论