vue导入导出excel、设置单元格文字颜色、背景色、合并单元格(使用xlsx-js-style库)

javascript 复制代码
npm i xlsx-js-style
javascript 复制代码
<template>
  <button @click="download">下载 Excel 表格</button>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180" />
    <el-table-column prop="name" label="Name" width="180" />
    <el-table-column prop="维生素A" label="维生素A" width="180" />
    <el-table-column prop="维生素D" label="维生素D" />
    <el-table-column prop="维生素E" label="维生素E" width="180" />
    <el-table-column prop="维生素B1" label="维生素B1" width="180" />
    <el-table-column prop="维生素B2" label="维生素B2" width="180" />
    <el-table-column prop="维生素B6" label="维生素B6" width="180" />
  </el-table>
</template>
<script setup>
import { reactive } from "vue";
import XLSX from "xlsx-js-style";

const tableData = reactive([
  {
    name: "下限",
    维生素A: 500,
    维生素D: 6,
    维生素E: 10,
    维生素B1: 500,
    维生素B2: 800,
    维生素B6: 300,
    date: "/",
  },
  {
    name: "上限",
    维生素A: 1200,
    维生素D: 10,
    维生素E: 20,
    维生素B1: 1000,
    维生素B2: 1600,
    维生素B6: 600,
    date: "/",
  },
  {
    name: "Charlie",
    维生素A: 674,
    维生素D: 7.2,
    维生素E: 21,
    维生素B1: 798,
    维生素B2: 1200,
    维生素B6: 485,
    date: "2024.12.29",
  },
  {
    name: "Alice",
    维生素A: 690,
    维生素D: 8.1,
    维生素E: 18,
    维生素B1: 698,
    维生素B2: 1112,
    维生素B6: 674,
    date: "2024.12.29",
  },
  {
    name: "Bob",
    维生素A: 719,
    维生素D: 9,
    维生素E: 9.8,
    维生素B1: 498,
    维生素B2: 1342,
    维生素B6: 241,
    date: "2024.12.29",
  },
  {
    name: "Charlie",
    维生素A: 674,
    维生素D: 7.2,
    维生素E: 21,
    维生素B1: 798,
    维生素B2: 1200,
    维生素B6: 485,
    date: "2024.12.30",
  },
  {
    name: "Alice",
    维生素A: 690,
    维生素D: 8.1,
    维生素E: 18,
    维生素B1: 698,
    维生素B2: 1112,
    维生素B6: 674,
    date: "2024.12.30",
  },
  {
    name: "Bob",
    维生素A: 719,
    维生素D: 9,
    维生素E: 9.8,
    维生素B1: 498,
    维生素B2: 1342,
    维生素B6: 241,
    date: "2024.12.30",
  },
  {
    name: "Charlie",
    维生素A: 684,
    维生素D: 5.9,
    维生素E: 9,
    维生素B1: 478,
    维生素B2: 1462,
    维生素B6: 123,
    date: "2024.12.30",
  },
]);

// 获取上下限
const lowerLimit = tableData[0];
const upperLimit = tableData[1];

// 判断每列的值,超出范围时给相应单元格添加红色样式
const getFormattedData = () => {
  const formattedData = [];
  const merges = []; // 用于存储需要合并的单元格

  // 插入下限行并设置背景色为灰色
  const lowerLimitRow = { name: "下限" };
  for (const [key, value] of Object.entries(lowerLimit)) {
    if (key !== "name") {
      lowerLimitRow[key] = {
        v: value,
        s: {
          font: { color: { rgb: "000000" } },
          fill: { fgColor: { rgb: "D3D3D3" } }, // 设置背景色为灰色
        },
      };
    } else {
      lowerLimitRow[key] = {
        v: value,
        s: {
          font: { color: { rgb: "000000" } },
          fill: { fgColor: { rgb: "D3D3D3" } }, // 设置背景色为灰色
        },
      };
    }
  }
  formattedData.push(lowerLimitRow);

  // 插入上限行并设置背景色为灰色
  const upperLimitRow = { name: "上限" };
  for (const [key, value] of Object.entries(upperLimit)) {
    if (key !== "name") {
      upperLimitRow[key] = {
        v: value,
        s: {
          font: { color: { rgb: "000000" } },
          fill: { fgColor: { rgb: "D3D3D3" } }, // 设置背景色为灰色
        },
      };
    } else {
      upperLimitRow[key] = {
        v: value,
        s: {
          font: { color: { rgb: "000000" } },
          fill: { fgColor: { rgb: "D3D3D3" } }, // 设置背景色为灰色
        },
      };
    }
  }
  formattedData.push(upperLimitRow);
  let currentDate = "";
  let startRow = 2; // 从第三行开始(下限和上限已经插入)
  // 遍历表格数据
  for (let i = 2; i < tableData.length; i++) {
    const row = tableData[i];
    const formattedRow = { name: row.name };
    // 遍历每一列
    for (const [key, value] of Object.entries(row)) {
      if (key === "name" || key === "date") {
        formattedRow[key] = value;
        // 检查日期是否与上一行相同,若相同则合并单元格
        if (row.date === currentDate) {
          // 继续处理
        } else {
          if (currentDate !== "") {
            // 合并日期单元格
            merges.push({ s: { r: startRow, c: 0 }, e: { r: i, c: 0 } });
          }
          currentDate = row.date;
          startRow = i + 1;
        }
        continue;
      }
      // 获取下限和上限
      const lower = lowerLimit[key];
      const upper = upperLimit[key];

      // 判断是否超出范围
      let cellStyle = {};
      if (value < lower) {
        cellStyle = { font: { color: { rgb: "FF0000" } } }; // 红色字体
      } else if (value > upper) {
        cellStyle = { font: { color: { rgb: "FF0000" } } }; // 红色字体
      }

      // 将样式和数据一起保存
      formattedRow[key] = { v: value, s: cellStyle };
    }
    formattedData.push(formattedRow);
  }
  // 合并最后一个日期的单元格
  merges.push({
    s: { r: startRow, c: 0 },
    e: { r: tableData.length, c: 0 },
  });
  console.log("merges", merges);
  return { formattedData, merges };
};

// 下载 Excel 文件
const download = () => {
  const { formattedData, merges } = getFormattedData();
  const reformattedData = formattedData.map((item) => {
    // 创建一个新的对象,确保 `date` 始终在最前面
    const { date, ...rest } = item;
    return { date, ...rest };
  });
  // 转换格式化后的表格数据为工作表
  const ws = XLSX.utils.json_to_sheet(reformattedData);
  // 添加合并单元格的逻辑
  ws["!merges"] = merges;
  // 创建一个新的工作簿并添加工作表
  const wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, "Sheet1");

  // 导出 Excel 文件
  XLSX.writeFile(wb, "example.xlsx");
};
</script>
相关推荐
T***u3335 分钟前
前端框架在性能优化中的实践
javascript·vue.js·前端框架
jingling5551 小时前
vue | 在 Vue 3 项目中集成高德地图(AMap)
前端·javascript·vue.js
油丶酸萝卜别吃1 小时前
Vue3 中如何在 setup 语法糖下,通过 Layer 弹窗组件弹出自定义 Vue 组件?
前端·vue.js·arcgis
J***Q2928 小时前
Vue数据可视化
前端·vue.js·信息可视化
JIngJaneIL9 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
ttod_qzstudio9 小时前
深入理解 Vue 3 的 h 函数:构建动态 UI 的利器
前端·vue.js
_大龄10 小时前
前端解析excel
前端·excel
1***s63210 小时前
Vue图像处理开发
javascript·vue.js·ecmascript
一 乐10 小时前
应急知识学习|基于springboot+vue的应急知识学习系统(源码+数据库+文档)
数据库·vue.js·spring boot
一叶茶10 小时前
移动端平板打开的三种模式。
前端·javascript