vue3集成excel表格展示
- EXCEL
- 20分钟前
- 2 热度
- 0 评论
<template>
<div>
<!-- 表格展示 -->
<div class="table-container">
<div v-if="!tableData.length">数据加载中...</div>
<table v-else class="excel-table">
<thead>
<tr>
<th
v-for="(header, colIndex) in tableHeaders"
:key="colIndex"
:rowspan="getHeaderRowspan(0, colIndex)"
:colspan="getHeaderColspan(0, colIndex)"
v-show="!isCellHidden(0, colIndex)"
>
{{ header }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in tableBody" :key="rowIndex">
<td
v-for="(cell, colIndex) in row"
:key="colIndex"
:rowspan="getCellRowspan(rowIndex + 1, colIndex)"
:colspan="getCellColspan(rowIndex + 1, colIndex)"
:class="{ 'merged-cell': isMergedCell(rowIndex + 1, colIndex) }"
v-show="!isCellHidden(rowIndex + 1, colIndex)"
>
{{ cell }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script setup>
import axios from "axios";
import * as XLSX from "xlsx";
const tableData = ref([]);
const tableHeaders = ref([]);
const mergeInfo = ref([]); // 存储合并单元格信息
const cellStyles = ref({}); // 存储单元格样式信息
// 获取表格主体数据(排除表头)
const tableBody = computed(() => {
return tableData.value.slice(1);
});
// 检查单元格是否被隐藏(在合并区域中但不是起始单元格)
const isCellHidden = (rowIndex, colIndex) => {
for (const merge of mergeInfo.value) {
if (rowIndex >= merge.startRow && rowIndex <= merge.endRow && colIndex >= merge.startCol && colIndex <= merge.endCol) {
// 如果是合并区域的起始单元格,不隐藏
if (rowIndex === merge.startRow && colIndex === merge.startCol) {
return false;
}
// 其他合并区域的单元格需要隐藏
return true;
}
}
return false;
};
// 获取单元格的 rowspan
const getCellRowspan = (rowIndex, colIndex) => {
for (const merge of mergeInfo.value) {
if (rowIndex === merge.startRow && colIndex === merge.startCol) {
return merge.endRow - merge.startRow + 1;
}
}
return 1;
};
// 获取单元格的 colspan
const getCellColspan = (rowIndex, colIndex) => {
for (const merge of mergeInfo.value) {
if (rowIndex === merge.startRow && colIndex === merge.startCol) {
return merge.endCol - merge.startCol + 1;
}
}
return 1;
};
// 获取表头的 rowspan
const getHeaderRowspan = (rowIndex, colIndex) => {
for (const merge of mergeInfo.value) {
if (rowIndex === merge.startRow && colIndex === merge.startCol) {
return merge.endRow - merge.startRow + 1;
}
}
return 1;
};
// 获取表头的 colspan
const getHeaderColspan = (rowIndex, colIndex) => {
for (const merge of mergeInfo.value) {
if (rowIndex === merge.startRow && colIndex === merge.startCol) {
return merge.endCol - merge.startCol + 1;
}
}
return 1;
};
// 检查是否为合并单元格的起始位置
const isMergedCell = (rowIndex, colIndex) => {
for (const merge of mergeInfo.value) {
if (rowIndex === merge.startRow && colIndex === merge.startCol) {
return true;
}
}
return false;
};
// 处理文件选择
const loadProjectExcel = async () => {
try {
const response = await axios.get("/park.xlsx", { responseType: "arraybuffer" });
const data = new Uint8Array(response.data);
const workbook = XLSX.read(data, { type: "array" });
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
// 获取合并单元格信息
if (worksheet["!merges"]) {
mergeInfo.value = worksheet["!merges"].map(merge => ({
startRow: merge.s.r,
startCol: merge.s.c,
endRow: merge.e.r,
endCol: merge.e.c,
}));
} else {
mergeInfo.value = [];
}
// 转换工作表数据
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
header: 1,
defval: "", // 为空单元格提供默认值
});
// 处理数据
if (jsonData.length > 0) {
tableHeaders.value = jsonData[0] || [];
tableData.value = jsonData;
}
} catch (error) {
console.error("处理 Excel 文件时出错:", error);
}
};
onMounted(() => {
loadProjectExcel();
});
</script>
<style scoped>
.table-container {
overflow-x: auto;
margin-top: 20px;
min-height: 500px;
}
.excel-table {
width: 100%;
border-collapse: collapse;
border: 1px solid #ddd;
}
.excel-table th,
.excel-table td {
border: 1px solid #ddd;
padding: 8px 12px;
text-align: left;
vertical-align: top;
}
.excel-table th {
background-color: #f5f5f5;
font-weight: bold;
}
.excel-table tr:nth-child(even) {
background-color: #f9f9f9;
}
.excel-table tr:hover {
background-color: #f0f0f0;
}
.merged-cell {
/* background-color: #e8f4fd; */
text-align: center;
}
</style>

图片说明文字