vue使用luckyexcel實(shí)現(xiàn)在線表格及導(dǎo)出導(dǎo)入方式
話不多說。
vue需要在public-index.html中在線導(dǎo)入以下這些
或者找到相應(yīng)的資源下載到本地,本地導(dǎo)入更快。
<link rel="stylesheet" rel="external nofollow" /> <link rel="stylesheet" rel="external nofollow" /> <link rel="stylesheet" rel="external nofollow" /> <link rel="stylesheet" rel="external nofollow" /> <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>
引入
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'
注意:
- 按照以上導(dǎo)入去下載相應(yīng)的包
- excelOptions 是表格功能的一一些配置
- 我只是放在外面了
版本:
定義當(dāng)前表格容器
我多加了一個(gè)表格名稱
<div class="allbtn"> <button class="btn" @click="saveExcel">保存</button> <button class="btn" @click="outputExcel">導(dǎo)出表格</button> <input type="file" accept=".xlsx" @change="importExcel($event)" value="導(dǎo)入表格" /> </div> <h2>當(dāng)前表格名稱</h2> <input class="inp" type="text" v-model="excelTitel"> <div id="luckysheet"></div>
導(dǎo)入excel并展示
// 導(dǎo)入表格 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文件的內(nèi)容,當(dāng)前不支持xls文件!') return } window.luckysheet.destroy() this.changeExcelOption.data = exportJson.sheets window.luckysheet.create(this.changeExcelOption) }) },
導(dǎo)出表格
這里我做了一點(diǎn)處理,初次加載時(shí)獲取表格名稱,然后可編輯當(dāng)前表格名稱,點(diǎn)擊保存按鈕后進(jìn)行導(dǎo)出,則會導(dǎo)出你編輯的表格名稱
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數(shù)據(jù) saveExcel () { var objsheet = luckysheet.getAllSheets() // 得到表的數(shù)據(jù) // options = objsheet // 將表的數(shù)據(jù)保存本地 // console.log(objsheet) // 獲取標(biāo)內(nèi)容更新變化 luckysheet.setWorkbookName(this.excelTitel) this.changeExcelOption.title = this.excelTitel; },
// 導(dǎo)出表格 outputExcel () { this.exportExcel(luckysheet.getluckysheetfile("修改")); }, async exportExcel (luckysheet) { // 參數(shù)為luckysheet.getluckysheetfile()獲取的對象 // 1.創(chuàng)建工作簿,可以為工作簿添加屬性 const workbook = new ExcelJS.Workbook(); // 2.創(chuàng)建表格,第二個(gè)參數(shù)可以配置創(chuàng)建什么樣的工作表 luckysheet.every((table) => { if (table.data.length === 0) return true; const worksheet = workbook.addWorksheet(table.name); // 3.設(shè)置單元格合并,設(shè)置單元格邊框,設(shè)置單元格樣式,設(shè)置值 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(); //調(diào)用文件保存插件 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} // 按開始行,開始列,結(jié)束行,結(jié)束列合并(相當(dāng)于 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()轉(zhuǎn)成16進(jìn)制 colorHex (color) { // RGB顏色值的正則 var reg = /^(rgb|RGB)/; if (reg.test(color)) { var strHex = "#"; // 把RGB的3個(gè)數(shù)值變成數(shù)組 var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); // 轉(zhuǎn)成16進(jìn)制 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(旋轉(zhuǎn)) 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") { // 對應(yīng)luckysheet的config中borderinfo的的參數(shù) 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; }
總結(jié)
該開源表格確實(shí)很好用,但是更多功能可以深度挖掘,我只是簡單玩了一下,體驗(yàn)可以,不過配合后端一起食用效果更佳。
說個(gè)題外話:
寫這個(gè)完全是被坑了,一天時(shí)間實(shí)現(xiàn)多人在線協(xié)同表格,我使用了本地緩存寫了個(gè)簡易版的,完事了又問我會不會pythonWeb…我應(yīng)屆生,也只會一點(diǎn)python語法,自然是掛了,雖然對這種外包公司印象一般,但是這樣搞我確實(shí)頭大。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Vue3如何利用xlsx、xlsx-js-style導(dǎo)出Excel表格使用(適合新手)
- 前端實(shí)現(xiàn)Excel文件導(dǎo)出功能的完整代碼解析(vue實(shí)現(xiàn)excel文件導(dǎo)出)
- vue2項(xiàng)目使用exceljs多表頭導(dǎo)出功能詳解
- Vue用Export2Excel導(dǎo)出excel,多級表頭數(shù)據(jù)方式
- vue使用Luckysheet插件實(shí)現(xiàn)excel導(dǎo)入導(dǎo)出
- vue使用xlsx庫和xlsx-style庫導(dǎo)入導(dǎo)出excel、設(shè)置單元格背景色、文字居中、合并單元格、設(shè)置列寬
- 在Vue中使用xlsx組件實(shí)現(xiàn)Excel導(dǎo)出功能的步驟詳解
- 在Vue中實(shí)現(xiàn)Excel導(dǎo)出功能(數(shù)據(jù)導(dǎo)出)
相關(guān)文章
vue實(shí)現(xiàn)自定義日期組件功能的實(shí)例代碼
這篇文章主要介紹了vue自定義日期組件的實(shí)現(xiàn)代碼,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11Vue開發(fā)高德地圖應(yīng)用的最佳實(shí)踐
要在Web頁面中加入地圖,我推薦你使用高德地圖,下面這篇文章主要給大家介紹了關(guān)于Vue開發(fā)高德地圖應(yīng)用的最佳實(shí)踐,需要的朋友可以參考下2021-07-07Vue項(xiàng)目設(shè)置多個(gè)靜態(tài)文件及自定義靜態(tài)文件目錄的方案詳解
本文介紹了如何在Vue項(xiàng)目中配置多個(gè)靜態(tài)文件目錄,并提供了使用Vite和Webpack實(shí)現(xiàn)的示例,通過在vite.config.ts或vue.config.js中引入相關(guān)插件和配置,可以輕松實(shí)現(xiàn)自定義靜態(tài)文件目錄,希望這些內(nèi)容對您有所幫助,感興趣的朋友一起看看吧2025-01-01解決vue項(xiàng)目跳轉(zhuǎn)同樣的頁面不刷新的問題思路詳解
做公司官網(wǎng)項(xiàng)目的時(shí)候遇到的場景,頂部導(dǎo)航欄分類商品跳轉(zhuǎn)到分類詳情,然后在分類詳情再次點(diǎn)擊頂部導(dǎo)航欄里另外的分類商品,跳到同樣的頁面數(shù)據(jù)不刷新,下面小編給大家分享解決方式,關(guān)于vue跳轉(zhuǎn)不刷新問題感興趣的朋友一起看看吧2023-09-09Vue中對<style scoped> 中的scoped屬性解析
在Vue的單文件組件中,<style scoped> 的 scoped 屬性用于實(shí)現(xiàn)?樣式作用域隔離?,下面通過實(shí)例代碼講解Vue中對<style scoped>中的scoped屬性,感興趣的朋友一起看看吧2025-03-03vue-quill-editor插入圖片路徑太長問題解決方法
這篇文章主要介紹了vue-quill-editor插入圖片路徑太長問題解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01詳解vue中的動(dòng)態(tài)組件component和keep-alive
這篇文章主要介紹了詳解vue中的動(dòng)態(tài)組件component和keep-alive的相關(guān)資料,這大家需要注意include屬性和exclude屬性只能用一個(gè),不能同時(shí)使用,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-11-11詳解vue-router 2.0 常用基礎(chǔ)知識點(diǎn)之router-link
這篇文章主要介紹了詳解vue-router 2.0 常用基礎(chǔ)知識點(diǎn)之router-link,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05