一、POI
Apache POI 是一个用于操作 Microsoft Office 格式文件(如 Excel、Word、PowerPoint)的开源 Java 库。它提供了一组 API,使开发人员能够读取、创建和修改这些 Office 文件,从而实现对这些文件的灵活处理。
Apache POI 主要包括以下几个模块:
- HSSF(Horrible Spreadsheet Format):用于读写 Excel 97-2003 格式(.xls 文件)的 API。
- XSSF(XML Spreadsheet Format):用于读写 Excel 2007 及以上版本的 OOXML 格式(.xlsx 文件)的 API。
- SXSSF(Streaming Usermodel API):用于处理大型 Excel 文件而不会占用过多内存的 API。
- HWPF(Horrible Word Processor Format):用于读写 Word 97-2003 格式(.doc 文件)的 API。
- XWPF(XML Word Processor Format):用于读写 Word 2007 及以上版本的 OOXML 格式(.docx 文件)的 API。
- HSLF(Horrible Slide Layout Format):用于读写 PowerPoint 97-2003 格式(.ppt 文件)的 API。
- XSLF(XML Slide Layout Format):用于读写 PowerPoint 2007 及以上版本的 OOXML 格式(.pptx 文件)的 API。
通过使用 Apache POI,开发人员可以实现对 Office 文件的读取、创建和修改,包括设置样式、添加数据验证、插入图表等操作。这使得开发人员能够灵活地处理各种 Office 文件,满足不同的业务需求。
二、WriteHandler
在 Apache POI 中,WriteHandler
接口是一个通用的写处理器接口,用于在 Excel 写入过程中进行自定义处理。WriteHandler
接口没有直接定义方法,而是通过其子接口来实现具体的处理逻辑。以下是一些常用的 WriteHandler
子接口:
SheetWriteHandler
: 用于处理工作表(Sheet)级别的写入操作,可以在创建工作表时添加样式、数据验证等功能。RowWriteHandler
: 用于处理行(Row)级别的写入操作,可以在创建行时添加样式、数据验证等功能。CellWriteHandler
: 用于处理单元格(Cell)级别的写入操作,可以在创建单元格时添加样式、数据验证等功能。
通过实现这些接口,您可以在 Excel 写入过程中对不同级别的元素进行个性化处理,以满足特定需求或添加额外功能。
三、SheetWriteHandler
SheetWriteHandler
是 EasyExcel 提供的一个接口,用于在写入 Excel 时对每个 Sheet 进行自定义处理。通过实现 SheetWriteHandler
接口,您可以在写入 Excel 时对每个 Sheet 进行一些额外的操作,例如设置样式、合并单元格、添加批注等。
以下是一个示例,展示如何实现 SheetWriteHandler
接口:
public class CustomSheetWriteHandler implements SheetWriteHandler {
@Override
public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
// 在创建 Sheet 之前执行的操作
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
// 在创建 Sheet 之后执行的操作
}
@Override
public void beforeSheetWrite(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder,
WriteTableHolder writeTableHolder) {
// 在写入 Sheet 之前执行的操作
}
@Override
public void afterSheetWrite(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder,
WriteTableHolder writeTableHolder) {
// 在写入 Sheet 之后执行的操作
}
}
在上面的示例中,我们实现了 SheetWriteHandler
接口,并重写了其中的四个方法:
beforeSheetCreate
:在创建 Sheet 之前执行的操作。afterSheetCreate
:在创建 Sheet 之后执行的操作。beforeSheetWrite
:在写入 Sheet 之前执行的操作。afterSheetWrite
:在写入 Sheet 之后执行的操作。
您可以根据需要在这些方法中添加自定义的操作逻辑。例如,您可以在 beforeSheetWrite
方法中设置单元格样式,或在 afterSheetWrite
方法中添加批注。
要使用自定义的 SheetWriteHandler
,您可以在写入 Excel 时通过 WriteSheet
的 registerWriteHandler
方法注册它,如下所示:
EasyExcel.write(fileName, YourDataClass.class)
.sheet("Sheet1")
.registerWriteHandler(new CustomSheetWriteHandler())
.doWrite(dataList);
在上面,我们通过 registerWriteHandler
方法注册了自定义的CustomSheetWriteHandler
。
四、DataValidationConstraint 数据验证约束
DataValidationConstraint
是 EasyExcel 提供的一个类,用于定义数据验证的约束条件。通过使用 DataValidationConstraint
,您可以指定数据验证的类型、限制条件和错误提示信息。
以下是 DataValidationConstraint
的一些常用方法和示例用法:
1.DataValidationConstraint.createNumericConstraint(operator, formula1, formula2)
:创建数值类型的约束条件。
示例:
operator
:操作符,可以是OperatorType.BETWEEN
、OperatorType.NOT_BETWEEN
、OperatorType.EQUAL
、OperatorType.NOT_EQUAL
等。formula1
:第一个公式,用于指定数值的限制条件。formula2
:第二个公式,用于指定数值的限制条件(仅在操作符为OperatorType.BETWEEN
或OperatorType.NOT_BETWEEN
时使用)。
DataValidationConstraint constraint = DataValidationConstraint.createNumericConstraint(OperatorType.BETWEEN, "1", "10");
2.DataValidationConstraint.createFormulaListConstraint(formula)
:创建公式列表类型的约束条件。
formula
:公式,用于指定数据验证的条件。
示例:
DataValidationConstraint constraint = DataValidationConstraint.createFormulaListConstraint("A1:A10");
3.DataValidationConstraint.createExplicitListConstraint(list)
:创建显式列表类型的约束条件。
list
:列表,用于指定数据验证的可选值。
示例:
List<String> options = Arrays.asList("Option1", "Option2", "Option3");
DataValidationConstraint constraint = DataValidationConstraint.createExplicitListConstraint(options);
4.DataValidationConstraint.createCustomConstraint(formula)
:创建自定义类型的约束条件。
formula
:公式,用于指定自定义的数据验证条件。
示例:
DataValidationConstraint constraint = DataValidationConstraint.createCustomConstraint("A1>0");
通过使用 DataValidationConstraint
,您可以为 Excel 中的单元格设置数据验证的约束条件,以确保输入的数据符合指定的规则。
五、导出设置下拉框
1.需要写一个handler类 实现 SheetWriteHandler 并且重写方法,设置下拉的具体实现要写在 afterSheetCreate(sheet创建之后) 方法中
2.需要有一个字符串类型的集合,是你要下拉的选项
3.需要有一个下标,来指定下拉框在哪个下标列(列从0开始)
4.需要指定开始行和结束行(从1开始)
5.如果下拉值总数大于100,需使用一个新sheet存储,避免生成的导入模板下拉值获取不到
6.设置下拉选的sheet页是否隐藏(不隐藏的话导出后可以看到一个sheet有下拉值的sheet页)
7.如果有多列需要设置下拉框,最好使用一个collection或者map来进行遍历
8.代码实现:
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
Sheet sheet = writeSheetHolder.getSheet();
DataValidationHelper helper = sheet.getDataValidationHelper();
if (CollUtil.isEmpty(selectedMap)) {
return;
}
selectedMap.forEach((k, v) -> {
// 下拉 首行 末行 首列 末列
CellRangeAddressList list = new CellRangeAddressList(v.getStartRow(), v.getEndRow(), k, k);
DataValidation validation = null;
// 如果下拉值总数大于100,则使用一个新sheet存储,避免生成的导入模板下拉值获取不到
if (v.getSelectorData().length > LIMIT_NUMBER) {
//定义sheet的名称
String sheetName = v.getHiddenSelectorSheetName();
Workbook workbook = writeWorkbookHolder.getWorkbook();
Sheet hiddenSheet = workbook.createSheet(sheetName);
for (int i = 0, length = v.getSelectorData().length; i < length; i++) {
// 开始的行数i,列数k
hiddenSheet.createRow(i).createCell(k).setCellValue(v.getSelectorData()[i]);
}
Name category1Name = workbook.createName();
category1Name.setNameName(sheetName);
String excelLine = getExcelLine(k);
// =hidden!$H:$1:$H$50 sheet为hidden的 H1列开始H50行数据获取下拉数组
String refers = sheetName + "!$" + excelLine + "$1:$" + excelLine + "$" + (v.getSelectorData().length + 1);
// 将刚才设置的sheet引用到你的下拉列表中
category1Name.setRefersToFormula(refers);
DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);
validation = helper.createValidation(constraint, list);
// 设置存储下拉列值得sheet为隐藏
if(v.getHiddenSelectorSheet()){
int hiddenIndex = workbook.getSheetIndex(sheetName);
if (!workbook.isSheetHidden(hiddenIndex)) {
workbook.setSheetHidden(hiddenIndex, v.getHiddenSelectorSheet());
}
}
}else{
DataValidationConstraint constraint = helper.createExplicitListConstraint(v.getSelectorData());
validation = helper.createValidation(constraint, list);
}
validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
validation.setShowErrorBox(true);
validation.setSuppressDropDownArrow(true);
validation.createErrorBox("提示", "请输入下拉选项中的内容");
sheet.addValidationData(validation);
});
}
代码中 selectedMap 是在handler构造方法中传入进来的,map中是下标和对应的下标对应的下拉值/sheet页名/是否需要隐藏(这样可以实现handler的复用,不用一个导出创建一个handler)
/** * 下拉数据集 */ private String[] selectorData; /** * 设置下拉选的sheet页是否隐藏 */ private boolean hiddenSelectorSheet ; /** * 下拉选的sheet页名称 */ private String hiddenSelectorSheetName;
9.只需要在导出的时候,给 ExcelWriterSheetBuilder.registerWriteHandler(new handler())