狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

小小導(dǎo)出,我大前端足矣!

admin
2024年3月30日 0:40 本文熱度 671

一、問(wèn)題剖析

那是一個(gè)傾盆大雨的早上,花瓣隨風(fēng)雨落在我的肩膀上,是五顏六色的花朵。

我輕輕撫摸著他,隨后撥開第一朵花瓣,她不愛(ài)我。

撥開第二朵,她愛(ài)我。

正當(dāng)我沉迷于甜蜜的幻想中,后端小白 🙋 喊道:這個(gè)導(dǎo)出你前端應(yīng)該就能做的吧!

🙋🏻‍♂️ 那是自然,有什么功能是我大前端做不了的,必須得讓你們大開眼界。

二、為什么導(dǎo)出要前端做?

前端導(dǎo)出的場(chǎng)景:

  1. 輕量級(jí)數(shù)據(jù):如果要導(dǎo)出的表格數(shù)據(jù)相對(duì)較小,可以直接在前端生成和導(dǎo)出,避免服務(wù)器端的處理和通信開銷。
  2. 數(shù)據(jù)已存在于前端:如果表格數(shù)據(jù)已經(jīng)以 JSON 或其他形式存在于前端,可以直接利用前端技術(shù)將其導(dǎo)出為 Excel、CSV 或其他格式。
  3. 實(shí)時(shí)生成/計(jì)算:如果導(dǎo)出的表格需要根據(jù)用戶輸入或動(dòng)態(tài)生成,可以使用前端技術(shù)基于用戶操作實(shí)時(shí)生成表格,并提供導(dǎo)出功能。
  4. 快速響應(yīng):前端導(dǎo)出表格可以提供更快的響應(yīng)速度,避免等待服務(wù)器端的處理和下載時(shí)間。

后端導(dǎo)出的場(chǎng)景:

  1. 大量數(shù)據(jù):如果要導(dǎo)出的表格數(shù)據(jù)量很大,超過(guò)了前端處理能力或網(wǎng)絡(luò)傳輸限制,那么在服務(wù)器端進(jìn)行導(dǎo)出會(huì)更高效。
  2. 安全性和數(shù)據(jù)保護(hù):敏感數(shù)據(jù)不適合在前端暴露,因此在服務(wù)器端進(jìn)行導(dǎo)出可以更好地控制和保護(hù)數(shù)據(jù)的安全。
  3. 復(fù)雜的業(yè)務(wù)邏輯:如果導(dǎo)出涉及復(fù)雜的業(yè)務(wù)邏輯、數(shù)據(jù)處理或數(shù)據(jù)查詢,使用服務(wù)器端的計(jì)算能力和數(shù)據(jù)庫(kù)訪問(wèn)更合適。
  4. 跨平臺(tái)支持:如果需要支持多個(gè)前端平臺(tái)(如 Web、移動(dòng)應(yīng)用等),將導(dǎo)出功能放在服務(wù)器端可以提供一致的導(dǎo)出體驗(yàn)。

三、講解一下在前端做的導(dǎo)出

xlsx、xlsx-style

如果是只做表格導(dǎo)出:www.npmjs.com/package/xls…[4]

如果導(dǎo)出要包含樣式:www.npmjs.com/package/xls…[5]

import XLSX from"xlsx";

exportData() {
 let tableName = '表格'

 if(!getVal(this.dataList, 'length')){
   this.$message.info("暫時(shí)數(shù)據(jù)");
   return
 }


 // 處理頭部
 let headers = {
   "B2": "字段-B2",
   "E2": "字段-E2",
 }
 const props = [ "B2", "E2" ]
 let tmp_dataListFilter = [
   {
     "B2": "字段-B2",
     "E2": "字段-E2",
   },
   {
     "E2": "2",
     "B2": "2",
   }
 ]

 tmp_dataListFilter.unshift(headers) // 將表頭放入數(shù)據(jù)源前面
 let wb =  XLSX.utils.book_new();
 let contentWs =  XLSX.utils.json_to_sheet(tmp_dataListFilter, {
   skipHeader: true,   // 是否忽略表頭,默認(rèn)為false
   origin: "A2"// 設(shè)置插入位置
 });
 // /單獨(dú)設(shè)置某個(gè)單元格內(nèi)容
 contentWs["A1"]={
   t:"s",
   v:tableName,
 };
 // /設(shè)置單元格合并!merges為一個(gè)對(duì)象數(shù)組,每個(gè)對(duì)象設(shè)定了單元格合并的規(guī)側(cè),
 // /{s:{r:0,c:},e:{r:0,c:2}為一個(gè)規(guī)則,s:起始位置,e:結(jié)束位置,r:行,c:列
 contentWs["!merges"]=[{ s:{r:0,c:0 },e:{r:0,c:props.length - 1 }}]

 // 設(shè)置單元格的寬度
 contentWs["!cols"] = []
 props.forEach(p => contentWs["!cols"].push({wch: 35}))
 XLSX.utils.book_append_sheet(wb,contentWs,tableName)    // 表格內(nèi)的下面的tab
 XLSX.writeFile(wb,tableName + ".xlsx"); // 導(dǎo)出文件名字
},

package.json

"xlsx": "^0.15.5",
"xlsx-style": "^0.8.13"

大概效果如下:

3.png

感覺(jué)前端導(dǎo)出也很容易。

哦哦,那你別高興太早。

四、需求升級(jí):?jiǎn)卧褚又泻图哟帧?/span>

xlsx

嘗試使用 xlsx-style 設(shè)樣式。

官方文檔:github.com/rockboom/Sh…[6]

文檔說(shuō)給單元格設(shè)置 s 為對(duì)象

4.png

let contentWs = XLSX.utils.json_to_sheet(tmp_dataListFilter, {
 skipHeader: true, // 是否忽略表頭,默認(rèn)為false
 origin: "A2", // 設(shè)置插入位置
});
// /單獨(dú)設(shè)置某個(gè)單元格內(nèi)容
contentWs["A1"] = {
 t: "s",
 v: tableName,
 s:{ // 這個(gè)是關(guān)鍵s
   font: { bold: true },
   alignment: { horizontal: 'center' }
 }
};

發(fā)現(xiàn)設(shè)置無(wú)效。

有人說(shuō)要改 xlsx、xlsx-style 源碼:

大概的意思是:修改 xlsx.extendscript.js、xlsx.full.min.js 更改文件變量。

發(fā)現(xiàn)仍然無(wú)效。

使用 binary 方式保存

  1. 首先保存的時(shí)候 type 要改成 binary 方式
  2. 保存的時(shí)候需要使用 xlsx-style 模塊
var writingOpt = {
 bookType: 'xlsx',
 bookSST: true,
 type: 'binary'// <--- 1.改這里
}


/*
2.  type:'array'改為'binary' 后因?yàn)橄旅娲a會(huì)報(bào)錯(cuò), 打不開excel
new Blob([wbout], { type: 'application/octet-stream' }
要文本轉(zhuǎn)換成數(shù)組緩存后再生成二進(jìn)制對(duì)象
*/


// 添加String To ArrayBuffer
function s2ab(s) {
 var buf = newArrayBuffer(s.length);
 var view = newUint8Array(buf);
 for (var i = 0; i < s.length; i++) {
   view[i] = s.charCodeAt(i) & 0xFF;
 }
 return buf;
}

let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })

FileSaver.saveAs(blob, exportName)

可以下載了。但依然樣式?jīng)]起作用。

使用 xlsx-style 模塊生成文件

首先安裝模塊

npm install xlsx-style

在項(xiàng)目里安裝報(bào)好多錯(cuò)誤直接強(qiáng)制安裝,不檢查依賴。

npm install xlsx-style -force

安裝完成后 找不到 cptable 模塊會(huì)報(bào)錯(cuò)
報(bào)錯(cuò)內(nèi)容如下:

./node_modules/xlsx-style/dist/cpexcel.js Module not found: Error: Can't resolve './cptable' in

這個(gè)問(wèn)題在 vue.config.js 里配置一下就可以解決。
其他框架自己找找方法,反正只要不讓他報(bào)錯(cuò)能啟動(dòng)就行。

module.exports = {
//  ...其他配置省略
 configureWebpack: {
//  ...其他配置省略
   externals:{
     './cptable':'var cptable'
   },
 },

安裝完 xlsx-style 后改代碼

import XLSX2 from"xlsx-style";    // 1. 引入模塊

// 2. 使用`xlsx-style` 生成。 XLSX.write => XLSX2.write
var wbout = XLSX2.write(wb, writingOpt)

仍然無(wú)效。

總結(jié) xlsx

大概的意思是說(shuō):默認(rèn)不支持改變樣式,想要支持改變樣式,需要使用它的收費(fèi)版本。

本著勤儉節(jié)約的原則,很多人使用了另一個(gè)第三方庫(kù):xlsx-style[4] ,但是使用起來(lái)極其復(fù)雜,還需要改 node_modules 源碼,這個(gè)庫(kù)最后更新時(shí)間也定格在了 6 年前。還有一些其他的第三方樣式拓展庫(kù),質(zhì)量參差不齊。

使用成本和后期的維護(hù)成本很高,不得不放棄。

ExcelJS

ExcelJS 終于可以了

ExcelJS[5] 周下載量 450k,github star 9k,并且擁有中文文檔,對(duì)國(guó)內(nèi)開發(fā)者很友好。雖然文檔是以 README 的形式,可讀性不太好,但重在內(nèi)容,常用的功能基本都有覆蓋。

最近更新時(shí)間是 6 個(gè)月內(nèi),試用了一下,集成很簡(jiǎn)單,再加之文檔豐富,就選它了。

npm install exceljs
npm install file-saver // 下載到本地還需要另一個(gè)庫(kù):file-saver

基本操作

//導(dǎo)入ExcelJS
import ExcelJS from"exceljs";

//下載文件
download_file(buffer, fileName) {
console.log("導(dǎo)出");
let fileURL = window.URL.createObjectURL(new Blob([buffer]));
let fileLink = document.createElement("a");
fileLink.href = fileURL;
fileLink.setAttribute("download", fileName);
document.body.appendChild(fileLink);
fileLink.click();
}

導(dǎo)出 xlsx 表格的代碼

//下面是導(dǎo)出的函數(shù)
asyncexport() {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet("Sheet1");
//這里是數(shù)據(jù)列表
const data = [
{ id: 1, name: "艾倫", age: 20, sex: "男", achievement: 90 },
{ id: 2, name: "柏然", age: 25, sex: "男", achievement: 86 },
];
// 設(shè)置列,這里的width就是列寬
worksheet.columns = [
{ header: "序號(hào)", key: "id", width: 10},
       { header: "姓名", key: "name", width: 10 },
];

// 批量插入數(shù)據(jù)
data.forEach(item => worksheet.addRow(item));

// 寫入文件
const buffer = await workbook.xlsx.writeBuffer();
//下載文件
this.download_file(buffer, "填報(bào)匯總.xlsx");
}

設(shè)置行高和列寬

列寬上面已經(jīng)有了,這里說(shuō)明一下行高怎么設(shè)置
worksheet.getRow(2).height = 30;

合并單元格

worksheet.mergeCells("B1:C1");

自定義表格樣式

//設(shè)置樣式表格樣式,font里面設(shè)置字體大小,顏色(這里是argb要注意),加粗
//alignment 設(shè)置單元格的水平和垂直居中
const B1 = worksheet.getCell('B1')
B1.font = { size: 20, color:{ argb: 'FF8B008B' }, bold: true }
B1.alignment = { horizontal: 'center', vertical: 'middle' }

ExcelJS 實(shí)戰(zhàn)

import ExcelJS from"exceljs";

//下載文件
download_file(buffer, fileName) {
   console.log("導(dǎo)出");
   let fileURL = window.URL.createObjectURL(new Blob([buffer]));
   let fileLink = document.createElement("a");
   fileLink.href = fileURL;
   fileLink.setAttribute("download", fileName);
   document.body.appendChild(fileLink);
   fileLink.click();
},
async exportClick() {
   const loading = this.$loading({
     lock: true,
     text: "數(shù)據(jù)導(dǎo)出中,請(qǐng)耐心等待!",
     spinner: "el-icon-loading",
     background: "rgba(0, 0, 0, 0.7)",
   });

 this.tableData = [
   { a: 1, b:2 }
 ]
 const enterpriseVisitsColumns = [
   {
       prop: "a",
       label: "銀行",
     },
     {
       prop: "b",
       label: "企業(yè)數(shù)",
     }
 ]

   // 表格數(shù)據(jù):this.tableData
   if (!(this.tableData && this.tableData.length)) {
     this.$message.info("暫無(wú)數(shù)據(jù)");
     loading.close();
     return;
   }

   let tableName = this.tableName; // 表格名
   const workbook = new ExcelJS.Workbook();
   const worksheet = workbook.addWorksheet(tableName);
   const props = enterpriseVisitsColumns();
   //這里是數(shù)據(jù)列表
   const data = this.tableData;
   // 設(shè)置列,這里的width就是列寬
   let arr = [];
   props.forEach((p) => {
   arr.push({
       header: p.label,
       key: p.prop,
       width: 25,
   });
   });
   worksheet.columns = arr;

   // 插入一行到指定位置,現(xiàn)在我往表格最前面加一行,值為表名
   const rowIndex = 1; // 要插入的行位置
   const newRow = worksheet.insertRow(rowIndex);
   // 設(shè)置新行的單元格值
   newRow.getCell(1).value = tableName; // 值為表名

   // 批量插入數(shù)據(jù),上面插一條,這里就是從第二行開始加
   data.forEach((item) => worksheet.addRow(item));

   //設(shè)置樣式表格樣式,font里面設(shè)置字體大小,顏色(這里是argb要注意),加粗
   //alignment 設(shè)置單元格的水平和垂直居中
   // const B1 = worksheet.getCell("B1");
   // B1.font = { size: 20, color: { argb: "FF8B008B" }, bold: true };
   // B1.alignment = { horizontal: "center", vertical: "middle" };

   // 合并單元格,就是把A1開始到J1的單元格合并
   worksheet.mergeCells("A1:J1");

   // 批量設(shè)置所有表格數(shù)據(jù)的樣式
   worksheet.eachRow((row, rowNumber) => {
   let size = rowNumber == 1 ? 16 : rowNumber == 2 ? 12 : "";
   //設(shè)置表頭樣式
   row.eachCell((cell) => {
       cell.font = {
       size,
       // color:{ argb: 'FF8B008B' },
       bold: true,
       };
       cell.alignment = { horizontal: "center", vertical: "middle" };
   });

   //設(shè)置所有行高
   row.height = 30;
   });

   // 寫入文件
   const buffer = await workbook.xlsx.writeBuffer();
   //下載文件
   this.download_file(buffer, tableName + ".xlsx");

   loading.close();
},

后記

導(dǎo)出功能并不是說(shuō)都是前端或者后端實(shí)現(xiàn),要具體情況,具體分析,我相信哪方都可以做,但誰(shuí)適合做,這個(gè)才是我們需要去思考的。

就如同我們項(xiàng)目中,該例子后面也是前端實(shí)現(xiàn)的,大數(shù)據(jù)分頁(yè)當(dāng)然還是得后端同學(xué)來(lái)實(shí)現(xiàn)較好。


該文章在 2024/3/30 0:40:03 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved