Vue純前端實現(xiàn)導出Excel并修改樣式
之前寫過一篇前端導出:Vue實現(xiàn)導出功能(無后端配合) ,但是當時沒考慮到樣式的問題,后來要求導出的Excel單元格的樣式也需要調整,尤其是寬度,第一想到的就是xlsx-style這個包,之前也沒用過,這次用一下試著調一下寬度等樣式,剛安裝上就嘎嘎報錯~~~,下面就介紹一下該庫是使用,踩坑解決...
首先安裝:
npm i file-saver -S npm i xlsx -S npm i xlsx-style -S
然后引入
import * as XLSX from 'xlsx' import FileSaver from 'file-saver' import XLSXS from 'xlsx-style'
如果僅僅是為了導出,不修改樣式,也就是不引入 xlsx-style 這個庫 是沒有問題的,但是引入了 xlsx-style之后,直接報錯,項目直接跑不起來,首先報錯如下:
1. Module not found: Error: Can't resolve './cptable'
解決:
只需在vue.config.js中添加如下
configureWebpack: { // 解決 Module not found: Error: Can't resolve './cptable' externals: { './cptable': 'var cptable' } }
接著還有錯,
2. Module not found: Error: Can't resolve 'fs'
解決:
接著在vue.config.js中添加
configureWebpack: { // 解決 Module not found: Error: Can't resolve './cptable' externals: { './cptable': 'var cptable' }, // 解決 Module not found: Error: Can't resolve 'fs' resolve: { fallback: { fs: false } } }
再重新跑一下,哎呦呵,跑起來了,但是給出了個警告
它讓我們安裝一下 crypto-browserify 這個東東,再配置一下, 應該就可以避免了吧,唉,我這里暫時沒管它, 畢竟項目跑起來了,項目和人有一個能跑的就可以啦,哈哈哈哈哈哈哈哈哈哈哈...有時間再看下吧。。
當我們跑起來之后,然后使用的時候,就得使用xlsx-style中的write方法了,但是使用的時候瀏覽器控制臺還是報錯了,如下:
這個時候就得去修改源碼了,位置在 node_modules/xlsx-style/xlsx.js中1339行的位置處:
if(typeof jszip === 'undefined') jszip = require('./js'+'zip').JSZip;
修改為:
if(typeof jszip === 'undefined') jszip = require('./jszip.js');
但是我們這樣只是修改我們自己的本地,下次再裝依賴的時候還得重新去改,不可能每次都去這改,顯然是行不通的,這時候我們就可以在package.json中scripts中添加一個腳本,有個 postinstall 鉤子,在我們執(zhí)行完npm install后會執(zhí)行postinstall對應的腳本,所以我們可以在這里做處理。
首先我們在項目根目錄下新建 lib/xlsx-style/xlsx.js,然后將node_modules/xlsx-style/xlsx.js拷貝過來一份,我們修改 lib/xlsx-style/xlsx.js 中的代碼,將1339行修改掉,然后在scripts中添加postinstall
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"postinstall": "node install-xlsx-style-xlsx.js"
},
然后在根目錄下新建 install-xlsx-style-xlsx.js
const path = require('path') const fs = require('fs') const xlsxStyleModulesPath = path.join(__dirname, 'node_modules/xlsx-style/xlsx.js') const xlsxStyleLibPath = path.join(__dirname, 'lib/xlsx-style/xlsx.js') fs.writeFileSync(xlsxStyleModulesPath, fs.readFileSync(xlsxStyleLibPath))
這樣就可以了,之后再安裝依賴的時候就會自動替換掉node_modules/xlsx-style/xlsx.js。
key | 簡介 |
v | 原始值(有關更多信息,請參見“數(shù)據(jù)類型”部分) |
w | 格式化文本 |
t | 單元格類型:b布爾值,n數(shù)字,e錯誤,s字符串,d日期 |
f | 單元格公式 |
r | 富文本編碼 |
h | 富文本格式的HTML呈現(xiàn) |
c | 與單元格相關的評論 |
z | 與單元格關聯(lián)的數(shù)字格式字符串 |
l | 單元超鏈接對象(Target含鏈接,tooltip工具提示) |
s | 單元格的樣式/主題 |
接下來就是方法的封裝:
閑話不多說了,直接上代碼:
1. 這個是我們只需要把要打印的表格dom和下載的文件名稱(name.xlsx)傳入即可
但是這個只能打印當前的數(shù)據(jù)
import * as XLSX from 'xlsx' import FileSaver from 'file-saver' import XLSXS from 'xlsx-style' export default function(dom, fileName) { let tableDom = dom.cloneNode(true) let elTableFixedRight = tableDom.querySelector(".el-table__fixed-right") let elTableFixed = tableDom.querySelector(".el-table__fixed") if(elTableFixedRight) tableDom.removeChild(elTableFixedRight); if(elTableFixed) tableDom.removeChild(elTableFixed); let wb = XLSX.utils.table_to_book(tableDom, { raw: true, sheet: '運行日志表' }) setExcelStyle(wb['Sheets']['運行日志表']) // 設置樣式 let wbout = XLSXS.write(wb, { // 使用 xlsx-style 中的write方法 bookType: 'xlsx', bookSST: false, type: 'binary' }) try { FileSaver.saveAs( new Blob([s2ab(wbout)], { type: "application/octet-stream" }), fileName); } catch(e) { console.error(e, wbout, '----->>>') } } // 設置導出Excel樣式 這里主要是關注單元格寬度 function setExcelStyle(data) { let borderAll = { //單元格外側框線 top: { style: "thin", }, bottom: { style: "thin", }, left: { style: "thin", }, right: { style: "thin", }, } data['!cols'] = [] for(let key in data) { if(data[key].constructor === Object) { data[key].s = { // border: borderAll, // 邊框 alignment: { horizontal: "center", //水平居中對齊 vertical: "center", // 垂直居中 }, font: { sz: 11, }, bold: true, numFmt: 0 } data["!cols"].push({ wpx: 160 }); // 單元格寬度 } } } function s2ab(s) { var buf = new ArrayBuffer(s.length) var view = new Uint8Array(buf) for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff return buf } /** * 根據(jù)dom導出多個Sheet頁 * 按需使用 */ export class ExcelMultipleSheet { #book constructor() { this.#book = XLSX.utils.book_new() } append(dom, sheetname) { let sheet = XLSX.utils.table_to_sheet(dom) XLSX.utils.book_append_sheet(this.#book, sheet, sheetname) this.#editStyle(this.#book['Sheets'][sheetname]) } download(filename = 'WFT.xlsx') { let wbout = XLSXS.write(this.#book, { bookType: 'xlsx', bookSST: false, type: 'binary' }) try { FileSaver.saveAs(new Blob([this.#s2ab(wbout)], { type: "application/octet-stream" }), filename); } catch(e) { console.error(e, wbout, '----->>>') } } #editStyle(data) { data["!cols"] = [] for(let key in data) { if(data.hasOwnProperty(key)) { if(data[key].constructor === Object) { data[key].s = { alignment: { horizontal: "center", vertical: "center" }, font: { sz: 11, }, bold: true, numFmt: 0 } data["!cols"].push({ wpx: 160 }); // 單元格寬度 } } } } #s2ab(s) { var buf = new ArrayBuffer(s.length) var view = new Uint8Array(buf) for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff return buf } }
2. 這個是我們可以自定義導出數(shù)據(jù)(一般表格會分頁展示數(shù)據(jù),如果按照上面的方式 只會導出當前頁的,如果想導出所有數(shù)據(jù) 就使用該方法)傳入數(shù)據(jù)list和一個導出的文件名
我們要遍歷傳入的list,所以里面的字段還需要根據(jù)自己的去修改一下
// 導出Excel export function exportExcel(tableList, fileName) { let tableData = [['故障報警', '設備名稱', '故障內容', '系統(tǒng)', '狀態(tài)', '開始時間', '結束時間']] tableList.forEach(item => { tableData.push([ item.alarm, item.equipname, item.point, item.system, item.status, item.starttime, item.endtime ]) }) let ws = XLSX.utils.aoa_to_sheet(tableData) setExcelStyle(ws) // 設置樣式 let wb = XLSX.utils.book_new() XLSX.utils.book_append_sheet(wb, ws) let wbout = XLSXS.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' }) try { FileSaver.saveAs( new Blob([s2ab(wbout)], { type: "application/octet-stream" }), fileName); } catch(e) { console.error(e, wbout, '----->>>') } } // 設置導出Excel樣式 這里主要是關注單元格寬度 function setExcelStyle(data) { let borderAll = { //單元格外側框線 top: { style: "thin", }, bottom: { style: "thin", }, left: { style: "thin", }, right: { style: "thin", }, } data['!cols'] = [] for(let key in data) { if(data[key].constructor === Object) { data[key].s = { // border: borderAll, // 邊框 alignment: { horizontal: "center", //水平居中對齊 vertical: "center", // 垂直居中 }, font: { sz: 11, }, bold: true, numFmt: 0 } data["!cols"].push({ wpx: 180 }); // 單元格寬度 } } } function s2ab(s) { var buf = new ArrayBuffer(s.length) var view = new Uint8Array(buf) for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff return buf }
到此這篇關于Vue純前端實現(xiàn)導出Excel并修改樣式的文章就介紹到這了,更多相關Vue導出Excel內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue2?Observer實例dep和閉包中dep區(qū)別詳解
這篇文章主要為大家介紹了Vue2?Observer實例dep和閉包中dep區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10vue3+vite+移動端webview打包后頁面加載空白問題解決辦法
這篇文章主要給大家介紹了關于vue3+vite+移動端webview打包后頁面加載空白問題的解決辦法,文中通過代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-06-06報錯[vuex] unknown action type: userLogin問
這篇文章主要介紹了報錯[vuex] unknown action type: userLogin問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06vue使用echarts實現(xiàn)柱狀圖動態(tài)排序效果
echarts在前端開發(fā)中實屬必不可缺的大數(shù)據(jù)可視化工具,這篇文章主要為大家詳細介紹了vue如何使用echarts實現(xiàn)柱狀圖動態(tài)排序效果,感興趣的可以了解下2023-10-10