如何在不调用protectSheet()时设置.xlsx指定行不可编辑?
仅锁定指定行实现不可编辑的可行方案
当然可以实现,核心是利用Excel的工作表保护机制:开启保护后,单元格默认处于锁定不可编辑状态,我们只需要把允许编辑的单元格设置为解锁状态,指定行保持锁定即可。
你的代码问题分析
你当前的逻辑完全搞反了:创建了setLocked(false)的样式却给需要不可编辑的行应用,且未处理其他行的解锁设置,导致达不到预期效果。
修改后的实现步骤
- 创建允许编辑的单元格样式,设置
setLocked(false) - 给所有需要用户编辑的行/单元格应用这个样式
- 开启工作表保护(
protectSheet),此时未应用解锁样式的指定行会保持不可编辑 - 注意:合并单元格的锁定状态由左上角单元格决定,需确保合并区域的左上角单元格样式正确
修改后的代码片段
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.usermodel.*; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; public class CmWriteXLSXTemplateFile { public static void main(String[] args) { XSSFWorkbook wb = new XSSFWorkbook(); try { FileOutputStream fileOut = new FileOutputStream("D:\\Personal\\Practise\\test.xlsx"); XSSFSheet sheet1 = wb.createSheet("Main_Tab"); XSSFSheet sheet2 = wb.createSheet("Defination"); // 创建允许编辑的样式:设置为未锁定 CellStyle editableStyle = wb.createCellStyle(); editableStyle.setLocked(false); // 创建锁定样式(可选,显式设置更清晰,默认单元格已锁定) CellStyle lockedStyle = wb.createCellStyle(); lockedStyle.setLocked(true); // 生成原有内容结构 ArrayList<String> tt = new ArrayList<>(); for(int kk=0;kk< 42;kk++){ tt.add("C"+kk); } // 第0行:设置为不可编辑 XSSFRow row0 = sheet1.createRow(0); Cell cell0 = row0.createCell(0); sheet1.addMergedRegion(new CellRangeAddress(0, 0, 0, 7)); CellStyle cellStyle0 = wb.createCellStyle(); cellStyle0.setFillBackgroundColor(IndexedColors.BLUE.getIndex()); cellStyle0.setAlignment(CellStyle.ALIGN_CENTER); cellStyle0.setLocked(true); // 显式锁定 XSSFFont fontBoldItalic = wb.createFont(); fontBoldItalic.setBold(true); fontBoldItalic.setItalic(true); XSSFRichTextString cellValue0 = new XSSFRichTextString(); cellValue0.append("Fixed Columns", fontBoldItalic); cell0.setCellValue(cellValue0); cell0.setCellStyle(cellStyle0); Cell cell0_1 = row0.createCell(8); sheet1.addMergedRegion(new CellRangeAddress(0, 0, 8, 28)); CellStyle cellStyle0_1 = wb.createCellStyle(); cellStyle0_1.setFillBackgroundColor(IndexedColors.BROWN.index); cellStyle0_1.setAlignment(CellStyle.ALIGN_CENTER); cellStyle0_1.setLocked(true); // 显式锁定 XSSFFont fontBoldItalic0_1 = wb.createFont(); fontBoldItalic0_1.setBold(true); fontBoldItalic0_1.setItalic(true); XSSFRichTextString cellValue0_1 = new XSSFRichTextString(); cellValue0_1.append("Dynamics Columns", fontBoldItalic0_1); cell0_1.setCellValue(cellValue0_1); cell0_1.setCellStyle(cellStyle0_1); // 第1行:设置为不可编辑 Row row1 = sheet1.createRow(1); Cell cell12 = row1.createCell(0); sheet1.addMergedRegion(new CellRangeAddress(1, 1, 0, 1)); CellStyle cellStyle12 = wb.createCellStyle(); cellStyle12.setFillBackgroundColor(IndexedColors.BROWN.index); cellStyle12.setAlignment(CellStyle.ALIGN_CENTER); cellStyle12.setLocked(true); // 显式锁定 XSSFFont fontBoldItalic12 = wb.createFont(); fontBoldItalic12.setBold(true); fontBoldItalic12.setItalic(true); XSSFRichTextString cellValue12 = new XSSFRichTextString(); cellValue12.append("Name", fontBoldItalic12); cell12.setCellValue(cellValue12); cell12.setCellStyle(cellStyle12); // 第1行其他单元格及数据验证逻辑保留,注意所有单元格样式添加setLocked(true) Cell cell13 = row1.createCell(2); XSSFDataValidation dv = null; XSSFDataValidationConstraint dvc = null; XSSFDataValidationHelper dvh = null; CellRangeAddressList addList = new CellRangeAddressList(1, 1, 2, 4); sheet1.addMergedRegion(new CellRangeAddress(1, 1, 2, 4)); dvh = new XSSFDataValidationHelper(sheet1); dvc =(XSSFDataValidationConstraint) dvh.createFormulaListConstraint("Defination!$A$2:$A$" + 40); dv = (XSSFDataValidation) dvh.createValidation(dvc, addList); dv.setSuppressDropDownArrow(true); sheet1.addValidationData(dv); // 给该合并单元格的左上角设置锁定样式 CellStyle cellStyle13 = wb.createCellStyle(); cellStyle13.setFillBackgroundColor(IndexedColors.BROWN.index); cellStyle13.setAlignment(CellStyle.ALIGN_CENTER); cellStyle13.setLocked(true); cell13.setCellStyle(cellStyle13); // 第2行:设置为不可编辑,原有逻辑保留,所有单元格样式添加setLocked(true) Row row2 = sheet1.createRow(2); CellStyle cellStyle17 = wb.createCellStyle(); cellStyle17.setFillBackgroundColor(IndexedColors.LIME.index); cellStyle17.setAlignment(CellStyle.ALIGN_CENTER); cellStyle17.setLocked(true); XSSFRichTextString cellValue17 = null; CellStyle cellStyle18 = wb.createCellStyle(); cellStyle18.setFillBackgroundColor(IndexedColors.CORAL.index); cellStyle18.setAlignment(CellStyle.ALIGN_CENTER); cellStyle18.setLocked(true); XSSFRichTextString cellValue18 = null; int k = 1; for(int j=0;j<27;j++){ Cell cell17 = row2.createCell(j); if(j < 7){ cellValue17 = new XSSFRichTextString(); switch(j){ case 0: cellValue17.append("Class", fontBoldItalic); break; case 1: cellValue17.append("Student_ID", fontBoldItalic); break; case 2: cellValue17.append("Birth_Date", fontBoldItalic); break; case 3: cellValue17.append("Section", fontBoldItalic); break; case 4: cellValue17.append("Strength", fontBoldItalic); break; case 5: cellValue17.append("Subject", fontBoldItalic); break; case 6: cellValue17.append("Marks", fontBoldItalic); break; } cell17.setCellValue(cellValue17); cell17.setCellStyle(cellStyle17); } else { cellValue18 = new XSSFRichTextString(); cellValue18.append("Field_"+k, fontBoldItalic); cell17.setCellValue(cellValue18); cell17.setCellStyle(cellStyle18); k++; } } // 创建可编辑行示例:第3行及以后应用解锁样式 Row editableRow = sheet1.createRow(3); for(int j=0;j<27;j++){ Cell cell = editableRow.createCell(j); cell.setCellValue("可编辑内容"); cell.setCellStyle(editableStyle); } // 开启工作表保护,密码为"0" sheet1.protectSheet("0"); wb.write(fileOut); fileOut.close(); } catch (IOException e){ e.printStackTrace(); } } }
关键注意点
- 合并单元格的锁定状态由左上角单元格的样式决定,无需给合并区域所有单元格重复设置
- 若需批量处理指定行,可遍历这些行的所有单元格,为其样式设置
setLocked(true) - 必须开启工作表保护,否则所有锁定设置都不会生效
内容的提问来源于stack exchange,提问作者Shashank Rastogi
相关产品推荐
相关产品推荐

