EasyExcel锁定指定单元格 & 禁止表格复制

您所在的位置:网站首页 excel设置成不可编辑 EasyExcel锁定指定单元格 & 禁止表格复制

EasyExcel锁定指定单元格 & 禁止表格复制

2024-05-26 18:46| 来源: 网络整理| 查看: 265

3.0版本:https://github.com/asdfLiang/easy-excel-test 2.0版本:https://github.com/asdfLiang/easyexcel-low-test

一、目标效果 导出一个excel表格,如果单元格中有内容,则进行锁定不允许修改;如果没有,则不锁定允许修改;禁止用户复制sheet,防止复制整个sheet到其他excel中进行修改。 最终效果如下: 在这里插入图片描述 表头和灰色的文字是导出时就有的,不允许修改;4C、5C这两个单元格导出时是空的,允许修改。其他单元格都不允许修改(包括行>5、列>G的单元格)。整个sheet无法选中,也无法进行复制。 二、依赖 com.alibaba easyexcel 3.1.1 junit junit 4.13.2 test 三、代码实现 测试代码入口 import com.alibaba.excel.EasyExcel; import excel.CustomSheetWriteHandler; import excel.StyleWriteHandler; import org.junit.Test; import java.io.File; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author by liangzj * @since 2022/9/17 15:32 */ public class EasyExcelTest { @Test public void testWriteExcel() { String pathname = "E:\\liangzj\\Desktop\\test.xlsx"; EasyExcel.write(new File(pathname)) .head(header()) .registerWriteHandler(new StyleWriteHandler()) .registerWriteHandler(new CustomSheetWriteHandler()) .sheet("Sheet1") .doWrite(data()); } /** * 数据是先行后列 * * @return */ public List data() { List data = getRowColMatrix(3, 5); data.get(0).set(0, "用户1"); data.get(0).set(1, "1234567890"); data.get(0).set(2, "合同1"); data.get(0).set(3, "文本1"); data.get(0).set(4, "210283202209078615"); data.get(1).set(0, "用户2"); data.get(1).set(1, "1234553478"); data.get(1).set(2, null); data.get(1).set(3, "文本2"); data.get(1).set(4, "210211202209073951"); data.get(2).set(0, "用户3"); data.get(2).set(1, "8332675567"); data.get(2).set(2, null); data.get(2).set(3, "文本3"); data.get(2).set(4, "120221202209076790"); return data; } /** * 表头是先列后行 * * @return */ public List header() { List header = getColRowMatrix(2, 5); header.get(0).set(0, "姓名"); header.get(0).set(1, "姓名"); header.get(1).set(0, "手机/邮箱"); header.get(1).set(1, "手机/邮箱"); header.get(2).set(0, "合同名称"); header.get(2).set(1, "合同名称"); header.get(3).set(0, "文件1"); header.get(3).set(1, "单行文本"); header.get(4).set(0, "文件1"); header.get(4).set(1, "身份证号"); return header; } /** * 生成一个先行后列的矩阵数组 * * @param maxRow * @param maxCol * @return */ private static List getRowColMatrix(int maxRow, int maxCol) { List header = Stream.generate( () -> Stream.generate(() -> "") .limit(maxCol) .collect(Collectors.toList())) .limit(maxRow) .collect(Collectors.toList()); return header; } /** * 生成一个先列后行的矩阵数组 * * @param maxRow * @param maxCol * @return */ private static List getColRowMatrix(int maxRow, int maxCol) { return getRowColMatrix(maxCol, maxRow); } } 设置保护表格

((SXSSFSheet) writeSheetHolder.getSheet()).lockSelectLockedCells(true);这行代码设置的是"已锁定的单元格不可复制",效果就是别人无法复制整个sheet,这样可以防止别人把内容复制到其他excel表中进行修改。如果允许复制,可以不加,不会影响锁单元格的效果。

package excel; import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import org.apache.poi.xssf.streaming.SXSSFSheet; /** * @author by liangzj * @since 2022/9/17 16:08 */ public class CustomSheetWriteHandler implements SheetWriteHandler { @Override public void afterSheetCreate( WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { // 设置保护密码 writeSheetHolder.getSheet().protectSheet("123456"); // 锁定单元格不可选中(防止别人直接复制内容到其他excel修改) ((SXSSFSheet) writeSheetHolder.getSheet()).lockSelectLockedCells(true); } } 设置单元格锁定状态

contentStyle和contentStyle2实现的效果是一样的,都是设置指定的单元格是否锁定。contentStyle2方法要注意不能直接cell.getCellStyle().setLocked(true),这么写无法生效。 注意:解锁单元格的关键代码是:cellStyle.setLocked(false),方法1中是writeCellStyle.setLocked(false)。

package excel; import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.IndexedColors; /** * 单元格样式处理器 * * @author by liangzj * @since 2022/9/17 16:26 */ public class StyleWriteHandler extends LongestMatchColumnWidthStyleStrategy { @Override public void afterCellDispose(CellWriteHandlerContext context) { if (context.getHead()) { // 表头属性设置 headerStyle(context); } else { // 表数据属性设置 // contentStyle(context); contentStyle2(context.getCell()); } } /** * 解锁没有内容的单元格(方法1) * * @param context */ private void contentStyle(CellWriteHandlerContext context) { WriteCellStyle writeCellStyle = context.getFirstCellData().getOrCreateStyle(); /* !! 注意:这行就是解锁单元格的代码,locked == true为锁定,locked == false为不锁定 */ writeCellStyle.setLocked(StringUtils.isNotBlank(context.getCell().getStringCellValue())); // 如果锁定,置灰(这行只是设置样式,不重要) if (writeCellStyle.getLocked()) { WriteFont writeFont = new WriteFont(); writeFont.setColor(IndexedColors.GREY_40_PERCENT.index); writeCellStyle.setWriteFont(writeFont); } } /** * 解锁没有内容的单元格(方法2) * * @param cell */ private void contentStyle2(Cell cell) { // 创建一个新的单元格样式 CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle(); // 复制原来单元格的样式(这样就能保证原来单元格的样式不丢失) cellStyle.cloneStyleFrom(cell.getCellStyle()); /* !! 注意:这行就是解锁单元格的代码,locked == true为锁定,locked == false为不锁定 */ cellStyle.setLocked(StringUtils.isNotBlank(cell.getStringCellValue())); // 把新建的样式设置为当前单元格样式 cell.setCellStyle(cellStyle); // 如果锁定,置灰(样式设置,不重要) if (cell.getCellStyle().getLocked()) { Font font = cell.getSheet().getWorkbook().createFont(); font.setColor(IndexedColors.GREY_40_PERCENT.index); cellStyle.setFont(font); } } /** * 表头格式处理 * * @param context */ private static void headerStyle(CellWriteHandlerContext context) { Cell cell = context.getCell(); int colWidth = cell.getStringCellValue().length() * 1500; boolean needHidden = "requireId".equals(cell.getStringCellValue()); // 根据表头文字设置列宽 cell.getSheet().setColumnWidth(cell.getColumnIndex(), colWidth); // 冻结表头 cell.getSheet().createFreezePane(1, 2); // 隐藏指定列 cell.getSheet().setColumnHidden(cell.getColumnIndex(), needHidden); } } 2.0版本

如果你用的是2.0版本的EasyExcel,那么写法稍有不同,如下(注意:解锁单元格的关键代码是:cellStyle.setLocked(false)):

package excel; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.IndexedColors; import java.util.List; /** * @author by liangzj * @since 2022/9/17 16:26 */ public class StyleWriteHandler extends LongestMatchColumnWidthStyleStrategy { @Override public void afterCellDispose( WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { super.afterCellDispose( writeSheetHolder, writeTableHolder, cellDataList, cell, head, relativeRowIndex, isHead); if (isHead) { // 表头属性设置 headerStyle(cell); } else { // 表数据属性设置 contentStyle(cell); } } private void contentStyle(Cell cell) { // 创建一个新的单元格样式 CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle(); // 复制原单元格的样式(这样就能保证单元格原有的样式不丢失) cellStyle.cloneStyleFrom(cell.getCellStyle()); /* !! 注意:这行就是解锁单元格的代码,locked == true为锁定,locked == false为不锁定 */ cellStyle.setLocked(!StringUtils.isEmpty(cell.getStringCellValue())); // 把新创建的样式设置为当前单元格的样式 cell.setCellStyle(cellStyle); // 不可编辑的单元格置灰(样式设置,不重要) if (cell.getCellStyle().getLocked()) { Font font = cell.getSheet().getWorkbook().createFont(); font.setColor(IndexedColors.GREY_40_PERCENT.getIndex()); cell.getCellStyle().setFont(font); } else { cell.setCellValue("可填写"); } } private static void headerStyle(Cell cell) { int colWidth = cell.getStringCellValue().length() * 1500; // 根据表头文字设置列宽 cell.getSheet().setColumnWidth(cell.getColumnIndex(), colWidth); // 冻结表头 cell.getSheet().createFreezePane(1, 2); } } 四、总结

点击执行最上方的测试代码,即可在指定位置生成一个excel文件。总结一下,这个实现思路是,先锁定sheet的所有单元格,再在对允许修改单元格进行解锁。实现这个效果的关键点:

设置保护单元格,没有这个设置,锁定单元格不会生效;设置单元格保护状态,注意一定要生成一个新的cellStyle,不要直接cell.getCellStyle().setLocked(true);创建新的cellStyle后,加上cellStyle.cloneStyleFrom(cell.getCellStyle()),这样可以保证原有的单元格样式不丢失。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3