必须使用 SheetJS 手动构造合并,因 layui.exportFile() 仅支持纯数据导出,无单元格合并能力;需遍历分组计算行范围,设置 ws['!merges'] 并用 XLSX.writeFile 输出真实 .xlsx 文件。
layui table 导出 Excel 时怎么合并相同 id 的行?
layui 自带的 table.exportfile() 不支持单元格合并,导出的是纯数据表格,所有单元格独立存在。想按 id 合并,必须绕过它,自己构造 excel 文件。
为什么不能直接用 table.exportFile() 实现合并?
因为这个方法底层调用的是简单 CSV 或 JSON 转 Sheet 的逻辑,没有 Excel 格式控制能力,更不提供 mergeCells、rowspan 这类操作接口。你传给它的数据是扁平数组,它就原样打出来。
- 导出格式固定为
.csv或.xls(非真正的 Excel),不支持样式、合并、公式 - 即使你提前把数据“拼成”带空字符串的结构(比如第二行
id设为空),Excel 打开后也不会自动合并——那只是视觉错觉,实际仍是独立单元格 - 浏览器端无法用原生 JS 操作 Excel 的单元格合并逻辑,必须依赖专门的库
用 xlsx + SheetJS 手动合并 id 单元格的实操要点
推荐用 SheetJS(即 xlsx 包)生成真实 .xlsx 文件,在写入前手动计算哪些行的 id 相同,然后加 !merges。
- 先用
table.cache['your-id']拿到当前表格的原始数据(含排序、筛选后结果) - 遍历数据,按
id分组,记录每组起始行索引和长度(注意:Excel 行号从 1 开始,JS 数组从 0 开始,要 +1) - 构建
ws['!merges'] = [ { s: { r: 0, c: 0 }, e: { r: 2, c: 0 } } ]这样的合并区域数组,r是行,c是列(id在第 0 列就填c: 0) - 用
XLSX.utils.aoa_to_sheet()转二维数组,再挂上!merges,最后XLSX.writeFile()
示例关键片段:
const data = table.cache['demo']; // 假设你的 table id 是 demo
const merges = [];
let i = 0;
while (i < data.length) {
const startRow = i;
const idVal = data[i].id;
while (i < data.length && data[i].id === idVal) i++;
const endRow = i - 1;
if (endRow > startRow) {
merges.push({
s: { r: startRow + 1, c: 0 }, // +1 因为第 0 行是表头
e: { r: endRow + 1, c: 0 }
});
}
}
const ws = XLSX.utils.aoa_to_sheet([['ID', 'Name', 'Time'], ...data.map(d => [d.id, d.name, d.time])]);
ws['!merges'] = merges;
XLSX.writeFile(ws, 'merged.xlsx');
容易被忽略的细节和坑
合并不是“看起来一样就行”,Excel 解析和打印行为对合并区域很敏感。
-
!merges中的行列索引必须严格连续,不能重叠、不能交叉,否则 Excel 打开报错或显示异常 - 表头行(第 0 行)不能参与合并,否则
s.r写成 0 就会把表头也卷进去 - 如果表格启用了
scrollbar或虚拟滚动,table.cache可能只含当前页数据——得确认你导出的是全量还是当前页 - 合并只作用于单列;若需多列(如
id和name同时合并),要分别计算每列的合并区间,并确保它们对齐,否则 Excel 会拒绝打开文件
真正麻烦的不是写代码,而是校验合并逻辑是否覆盖所有边界情况:空数据、单条数据、跨页分组、ID 为 null/undefined……这些地方一漏,导出来的 Excel 就打不开。

















