使用EasyExcel實現Excel單元格保護:自由鎖定表頭和數據行

使用EasyExcel實現Excel單元格保護:鎖定表頭和第二行數據

前言

在日常開發中,我們經常需要導出Excel文件,有時還需要對Excel中的某些單元格進行保護,防止用戶誤修改。本文將介紹如何使用EasyExcel 4.0.3實現鎖定Excel表頭和第二行數據,同時允許其他單元格自由編輯的功能。

技術背景

EasyExcel是阿里巴巴開源的一個基于Java的簡單、省內存的讀寫Excel工具。它能夠幫助我們輕松實現Excel的各種操作,包括單元格樣式設置、數據保護等。

實現目標

  • 鎖定Excel表頭(第一行)
  • 鎖定第二行數據
  • 允許第三行及之后的數據自由編輯
  • 允許用戶添加新行/列并編輯

Maven依賴

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>4.0.3</version>
</dependency>

核心代碼實現

1. 數據模型定義

public static class TestDataModel {
@ExcelProperty("姓名")
private String name;@ExcelProperty("年齡")
private Integer age;@ExcelProperty("城市")
private String city;// 構造方法和getter/setter省略
}

2. 自定義單元格樣式策略

static class CustomCellStyleStrategy extends HorizontalCellStyleStrategy {
public CustomCellStyleStrategy(WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) {
super(headWriteCellStyle, contentWriteCellStyle);
}@Override
public void afterCellDispose(CellWriteHandlerContext context) {
// 表頭行處理
if (context.getHead()) {
super.afterCellDispose(context);
return;
}// 數據行處理
if (context.getRowIndex() != null) {
if (context.getRowIndex() == 1) {
// 第二行數據,應用鎖定樣式
Cell cell = context.getCell();
Workbook workbook = context.getWriteSheetHolder().getSheet().getWorkbook();// 創建新樣式(基于當前樣式)
CellStyle newStyle = workbook.createCellStyle();
if (cell.getCellStyle() != null) {
newStyle.cloneStyleFrom(cell.getCellStyle());
}
newStyle.setLocked(true); // 設置為鎖定
cell.setCellStyle(newStyle);
} else {
// 其他行應用解鎖樣式
super.afterCellDispose(context);
}
}
}
}

3. 工作表保護處理器

static class SheetProtectionHandler implements SheetWriteHandler {
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
Sheet sheet = writeSheetHolder.getSheet();
Workbook workbook = writeWorkbookHolder.getWorkbook();// 設置整個工作表的默認樣式為可編輯
CellStyle defaultStyle = workbook.createCellStyle();
defaultStyle.setLocked(false);// 設置所有列的默認樣式
int maxColumns = 256;
for (int i = 0; i < maxColumns; i++) {
sheet.setDefaultColumnStyle(i, defaultStyle);
}// 啟用工作表保護(密碼:123)
sheet.protectSheet("123");
}
}

4. 導出Excel主方法

public static void exportExcel(String fileName, List<?> dataList) {
// 定義鎖定樣式
WriteCellStyle lockedStyle = new WriteCellStyle();
lockedStyle.setLocked(true);// 定義解鎖樣式
WriteCellStyle unlockedStyle = new WriteCellStyle();
unlockedStyle.setLocked(false);// 創建處理器實例
HorizontalCellStyleStrategy styleStrategy = new CustomCellStyleStrategy(lockedStyle, unlockedStyle);
SheetWriteHandler sheetProtectionHandler = new SheetProtectionHandler();// 寫入Excel
EasyExcel.write(fileName, TestDataModel.class)
.registerWriteHandler(styleStrategy)
.registerWriteHandler(sheetProtectionHandler)
.sheet("員工數據")
.doWrite(dataList);
}

完整代碼

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;import java.util.ArrayList;
import java.util.List;public class ExcelExporter {public static void main(String[] args) {// 創建測試數據List<TestDataModel> dataList = new ArrayList<>();dataList.add(new TestDataModel("張三", 25, "北京"));dataList.add(new TestDataModel("李四", 30, "上海"));dataList.add(new TestDataModel(null, 28, "廣州"));dataList.add(new TestDataModel("趙六", 35, null));// 導出ExcelexportExcel("test_output.xlsx", dataList);System.out.println("Excel文件已生成: test_output.xlsx");}public static void exportExcel(String fileName, List<?> dataList) {// 1. 定義鎖定樣式(用于表頭和第二行)WriteCellStyle lockedStyle = new WriteCellStyle();lockedStyle.setLocked(true); // 設置單元格鎖定// 2. 定義解鎖樣式(用于第三行及之后的數據)WriteCellStyle unlockedStyle = new WriteCellStyle();unlockedStyle.setLocked(false); // 設置單元格可編輯// 3. 創建自定義樣式策略HorizontalCellStyleStrategy styleStrategy = new CustomCellStyleStrategy(lockedStyle, unlockedStyle);// 4. 創建工作表保護處理器SheetWriteHandler sheetProtectionHandler = new SheetProtectionHandler();// 5. 寫入ExcelEasyExcel.write(fileName, TestDataModel.class).registerWriteHandler(styleStrategy).registerWriteHandler(sheetProtectionHandler).sheet("員工數據").doWrite(dataList);}/*** 自定義單元格樣式策略*/static class CustomCellStyleStrategy extends HorizontalCellStyleStrategy {public CustomCellStyleStrategy(WriteCellStyle headWriteCellStyle, WriteCellStyle contentWriteCellStyle) {super(headWriteCellStyle, contentWriteCellStyle);}/*** 重寫方法,根據行號應用不同樣式** @param context*/@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {// 表頭行(isHead=true)直接使用父類方法,即應用鎖定樣式if (context.getHead()) {super.afterCellDispose(context);return;}// 數據行處理,數據行的格式是解鎖還是鎖定,要看創建時傳參if (context.getRowIndex() != null) {if (context.getRowIndex() == 1) {// 獲取當前單元格Cell cell = context.getCell();Workbook workbook = context.getWriteSheetHolder().getSheet().getWorkbook();// 1. 創建新樣式(基于當前樣式)CellStyle newStyle = workbook.createCellStyle();// 2. 復制當前樣式(如果存在)if (cell.getCellStyle() != null) {newStyle.cloneStyleFrom(cell.getCellStyle());}// 3. 設置為鎖定newStyle.setLocked(true);// 4. 應用新樣式cell.setCellStyle(newStyle);} else {super.afterCellDispose(context);}}}}/*** 工作表保護處理器*/static class SheetProtectionHandler implements SheetWriteHandler {@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Sheet sheet = writeSheetHolder.getSheet();Workbook workbook = writeWorkbookHolder.getWorkbook();// 1. 設置整個工作表的默認樣式為可編輯CellStyle defaultStyle = workbook.createCellStyle();defaultStyle.setLocked(false); // 解鎖所有單元格// 設置所有列的默認樣式(假設最大列數為256)int maxColumns = 256;for (int i = 0; i < maxColumns; i++) {sheet.setDefaultColumnStyle(i, defaultStyle);}// 3. 啟用工作表保護(使用空密碼)sheet.protectSheet("123");}}// 測試數據模型public static class TestDataModel {@ExcelProperty("姓名")private String name;@ExcelProperty("年齡")private Integer age;@ExcelProperty("城市")private String city;public TestDataModel() {// 無參構造函數}public TestDataModel(String name, Integer age, String city) {this.name = name;this.age = age;this.city = city;}// Getters and Setterspublic String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}}
}

關鍵點解析

  1. 樣式繼承機制
  • 表頭行直接應用鎖定樣式
  • 第二行顯式創建并應用鎖定樣式
  • 其他行應用解鎖樣式
  1. 工作表保護
  • 設置所有列默認可編輯
  • 啟用工作表保護(密碼保護)
  • 只有鎖定樣式的單元格受到保護
  1. 單元格處理流程
  • 每個單元格獨立處理
  • 樣式應用是逐個單元格進行的
  • 顯式設置覆蓋所有默認行為

效果驗證

生成的Excel文件將具有以下特性:

  1. 鎖定區域
  • 第一行(表頭):完全鎖定
  • 第二行(第一行數據):完全鎖定
  1. 可編輯區域
  • 第三行及之后的數據行
  • 工作表的空白區域
  • 新添加的行/列
  1. 保護機制
  • 需要密碼"123"才能修改受保護區域
  • 可編輯區域可以直接修改

總結

通過EasyExcel的樣式策略和工作表保護機制,我們實現了靈活控制Excel單元格編輯權限的功能。這種方案具有以下優點:

  1. 精確控制:可以精確鎖定特定行/列
  2. 靈活性:不影響用戶在其他區域的編輯
  3. 兼容性:適用于各種數據模型
  4. 易擴展:可以輕松調整鎖定策略

這種實現方式特別適用于需要保護表頭和示例數據,同時允許用戶自由編輯其他數據的場景,如數據模板導出等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95295.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95295.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

dify docker知識庫topk最大值參數配置

1 問題說明 dify構建RAG知識庫過程中&#xff0c;通過會遇到一些默認配置不能解決的問題。 比如topk&#xff0c;topk默認最大10&#xff0c;對語義模糊的檢索&#xff0c;目標文檔可能沒進前10&#xff0c;出現在10-30區間。 所以&#xff0c;需要調整topk最大值參數。 # T…

SRE命令行兵器譜之一:精通top/htop - 從性能“體檢”到瓶頸“解剖”

SRE命令行兵器譜之一:精通top/htop - 從性能“體檢”到瓶頸“解剖” SRE的“戰場”:真實故障場景 下午三點,監控系統告警:“核心API服務響應時間(P99)飆升至5秒”。用戶已經開始在群里抱怨接口超時。這是一個典型的線上性能問題,每一秒的延遲都在影響用戶體驗和公司收…

一、Git與Gitee常見問題解答

Git與Gitee常見問題解答 Git相關問題 Q1: 什么是Git&#xff1f; A: Git是一個分布式版本控制系統&#xff0c;由Linux之父Linus Torvalds開發。它能夠跟蹤文件的變更歷史&#xff0c;支持多人協作開發&#xff0c;是現代軟件開發中不可或缺的工具。 Q2: Git的三個區域是什么&a…

kubernetes服務質量之QoS類

一、QoS類 Kubernetes的QoS&#xff08;Quality of Service&#xff09;類別允許您指定可用于應用程序的可用資源數量&#xff0c;以便更好地控制應用程序的可用性。它還允許您限制特定應用程序的資源使用率&#xff0c;以幫助保護系統的穩定性和性能。 Kubernetes 創建 Pod 時…

Redis--Lua腳本以及在SpringBoot中的使用

前言、為什么要用 Lua&#xff1f;多步操作合并為一步&#xff0c;保證原子性。減少網絡通信次數。下推邏輯到 Redis&#xff0c;提高性能。一、Redis 使用 Lua 腳本的兩種方式方式一&#xff1a;使用 --eval 執行腳本文件這種方式 需要先寫一個 Lua 文件。&#x1f4cc; 示例&…

基于 C 語言的網絡單詞查詢系統設計與實現(客戶端 + 服務器端)

一、項目概述本文將介紹一個基于 C 語言開發的網絡單詞查詢系統&#xff0c;該系統包含客戶端和服務器端兩部分&#xff0c;支持用戶注冊、登錄、單詞查詢及歷史記錄查詢等功能。系統采用 TCP socket 實現網絡通信&#xff0c;使用 SQLite 數據庫存儲用戶信息、單詞數據及查詢記…

《JAVA EE企業級應用開發》第一課筆記

《JAVA EE企業級應用開發》第一課筆記 文章目錄《JAVA EE企業級應用開發》第一課筆記課程主題&#xff1a;三層架構與SSM框架概述一、核心架構&#xff1a;三層架構 (MVC)1. 表現層 (Presentation Layer)2. 業務邏輯層 (Business Logic Layer)3. 數據持久層 (Data Persistence …

RT-DETR網絡結構

1.前言 本章主要來介紹下RT-DETR的網絡結構,參考的依舊是ultralytics實現的RT-DETR-L,代碼如下: ultralytics/ultralytics: Ultralytics YOLO ?? 首先談談我對RT-DETR的淺顯認識,他不像是YOLOv8這種純CNN實現的網絡,也不像是Vit這種以Transformer實現的網絡,他是前一…

Python 文件復制實戰指南:從基礎操作到高效自動化的最佳實踐

Python 文件復制實戰指南:從基礎操作到高效自動化的最佳實踐 1. 引言:文件復制為何是自動化的核心能力? 在日常開發與運維工作中,文件復制是一項基礎卻至關重要的操作。無論是備份日志、同步配置、部署代碼,還是批量遷移數據,都離不開對文件的精準復制與路徑管理。而 Py…

WebSocket的基本使用方法

一. 與HTTP對比WebSocket 是一種在單個 TCP 連接上實現全雙工&#xff08;雙向&#xff09;通信的網絡協議&#xff0c;它解決了傳統 HTTP 協議 “請求 - 響應” 模式的局限性&#xff0c;讓客戶端&#xff08;如瀏覽器&#xff09;和服務器能建立持久連接&#xff0c;實現實時…

架構選型:為何用對象存儲替代HDFS構建現代數據湖

在過去十余年的大數據浪潮中&#xff0c;Hadoop及其核心組件HDFS&#xff08;Hadoop分布式文件系統&#xff09;無疑是整個技術生態的基石。它開創性地解決了海量數據的分布式存儲難題&#xff0c;支撐了無數企業從數據中挖掘價值。然而&#xff0c;隨著數據規模的指數級增長以…

智能養花誰更優?WebIDE PLOY技術與裝置的結合及實踐價值 —— 精準養護的賦能路徑

一、WebIDEPLOY 技術支撐下的智能養花系統核心構成在 WebIDEPLOY 技術的框架下&#xff0c;智能養花裝置形成了一套精準協同的閉環系統&#xff0c;其核心在于通過技術整合實現 “監測 - 決策 - 執行 - 遠程交互” 的無縫銜接&#xff0c;讓植物養護更貼合城市居民的生活節奏。…

基于llama.cpp在CPU環境部署Qwen3

大家好,我是奇文王語,NLP愛好者,長期分享大模型實戰技巧,歡迎關注交流。 最近兩天在研究如何使用小規模參數的模型在CPU環境上進行落地應用,比如模型Qwen3-0.6B。開始使用Transformers庫能夠正常把模型服務進行部署起來,但是通過測試速度比較慢,用戶的體驗會比較差。 …

?NAT穿透技術原理:P2P通信中的打洞機制解析?

要說網絡世界里的 “幕后功臣”&#xff0c;NAT 絕對得算一個&#xff0c;大家伙兒有沒有琢磨過&#xff0c;為啥家里的電腦、手機&#xff0c;還有公司那一堆設備&#xff0c;都能同時連上網&#xff0c;還不打架呢&#xff1f; NAT 這東西&#xff0c;全名叫網絡地址轉換&am…

工業 5G + AI:智能制造的未來引擎

工業 5G AI&#xff1a;智能制造的未來引擎 文章目錄工業 5G AI&#xff1a;智能制造的未來引擎摘要一、為什么工業需要 5G&#xff1f;二、工業 5G 的典型應用場景1. 智能制造工廠2. 遠程控制與運維3. 智慧物流與倉儲4. 能源、電力、礦山5. 智慧港口與交通三、成功案例解析1…

邊緣計算設備 RK3576芯片

RK3576是瑞芯微&#xff08;Rockchip&#xff09;公司專為人工智能物聯網&#xff08;AIoT&#xff09;市場精心設計的一款高算力、高性能及低功耗的國產化應用處理器。該處理器采用了先進的ARM架構&#xff0c;集成了四個ARM Cortex-A72高性能核心與四個ARM Cortex-A53高效能核…

ROS1系列學習筆記之T265的Python數據訂閱顯示、串口輸出到凌霄飛控,以及開機自啟動設置等一些問題處理方法(持續更新)

前言 關于T265的環境配置與安裝&#xff0c;在前兩期的ROS筆記中已經提及&#xff0c;包括英特爾本家的SDK安裝&#xff0c;以及對應支持版本的ROS支持開發工具包。 ROS1系列學習筆記之Linux&#xff08;Ubuntu&#xff09;的環境安裝、依賴準備、踩坑提示&#xff08;硬件以…

UART控制器——ZYNQ學習筆記14

UART 控制器是一個全雙工異步收發控制器&#xff0c; MPSoC 內部包含兩個 UART 控制器&#xff0c; UART0 和 UART1。每一個 UART 控制器支持可編程的波特率發生器、 64 字節的接收 FIFO 和發送 FIFO、產生中斷、 RXD 和TXD 信號的環回模式設置以及可配置的數據位長度、停止位和…

C++ 登錄狀態機項目知識筆記

C 登錄狀態機項目知識筆記 1. 項目源碼 1.1 login_state_machine.h #pragma once#include <string>// 登錄狀態枚舉 enum class LoginState { IDLE, AUTHENTICATING, SUCCESS, FAILURE, LOCKED };// 登錄事件枚舉 enum class LoginEvent { REQUEST, SUCCESS, FAILURE, RE…

docker-nacos-v3

nacos官網&#xff1a; Redirecting to: https://nacos.io/ 服務發現和服務健康監測 Nacos 支持基于 DNS 和基于 RPC 的服務發現。服務提供者使用 原生SDK、OpenAPI、或一個獨立的Agent TODO注冊 Service 后&#xff0c;服務消費者可以使用DNS TODO 或HTTP&API查找和發現服…