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>
相关推荐
Jiaberrr13 分钟前
Vue 3 中搭建菜单权限配置界面的详细指南
前端·javascript·vue.js·elementui
懒大王952718 分钟前
uniapp+Vue3 组件之间的传值方法
前端·javascript·uni-app
烛阴1 小时前
秒懂 JSON:JavaScript JSON 方法详解,让你轻松驾驭数据交互!
前端·javascript
拉不动的猪1 小时前
刷刷题31(vue实际项目问题)
前端·javascript·面试
zeijiershuai1 小时前
Ajax-入门、axios请求方式、async、await、Vue生命周期
前端·javascript·ajax
恋猫de小郭1 小时前
Flutter 小技巧之通过 MediaQuery 优化 App 性能
android·前端·flutter
只会写Bug的程序员1 小时前
面试之《webpack从输入到输出经历了什么》
前端·面试·webpack
拉不动的猪2 小时前
刷刷题30(vue3常规面试题)
前端·javascript·面试
狂炫一碗大米饭2 小时前
面试小题:写一个函数实现将输入的数组按指定类型过滤
前端·javascript·面试
最胖的小仙女2 小时前
通过动态获取后端数据判断输入的值打小
开发语言·前端·javascript