vue純前端使用exceljs導出excel文件方式
概述
本文是使用excel.js 插件結合 vue,實現(xiàn)的純前端excel文件導出!下面是實現(xiàn)后的實例!

大致分為以下幾步:
一:excel.js 插件的安裝及引用
使用 npm 或者根據具體項目使用的 包管理工具下載:
npm i exceljs
在具體使用頁面中直接 import 動態(tài)引入,或者使用require方法:
import Exceljs form 'exceljs'
// 或者
exportExcel() {
const Exceljs = require('exceljs'); // 引入exceljs
}二:創(chuàng)建excel工作簿
exportExcel() {
const Exceljs = require('exceljs'); // 引入exceljs
const workbook = new Exceljs.Workbook();// 創(chuàng)建工作簿
}根據官網方法使用配置,這里采用的 saveAs 方法,這個插件直接搜索下載就行,這里就不做介紹了!
exportExcel() {
const Exceljs = require('exceljs'); // 引入exceljs
const workbook = new Exceljs.Workbook(); // 創(chuàng)建工作簿
// 下載工作簿
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), '測試導出.xlsx');});
}如果下載成功,說明組件引入都沒有問題,進行下一步操作
三:創(chuàng)建excel工作表(sheet欄)
excel是可以有多個sheet欄的,創(chuàng)建好工作簿后,下一步一定是創(chuàng)建一個工作表,也就是sheet,調用 workbook.addWorksheet(‘sheet欄的名字’) ,必須用變量接收一下,因為后續(xù)要對它進行操作!
exportExcel() {
const Exceljs = require('exceljs'); // 引入exceljs
const workbook = new Exceljs.Workbook(); // 創(chuàng)建工作簿
const workSheet = workbook.addWorksheet('總報價');// 創(chuàng)建工作表(sheet1)
}四:為excel工作表定義每列的數據
exceljs支持快速定義表頭,每列的數據字段,傳入表頭配置數組,對應的列,就會自動賦值,與 el-table 的理念差不多,前端理解后,使用非常方便。
workSheet.columns = this.exportTableProp; // 工作表添加表頭
exportTableProp的格式為:header是表頭列名,key是每列的數據源,width是列寬。
const exportTableProp = [
{
header: '姓名',
key: 'name',
width: 14
},
{
header: '年齡',
key: 'age',
width: 14
},
{
header: '性別',
key: 'sex',
width: 14
},
{
header: '生日',
key: 'birth',
width: 14
}
]表頭定義好后,之后就要灌輸數據啦:
// exportDataList:鍵值跟上方定義的列 key 一樣。
// { name: '姓名', age: '年齡', sex: '性別', birth: '生日' }
workSheet.addRows(this.exportDataList); // 往工作表插入數據
// 最后代碼集合
exportExcel() {
const Exceljs = require('exceljs'); // 引入exceljs
const workbook = new Exceljs.Workbook(); // 創(chuàng)建工作簿
const workSheet = workbook.addWorksheet('sheet1');// 創(chuàng)建工作表(sheet1)
workSheet.columns = this.exportTableProp; // 工作表添加表頭
workSheet.addRows(this.exportDataList);// 往工作表插入數據
// 下載工作簿
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), '測試導出.xlsx');});
}五:excel設置樣式(合并單元格等)
exceljs提供了一系列方法,正確調用即可畫出任何樣式的excel。
合并單元格:
workSheet.mergeCells('A1:M1') // 將A1到M1的單元格合并
獲取單元格:(設置樣式的前提)
const cell = workSheet.getCell('A1') // 獲取A1單元格
設置A1單元格顯示的內容:
cell.value = '我是A1各自的數據'設置A1單元格的樣式:font設置文字樣式,alignment設置格子內文本如何顯示,fill 設置單元格背景色。
cell.font = { size: 16, bold: true, name: '仿宋' }; // 設置字體大小為16,加粗,仿宋
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'A9D08E' } // 設置背景色
};六:excel的行級操作
獲取第一行: workSheet.getRow(1) 調整第一行的行高: workSheet.getRow(1).height = 70 手動添加一行: workSheet.addRow(); // 不傳參:在最下方加一行 workSheet.addRow(2); // 傳數字:在指定列加一行 workSheet.addRow(['姓名','年齡','性別']) // 傳數組:加一行,且設置行內數據
七:遍歷所有行
調用workSheet.eachRow 可以遍歷所有行,比如快捷設置全部行高。
workSheet.eachRow((row, rowIndex) => {
// 循環(huán)每一行
console.log(row)
row.height = 17;
})八:遍歷所有單元格
嵌套操作,可以遍歷到全部單元格,代碼演示:
workSheet.eachRow((row, rowIndex) => {
// 循環(huán)每個單元格
row.eachCell((cell, colIndex) => {
cell.font = { size: 11, bold: true };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
});
})當然,加一些判斷:
workSheet.eachRow((row, rowIndex) => {
if (rowIndex === 14) {
row.eachCell((cell, colIndex) => {
cell.font = { size: 11, bold: true };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
});
}
if (rowIndex > 14 && rowIndex <= 25) {
row.height = 17;
row.eachCell((cell, colIndex) => {
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
});
}
})來個實用案例: 為所有單元格設置邊框:
// 定義邊框樣式
const borderStyle = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
}
// 遍歷工作表中的所有單元格并添加邊框
workSheet.eachRow((row, rowIndex) => {
row.eachCell((cell, colIndex) => {
cell.border = borderStyle;
});
})九:向excel中插入圖片
如果是base64編碼圖片,直接插入就可以,如果不是,需要轉為base64。
// 將logo放入第一行
const base64 = await this.imageToBase64(); // 這里是轉base64方法,不放了
// 把base64編碼的圖片插入excel工作簿里面
const imageId = workbook.addImage({
base64: base64,
extension: 'png'
})
// 當前工作表(當前excel頁)加入圖片,tl.col:excel第幾列,tl.row:excel第幾行,ext里面表示圖片寬高
workSheet.addImage(imageId, {
tl: { col: 0.1, row: 0.1 },
// br: { col: columns.length + ai - 11.1, row: ri + 2 }
ext: { width: 100, height: 85 }
})十:插入超鏈接
超鏈接一定是單元格級別的,先獲取到單元格,然后設置value即可。
cell.value = {
text: '要顯示的文字',
hyperlink: 'www.baidu.com',
tooltip: 'hover的提示'
};最后,附主圖的完整代碼。
async exportExcel(row) {
const loading = this.$loading({
lock: true,
text: '導出excel中...(若長時間無響應請刷新頁面)',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
// 查商務報價版本
let para = {
CommercialQuotationVersionId: row.commercialQuotationVersionId
};
let res = await GetCommercialQuotationVersion(para);
if (res.success) {
let totalQuotationData = res.response;
const Exceljs = require('exceljs');
// 創(chuàng)建工作簿
const workbook = new Exceljs.Workbook();
// 創(chuàng)建工作表(sheet1)
const workSheet = workbook.addWorksheet('總報價');
// 表格的表頭配置
workSheet.columns = this.exportTableProp; // 工作表添加表頭
//======================================= 第一行 =================================
// 合并A1到L1的單元格 (大標題)
workSheet.mergeCells('A1:M1');
const cell = workSheet.getCell('A1');
cell.value = 'Mechanical CO., LTD. - Quotation \n - 報價單';
// 設置第一行的單元格樣式
cell.font = { size: 16, bold: true, name: '仿宋' }; // 設置字體大小為16,加粗,仿宋
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
// 調整第一行的高度
workSheet.getRow(1).height = 70;
// ==================================== 第二 到 第十二行 ================= 樣式差不多,一起搞
for (let ri = 2; ri < 14; ri++) {
// 創(chuàng)建第ri行
workSheet.addRow(ri);
// 合并單元格
workSheet.mergeCells(`A${ri}:C${ri}`);
workSheet.mergeCells(`D${ri}:F${ri}`);
workSheet.mergeCells(`G${ri}:I${ri}`);
workSheet.mergeCells(`J${ri}:M${ri}`);
// A列的標題數據
let headerCellA = workSheet.getCell(`A${ri}`);
headerCellA.value = this.excelHeader[(ri - 2) * 2].label;
headerCellA.alignment = {
vertical: 'middle' // 垂直居中
};
if (ri <= 10) {
headerCellA.font = { size: 11, name: '仿宋' };
} else {
headerCellA.font = { size: 11, name: '仿宋', bold: true, color: { argb: 'FF0000' } };
}
// D列
let headerCellD = workSheet.getCell(`D${ri}`);
if (ri > 10) {
headerCellD.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFD966' } // 設置背景色
};
}
headerCellD.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
// G列
let headerCellG = workSheet.getCell(`G${ri}`);
headerCellG.value = this.excelHeader[(ri - 1) * 2 - 1].label;
headerCellG.alignment = {
vertical: 'middle' // 垂直居中
};
if (ri <= 10) {
headerCellG.font = { size: 11, name: '仿宋' };
} else {
headerCellG.font = { size: 11, name: '仿宋', bold: true, color: { argb: 'FF0000' } };
}
// J列
let headerCellJ = workSheet.getCell(`J${ri}`);
if (ri > 10 && ri !== 13) {
headerCellJ.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFD966' } // 設置背景色
};
}
headerCellJ.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
workSheet.getRow(ri).height = 15;
// 獲取第ri行的單元格
// const cell = workSheet.getCell(`A${ri}`);
// 設置單元格樣式
}
// 插入表頭一堆數據 row 是主表數據 totalQuotationData 是子表數據
workSheet.getCell('D2').value = row.inquiryName; // 項目名稱
workSheet.getCell('D3').value = row.commercialQuotationNumber; // 報價單號
workSheet.getCell('J3').value = row.creationTime; // 報價日期
workSheet.getCell('D4').value = row.customer; // 客戶名稱
workSheet.getCell('D11').value = ''; // 交費周期
let string = '';
this.PaymentMethod.forEach((item) => {
if (item.key === totalQuotationData.paymentMethod) {
string = item.value;
}
});
workSheet.getCell('J11').value = string; // 付款方式
workSheet.getCell('D12').value = totalQuotationData.customerRequirementVersion; // 技術要求版本號
workSheet.getCell('J12').value = totalQuotationData.versionNumber; // 報價版本號
workSheet.getCell('D13').value = totalQuotationData.solutionVersion; // 方案版本號
// ================================ 數據部分行 =============================================================
workSheet.addRow(
this.exportTableProp.map((item) => {
return item.header;
})
);
// 添加數據,表頭信息已經在最上面定好了(這里是從接口取回來的數據)
totalQuotationData.commercialQuotationVersionWorkstationList.forEach((item, index) => {
for (let key in item) {
if (item[key] === null) item[key] = '';
}
item.index = index + 1;
});
let tableData = totalQuotationData.commercialQuotationVersionWorkstationList;
workSheet.addRows(tableData);
// 設置第14行到數據結束 行的所有單元格的樣式
workSheet.eachRow((row, rowIndex) => {
// 循環(huán)每一行
if (rowIndex === 14) {
row.eachCell((cell, colIndex) => {
cell.font = { size: 11, bold: true };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
});
}
if (rowIndex > 14 && rowIndex <= 14 + tableData.length) {
row.height = 17;
row.eachCell((cell, colIndex) => {
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
});
}
});
// =======================================最下方合計部分 ============================================
// ======================================= 成本小計行 ==========================================
let rowNUM = 15 + tableData.length; // 從第幾行開始
workSheet.addRow();
workSheet.mergeCells(`A${rowNUM}:C${rowNUM}`);
workSheet.getCell(`A${rowNUM}`).value = '成本小計';
// 下面是 成本小計行的數據
workSheet.getCell(`D${rowNUM}`).value = totalQuotationData.mechanicalMaterialsAndProcessingCosts_TotalCost || '';
workSheet.getCell(`E${rowNUM}`).value = totalQuotationData.mechanicalPurchaseCost_TotalCost || '';
workSheet.getCell(`F${rowNUM}`).value = totalQuotationData.electricalpurchaseCost_TotalCost || '';
workSheet.getCell(`G${rowNUM}`).value = totalQuotationData.industrialControlCost_TotalCost || '';
workSheet.getCell(`H${rowNUM}`).value = totalQuotationData.totalHardwareCost_TotalCost || '';
workSheet.getCell(`I${rowNUM}`).value = totalQuotationData.laborCost_TotalCost || '';
workSheet.getCell(`J${rowNUM}`).value = totalQuotationData.travelAndAccommodationCost_TotalCost || '';
workSheet.getCell(`K${rowNUM}`).value = totalQuotationData.transportationAndOtherMaterialCosts_TotalCost || '';
workSheet.getCell(`L${rowNUM}`).value = totalQuotationData.totalCost || '';
workSheet.getCell(`M${rowNUM}`).value = totalQuotationData.costSubtotal_Remarks || '';
// 設置成本小計樣式
workSheet.eachRow((row, rowIndex) => {
if (rowIndex === rowNUM) {
row.eachCell((cell, colIndex) => {
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
// 除備注列外,其他列設置顏色
if (cell._address.indexOf('M') < 0) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'F8CBAD' } // 設置背景色
};
}
});
row.height = 17;
}
});
// =================================================== 其他合計行 ===================================================
let otherSunRow = [
{
name: '成本合計(未稅)/ 元',
prop: 'totalCost',
remark: 'totalCost_Remarks'
},
{
name: '管理費 / 元:',
prop: 'managementFee_TotalCost',
remark: 'managementFee_Remarks'
},
{
name: '財務費 / 元:',
prop: 'financialFee_TotalCost',
remark: 'financialFee_Remarks'
},
{
name: '利潤 / 元:',
prop: 'profit_TotalCost',
remark: 'profit_Remarks'
},
{
name: '價格合計(未稅)/ 元:',
prop: 'totalPriceExcludingTax_TotalCost',
remark: 'totalPriceExcludingTax_Remarks'
},
{
name: '增值稅 / 元:',
prop: 'valueAddedTax_TotalCost',
remark: 'valueAddedTax_Remarks'
},
{
name: '價格合計(含稅)/ 元:',
prop: 'totalPriceIncludingTax_TotalCost',
remark: 'totalPriceIncludingTax_Remarks'
},
{
name: '優(yōu)惠后價格(含稅)/ 元:',
prop: 'discountedPrice',
remark: 'discountedPrice_Remarks'
},
{
name: '針對此次報價的其他說明',
prop: 'remarks',
remark: 'remarks'
}
];
// 如果沒有優(yōu)惠后價格就不顯示
let havePrice = true;
if (totalQuotationData.discountedPrice === null || totalQuotationData.discountedPrice === '' || totalQuotationData.discountedPrice === undefined) {
havePrice = false;
otherSunRow = otherSunRow.filter((item) => {
return item.prop !== 'discountedPrice';
});
}
// 插入數據
let otherNum = rowNUM + 1;
for (let oi = 0; oi < otherSunRow.length; oi++) {
workSheet.addRow();
workSheet.mergeCells(`A${oi + otherNum}:C${oi + otherNum}`);
workSheet.getCell(`A${oi + otherNum}`).value = otherSunRow[oi].name || '';
if (oi === otherSunRow.length - 1) {
workSheet.mergeCells(`D${oi + otherNum}:M${oi + otherNum}`);
} else {
workSheet.mergeCells(`D${oi + otherNum}:L${oi + otherNum}`);
}
workSheet.getCell(`D${oi + otherNum}`).value = totalQuotationData[otherSunRow[oi].prop] || '';
workSheet.getCell(`M${oi + otherNum}`).value = totalQuotationData[otherSunRow[oi].remark] || '';
}
// 設置其他合計樣式
workSheet.eachRow((row, rowIndex) => {
if (rowIndex > rowNUM && rowIndex < rowNUM + otherSunRow.length + 1) {
if (rowIndex === rowNUM + 6) {
row.height = 17;
// 增值稅
row.eachCell((cell, colIndex) => {
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
// 除備注列外,其他列設置顏色
if (cell._address.indexOf('M') < 0) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: '9BC2E6' } // 設置背景色
};
}
});
} else if (rowIndex === rowNUM + 7 || (havePrice ? rowIndex === rowNUM + 8 : false)) {
row.height = 17;
// 價稅合計 、優(yōu)惠后價格
row.eachCell((cell, colIndex) => {
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('M') < 0) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFD966' } // 設置背景色
};
}
});
} else if (havePrice ? rowIndex === rowNUM + 9 : rowIndex === rowNUM + 8) {
row.height = 17;
// 最后的其他說明
row.eachCell((cell, colIndex) => {
cell.font = { size: 11, bold: true };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'A9D08E' } // 設置背景色
};
});
} else {
row.height = 17;
row.eachCell((cell, colIndex) => {
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('M') < 0) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'F8CBAD' } // 設置背景色
};
}
});
}
}
});
// 將logo放入第一行 放到最后就行啦
// 獲取圖片的 Blob 數據
const base64 = await this.imageToBase64();
// 把base64編碼的圖片插入excel工作簿里面
const imageId = workbook.addImage({
base64: base64,
extension: 'png'
});
// 當前工作表(當前excel頁)加入圖片,tl.col:excel第幾列,tl.row:excel第幾行,ext里面表示圖片寬高
workSheet.addImage(imageId, {
tl: { col: 0.1, row: 0.1 },
// br: { col: columns.length + ai - 11.1, row: ri + 2 }
ext: { width: 100, height: 85 }
});
// 調整所有列的寬度
workSheet.columns.forEach((column) => {
column.width = 17; // 將寬度設為20個字符
});
// 定義邊框樣式
const borderStyle = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
// 遍歷工作表中的所有單元格并添加邊框
workSheet.eachRow((row, rowIndex) => {
row.eachCell((cell, colIndex) => {
cell.border = borderStyle;
});
});
// =================================== 工位 Sheet =======================================
var that = this;
async function getData() {
let details = totalQuotationData.commercialQuotationVersionWorkstationList; // 這是所有工位
for (let i = 0; i < details.length; i++) {
let spara = {
CommercialQuotationVersionWorkstationId: details[i].commercialQuotationVersionWorkstationId
};
let sres = await GetCommercialQuotationVersionWorkstation(spara);
console.log('工位', sres);
let tableData = sres.response;
// 創(chuàng)建工位的工作表
let sworkSheet = workbook.addWorksheet(details[i].inquiryStationCode);
//======================================= 第一行 =================================
// 合并A1到L1的單元格 (大標題)
sworkSheet.mergeCells('A1:L1');
const cell = sworkSheet.getCell('A1');
cell.value = 'ChangChun HeXin Mechanical Manufacturing CO., LTD. - Quotation \n 長春合心機械制造有限公司 - 報價單';
// 設置第一行的單元格樣式
cell.font = { size: 16, bold: true, name: '仿宋' }; // 設置字體大小為16,加粗,仿宋
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
// 調整第一行的高度
sworkSheet.getRow(1).height = 70;
// ==================================== 第二 到 第十二行 ================= 樣式差不多,一起搞
for (let ri = 2; ri < 14; ri++) {
// 創(chuàng)建第ri行
sworkSheet.addRow(ri);
// 合并單元格
sworkSheet.mergeCells(`A${ri}:C${ri}`);
sworkSheet.mergeCells(`D${ri}:F${ri}`);
sworkSheet.mergeCells(`G${ri}:I${ri}`);
sworkSheet.mergeCells(`J${ri}:L${ri}`);
// A列的標題數據
let headerCellA = sworkSheet.getCell(`A${ri}`);
headerCellA.value = that.excelHeader[(ri - 2) * 2].label;
headerCellA.alignment = {
vertical: 'middle' // 垂直居中
};
if (ri <= 10) {
headerCellA.font = { size: 11, name: '仿宋' };
} else {
headerCellA.font = { size: 11, name: '仿宋', bold: true, color: { argb: 'FF0000' } };
}
// D列
let headerCellD = sworkSheet.getCell(`D${ri}`);
if (ri > 10) {
headerCellD.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFD966' } // 設置背景色
};
}
headerCellD.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
// G列
let headerCellG = sworkSheet.getCell(`G${ri}`);
headerCellG.value = that.excelHeader[(ri - 1) * 2 - 1].label;
headerCellG.alignment = {
vertical: 'middle' // 垂直居中
};
if (ri <= 10) {
headerCellG.font = { size: 11, name: '仿宋' };
} else {
headerCellG.font = { size: 11, name: '仿宋', bold: true, color: { argb: 'FF0000' } };
}
// J列
let headerCellJ = sworkSheet.getCell(`J${ri}`);
if (ri > 10 && ri !== 13) {
headerCellJ.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFD966' } // 設置背景色
};
}
headerCellJ.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
sworkSheet.getRow(ri).height = 15;
// 獲取第ri行的單元格
// const cell = sworkSheet.getCell(`A${ri}`);
// 設置單元格樣式
}
// 插入表頭一堆數據 row 是主表數據 totalQuotationData 是子表數據
sworkSheet.getCell('D2').value = row.inquiryName; // 項目名稱
sworkSheet.getCell('D3').value = row.commercialQuotationNumber; // 報價單號
sworkSheet.getCell('J3').value = row.creationTime; // 報價日期
sworkSheet.getCell('D4').value = row.customer; // 客戶名稱
sworkSheet.getCell('D11').value = ''; // 交費周期
let string = '';
that.PaymentMethod.forEach((item) => {
if (item.key === totalQuotationData.paymentMethod) {
string = item.value;
}
});
sworkSheet.getCell('J11').value = string; // 付款方式
sworkSheet.getCell('D12').value = totalQuotationData.customerRequirementVersion; // 技術要求版本號
sworkSheet.getCell('J12').value = totalQuotationData.versionNumber; // 報價版本號
sworkSheet.getCell('D13').value = totalQuotationData.solutionVersion; // 方案版本號
// ==================================== 工位的數據部分 =================================================
// 標題行 ['No.','Item 項目','小時數','費率','Price 價格','備注:']
sworkSheet.addRow();
sworkSheet.getCell('A14').value = 'No.';
sworkSheet.mergeCells(`B14:C14`);
sworkSheet.getCell('B14').value = 'Item 項目';
sworkSheet.getCell('D14').value = '小時數';
sworkSheet.getCell('E14').value = '費率';
sworkSheet.getCell('F14').value = 'Price 價格';
sworkSheet.getCell('G14').value = '備注:';
sworkSheet.mergeCells(`G14:L14`);
// 機械材料成本
sworkSheet.addRow();
sworkSheet.getCell('A15').value = 1; // 序號
sworkSheet.mergeCells(`B15:C15`);
sworkSheet.getCell('B15').value = '機械材料成本';
sworkSheet.getCell('D15').value = '/'; // 小時數
sworkSheet.getCell('E15').value = '/'; // 費率
sworkSheet.getCell('F15').value = ''; // 價格
sworkSheet.getCell('G15').value = ''; // 備注
sworkSheet.mergeCells(`G15:L15`);
// 機械加工成本
sworkSheet.addRow();
sworkSheet.getCell('A16').value = 2;
sworkSheet.mergeCells(`B16:C16`);
sworkSheet.getCell('B16').value = '機械加工成本';
sworkSheet.getCell('D16').value = '/'; // 小時數
sworkSheet.getCell('E16').value = '/'; // 費率
sworkSheet.getCell('F16').value = tableData.mechanicalMaterialsAndProcessingCosts_AfterMarkup || ''; // 價格
sworkSheet.getCell('G16').value = tableData.mechanicalMaterialsAndProcessingCosts_Remarks || ''; // 備注
sworkSheet.mergeCells(`G16:L16`);
// 機械采購成本
sworkSheet.addRow();
sworkSheet.getCell('A17').value = 3;
sworkSheet.mergeCells(`B17:C17`);
sworkSheet.getCell('B17').value = '機械采購成本';
sworkSheet.getCell('D17').value = '/'; // 小時數
sworkSheet.getCell('E17').value = '/'; // 費率
sworkSheet.getCell('F17').value = tableData.mechanicalPurchaseCost_AfterMarkup || ''; // 價格
sworkSheet.getCell('G17').value = tableData.mechanicalPurchaseCost_Remarks || ''; // 備注
sworkSheet.mergeCells(`G17:L17`);
// 型材及配件
sworkSheet.addRow();
sworkSheet.getCell('A18').value = 4;
sworkSheet.mergeCells(`B18:C18`);
sworkSheet.getCell('B18').value = '型材及配件';
sworkSheet.getCell('D18').value = '/'; // 小時數
sworkSheet.getCell('E18').value = '/'; // 費率
sworkSheet.getCell('F18').value = ''; // 價格
sworkSheet.getCell('G18').value = ''; // 備注
sworkSheet.mergeCells(`G18:L18`);
// 電氣采購成本
sworkSheet.addRow();
sworkSheet.getCell('A19').value = 5;
sworkSheet.mergeCells(`B19:C19`);
sworkSheet.getCell('B19').value = '電氣采購成本';
sworkSheet.getCell('D19').value = '/'; // 小時數
sworkSheet.getCell('E19').value = '/'; // 費率
sworkSheet.getCell('F19').value = tableData.electricalpurchaseCost_AfterMarkup || ''; // 價格
sworkSheet.getCell('G19').value = tableData.electricalpurchaseCost_Remarks || ''; // 備注
sworkSheet.mergeCells(`G19:L19`);
// 機械設計費
sworkSheet.addRow();
sworkSheet.getCell('A20').value = 6;
sworkSheet.mergeCells(`B20:C20`);
sworkSheet.getCell('B20').value = '機械設計費';
sworkSheet.getCell('D20').value = tableData.mechanicalDesignFee_Hours || ''; // 小時數
sworkSheet.getCell('E20').value = tableData.mechanicalDesignFee_PerHourRate || ''; // 費率
sworkSheet.getCell('F20').value = tableData.mechanicalDesignFee_TotalCost || ''; // 價格
sworkSheet.getCell('G20').value = tableData.mechanicalDesignFee_Remarks || ''; // 備注
sworkSheet.mergeCells(`G20:L20`);
// 電氣設計費
sworkSheet.addRow();
sworkSheet.getCell('A21').value = 7;
sworkSheet.mergeCells(`B21:C21`);
sworkSheet.getCell('B21').value = '電氣設計費';
sworkSheet.getCell('D21').value = tableData.electricalDesignFee_Hours || ''; // 小時數
sworkSheet.getCell('E21').value = tableData.electricalDesignFee_PerHourRate || ''; // 費率
sworkSheet.getCell('F21').value = tableData.electricalDesignFee_TotalCost || ''; // 價格
sworkSheet.getCell('G21').value = tableData.electricalDesignFee_Remarks || ''; // 備注
sworkSheet.mergeCells(`G21:L21`);
// 軟件編程及開發(fā)
sworkSheet.addRow();
sworkSheet.getCell('A22').value = 8;
sworkSheet.mergeCells(`B22:C22`);
sworkSheet.getCell('B22').value = '軟件編程及開發(fā)';
sworkSheet.getCell('D22').value = tableData.softwareProgramming_Hours || ''; // 小時數
sworkSheet.getCell('E22').value = tableData.softwareProgramming_PerHourRate || ''; // 費率
sworkSheet.getCell('F22').value = tableData.softwareProgramming_TotalCost || ''; // 價格
sworkSheet.getCell('G22').value = tableData.softwareProgramming_Remarks || ''; // 備注
sworkSheet.mergeCells(`G22:L22`);
// 機器人調試
sworkSheet.addRow();
sworkSheet.getCell('A23').value = 9;
sworkSheet.mergeCells(`B23:C23`);
sworkSheet.getCell('B23').value = '機器人調試';
sworkSheet.getCell('D23').value = tableData.robotDebugging_Hours || ''; // 小時數
sworkSheet.getCell('E23').value = tableData.robotDebugging_PerHourRate || ''; // 費率
sworkSheet.getCell('F23').value = tableData.robotDebugging_TotalCost || ''; // 價格
sworkSheet.getCell('G23').value = tableData.robotDebugging_Remarks || ''; // 備注
sworkSheet.mergeCells(`G23:L23`);
// 項目經理費用
sworkSheet.addRow();
sworkSheet.getCell('A24').value = 10;
sworkSheet.mergeCells(`B24:C24`);
sworkSheet.getCell('B24').value = '項目經理費用';
sworkSheet.getCell('D24').value = tableData.projectManagerFee_Hours || ''; // 小時數
sworkSheet.getCell('E24').value = tableData.projectManagerFee_PerHourRate || ''; // 費率
sworkSheet.getCell('F24').value = tableData.projectManagerFee_TotalCost || ''; // 價格
sworkSheet.getCell('G24').value = tableData.projectManagerFee_Remarks || ''; // 備注
sworkSheet.mergeCells(`G24:L24`);
// 機械安裝調試費用
sworkSheet.addRow();
sworkSheet.getCell('A25').value = 11;
sworkSheet.mergeCells(`B25:C25`);
sworkSheet.getCell('B25').value = '機械安裝調試費用';
sworkSheet.getCell('D25').value = tableData.mechanicalInstallationDebugging_Hours || ''; // 小時數
sworkSheet.getCell('E25').value = tableData.mechanicalInstallationDebugging_PerHourRate || ''; // 費率
sworkSheet.getCell('F25').value = tableData.mechanicalInstallationDebugging_TotalCost || ''; // 價格
sworkSheet.getCell('G25').value = tableData.mechanicalInstallationDebugging_Remarks || ''; // 備注
sworkSheet.mergeCells(`G25:L25`);
// 電氣安裝調試費用
sworkSheet.addRow();
sworkSheet.getCell('A26').value = 12;
sworkSheet.mergeCells(`B26:C26`);
sworkSheet.getCell('B26').value = '電氣安裝調試費用';
sworkSheet.getCell('D26').value = tableData.electricalInstallationDebugging_Hours || ''; // 小時數
sworkSheet.getCell('E26').value = tableData.electricalInstallationDebugging_PerHourRate || ''; // 費率
sworkSheet.getCell('F26').value = tableData.electricalInstallationDebugging_TotalCost || ''; // 價格
sworkSheet.getCell('G26').value = tableData.electricalInstallationDebugging_Remarks || ''; // 備注
sworkSheet.mergeCells(`G26:L26`);
// 現(xiàn)場調試服務費
sworkSheet.addRow();
sworkSheet.getCell('A27').value = 13;
sworkSheet.mergeCells(`B27:C27`);
sworkSheet.getCell('B27').value = '現(xiàn)場調試服務費';
sworkSheet.getCell('D27').value = tableData.onSiteDebuggingService_Hours || ''; // 小時數
sworkSheet.getCell('E27').value = tableData.onSiteDebuggingService_PerHourRate || ''; // 費率
sworkSheet.getCell('F27').value = tableData.onSiteDebuggingService_TotalCost || ''; // 價格
sworkSheet.getCell('G27').value = tableData.onSiteDebuggingService_Remarks || ''; // 備注
sworkSheet.mergeCells(`G27:L27`);
// 售后服務費
sworkSheet.addRow();
sworkSheet.getCell('A28').value = 14;
sworkSheet.mergeCells(`B28:C28`);
sworkSheet.getCell('B28').value = '售后服務費';
sworkSheet.getCell('D28').value = tableData.afterSalesService_Hours || ''; // 小時數
sworkSheet.getCell('E28').value = tableData.afterSalesService_PerHourRate || ''; // 費率
sworkSheet.getCell('F28').value = tableData.afterSalesService_TotalCost || ''; // 價格
sworkSheet.getCell('G28').value = tableData.afterSalesService_Remarks || ''; // 備注
sworkSheet.mergeCells(`G28:L28`);
// 包裝及運輸費用
sworkSheet.addRow();
sworkSheet.getCell('A29').value = 15;
sworkSheet.mergeCells(`B29:C29`);
sworkSheet.getCell('B29').value = '包裝及運輸費用';
sworkSheet.getCell('D29').value = '/'; // 小時數
sworkSheet.getCell('E29').value = '/'; // 費率
sworkSheet.getCell('F29').value = tableData.shippingPackagingCost_AfterMarkup || ''; // 價格
sworkSheet.getCell('G29').value = tableData.shippingPackagingCost_Remarks || ''; // 備注
sworkSheet.mergeCells(`G29:L29`);
// 差旅費
sworkSheet.addRow();
sworkSheet.getCell('A30').value = 16;
sworkSheet.mergeCells(`B30:C30`);
sworkSheet.getCell('B30').value = '差旅費';
sworkSheet.getCell('D30').value = '/'; // 小時數
sworkSheet.getCell('E30').value = '/'; // 費率
sworkSheet.getCell('F30').value = tableData.travelAndAccommodationCost_AfterMarkup || ''; // 價格
sworkSheet.getCell('G30').value = tableData.travelAndAccommodationCost_Remarks || ''; // 備注
sworkSheet.mergeCells(`G30:L30`);
// 資料費
sworkSheet.addRow();
sworkSheet.getCell('A31').value = 17;
sworkSheet.mergeCells(`B31:C31`);
sworkSheet.getCell('B31').value = '資料費';
sworkSheet.getCell('D31').value = '/'; // 小時數
sworkSheet.getCell('E31').value = '/'; // 費率
sworkSheet.getCell('F31').value = tableData.documentCost_AfterMarkup || ''; // 價格
sworkSheet.getCell('G31').value = tableData.documentCost_Remarks || ''; // 備注
sworkSheet.mergeCells(`G31:L31`);
// 成本合計(小結)
sworkSheet.addRow();
sworkSheet.getCell('A32').value = 18;
sworkSheet.mergeCells(`B32:C32`);
sworkSheet.getCell('B32').value = '成本合計(小結)';
sworkSheet.getCell('D32').value = '/'; // 小時數
sworkSheet.getCell('E32').value = '/'; // 費率
sworkSheet.getCell('F32').value = tableData.totalCost || ''; // 價格
sworkSheet.getCell('G32').value = ''; // 備注
sworkSheet.mergeCells(`G32:L32`);
// 管理費
sworkSheet.addRow();
sworkSheet.getCell('A33').value = 19;
sworkSheet.mergeCells(`B33:C33`);
sworkSheet.getCell('B33').value = '管理費';
sworkSheet.getCell('D33').value = '/'; // 小時數
sworkSheet.getCell('E33').value = '/'; // 費率
sworkSheet.getCell('F33').value = tableData.managementFee || ''; // 價格
sworkSheet.getCell('G33').value = ''; // 備注
sworkSheet.mergeCells(`G33:L33`);
// 財務費
sworkSheet.addRow();
sworkSheet.getCell('A34').value = 20;
sworkSheet.mergeCells(`B34:C34`);
sworkSheet.getCell('B34').value = '財務費';
sworkSheet.getCell('D34').value = '/'; // 小時數
sworkSheet.getCell('E34').value = '/'; // 費率
sworkSheet.getCell('F34').value = tableData.financialFee || ''; // 價格
sworkSheet.getCell('G34').value = ''; // 備注
sworkSheet.mergeCells(`G34:L34`);
// 利潤
sworkSheet.addRow();
sworkSheet.getCell('A35').value = 21;
sworkSheet.mergeCells(`B35:C35`);
sworkSheet.getCell('B35').value = '利潤';
sworkSheet.getCell('D35').value = '/'; // 小時數
sworkSheet.getCell('E35').value = '/'; // 費率
sworkSheet.getCell('F35').value = tableData.profit || ''; // 價格
sworkSheet.getCell('G35').value = ''; // 備注
sworkSheet.mergeCells(`G35:L35`);
// 價格合計(未稅)
sworkSheet.addRow();
sworkSheet.getCell('A36').value = 22;
sworkSheet.mergeCells(`B36:C36`);
sworkSheet.getCell('B36').value = '價格合計(未稅)';
sworkSheet.getCell('D36').value = '/'; // 小時數
sworkSheet.getCell('E36').value = '/'; // 費率
sworkSheet.getCell('F36').value = tableData.totalPriceExcludingTax || ''; // 價格
sworkSheet.getCell('G36').value = ''; // 備注
sworkSheet.mergeCells(`G36:L36`);
// 增值稅
sworkSheet.addRow();
sworkSheet.getCell('A37').value = 23;
sworkSheet.mergeCells(`B37:C37`);
sworkSheet.getCell('B37').value = '增值稅';
sworkSheet.getCell('D37').value = '/'; // 小時數
sworkSheet.getCell('E37').value = '/'; // 費率
sworkSheet.getCell('F37').value = tableData.valueAddedTax || ''; // 價格
sworkSheet.getCell('G37').value = ''; // 備注
sworkSheet.mergeCells(`G37:L37`);
// 價格合計(含稅)
sworkSheet.addRow();
sworkSheet.getCell('A38').value = 24;
sworkSheet.mergeCells(`B38:C38`);
sworkSheet.getCell('B38').value = '價格合計(含稅)';
sworkSheet.getCell('D38').value = '/'; // 小時數
sworkSheet.getCell('E38').value = '/'; // 費率
sworkSheet.getCell('F38').value = tableData.valueAddedTax || ''; // 價格
sworkSheet.getCell('G38').value = ''; // 備注
sworkSheet.mergeCells(`G38:L38`);
// 數據行統(tǒng)一樣式處理
sworkSheet.eachRow((row, rowIndex) => {
// 循環(huán)每一行
if (rowIndex >= 14 && rowIndex <= 38) {
if (rowIndex === 14) {
// 標題行
row.eachCell((cell, colIndex) => {
console.log('cell', cell);
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
cell.font = { size: 11, bold: true };
if (cell._address === 'D14' || cell._address === 'E14') {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: '00B0F0' } // 設置背景色
};
}
});
} else if (rowIndex >= 20 && rowIndex <= 28) {
// 從機械設計 到 售后服務行
row.eachCell((cell, colIndex) => {
console.log('cell', cell);
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('B') > -1 || cell._address.indexOf('F') > -1) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'D9E1F2' } // 設置背景色
};
}
if (cell._address.indexOf('D') > -1 || cell._address.indexOf('E') > -1) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: '00B0F0' } // 設置背景色
};
}
});
} else if (rowIndex === 32) {
row.eachCell((cell, colIndex) => {
console.log('cell', cell);
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('B') > -1 || cell._address.indexOf('F') > -1) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'E2EFDA' } // 設置背景色
};
}
});
} else if (rowIndex === 36) {
row.eachCell((cell, colIndex) => {
console.log('cell', cell);
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('B') > -1 || cell._address.indexOf('F') > -1) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'C6E0B4' } // 設置背景色
};
}
});
} else if (rowIndex === 38) {
row.eachCell((cell, colIndex) => {
console.log('cell', cell);
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('B') > -1 || cell._address.indexOf('F') > -1) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'A9D08E' } // 設置背景色
};
}
});
} else {
row.eachCell((cell, colIndex) => {
console.log('cell', cell);
cell.font = { size: 11 };
cell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
if (cell._address.indexOf('B') > -1 || cell._address.indexOf('F') > -1) {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'D9E1F2' } // 設置背景色
};
}
});
}
row.height = 17;
}
});
// 最下方針對報價其他說明列
sworkSheet.addRow();
sworkSheet.mergeCells(`A39:C39`);
sworkSheet.mergeCells(`D39:L39`);
let remarkcell = sworkSheet.getCell('A39');
remarkcell.value = '針對此次報價的其他說明:';
remarkcell.font = { size: 12, bold: true };
remarkcell.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
remarkcell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'A9D08E' } // 設置背景色
};
let remarkcell1 = sworkSheet.getCell('D39');
remarkcell1.font = { size: 12 };
remarkcell1.alignment = {
vertical: 'middle', // 垂直居中
horizontal: 'center', // 水平居中
wrapText: true // 自動換行
};
remarkcell1.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'A9D08E' } // 設置背景色
};
sworkSheet.getRow(39).height = 20;
// 將logo放入第一行 放到最后就行啦(復用總報價)
// 前面已經加載了 imageid,這里直接用
// 當前工作表(當前excel頁)加入圖片,tl.col:excel第幾列,tl.row:excel第幾行,ext里面表示圖片寬高
sworkSheet.addImage(imageId, {
tl: { col: 0.1, row: 0.1 },
// br: { col: columns.length + ai - 11.1, row: ri + 2 }
ext: { width: 100, height: 85 }
});
// 調整所有列的寬度
sworkSheet.columns.forEach((column) => {
column.width = 17; // 將寬度設為20個字符
});
// 定義邊框樣式
const borderStyle = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
// 遍歷工作表中的所有單元格并添加邊框
sworkSheet.eachRow((row, rowIndex) => {
row.eachCell((cell, colIndex) => {
cell.border = borderStyle;
});
});
}
}
await getData();
// 保存工作簿
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), '商務報價單導出.xlsx');
});
} else {
this.$message(res.msg);
}
loading.close();
},總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
webpack4+express+mongodb+vue實現(xiàn)增刪改查的示例
這篇文章主要介紹了webpack4+express+mongodb+vue 實現(xiàn)增刪改查的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
Vue $nextTick 為什么能獲取到最新Dom源碼解析
這篇文章主要為大家介紹了Vue $nextTick 為什么能獲取到最新Dom源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
vue2如何使用vue-i18n搭建多語言切換環(huán)境
這篇文章主要介紹了vue2-使用vue-i18n搭建多語言切換環(huán)境的相關知識,在data(){}中獲取的變量存在更新this.$i18n.locale的值時無法自動切換的問題,需要刷新頁面才能切換語言,感興趣的朋友一起看看吧2023-12-12
vue不用import直接調用實現(xiàn)接口api文件封裝
這篇文章主要為大家介紹了vue不用import直接調用實現(xiàn)接口api文件封裝,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06

