3.0版本:
2.0版本:
一、目标效果 导出一个excel表格,如果单元格中有内容,则进行锁定不允许修改;如果没有,则不锁定允许修改;禁止用户复制sheet,防止复制整个sheet到其他excel中进行修改。
最终效果如下:
表头和灰色的文字是导出时就有的,不允许修改;4C、5C这两个单元格导出时是空的,允许修改。其他单元格都不允许修改,包括行>5、列>G的单元格。整个sheet无法选中,也无法进行复制。 二、依赖
<dependencies> <dependency> <groupId>com.alibabagroupId> <artifactId>easyexcelartifactId> <version>3.1.1version> dependency> <dependency> <groupId>junitgroupId> <artifactId>junitartifactId> <version>4.13.2version> <scope>testscope> dependency> dependencies>
三、代码实现 测试代码入口
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<List<String>> data() { List<List<String>> 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<List<String>> header() { List<List<String>> 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<List<String>> getRowColMatrix(int maxRow, int maxCol) { List<List<String>> 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<List<String>> 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),这么写无法生效。
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) { // 锁定有内容过的单元格(方法1) WriteCellStyle writeCellStyle = context.getFirstCellData().getOrCreateStyle(); 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) { // 锁定有内容过的单元格(方法2) CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle(); 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,那么写法稍有不同,如下:
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<CellData> 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.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)。
免责声明:本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即在【本页面底部评论留言】通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意