需求如图
首先说明是不能拆分单元格的,因为单元格是最小单位。只能通过合并单元格来实现。
实现思路:点击导出按钮,去请求后端数据。data数据如下:
[{OrderNo: 'No637829645038060996', Name: '营养快线', Num: 1, Floor: 1}
{OrderNo: 'No637829644168104671', Name: '营养快线', Num: 1, Floor: 1}
{OrderNo: 'No637829644168104671', Name: '营养快线', Num: 1, Floor: 1}
{OrderNo: 'No637829640444687386', Name: '营养快线', Num: 1, Floor: 1}
{OrderNo: 'No637829621299943451', Name: '营养快线', Num: 1, Floor: 1}
{OrderNo: 'No637829582358522702', Name: '营养快线', Num: 1, Floor: 1}]
将相同OrderNo的数据合并,必须相邻。
使用组件:layui-excel,先去看这个组件的文档,才能看得懂代码,此组件不仅仅是layui,可以应用于各种项目。
核心代码如下:
$.get('/Order/GetOrderListByExportFile', { startTime, endTime, deviceCode, phoneNum, orderNo, merchantName, limit: 0, page: 0 },
function (data) {
data.data.unshift({ OrderNo: '订单号', Name: '商品名称', Num: '数量', Floor: '所在层' });
data = data.data
var mergeConfigArr = [], temp = [];
data.forEach((item, i) => {
if (!data[i + 1]) {//如果到最后一个了 直接返回
if (temp.length == 1) {//如果已经有记录了
temp.push('A' + (i + 1))//因为有表头所以i+1
mergeConfigArr.push(temp)
temp = []
}
return
}
var nextOrder = data[i + 1]['OrderNo'], thisOrder = item['OrderNo'];
if (thisOrder== nextOrder) {//如果跟下一行一样的订单号一样
if (temp.length == 0) {//如果记录为空 添加进去
temp.push('A' + (i+1))
}
} else {//跟下一行不一样
if (temp.length == 1) {//如果已经有记录了
temp.push('A' + (i+1))
mergeConfigArr.push(temp)
temp = []
}
}
})
var mergeConf = LAY_EXCEL.makeMergeConfig(mergeConfigArr);
LAY_EXCEL.exportExcel(data, '订单列表.xlsx', 'xlsx', {
extend: {
sheet1: {
'!merges': mergeConf
}
}
})
})
这个时候一个temp数组就不够用了,需要多个数组,把这些数组放到一个对象里面,通过循环依次添加。代码基本还跟上面一样。
var letterMerge = { A: [], B: [], C: [], D: [], E: [] };//要合并的列
然后再创建个function循环添加,把上面代码中的temp.push('A' + (i+1))
替换成 pushArr(i + 1)
//通过循环依次添加进去
//i:下标
function pushArr(i) {
for (var key in letterMerge) {
letterMerge[key].push(`${key}${i}`)
if (letterMerge[key].length == 2) {
mergeConfigArr.push(letterMerge[key])
letterMerge[key]=[]
}
}
}
合并单元格应该只保留一行数据,但是事实上被合并的单元格数据仍然存在,只是被隐藏了。用sum公式算出来的数据不对,比预计的多。所以想要准确的求和,需要只保留合并行的第一行,其他数据设置为0。以下是完整的代码
$.get('/Order/GetOrderListByExportFile', { startTime, endTime, deviceCode, phoneNum, orderNo, merchantName, limit: 0, page: 0 },
function (data) {
var head = { OrderNo: '订单号', Amount: '金额', PhoneNum:'手机号码',DeviceCode: '设备码', PayType: '支付方式', CreateTime: '创建时间', Name: '商品名称', Num: '数量', Floor: '所在层', Money: '售价' }
data.data.unshift(head);
data = data.data
//通过循环依次添加进去
function pushArr(i) {
for (var key in letterMerge) {
letterMerge[key].push(`${key}${i}`)
if (letterMerge[key].length == 2) {
mergeConfigArr.push(letterMerge[key])
letterMerge[key]=[]
}
}
}
var mergeConfigArr = [], letterMerge = { A: [], B: [], C: [], D: [], E: [] };//要添加的列
data.forEach((item, i) => {
if (!data[i + 1]) {//如果到最后一个了 直接返回
if (letterMerge.A.length == 1) {//如果已经有记录了
pushArr(i + 1);
item.Amount = 0
}
return
}
var previousOrder;
if (i !== 0) {
previousOrder = data[i - 1].OrderNo
}
var nextOrder = data[i + 1]['OrderNo'], thisOrder = item['OrderNo'];
if (thisOrder == previousOrder) {
item.Amount=0
}
if (thisOrder == nextOrder) {//如果跟下一行一样的订单号
if (letterMerge.A.length == 0) {//为空添加进去,否则什么也不干
pushArr(i + 1)
}
} else {//跟下一行不一样
if (letterMerge.A.length == 1) {//如果已经有记录了
pushArr(i + 1)
}
}
})
//把需要求和的列的属性设置为数值
data = LAY_EXCEL.filterExportData(data, {
OrderNo: 'OrderNo',
Amount: function (value, line, data) {
return {
v: value,
t: 'n'
}
},
PhoneNum: 'PhoneNum',
DeviceCode: 'DeviceCode',
PayType: 'PayType',
CreateTime: 'CreateTime',
Name: 'Name',
Num: 'Num',
Floor: 'Floor',
Money:'Money'
})
data.push({
OrderNo: '合计',
Amount: { t: 'n', f: `SUM(B2:B${data.length})` },
});
var mergeConf = LAY_EXCEL.makeMergeConfig(mergeConfigArr);
var colConf = LAY_EXCEL.makeColConfig({
'A': 180,
'E': 120,
'G':120
}, 80);
//列宽
LAY_EXCEL.setExportCellStyle(data, 'A1:I'+data.length, {
s: {
alignment: {
horizontal: 'center',
vertical: 'center'
}
}
})
//居中
LAY_EXCEL.exportExcel(data, '订单列表.xlsx', 'xlsx', {
extend: {
// extend 中可以指定某个 sheet 的属性,如果不指定 sheet 则所有 sheet 套用同一套属性
sheet1: {
// 以下配置仅 sheet1 有效
'!merges': mergeConf,
'!cols': colConf,
}
}
})
})