持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第16天,点击查看活动详情
table可视化合并、生成组件开发
平常看多了,xxx 低代码平台、xxx低代码平台,眼花缭乱。
今天我们也来实现一个"所见即所得"的需求:table可视化合并、生成组件。 项目地址
为什么要做这样的一个组件
最近的工作业务中心都在 erp 平台上,报表奇多;经常有需要导出报表模板给后端,让后端生成数据的情况,出于这个目的,我想做一个低代码的报表生成器,提供给产品和后端。
步骤一:生成table
我选择使用原生的 table
+ td
元素来进行;表格的数组我们选择使用二维数组来进行存放
核心代码
// 创建新表格数据
const createdTable = (row: number, column: number) => {
clear();
if (!row && !column) {
tableData.value = [];
return;
}
tableData.value = Array(row)
.fill(0)
.map((item, index) => {
const res: TdOption[] = [];
// 列的标志
for (let columnIndex = 0; columnIndex < column; columnIndex++) {
res.push(new TdOption(index, columnIndex));
}
return res;
});
};
这里的TdOption
是我们为每一个 td
项目设置的一个类,它包含:
- colSpan:表示该单元格占据多少列
- rowSpan:表示该单元格占据多少行
- show:表示该单元格是否显示
- value:表示该单元格的内容
- id
- style
其中
colSpan、rowSpan、show、id
是我们之后进行单元格合并的重要数据
步骤二:可以合并
既然是表格,那么就要可以做到表格合并嘛!
合并目标
合并结果
核心代码:
// 合并单元格
const merge = () => {
if (selectDomList.value.length < 2) {
return;
}
// const start = selectDomList.value[0]; // 开始节点
// let value = tableData.value[start.row][start.column];
const { row, column } = selectDomList.value[0];
let targetNode = {
id: `${row}-${column}`,
row,
column,
};
let value: TdOption = new TdOption();
selectDomMap.value.delete(targetNode.id); // 从合并的表格中删除掉我们用来合并的节点防止重复
// 不仅要转换表格的合并值
// 首先合并行
// 从起始行开始 合并每一个单元行
for (let i = 0; i < tableData.value.length; i++) {
tableData.value[i] = tableData.value[i].filter((subItem, subIndex) => {
const {
id,
style: { width, height },
colSpan,
rowSpan,
row,
column
} = subItem;
// 如果当前节点就是我们要进行合并的第一个节点
// 就将这个节点取出来进行合并操作
if (targetNode.id === id) {
value = subItem;
}
// 如果是初始节点就不进行操作了
if (selectDomMap.value.has(id)) {
// 已经被合并的就不加上去了
// 还需要转换合并后的宽度
// 同行合并宽度
if (row == targetNode.row) {
value.style.width = getValue(value.style.width, width);
value.colSpan += colSpan;
}
// 同列合并高度
if (column == targetNode.column) {
value.style.height = getValue(value.style.height, height);
value.rowSpan += rowSpan;
}
} else {
return subItem;
}
});
}
// 合并单元格
resSetXY();
};
实现HTML导出为Excel
npm i xlsx
npm i file-saver
通过如上的两个组件进行的excel导出
import { saveAs } from 'file-saver';
import { write, utils } from "xlsx";
export default function () {
// 导出excel
function exportExcel(Dom: any) {
let et = utils.table_to_book(
Dom
); //此处传入table的DOM节点
let etout = write(et, {
bookType: "xlsx",
bookSST: true,
type: "array"
});
try {
saveAs(
new Blob([etout], {
type: "application/octet-stream"
}),
"自定义表格.xlsx"
); //trade-publish.xlsx 为导出的文件名
} catch (e) {
console.log(e, etout);
}
return etout;
}
return {
exportExcel,
};
}
当然,这里的 Dom 数组,其实就是我们之前生成的 tableValue 数据