参考:https://www.cnblogs.com/cjbbk/p/7527276.html
解决POI3.17 与其它版本的不同的坑:https://blog.csdn.net/Weirdo_zhu/article/details/79912606
3.17 非常详细:https://www.cnblogs.com/huajiezh/p/5467821.html
参考:http://www.360doc.com/content/17/1101/11/40984640_699967795.shtml
POI 冻结某一行:
在POI中 有createFreezePane方法能直接固定单元格,具体参数如下:
sheet.createFreezePane(int cellNum,int rowNum,int firstCellNum,int firstRollNum );
四个参数分别代表:
cellNum:表示要冻结的列数;
rowNum:表示要冻结的行数;
firstCellNum:表示被固定列右边第一列的列号;
firstRollNum :表示被固定行下边第一列的行号;
注意: 后2个参数均从0开始计算列号和行号,且firstCellNum>=cellNum &&firstRollNum >=cellNum
如:
// 冻结第一行
sheet1.createFreezePane( 0, 1, 0, 1 );
// 冻结第一列
sheet2.createFreezePane( 1, 0, 1, 0 );
sheet.createFreezePane(1,0,1,0);//就是固定了首列,列号的显示为:A,BCDEF...
sheet.createFreezePane(1,0,3,0);//固定了首列,列号的显示为:A,DEF...
//注意:BC列不是被隐藏,而是默认显示列为A,DEF,若想要看BC列,只需移动滚轮即可.行号同理 --------------------- 原文:https://blog.csdn.net/qq_24076135/article/details/77449898?utm_source=copy
依赖:
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>3.17</version> </dependency>
注释,下拉选(生成execl基本使用)

package com.icil.esolution; import static org.junit.Assert.*; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Date; import org.apache.poi.hssf.usermodel.DVConstraint; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFRichTextString; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.Test; import org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration; public class ReadExcelByPOITest { @Test public void CreateExceltest01() throws Exception { Workbook[] wbs = new Workbook[] { new HSSFWorkbook(), new XSSFWorkbook() }; Workbook workbook = new HSSFWorkbook(); // 得到一个POI的工具类 CreationHelper createHelper = workbook.getCreationHelper(); // 在Excel工作簿中建一工作表,其名为缺省值, 也可以指定Sheet名称 Sheet sheet = workbook.createSheet(); // Sheet sheet = workbook.createSheet("SheetName"); // 用于格式化单元格的数据 DataFormat format = workbook.createDataFormat(); // 设置字体 Font font = workbook.createFont(); font.setFontHeightInPoints((short) 20); // 字体高度 font.setColor(Font.COLOR_RED); // 字体颜色 font.setFontName("黑体"); // 字体 // font.setBoldweight(Font.BOLDWEIGHT_BOLD); // 宽度 font.setItalic(true); // 是否使用斜体 // font.setStrikeout(true); //是否使用划线 // 设置单元格类型 CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框 cellStyle.setBorderLeft(BorderStyle.THIN);// 左边框 cellStyle.setBorderTop(BorderStyle.THIN);// 上边框 cellStyle.setBorderRight(BorderStyle.THIN);// 右边框 cellStyle.setFont(font); // cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平布局:居中 cellStyle.setWrapText(true); CellStyle cellStyle2 = workbook.createCellStyle(); cellStyle2.setDataFormat(format.getFormat("#, ## 0.0")); CellStyle cellStyle3 = workbook.createCellStyle(); cellStyle3.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm:ss")); // 添加单元格注释 // 创建Drawing对象,Drawing是所有注释的容器. Drawing drawing = sheet.createDrawingPatriarch(); // ClientAnchor是附属在WorkSheet上的一个对象, 其固定在一个单元格的左上角和右下角. ClientAnchor anchor = createHelper.createClientAnchor(); // 设置注释位子 anchor.setRow1(0); anchor.setRow2(2); anchor.setCol1(0); anchor.setCol2(2); // 定义注释的大小和位置,详见文档 Comment comment = drawing.createCellComment(anchor); // 设置注释内容 RichTextString str = createHelper.createRichTextString("hello sea"); comment.setString(str); // 设置注释作者. 当鼠标移动到单元格上是可以在状态栏中看到该内容. comment.setAuthor("Sea"); //注释方法2 // 定义注释的大小和位置,详见文档 /** * 前面四个参数:指定位置://从那一行开始,到那一行结束,从那一列开始,到那一列结束; */ Comment comment1 = drawing.createCellComment(new HSSFClientAnchor(0,0,0,0, (short)4, 2 ,(short) 6, 5)); // 设置注释内容 comment1.setString(str); //下拉选 //(int firstRow, int lastRow, int firstCol, int lastCol) //从那一行开始,到那一行结束,从那一列开始,到那一列结束; CellRangeAddressList regions = new CellRangeAddressList(0, 65535,0, 0); DVConstraint constraint =DVConstraint.createExplicitListConstraint(new String[] { "百度","阿里", "腾讯" });//限制只能选中这些值,否则报错 HSSFDataValidation dataValidate = new HSSFDataValidation(regions,constraint); sheet.addValidationData(dataValidate); // 定义几行 for (int rownum = 0; rownum < 10; rownum++) { // 创建行 Row row = sheet.createRow(rownum); // 创建单元格 Cell cell = row.createCell((short) 1); cell.setCellValue(createHelper.createRichTextString("Hello!" + rownum));// 设置单元格内容 cell.setCellStyle(cellStyle);// 设置单元格样式 cell.setCellType(Cell.CELL_TYPE_STRING);// 指定单元格格式:数值、公式或字符串 /** * 说明注释是唯一的,只会加载一个地方,在for 循环中.默认会加载到最后一个地方 */ cell.setCellComment(comment);// 添加注释 // 格式化数据 Cell cell2 = row.createCell((short) 3); //参数表示在那一列显示(起始值为0) cell2.setCellValue(11111.25); cell2.setCellStyle(cellStyle2); Cell cell3 = row.createCell((short) 7); cell3.setCellValue(new Date()); cell3.setCellStyle(cellStyle3); sheet.autoSizeColumn((short) 1); // 调整第一列宽度 //数子是+1 列 sheet.autoSizeColumn((short) 3); // 调整第二列宽度 sheet.autoSizeColumn((short) 0); // 调整第三列宽度 sheet.autoSizeColumn((short) 7); // 调整第四列宽度 } // 合并单元格//四个参数:前两个表示行:从哪行开始到哪一行结束 后面两个参数:从哪一列开始到哪以咧结束 sheet.addMergedRegion(new CellRangeAddress(1, // 第一行(0) 2, // last row(0-based) 1, // 第一列(基于0) 2 // 最后一列(基于0) )); // 保存 String filename = "/home/sea/Desktop/workbook01.xls"; if (workbook instanceof XSSFWorkbook) { filename = filename + "x"; } FileOutputStream out = new FileOutputStream(filename); workbook.write(out); out.close(); } }
自定义下拉选错误提示 可参考:http://wuhaidong.iteye.com/blog/2039848

/** * excel添加下拉数据校验 * @param sheet 哪个 sheet 页添加校验 * @param dataSource 数据源数组 * @param col 第几列校验(0开始) * @return */ public static DataValidation createDataValidation(Sheet sheet, String[] dataSource, int col) { CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 65535, col, col); DataValidationHelper helper = sheet.getDataValidationHelper(); DataValidationConstraint constraint = helper.createExplicitListConstraint(dataSource); DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList); //处理Excel兼容性问题 if (dataValidation instanceof XSSFDataValidation) { dataValidation.setSuppressDropDownArrow(true); dataValidation.setShowErrorBox(true); } else { dataValidation.setSuppressDropDownArrow(false); } dataValidation.setEmptyCellAllowed(true); dataValidation.setShowPromptBox(true); dataValidation.createPromptBox("提示", "只能选择下拉框里面的数据"); return dataValidation; } 作者:赛亚人之神 链接:https://www.jianshu.com/p/3fb7feca9685 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
未修改:联动

import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.poi.hssf.usermodel.DVConstraint; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFDataFormat; import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.util.CellRangeAddressList; public class ExcelLinkage { // 样式 private HSSFCellStyle cellStyle; // 初始化省份数据 private List<String> province = new ArrayList<String>(Arrays.asList("湖南", "广东")); // 初始化数据(湖南的市区) private List<String> hnCity = new ArrayList<String>(Arrays.asList("长沙市", "邵阳市")); // 初始化数据(广东市区) private List<String> gdCity = new ArrayList<String>(Arrays.asList("深圳市", "广州市")); public void setDataCellStyles(HSSFWorkbook workbook, HSSFSheet sheet) { cellStyle = workbook.createCellStyle(); // 设置边框 cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); // 设置背景色 cellStyle.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index); cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); // 设置居中 cellStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 设置字体 HSSFFont font = workbook.createFont(); font.setFontName("宋体"); font.setFontHeightInPoints((short) 11); // 设置字体大小 cellStyle.setFont(font);// 选择需要用到的字体格式 // 设置单元格格式为文本格式(这里还可以设置成其他格式,可以自行百度) HSSFDataFormat format = workbook.createDataFormat(); cellStyle.setDataFormat(format.getFormat("@")); } /** * 创建数据域(下拉联动的数据) * * @param workbook * @param hideSheetName * 数据域名称 */ private void creatHideSheet(HSSFWorkbook workbook, String hideSheetName) { // 创建数据域 HSSFSheet sheet = workbook.createSheet(hideSheetName); // 用于记录行 int rowRecord = 0; // 获取行(从0下标开始) HSSFRow provinceRow = sheet.createRow(rowRecord); // 创建省份数据 this.creatRow(provinceRow, province); // 根据省份插入对应的市信息 rowRecord++; for (int i = 0; i < province.size(); i++) { List<String> list = new ArrayList<String>(); // 我这里是写死的 , 实际中应该从数据库直接获取更好 if (province.get(i).toString().equals("湖南")) { // 将省份名称放在插入市的第一列, 这个在后面的名称管理中需要用到 list.add(0, province.get(i).toString()); list.addAll(hnCity); } else { list.add(0, province.get(i).toString()); list.addAll(gdCity); } //获取行 HSSFRow Cityrow = sheet.createRow(rowRecord); // 创建省份数据 this.creatRow(Cityrow, list); rowRecord++; } } /** * 创建一列数据 * * @param currentRow * @param textList */ public void creatRow(HSSFRow currentRow, List<String> text) { if (text != null) { int i = 0; for (String cellValue : text) { // 注意列是从(1)下标开始 HSSFCell userNameLableCell = currentRow.createCell(i++); userNameLableCell.setCellValue(cellValue); } } } /** * 名称管理 * * @param workbook * @param hideSheetName * 数据域的sheet名 */ private void creatExcelNameList(HSSFWorkbook workbook, String hideSheetName) { Name name; name = workbook.createName(); // 设置省名称 name.setNameName("province"); name.setRefersToFormula(hideSheetName + "!$A$1:$" + this.getcellColumnFlag(province.size())+ "$1"); // 设置省下面的市 for (int i = 0; i < province.size(); i++) { List<String> num = new ArrayList<String>(); if (province.get(i).toString().equals("湖南")) { name = workbook.createName(); num.add(0,province.get(i).toString()); num.addAll(hnCity); name.setNameName(province.get(i).toString()); name.setRefersToFormula(hideSheetName + "!$B$" + (i + 2) + ":$" + this.getcellColumnFlag(num.size()) + "$" + (i + 2)); } else { name = workbook.createName(); num.add(0,province.get(i).toString()); num.addAll(gdCity); name.setNameName(province.get(i).toString()); name.setRefersToFormula(hideSheetName + "!$B$" + (i + 2) + ":$" + this.getcellColumnFlag(num.size()) + "$" + (i + 2)); } } } // 根据数据值确定单元格位置(比如:28-AB) private String getcellColumnFlag(int num) { String columFiled = ""; int chuNum = 0; int yuNum = 0; if (num >= 1 && num <= 26) { columFiled = this.doHandle(num); } else { chuNum = num / 26; yuNum = num % 26; columFiled += this.doHandle(chuNum); columFiled += this.doHandle(yuNum); } return columFiled; } private String doHandle(final int num) { String[] charArr = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; return charArr[num - 1].toString(); } /** * 使用已定义的数据源方式设置一个数据验证 * * @param formulaString * @param naturalRowIndex * @param naturalColumnIndex * @return */ public DataValidation getDataValidationByFormula(String formulaString, int naturalRowIndex, int naturalColumnIndex) { // 加载下拉列表内容 DVConstraint constraint = DVConstraint .createFormulaListConstraint(formulaString); // 设置数据有效性加载在哪个单元格上。 // 四个参数分别是:起始行、终止行、起始列、终止列 int firstRow = naturalRowIndex; int lastRow = naturalRowIndex; int firstCol = naturalColumnIndex - 1; int lastCol = naturalColumnIndex - 1; CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol); // 数据有效性对象 DataValidation data_validation_list = new HSSFDataValidation(regions, constraint); return data_validation_list; } /** * 创建一列数据 * * @param hssfSheet */ public void creatAppRow(HSSFSheet hssfSheet, int naturalRowIndex) { // 获取行 HSSFRow hssfRow = hssfSheet.createRow(naturalRowIndex); HSSFCell province = hssfRow.createCell(0); province.setCellValue(""); province.setCellStyle(cellStyle); HSSFCell City = hssfRow.createCell(1); City.setCellValue(""); City.setCellStyle(cellStyle); // 得到验证对象 DataValidation data_validation_list1 = this.getDataValidationByFormula( "province", naturalRowIndex, 1); DataValidation data_validation_list2 = this .getDataValidationByFormula("INDIRECT($A" + (naturalRowIndex + 1) + ")", naturalRowIndex, 2); // 工作表添加验证数据 hssfSheet.addValidationData(data_validation_list1); hssfSheet.addValidationData(data_validation_list2); } public void Export() { try { File file = new File("F:/excel.xls"); FileOutputStream outputStream = new FileOutputStream(file); // 创建excel HSSFWorkbook workbook = new HSSFWorkbook(); // 设置sheet 名称 HSSFSheet excelSheet = workbook.createSheet("excel"); // 设置样式 this.setDataCellStyles(workbook, excelSheet); // 创建一个隐藏页和隐藏数据集 this.creatHideSheet(workbook, "shutDataSource"); // 设置名称数据集 this.creatExcelNameList(workbook, "shutDataSource"); // 创建一行数据 for (int i = 0; i < 50; i++) { this.creatAppRow(excelSheet,i); } workbook.write(outputStream); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { ExcelLinkage linkage = new ExcelLinkage(); linkage.Export(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?