如何限制生成的excel某列不可编辑?

背景:

项目技术栈: vue3 + vite;
导出数据用到的第三方库:exceljs;

  1. 有一个列表,前端批量导出,生成excel文件,诸如:
    image.png
  2. 但是生成的的excel文件每列都可以修改,和预期不符,
    预期效果: 序号、班级、姓名都不可以修改,只有得分列可以修改。
阅读 1.9k
2 个回答
 npm install exceljs file-saver
<template>
  <div>
    <button @click="exportToExcel">导出Excel</button>
  </div>
</template>

<script>
import ExcelJS from 'exceljs';
import { saveAs } from 'file-saver';

export default {
  name: 'ExportExcel',
  methods: {
    async exportToExcel() {
      const workbook = new ExcelJS.Workbook();
      const worksheet = workbook.addWorksheet('成绩单');

      // 添加标题行
      worksheet.addRow(['序号', '班级', '姓名', '得分']);

      // 添加数据行
      const data = [
        [1, '六年级三班', 'Buer', 99],
        [2, '六年级一班', 'Jack', 86],
        [3, '六年级三班', 'Mary', 58],
      ];

      data.forEach(row => {
        worksheet.addRow(row);
      });

      // 保护整个工作表
      worksheet.protect('yourpassword', {
        selectLockedCells: true,
        selectUnlockedCells: true,
      });

      // 解锁“得分”列
      worksheet.getColumn(4).eachCell((cell, rowNumber) => {
        if (rowNumber !== 1) { // 跳过标题行
          cell.protection = { locked: false };
        }
      });

      // 将工作簿写入文件
      const buffer = await workbook.xlsx.writeBuffer();
      const blob = new Blob([buffer], { type: 'application/octet-stream' });
      saveAs(blob, '成绩单.xlsx');
    }
  }
};
</script>
  1. 保护整个工作表:通过 worksheet.protect('yourpassword', { ... }) 方法保护整个工作表。
  2. 解锁特定列:通过 worksheet.getColumn(4).eachCell((cell, rowNumber) => { ... }) 方法遍历“得分”列的每个单元格,并将其 protection.locked 属性设置为 false 以解锁该列。
    image.png
    image.png

要确保只保护某些列,而不是整个工作表,并且允许用户编辑“得分”列,你可以尝试以下方式。这种方式不会保护整个工作表,而是只保护特定的单元格。这可以确保用户在试图编辑受保护单元格时会被提示输入密码,而非直接禁止操作。

<template>
  <div>
    <button @click="exportToExcel">导出Excel</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import ExcelJS from 'exceljs';
import { saveAs } from 'file-saver';

const exportToExcel = async () => {
  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet('成绩单');

  // 添加标题行
  const headerRow = worksheet.addRow(['序号', '班级', '姓名', '得分']);

  // 添加数据行
  const data = [
    [1, '六年级三班', 'Buer', 99],
    [2, '六年级一班', 'Jack', 86],
    [3, '六年级三班', 'Mary', 58],
  ];

  data.forEach(row => {
    worksheet.addRow(row);
  });

  // 保护整个工作表并设置密码
  worksheet.protect('yourpassword', {
    selectLockedCells: true,
    selectUnlockedCells: true,
  });

  // 解锁“得分”列
  worksheet.getColumn(4).eachCell((cell, rowNumber) => {
    if (rowNumber !== 1) { // 跳过标题行
      cell.protection = { locked: false };
    }
  });

  // 确保其他列被锁定
  for (let col = 1; col <= 3; col++) {
    worksheet.getColumn(col).eachCell((cell, rowNumber) => {
      if (rowNumber !== 1) { // 跳过标题行
        cell.protection = { locked: true };
      }
    });
  }

  // 将工作簿写入文件
  const buffer = await workbook.xlsx.writeBuffer();
  const blob = new Blob([buffer], { type: 'application/octet-stream' });
  saveAs(blob, '成绩单.xlsx');
};
</script>

解释:
1.保护整个工作表:通过 worksheet.protect('yourpassword', { ... }) 方法保护整个工作表。

2.解锁“得分”列:通过 worksheet.getColumn(4).eachCell((cell, rowNumber) => { ... }) 方法遍历“得分”列的每个单元格,并将其 protection.locked 属性设置为 false 以解锁该列。

3.锁定其他列:通过 worksheet.getColumn(col).eachCell((cell, rowNumber) => { ... }) 方法遍历其他列的每个单元格,并将其 protection.locked 属性设置为 true 以锁定这些列。

推荐问题