joken-前端工程师

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
<template>
  <div>
    <!-- 更复杂的 HTML 表格 -->
    <table class="styled-table" ref="table">
      <thead>
        <tr>
          <th rowspan="3">姓名</th>
          <th rowspan="3">年龄</th>
          <th colspan="4">成绩</th>
          <th rowspan="3">备注</th>
        </tr>
        <tr>
          <th colspan="2">期中考试</th>
          <th colspan="2">期末考试</th>
        </tr>
        <tr>
          <th>数学</th>
          <th>英语</th>
          <th>数学</th>
          <th>英语</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td rowspan="2" class="name-cell">张三</td>
          <td rowspan="2">20</td>
          <td>85</td>
          <td>90</td>
          <td>92</td>
          <td>95</td>
          <td rowspan="2" class="remark-cell">表现良好</td>
        </tr>
        <tr>
          <td>88</td>
          <td>92</td>
          <td>94</td>
          <td>97</td>
        </tr>
        <tr>
          <td class="name-cell">李四</td>
          <td>22</td>
          <td>88</td>
          <td>92</td>
          <td>94</td>
          <td>97</td>
          <td class="remark-cell">进步明显</td>
        </tr>
        <tr>
          <td class="name-cell">王五</td>
          <td>21</td>
          <td>80</td>
          <td>85</td>
          <td>88</td>
          <td>90</td>
          <td class="remark-cell">需努力</td>
        </tr>
        <tr>
          <td class="name-cell">赵六</td>
          <td>23</td>
          <td>90</td>
          <td>95</td>
          <td>92</td>
          <td>96</td>
          <td class="remark-cell">优秀</td>
        </tr>
      </tbody>
    </table>
    <!-- 下载按钮 -->
    <button @click="exportToExcel">导出到 Excel</button>
  </div>
</template>

<script>
import { ref } from 'vue';
import ExcelJS from 'exceljs';

export default {
  name: 'TableToExcel',
  setup() {
    const table = ref(null);

    const exportToExcel = async () => {
      const rows = table.value.querySelectorAll('tr');
      const workbook = new ExcelJS.Workbook();
      const worksheet = workbook.addWorksheet('Sheet1');

      let rowIndex = 1;
      const mergeCellsList = [];
      const rowSpans = []; // 用于跟踪跨行的单元格

      rows.forEach((row, rowIndexOriginal) => {
        let cellIndex = 1; // 逻辑上的单元格索引
        let physicalCellIndex = 1; // 实际的Excel单元格索引,考虑到跨列

        // 清除已经结束的跨行
        if (rowSpans[rowIndexOriginal]) {
          rowSpans[rowIndexOriginal] = rowSpans[rowIndexOriginal].filter(span => span.endRow > rowIndex);
        }

        const cells = row.querySelectorAll('th, td');
        cells.forEach(cell => {
          // 跳过被跨行单元格覆盖的单元格
          while (rowSpans[rowIndexOriginal - 1]?.some(span => span.startCol <= physicalCellIndex && span.endCol >= physicalCellIndex)) {
            physicalCellIndex++;
          }

          const rowSpan = parseInt(cell.getAttribute('rowspan') || 1, 10);
          const colSpan = parseInt(cell.getAttribute('colspan') || 1, 10);
          worksheet.getCell(rowIndex, physicalCellIndex).value = cell.textContent.trim();

          if (rowSpan > 1 || colSpan > 1) {
            mergeCellsList.push({ startRow: rowIndex, startCol: physicalCellIndex, endRow: rowIndex + rowSpan - 1, endCol: physicalCellIndex + colSpan - 1 });

            // 如果是跨行,则记录下来
            if (rowSpan > 1) {
              for (let i = 0; i < rowSpan; i++) {
                rowSpans[rowIndexOriginal + i] = rowSpans[rowIndexOriginal + i] || [];
                rowSpans[rowIndexOriginal + i].push({ startCol: physicalCellIndex, endCol: physicalCellIndex + colSpan - 1, endRow: rowIndex + rowSpan - 1 });
              }
            }
          }

          // 更新实际的单元格索引,考虑到跨列
          physicalCellIndex += colSpan;
        });

        rowIndex++;
      });

      // 合并单元格
      mergeCellsList.forEach(mergeInfo => {
        worksheet.mergeCells(mergeInfo.startRow, mergeInfo.startCol, mergeInfo.endRow, mergeInfo.endCol);
      });

      // 导出文件
      const buffer = await workbook.xlsx.writeBuffer();
      const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'tableData.xlsx';
      a.click();
      URL.revokeObjectURL(url);
    };

    return {
      table,
      exportToExcel
    };
  }
};
</script>

<style scoped>
/* 表格整体样式 */
.styled-table {
  width: 100%; /* 设置表格宽度为100% */
  max-width: 1200px; /* 最大宽度 */
  margin: 20px auto; /* 水平居中 */
  border-collapse: collapse; /* 边框合并 */
  font-family: Arial, sans-serif;
  font-size: 16px;
  border: 2px solid #007BFF; /* 外边框颜色 */
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
}

/* 表头样式 */
.styled-table thead th {
  background-color: #007BFF; /* 表头背景色 */
  color: white;
  text-align: center;
  padding: 15px;
  border: 1px solid #0056b3; /* 表头边框 */
}

/* 表格内容样式 */
.styled-table tbody td {
  padding: 12px 15px; /* 单元格内边距 */
  text-align: center;
  border: 1px solid #ddd; /* 单元格边框 */
}

/* 名字和备注单元格样式 */
.name-cell, .remark-cell {
  font-weight: bold; /* 加粗 */
  background-color: #f9f9f9; /* 浅灰色背景 */
}

/* 鼠标悬停时的行样式 */
.styled-table tbody tr:hover {
  background-color: #f1f1f1; /* 悬停时的背景色 */
}

/* 下载按钮样式 */
button {
  display: block;
  margin: 20px auto;
  padding: 10px 20px;
  font-size: 16px;
  background-color: #007BFF;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

button:hover {
  background-color: #0056b3;
}
</style>
  • 网页效果
    image

  • 导出excel效果
    image

posted on 2024-12-26 22:03  joken1310  阅读(147)  评论(0)    收藏  举报