EasyExcel 公式计算大全

EasyExcel 是基于 Apache POI 的封装,主要专注于简化 Excel 的读写操作,对于公式计算的支持相对有限。以下是 EasyExcel 中处理公式计算的全面指南:


1. 基本公式写入

1.1 写入简单公式

@Data
public class FormulaData {@ExcelProperty("数值1")private Double value1;@ExcelProperty("数值2")private Double value2;@ExcelProperty("求和")private String sumFormula;@ExcelProperty("平均值")private String avgFormula;
}// 写入公式
List<FormulaData> list = new ArrayList<>();
FormulaData data = new FormulaData();
data.setValue1(10.0);
data.setValue2(20.0);
data.setSumFormula("SUM(A2,B2)");  // 引用当前行的单元格
data.setAvgFormula("AVERAGE(A2,B2)");
list.add(data);EasyExcel.write("formula_example.xlsx", FormulaData.class).sheet("公式示例").doWrite(list);

1.2 使用绝对引用

data.setSumFormula("SUM($A$2:$B$2)");  // 绝对引用

2. 读取包含公式的Excel

2.1 基本读取

// 监听器实现
public class FormulaDataListener extends AnalysisEventListener<FormulaData> {@Overridepublic void invoke(FormulaData data, AnalysisContext context) {// 这里获取的是公式计算后的值System.out.println("求和结果: " + data.getSumFormula());}@Overridepublic void doAfterAllAnalysed(ActionContext context) {}
}// 读取文件
EasyExcel.read("formula_example.xlsx", FormulaData.class, new FormulaDataListener()).sheet().doRead();

2.2 获取公式本身(而非计算结果)

public class FormulaReadListener extends AnalysisEventListener<Map<Integer, String>> {@Overridepublic void invoke(Map<Integer, String> data, AnalysisContext context) {// 获取底层CellReadCellData<?> cellData = (ReadCellData<?>) data.get(2); // 第三列if (cellData.getFormulaData() != null) {System.out.println("公式内容: " + cellData.getFormulaData());}}
}EasyExcel.read("formula_example.xlsx", new FormulaReadListener()).sheet().doRead();

3. 动态公式设置

3.1 使用拦截器动态设置公式

public class FormulaWriteHandler implements CellWriteHandler {@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {if (!isHead && head.getFieldName().equals("sumFormula")) {// 设置求和公式,如SUM(A2,B2)int rowNum = cell.getRowIndex() + 1; // Excel行号从1开始String formula = String.format("SUM(A%d,B%d)", rowNum, rowNum);cell.setCellFormula(formula);}}
}// 使用
EasyExcel.write("dynamic_formula.xlsx", FormulaData.class).registerWriteHandler(new FormulaWriteHandler()).sheet().doWrite(dataList);

3.2 复杂公式示例

// IF函数示例
String ifFormula = "IF(A2>B2, \"A大于B\", IF(A2<B2, \"A小于B\", \"A等于B\"))";// VLOOKUP函数示例
String vlookupFormula = "VLOOKUP(D2,$A$2:$B$10,2,FALSE)";// 日期函数
String dateFormula = "TEXT(TODAY(),\"yyyy-mm-dd\")";

4. 公式计算控制

4.1 强制重新计算公式

// 写入后强制计算
ExcelWriter excelWriter = EasyExcel.write("output.xlsx", FormulaData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
excelWriter.write(dataList, writeSheet);// 获取底层Workbook并强制重新计算
SXSSFWorkbook workbook = (SXSSFWorkbook) excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();excelWriter.finish();

4.2 设置不计算公式(仅保留公式)

// 在读取时不计算公式
EasyExcel.read("input.xlsx", new FormulaReadListener()).ignoreEmptyRow(false).autoTrim(true).formulaResult(false)  // 不计算公式结果.sheet().doRead();

5. 常见函数示例

5.1 数学函数

// 基本数学运算
String addFormula = "A2+B2";
String multiplyFormula = "PRODUCT(A2,B2)";
String roundFormula = "ROUND(A2,2)";// 条件求和
String sumifFormula = "SUMIF(A2:A10,\">10\",B2:B10)";

5.2 文本函数

// 连接文本
String concatFormula = "CONCATENATE(A2,\"-\",B2)";// 提取子串
String leftFormula = "LEFT(A2,3)";
String midFormula = "MID(A2,2,3)";

5.3 日期函数

// 计算日期差
String dateDiffFormula = "DATEDIF(A2,B2,\"d\")";// 添加天数
String addDaysFormula = "A2+7";  // A2是日期单元格

6. 高级技巧

6.1 跨工作表公式

// 引用其他工作表的单元格
String crossSheetFormula = "SUM(Sheet2!A1:A10)";// 引用其他工作簿(需要文件在同一目录)
String externalRefFormula = "'[OtherWorkbook.xlsx]Sheet1'!A1";

6.2 数组公式

// 数组公式需要用大括号包围
String arrayFormula = "{SUM(A2:A10*B2:B10)}";// 写入时需要特殊处理
cell.setCellFormula("SUM(A2:A10*B2:B10)");
// 然后需要将单元格标记为数组公式区域
CellRangeAddress range = new CellRangeAddress(cell.getRowIndex(), cell.getRowIndex(),cell.getColumnIndex(), cell.getColumnIndex());
sheet.addMergedRegion(range);
sheet.setArrayFormula(cell.getCellFormula(), range);

6.3 命名范围公式

// 创建命名范围
Name namedRange = workbook.createName();
namedRange.setNameName("SalesData");
namedRange.setRefersToFormula("Sheet1!$A$2:$A$10");// 使用命名范围
String namedRangeFormula = "SUM(SalesData)";
// 1. 定义数据类
@Data
public class FinancialData {@ExcelProperty("月份")private String month;@ExcelProperty("收入")private Double income;@ExcelProperty("支出")private Double expense;@ExcelProperty("利润")private String profitFormula;@ExcelProperty("利润率")private String marginFormula;
}// 2. 公式写入处理器
public class FinancialFormulaHandler implements CellWriteHandler {@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {if (!isHead) {int rowNum = cell.getRowIndex() + 1;String column = head.getFieldName();if ("profitFormula".equals(column)) {cell.setCellFormula(String.format("B%d-C%d", rowNum, rowNum));} else if ("marginFormula".equals(column)) {cell.setCellFormula(String.format("(B%d-C%d)/B%d", rowNum, rowNum, rowNum));// 设置百分比格式CellStyle style = writeSheetHolder.getSheet().getWorkbook().createCellStyle();style.setDataFormat((short)0xa);  // 百分比格式cell.setCellStyle(style);}}}
}// 3. 使用示例
public void exportFinancialReport() {List<FinancialData> dataList = new ArrayList<>();// 添加数据...ExcelWriter excelWriter = EasyExcel.write("financial_report.xlsx", FinancialData.class).registerWriteHandler(new FinancialFormulaHandler()).build();WriteSheet writeSheet = EasyExcel.writerSheet("财务报告").build();excelWriter.write(dataList, writeSheet);// 强制计算公式SXSSFWorkbook workbook = (SXSSFWorkbook) excelWriter.writeContext().writeWorkbookHolder().getWorkbook();workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();excelWriter.finish();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917227.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年AI+数模竞赛培训意见征集-最后一轮

在过去几天的“AI时代下2025年数模竞赛培训课程需求调研紧急征集”我们收到了大量老师、学生的反馈。我们通过大家的实际需求&#xff0c;编写了下述2025年AI时代下最新的数学建模竞赛教学课程课程表&#xff0c;具体授课内容以及相关课件、支撑材料都将会免费发布&#xff0c;…

Qwen2 RotaryEmbedding 位置编码仅仅是第一层有吗

Qwen2 RotaryEmbedding 位置编码仅仅是第一层有吗,还是全部层都有 Qwen2 模型中的 Rotary Embedding(旋转位置编码)是应用于所有 Transformer 层 的,而非仅第一层。 1. Transformer 架构的核心逻辑 Qwen2 基于 Decoder-only Transformer 架构,而位置编码(如 Rotary Emb…

CNN卷积神经网络之LeNet和AlexNet经典网络模型(三)

CNN卷积神经网络之LeNet和AlexNet经典网络模型&#xff08;三&#xff09; 文章目录CNN卷积神经网络之LeNet和AlexNet经典网络模型&#xff08;三&#xff09;深度学习两大经典 CNN 模型速览1. LeNet-5&#xff1a;CNN 的开山之作&#xff08;1998&#xff09;2. AlexNet&#…

江协科技STM32 12-2 BKP备份寄存器RTC实时时钟

这一节我们要讲的主要内容是RTC实时时钟&#xff0c;实时时钟本质上是一个定时器&#xff0c;但是这个定时器是专门用来产生年月日时分秒&#xff0c;这种日期和时间信息的。所以学会了STM32的RTC就可以在STM32内部拥有一个独立运行的钟表。想要记录或读取日期和时间&#xff0…

【10】大恒相机SDK C++开发 ——对相机采集的原图像数据IFrameData裁剪ROI 实时显示在pictureBox中,3种方法实现(效率不同)

文章目录1 在回调函数中实现2 独立封装调用2.1 获取图像宽、高、pBuffer、channel2.2 内存图像数据截取ROI并显示2.3 回调函数调用3 for循环嵌套 方法24 for循环嵌套 方法35 按行复制数据提高效率&#xff0c;但很耗内存6 unsafe代码 解释及注意事项 看我另一篇文章7 ConvertTo…

ubuntu22.04系统入门 linux入门(二) 简单命令 多实践以及相关文件管理命令

以下有免费的4090云主机提供ubuntu22.04系统的其他入门实践操作 地址&#xff1a;星宇科技 | GPU服务器 高性能云主机 云服务器-登录 相关兑换码星宇社区---4090算力卡免费体验、共享开发社区-CSDN博客 之所以推荐给大家使用&#xff0c;是因为上面的云主机目前是免费使用的…

分布式ID方案(标记)

一、参考文章-标记 分布式ID方案有哪些&#xff1f;雪花算法如何搞定时钟回拨和动态机器ID&#xff1f; 二、应用 1.百度 uid-generator github项目地址 原理参考 2.百度 uid-generator 扩展应用 灯官网 灯 项目代码 lamp-util 单元模块 lamp-util 单元模块子模块 lamp-…

std::map 加锁

在并发环境下使用std::map&#xff0c;必须采取同步措施。 在并发环境下对 std::map 进行不加锁的读写操作会导致严重的线程安全问题&#xff0c;主要会产生以下几种问题&#xff1a; ⚠️ 主要风险与后果数据竞争&#xff08;Data Race&#xff09; 当多个线程同时修改同一个键…

学习笔记090——Ubuntu 中 UFW 防火墙的使用

文章目录1、允许特定的端口访问2、允许特定 IP 访问某个端口3、允许某个范围的端口4、查看 UFW 状态5、重新加载 UFW6、启用 UFW7、关闭 UFW1、允许特定的端口访问 # 允许 TCP 端口&#xff08;例如 80&#xff09;&#xff1a; sudo ufw allow 80/tcp# 允许 UDP 端口&#xf…

移动端 WebView 内存泄漏与性能退化问题如何排查 实战调试方法汇总

在混合 App 应用中&#xff0c;WebView 页面常承载复杂业务逻辑与交互。随着用户使用时间增长&#xff0c;特别在切换多个页面或反复打开界面后&#xff0c;常常会出现性能下降、页面卡顿、甚至白屏崩溃等现象。这通常是因为页面存在内存泄漏、事件监听未解绑或垃圾回收阻塞导致…

JSON 对象在浏览器中顺序与后端接口返回不一致的问题

一、问题描述 后端接口返回一个字典表的JSON对象&#xff0c;页面展示排序与预期排序不一致。 在浏览器调试面板Response中看到接口原始响应字符串&#xff0c;是期望顺序&#xff1a;在Preview中看到&#xff0c; key “22” 被提到最前&#xff0c;顺序发生变化&#xff1a;页…

Spring MVC数据传递全攻略

Spring MVC数据传递一、前端到后端的数据传递1. 使用 RequestParam 传递简单参数2. 使用 PathVariable传递路径参数3. 使用RequestBody传递 JSON 数据二、后端到前端的数据传递1. 使用Model或 ModelAndView传递数据到前端2. 使用HttpServletResponse直接写回数据3.使用Response…

仓库管理系统-12-前端之头部区域Header基于嵌套路由访问个人中心

文章目录 1 个人中心 1.1 DateUtils.vue(子组件) 1.2 Home.vue(父组件) 1.3 router/index.js(嵌套路由) 1.4 index.vue(路由占位符) 2 Header.vue 2.1 页面布局 2.2 toUser方法 2.3 初始加载 2.4 Header.vue 头部区域Header中有一个个人中心下拉菜单,点击个人中心选项,通过嵌…

【智能协同云图库】第七期:基于AI调用阿里云百炼大模型,实现AI图片编辑功能

摘要&#xff1a;AI 高速发展赋能传统业务&#xff0c;图库网站亦有诸多 AI 应用空间。以 AI 扩图功؜能为例&#xff0c;让我们来学习如何在项目⁠中快速接入 AI 绘图大模型。‏用户可以选择一张已上传的图片&#xff0c;‌通过 AI 扩图得到新的图片&#xff0c;希望可以帮到大…

Notepad++插件安装

方式一&#xff1a;自动安装&#xff08;有些notepad并不好用&#xff0c;推荐方式二&#xff09;工具栏-》插件-》插件管理如下点击安装后会提示&#xff0c;后端安装&#xff0c;安装成功后自动启动&#xff0c;本人使用的v8.6.4的版本&#xff0c;插件基本都无法自动安装&am…

git pull和git fetch的区别

git pull和git fetch是git版本控制系统中的两个基本命令&#xff0c;它们都用于从远程仓库更新本地仓库的信息&#xff0c;但执行的具体操作不同。git fetch:git fetch下载远程仓库最新的内容到你的本地仓库&#xff0c;但它并不自动合并或修改你当前的工作。它取回了远程仓库的…

Item35:考虑virtual函数以外的其他选择

在C++中,虚函数是实现多态的传统方式,但并非唯一选择。过度依赖虚函数可能导致派生类与基类的强耦合,或难以在运行时灵活切换行为。《Effective C++》Item35指出:应根据场景选择更合适的替代方案,包括NVI模式、函数指针、策略模式等。本文解析这些方案的原理、适用场景及实…

Vue3 状态管理新选择:Pinia 从入门到实战

一、什么是pinia? 在 Vue3 生态中&#xff0c;状态管理一直是开发者关注的核心话题。随着 Vuex 的逐步淡出&#xff0c;Pinia 作为官方推荐的状态管理库&#xff0c;凭借其简洁的 API、强大的功能和对 Vue3 特性的完美适配&#xff0c;成为了新时代的不二之选。今天我们就来深…

Unity相机控制

相机的控制无非移动和旋转&#xff0c;每种操作各3个轴6个方向&#xff0c;一共12种方式。在某些需要快速验证的项目或Demo里常常需要丝滑的控制相机调试效果。相机控制虽然不是什么高深的技术&#xff0c;但是要写的好用还是很磨人的。 锁定Z轴的旋转 一个自由的相机可以绕 …

vue2 使用liveplayer加载视频

vue2 使用liveplayer加载视频 官网: https://www.liveqing.com/docs/manuals/LivePlayer.html支持WebRTC/MP4播放;支持m3u8/HLS播放;支持HTTP-FLV/WS-FLV/RTMP播放;支持直播和点播播放;支持播放器快照截图;支持点播多清晰度播放;支持全屏或比例显示;自动检测IE浏览器兼容播放;支…