话不多说。
1.vue需要在public-index.html中在线导入以下这些东西,或者找到相应的资源下载到本地,本地导入更快。
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/css/pluginsCss.css"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/plugins.css"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/luckysheet/dist/css/luckysheet.css"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/luckysheet/dist/assets/iconfont/iconfont.css"
/>
<script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet/dist/luckysheet.umd.js"></script>
2.引入
npm i -S exceljs file-saver luckyexcel
import { excelOptions } from "@/common/common.js"
const ExcelJS = require("exceljs");
import FileSaver from "file-saver";
import LuckyExcel from 'luckyexcel';
import XLSX from 'xlsx'
注意:按照以上导入去下载相应的包,excelOptions 是表格功能的一一些配置,我只是放在外面了。
版本:
3.定义当前表格容器,我多加了一个表格名称
<div class="allbtn">
<button class="btn" @click="saveExcel">保存</button>
<button class="btn" @click="outputExcel">导出表格</button>
<input type="file" accept=".xlsx" @change="importExcel($event)" value="导入表格" />
</div>
<h2>当前表格名称</h2>
<input class="inp" type="text" v-model="excelTitel">
<div id="luckysheet"></div>
4.导入excel并展示
// 导入表格
importExcel (event) {
let file = event.target.files[0]
let that = this;
const types = file.name.split(".")[1];
// 判断类型
const fileType = ["xlsx"].some(
item => item === types
);
console.log(file)
if (!fileType) {
alert("只支持上传xlsx后缀的表格!")
return
}
LuckyExcel.transformExcelToLucky(file, (exportJson, luckysheetfile) => {
if (exportJson.sheets === null || exportJson.sheets.length === 0) {
this.$message.error('无法读取excel文件的内容,当前不支持xls文件!')
return
}
window.luckysheet.destroy()
this.changeExcelOption.data = exportJson.sheets
window.luckysheet.create(this.changeExcelOption)
})
},
导出表格:
这里我做了一点处理,初次加载时获取表格名称,然后可编辑当前表格名称,点击保存按钮后进行导出,则会导出你编辑的表格名称
1.初始获取表格名称
// 初始化加载
init () {
let opt = excelOptions();
// 检测本地库中是否有配置
let excelValue = window.localStorage.getItem("excelValue");
if (excelValue != null) {//有值
let checkExcelValue = JSON.parse(excelValue)
opt.data[0] = checkExcelValue;
}
this.changeExcelOption = opt;
luckysheet.create(opt)
// 保存初始表格名称
this.excelTitel = this.changeExcelOption.title;
},
// 保存excel数据
saveExcel () {
var objsheet = luckysheet.getAllSheets() // 得到表的数据
// options = objsheet // 将表的数据保存本地
// console.log(objsheet)
// 获取标内容更新变化
luckysheet.setWorkbookName(this.excelTitel)
this.changeExcelOption.title = this.excelTitel;
},
// 导出表格
outputExcel () {
this.exportExcel(luckysheet.getluckysheetfile("修改"));
},
async exportExcel (luckysheet) {
// 参数为luckysheet.getluckysheetfile()获取的对象
// 1.创建工作簿,可以为工作簿添加属性
const workbook = new ExcelJS.Workbook();
// 2.创建表格,第二个参数可以配置创建什么样的工作表
luckysheet.every((table) => {
if (table.data.length === 0) return true;
const worksheet = workbook.addWorksheet(table.name);
// 3.设置单元格合并,设置单元格边框,设置单元格样式,设置值
this.setStyleAndValue(table.data, worksheet);
this.setMerge(table.config.merge, worksheet);
this.setBorder(table.config.borderInfo, worksheet);
return true;
});
// 4.写入 buffer
const buffer = await workbook.xlsx.writeBuffer();
//调用文件保存插件
FileSaver.saveAs(
new Blob([buffer], { type: "application/octet-stream" }),
this.changeExcelOption.title + ".xlsx"
);
return buffer;
},
setMerge (luckyMerge = {}, worksheet) {
const mergearr = Object.values(luckyMerge);
mergearr.forEach((elem) => {
// elem格式:{r: 0, c: 0, rs: 1, cs: 2}
// 按开始行,开始列,结束行,结束列合并(相当于 K10:M12)
worksheet.mergeCells(elem.r + 1, elem.c + 1, elem.r + elem.rs, elem.c + elem.cs);
});
},
setBorder (luckyBorderInfo, worksheet) {
if (!Array.isArray(luckyBorderInfo)) return;
luckyBorderInfo.forEach(function (elem) {
var val = elem.value;
let border = {};
const luckyToExcel = {
type: {
"border-all": "all",
"border-top": "top",
"border-right": "right",
"border-bottom": "bottom",
"border-left": "left",
},
style: {
0: "none",
1: "thin",
2: "hair",
3: "dotted",
4: "dashDot", // 'Dashed',
5: "dashDot",
6: "dashDotDot",
7: "double",
8: "medium",
9: "mediumDashed",
10: "mediumDashDot",
11: "mediumDashDotDot",
12: "slantDashDot",
13: "thick",
},
};
if (val) {
if (val.t != undefined) {
border["top"] = {
style: luckyToExcel.style[val.t.style],
color: val.t.color,
};
}
if (val.r != undefined) {
border["right"] = {
style: luckyToExcel.style[val.r.style],
color: val.r.color,
};
}
if (val.b != undefined) {
border["bottom"] = {
style: luckyToExcel.style[val.b.style],
color: val.b.color,
};
}
if (val.l != undefined) {
border["left"] = {
style: luckyToExcel.style[val.l.style],
color: val.l.color,
};
}
worksheet.getCell(val.row_index + 1, val.col_index + 1).border = border;
}
});
},
setStyleAndValue (cellArr, worksheet) {
if (!Array.isArray(cellArr)) return;
cellArr.forEach((row, rowid) => {
row.every((cell, columnid) => {
if (!cell) return true;
let fill = this.fillConvert(cell.bg);
let font = this.fontConvert(
cell.ff,
cell.fc,
cell.bl,
cell.it,
cell.fs,
cell.cl,
cell.ul
);
let alignment = this.alignmentConvert(cell.vt, cell.ht, cell.tb, cell.tr);
let value;
if (cell.f) {
value = { formula: cell.f, result: cell.v };
} else {
value = cell.v;
}
let target = worksheet.getCell(rowid + 1, columnid + 1);
target.fill = fill;
target.font = font;
target.alignment = alignment;
target.value = value;
return true;
});
});
},
fillConvert (bg) {
if (!bg) {
return {
type: "pattern",
pattern: "solid",
fgColor: { argb: "#ffffff".replace("#", "") },
};
}
let fill = {
type: "pattern",
pattern: "solid",
fgColor: { argb: this.colorHex(bg).replace("#", "") },
};
console.log(fill);
return fill;
},
//将rgb()转成16进制
colorHex (color) {
// RGB颜色值的正则
var reg = /^(rgb|RGB)/;
if (reg.test(color)) {
var strHex = "#";
// 把RGB的3个数值变成数组
var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
// 转成16进制
for (var i = 0; i < colorArr.length; i++) {
var hex = Number(colorArr[i]).toString(16);
if (hex === "0") {
hex += hex;
}
strHex += hex;
}
return strHex;
} else {
return String(color);
}
},
fontConvert (ff = 0, fc = "#000000", bl = 0, it = 0, fs = 10, cl = 0, ul = 0) {
// luckysheet:ff(样式), fc(颜色), bl(粗体), it(斜体), fs(大小), cl(删除线), ul(下划线)
const luckyToExcel = {
0: "微软雅黑",
1: "宋体(Song)",
2: "黑体(ST Heiti)",
3: "楷体(ST Kaiti)",
4: "仿宋(ST FangSong)",
5: "新宋体(ST Song)",
6: "华文新魏",
7: "华文行楷",
8: "华文隶书",
9: "Arial",
10: "Times New Roman ",
11: "Tahoma ",
12: "Verdana",
num2bl: function (num) {
return num === 0 ? false : true;
},
};
let font = {
name: luckyToExcel[ff],
family: 1,
size: fs,
color: { argb: fc.replace("#", "") },
bold: luckyToExcel.num2bl(bl),
italic: luckyToExcel.num2bl(it),
underline: luckyToExcel.num2bl(ul),
strike: luckyToExcel.num2bl(cl),
};
return font;
},
alignmentConvert (vt = "default", ht = "default", tb = "default", tr = "default") {
// luckysheet:vt(垂直), ht(水平), tb(换行), tr(旋转)
const luckyToExcel = {
vertical: {
0: "middle",
1: "top",
2: "bottom",
default: "top",
},
horizontal: {
0: "center",
1: "left",
2: "right",
default: "left",
},
wrapText: {
0: false,
1: false,
2: true,
default: false,
},
textRotation: {
0: 0,
1: 45,
2: -45,
3: "vertical",
4: 90,
5: -90,
default: 0,
},
};
let alignment = {
vertical: luckyToExcel.vertical[vt],
horizontal: luckyToExcel.horizontal[ht],
wrapText: luckyToExcel.wrapText[tb],
textRotation: luckyToExcel.textRotation[tr],
};
return alignment;
},
borderConvert (borderType, style = 1, color = "#000") {
// 对应luckysheet的config中borderinfo的的参数
if (!borderType) {
return {};
}
const luckyToExcel = {
type: {
"border-all": "all",
"border-top": "top",
"border-right": "right",
"border-bottom": "bottom",
"border-left": "left",
},
style: {
0: "none",
1: "thin",
2: "hair",
3: "dotted",
4: "dashDot", // 'Dashed',
5: "dashDot",
6: "dashDotDot",
7: "double",
8: "medium",
9: "mediumDashed",
10: "mediumDashDot",
11: "mediumDashDotDot",
12: "slantDashDot",
13: "thick",
},
};
let template = {
style: luckyToExcel.style[style],
color: { argb: color.replace("#", "") },
};
let border = {};
if (luckyToExcel.type[borderType] === "all") {
border["top"] = template;
border["right"] = template;
border["bottom"] = template;
border["left"] = template;
} else {
border[luckyToExcel.type[borderType]] = template;
}
return border;
}
总结:该开源表格确实很好用,但是更多功能可以深度挖掘,我只是简单玩了一下,体验可以,不过配合后端一起食用效果更佳。代码我放在资源里,免费的,大家自己看看,但是本地缓存的多人编辑代码不全,全的代码在我自己电脑上,懒得发了,这功能反正也是多余的,我就不删了,大家可以自己扩展。
题外话:写这个完全是被坑了,一天时间实现多人在线协同表格,我使用了本地缓存写了个简易版的,完事了又问我会不会pythonWeb…我应届生,也只会一点python语法,自然是挂了,虽然对这种外包公司印象一般,但是这样搞我确实头大。