第一步
一定要安装这个版本,否则就会报错
npm install exceljs@4.3.0
demo直接改就行
<template>
<div style="height: 500px;">
<el-row :gutter="20" style="height: 480px;overflow: auto;">
<el-col :span="1" style="padding: 0 0;">
<div class="black-table">
空间
</div>
<div class="white-table" :style="{ 'height': (bigdatalength * 60) + 'px' }">
{{ itemall.roomName }}
</div>
</el-col>
<el-col :span="1" style="padding: 0 0;">
<!-- <el-tooltip content="这是一个提示"> -->
<div class="black-table">
类型
</div>
<div v-for="(itemtype, index) in itemall.category" :key="index">
<div class="white-table" :style="{ 'height': (middledatalength[index] * 60) + 'px' }">
{{ itemtype.categoryName }}
</div>
</div>
</el-col>
<el-col :span="1" style="padding: 0 0;">
<div class="black-table">
位置
</div>
<div v-for="(itemtype, index) in locationName" :key="index">
<div class="white-table" :style="{ 'height': (smalldatalength[index] * 60) + 'px' }">
{{ itemtype }}
</div>
</div>
</el-col>
<!-- <el-col :span="1" style="padding: 0 0;">
<div class="black-table">
图例
</div>
<div class="white-table">
<el-image style="width: 70px; height: 50px" :src="src" :preview-src-list="[src]"></el-image>
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
<div class="white-table">
图
</div>
</el-col> -->
<el-col :span="1" style="padding: 0 0;">
<div class="black-table">
面积
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.areaNum"></el-input>
</div>
</el-col>
<el-col :span="4" style="padding: 0 0;">
<div class="black-table">
商品
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.name"></el-input>
</div>
</el-col>
<el-col :span="2" style="padding: 0 0;">
<div class="black-table">
品牌
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.brandName"></el-input>
</div>
</el-col>
<el-col :span="2" style="padding: 0 0;">
<div class="black-table">
产品型号
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.model"></el-input>
</div>
</el-col>
<el-col :span="2" style="padding: 0 0;">
<div class="black-table">
规格尺寸
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.size"></el-input>
</div>
</el-col>
<el-col :span="2" style="padding: 0 0;">
<div class="black-table">
单价
</div>
<div v-for="(item, index) in smalldata" :key="index">
<div class="white-table" style="position: relative;">
<el-input autosize placeholder="" v-model="item.price"></el-input>
<div style="position: absolute;top: 20px;left: 3px;">¥</div>
</div>
</div>
</el-col>
<el-col :span="1" style="padding: 0 0;">
<div class="black-table">
建议用量
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.dosage"></el-input>
</div>
</el-col>
<el-col :span="1" style="padding: 0 0;">
<div class="black-table">
单位
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.unit"></el-input>
</div>
</el-col>
<el-col :span="1" style="padding: 0 0;">
<div class="black-table">
损耗
</div>
<div v-for="(item, index) in smalldata" :key="index">
<el-input type="textarea" class="white-table" autosize placeholder="" v-model="item.loss"></el-input>
</div>
</el-col>
<el-col :span="3" style="padding: 0 0;">
<div class="black-table">
小计
</div>
<div v-for="(item, index) in smalldata" :key="index">
<div class="white-table">
¥{{ item.price * item.dosage * (1 + (parseInt(item.loss, 10) / 100)) }}
</div>
</div>
</el-col>
<el-col :span="2" style="padding: 0 0;">
<div class="black-table">
备注
</div>
<!-- <div class="white-table">
该报价仅为建收用量下的主材价格。最终价格已订单价为准。加工学角以实行测量为主,收货及时验块,港货留好原包装,免费送货或补货一次。加工和水砖不退
</div> -->
<el-input type="textarea" style="border-bottom: 0;" class="white-table" autosize
:style="{ 'height': ((bigdatalength) * 60) + 'px' }" placeholder="" v-model="note"></el-input>
</el-col>
<el-col :span="22" style="padding: 0 0;">
<div class="white-table" style="align-items: flex-end;flex-direction: column;width: 100%;">
<div style="display: flex;justify-content: center;align-items: center;">
优惠金额:
<el-input style="width: 50px;" class="white-table" autosize placeholder="" v-model="free"></el-input>
<div style="margin-left: 10px;margin-right: 5px;">
元
</div>
</div>
</div>
<div class="white-table" style="align-items: flex-end;flex-direction: column;width: 100%;">
<div style="float: right;margin-right: 5px;">
商品总计: {{ computedData.toFixed(2) }}元
</div>
</div>
</el-col>
<el-col :span="2" style="padding: 0 0;">
<div class="white-table"
style="border-bottom: 1px solid rgb(195, 200, 209);border-top: 0;border-right: 1px solid rgb(195, 200, 209);height: 120px;">
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import ExcelJS from 'exceljs';
export default {
data() {
return {
inputshow: false,
src: "https://img2.baidu.com/it/u=1341091381,1189643914&fm=253&fmt=auto&app=120&f=JPEG?w=666&h=416",
input: 99999,
note: "该报价仅为建收用量下的主材价格。最终价格已订单价为准。加工学角以实行测量为主,收货及时验块,港货留好原包装,免费送货或补货一次。加工和水砖不退。",
locationName: [],
smalldata: [],
smalldatalength: [],
middledatalength: [],
locationNamelength: [],
bigdatalength: [],
free: 0,
itemall:
{
roomName: "未命名",
category: [
{
categoryName: "瓷砖",
location: [
{
locationName: "墙面",
goods: [
{
areaNum: 0,
name: "TDMF03160120PS",
brandName: "",
model: "",
size: "600*200",
price: 0,
dosage: 57.366578249999996,
unit: "块",
loss: "0%",
subtotal: 0
},
{
areaNum: 0,
name: "东鹏中板墙砖SG848101_A",
brandName: "东鹏",
model: "中板墙砖SG848101_A",
size: "600*200",
price: 38.7,
dosage: 52.333156498,
unit: "块",
loss: "0%",
subtotal: 1780.2
},
{
areaNum: 0,
name: "750*1500海浪灰XD1PA715208",
brandName: "熊小住",
model: "",
size: "600*200",
price: 199,
dosage: 51.76657825,
unit: "块",
loss: "0%",
subtotal: 9552
},
{
areaNum: 0,
name: "750*1500爵士灰XD1PA715205",
brandName: "熊小住",
model: "",
size: "600*300",
price: 199,
dosage: 39.333156498,
unit: "块",
loss: "0%",
subtotal: 6567
}
]
},
{
locationName: "地面",
goods: []
}
]
},
{
categoryName: "砖缝",
location: [
{
locationName: "墙面",
goods: [
{
areaNum: 0,
name: "木纹色",
brandName: "通配",
model: "鎏金黄",
size: "100*100",
price: 18.8,
dosage: 688.36657825,
unit: "米",
loss: "0%",
subtotal: 12765.2
},
{
areaNum: 0,
name: "水泥灰",
brandName: "通配",
model: "亚麻灰",
size: "100*100",
price: 1.99,
dosage: 263.76657825,
unit: "米",
loss: "0%",
subtotal: 517.4
}
]
},
{
locationName: "地面",
goods: []
}
]
}
]
},
};
},
methods: {
async updata() {
// 创建一个新的工作簿
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('瓷砖美缝');
// 添加表头
worksheet.addRow(['空间', '类型', '位置', '面积', '商品', '品牌', '产品型号', '规格尺寸', '单价', '建议用量', '单位', '损耗', '小计', '备注']);
// 添加数据
// worksheet.addRow(['张三', 25, 'zhangsan@example.com']);
// worksheet.addRow(['李四', 30, 'lisi@example.com']);
// worksheet.addRow(['王五', 28, 'wangwu@example.com']);
this.smalldata.map(item => {
worksheet.addRow([0, 0, 0, item.areaNum, item.name, item.brandName, item.model, item.size, item.price, item.dosage, item.unit, item.loss, item.price * item.dosage * (1 + (parseInt(item.loss, 10) / 100))]);
})
// 合并单元格面积A
worksheet.mergeCells(`A2:A${this.bigdatalength + 1}`);
// // 设置合并单元格的样式
const mergedCell = worksheet.getCell('A2');
mergedCell.value = this.itemall.roomName;
mergedCell.alignment = { vertical: 'middle', horizontal: 'center' };
mergedCell.font = { bold: true, size: 14 };
// 合并单元格-备注
worksheet.mergeCells(`N2:N${this.bigdatalength + 1}`);
const mergedCellnote = worksheet.getCell('N2');
mergedCellnote.value = this.note;
mergedCellnote.alignment = { vertical: 'middle', horizontal: 'center' ,wrapText: true };
mergedCellnote.font = { bold: true, size: 10 };
// 合并单元格面积B
let merge = 2
this.itemall.category.map((item, index) => {
if (!index) {
worksheet.mergeCells(`B${merge}:B${this.middledatalength[index] + 1}`);
const mergedCell = worksheet.getCell(`B${merge}`);
mergedCell.value = item.categoryName;
mergedCell.alignment = { vertical: 'middle', horizontal: 'center' };
mergedCell.font = { bold: true, size: 14 };
merge = this.middledatalength[index] + 1
} else {
console.log(index, merge, this.middledatalength[index] + 1 + merge)
worksheet.mergeCells(`B${merge + 1}:B${this.middledatalength[index] + merge}`);
const mergedCell = worksheet.getCell(`B${merge + 1}`);
mergedCell.value = item.categoryName;
mergedCell.alignment = { vertical: 'middle', horizontal: 'center' };
mergedCell.font = { bold: true, size: 14 };
merge = this.middledatalength[index] + merge
}
})
let mergeplace = 2
this.locationName.map((item, index) => {
if (!index) {
worksheet.mergeCells(`C${mergeplace}:C${this.smalldatalength[index] + 1}`);
const mergeplacedCell = worksheet.getCell(`C${mergeplace}`);
mergeplacedCell.value = item;
mergeplacedCell.alignment = { vertical: 'middle', horizontal: 'center' };
mergeplacedCell.font = { bold: true, size: 14 };
mergeplace = this.smalldatalength[index] + 1
} else {
worksheet.mergeCells(`C${mergeplace + 1}:C${this.smalldatalength[index] + mergeplace}`);
const mergeplacedCell = worksheet.getCell(`C${mergeplace + 1}`);
mergeplacedCell.value = item;
mergeplacedCell.alignment = { vertical: 'middle', horizontal: 'center' };
mergeplacedCell.font = { bold: true, size: 14 };
mergeplace = this.smalldatalength[index] + mergeplace
}
})
// 生成Excel文件并下载
const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = '瓷砖美缝.xlsx';
link.click();
},
},
computed: {
computedData() {
// 计算属性依赖于 originalData
let amous = 0
this.smalldata.map(item => {
amous += item.price * item.dosage * (1 + (parseInt(item.loss, 10) / 100))
})
return amous - this.free;
},
},
mounted() {
this.locationName = []
this.smalldata = []
this.smalldatalength = []
this.middledatalength = []
this.bigdatalength = 0
// this.locationNamelength=[]
let space = {
areaNum: "",
name: "",
brandName: "",
model: "",
size: "",
price: 0,
dosage: 0,
unit: "",
loss: "0%",
subtotal: 0
}
this.itemall.category.map(item => {
let middlespace = 0
item.location.map(item1 => {
this.locationName.push(item1.locationName)
let lengthnumber = 1
item1.goods.map(item2 => {
item2.dosage = Math.floor(item2.dosage)
item2.areaNum ? item2.areaNum : item2.areaNum = "";
this.smalldata.push(item2)
lengthnumber++
})
this.smalldatalength.push(lengthnumber)
this.smalldata.push(space)
middlespace += lengthnumber
})
this.middledatalength.push(middlespace)
}),
this.middledatalength.map(item => {
this.bigdatalength += item
})
}
}
</script>
<style lang="less" scoped>
.black-table {
width: 100%;
height: 30px;
background-color: rgb(195, 200, 209);
color: black;
display: flex;
justify-content: center;
align-items: center;
font-weight: 900;
}
.white-table {
display: flex;
justify-content: center;
align-items: center;
height: 60px;
border: 1px solid rgb(195, 200, 209);
overflow: hidden;
// white-space: nowrap;
// text-overflow: ellipsis;
// word-break: break-all;
}
& /deep/ .el-textarea__inner {
border: none;
resize: none;
overflow-y: hidden;
}
& /deep/ .el-input__inner {
border: none;
resize: none;
overflow-y: hidden;
.el-input-group__append,
.el-input-group__prepend {
background-color: #fff;
border: 0;
}
}
</style>