
com.moon.poi.excel.ExcelUtil Maven / Gradle / Ivy
package com.moon.poi.excel;
import com.moon.core.lang.DoubleUtil;
import com.moon.core.lang.StringUtil;
import com.moon.core.util.TypeUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.moon.core.lang.ThrowUtil.noInstanceError;
/**
* 此工具提供 Excel 写功能,基于 poi 4.x 开发,但默认并未导入 poi 相关依赖;
*
* 工具屏蔽了绝大多数具体实现,只需要在创建时指定类型({@link #xls()}、{@link #xlsx()})即可,
*
* 极少可能会用到{@link #stream()}
*
*
* 设计思路是参照 html 方式设计,它具有 html 类似的结构,如咱们可以这样使用它:
*
*
* ``` java
* public void test() {
*
* // 创建 excelFactory
* ExcelFactory excelFactory = ExcelUtil.xlsx();
*
* // 创建一个命名工作簿,如果指定名称工作簿存在就直接使用,否则就新建
* // 如果是已存在的 sheet,可传入 append 参数,
* // 表示数据默认是追加还是覆盖,默认 append = true;
* excelFactory.sheet("sheetName", sheetFactory -> {
*
* // 设置列宽,按索引设置列宽,忽略 null,
* // 可用 null 来跳过设置某些列
* sheetFactory.setColumnsWidth(3000,4000,null,5000,6000);
*
* // 定义样式,可以在任意位置定义样式,并在任意位置使用
* // 由于 excel 有限制 CellStyle 的数量上限,
* // 所以建议通过这“定义+引用”的方式使用
* // 尤其不要在循环里创建 CellStyle,
* sheetFactory.definitionStyle("classname", (style, font) > {
*
* // 如果要设置字体,需要手动 setFont
* style.setFont(font);
* });
*
* // 预定义一个注释
* sheetFactory.definitionComment("comment-name", "预定义注释");
*
* // 可以通过链式调用创建“行”和“单元格”
* sheetFactory.row(rowFactory -> {
*
* // 通过链式调用 next 可以不断创建单元格并设置值
* rowFactory.next(1).next(2).next(3);
*
* // 如果需要对 cell 更多操作(如引用样式)可通过这种方式
* rowFactory.cell().val(4).style("unique-classname");
*
* // 通过 comment 方法为单元格添加注释
* // 这个注释并不是预定义的,所以不受管理,而是立即执行添加
* rowFactory.cell().val(5).comment("这是一条注释");
*
* rowFactory.cell(cellFactory -> {
* // 这里通过 commentAs 使用预定义的注释
* cellFactory.val(6).commentAs("defined-comment-unique-name")
* });
* }).row(rowFactory -> {
* // 合并单元格,这里通过传入 rowspan 和 colspan 参数
* // 合并 2 行 5 列单元格,rowspan 和 colspan 最小值均为 1
* // 如果小于 1 则具有回退或替换单元格的功能,
* // 但还是别这样用了吧...
* rowFactory.next("value", 2, 5);
* });
*
* // 实际上预定义样式和注释都分别通过各自的“代理”分别管理,
* // 正因为如此,咱们才可以在任意位置定义,并在任意位置使用
* // 实际你要应用你所设置的样式和注释的话,
* // 需要手动调用 finish 方法才应用预定义样式和注释
* }).finish().write(...);
* // write 方法里也会调用 finish 方法,但可以重复调用
* // 可以通过 write 方法将构建好的 excel 写入到“文件”或“流”
* }
* ```
*
*
* @author moonsky
*/
public final class ExcelUtil extends LoadUtil {
private ExcelUtil() { noInstanceError(); }
/**
* 创建 Excel 2003 工厂
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory xls() { return of(ExcelType.XLS); }
/**
* 创建 Excel 2007 工厂
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory xlsx() { return of(ExcelType.XLSX); }
/**
* 创建 Excel 2007 工厂
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory stream() { return of(ExcelType.SUPER); }
/**
* 使用预定义类型创建 Excel 工厂
*
* @param type 预定义 Excel 类型
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory of(ExcelType type) { return of(type.get()); }
/**
* 自定义实现创建 Excel 工厂
*
* @param creator 自定义 Excel 创建器
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory of(Supplier creator) { return of(creator.get()); }
/**
* 自定义创建 Excel 工厂
*
* @param workbook 自定义 Excel 工作簿
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory of(Workbook workbook) { return new WorkbookFactory(workbook); }
/**
* 从已知 Excel 文件加载
*
* @param absoluteFilepath Excel 文件绝对路径
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory load(String absoluteFilepath) { return load(new File(absoluteFilepath)); }
/**
* 从已知 Excel 文件加载
*
* @param absoluteFilepath Excel 文件绝对路径
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory load(Path absoluteFilepath) { return load(absoluteFilepath.toFile()); }
/**
* 从已知 Excel 文件加载
*
* @param excelFile Excel 文件
*
* @return Excel 操作工厂(代理)
*
* @throws NullPointerException excelFile is null
* @throws UnsupportedOperationException excelFile type is unknown
*/
public static WorkbookFactory load(File excelFile) {
return load(excelFile, deduceType(excelFile).orElseGet(() -> {
// 这里用文件内容的方式判断类型
throw new UnsupportedOperationException("等待支持.");
}));
}
/**
* 从已知 Excel 文件加载
*
* @param excelFile Excel 文件
* @param type 类型
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory load(File excelFile, ExcelType type) { return of(type.load(excelFile)); }
/**
* 从已知 Excel 文件流加载
*
* @param excelInputStream Excel 输入流
*
* @return Excel 操作工厂(代理)
*/
public static WorkbookFactory load(InputStream excelInputStream, ExcelType type) {
return of(type.load(excelInputStream));
}
/**
* 格式化文件名
*
* @param originFilename 文件名
* @param workbook Excel 文档
*
* @return 符合格式的文件名
*/
public static String formatFilename(String originFilename, Workbook workbook) {
for (ExcelType value : ExcelType.values()) {
if (value.test(workbook)) {
return value.formatFilename(originFilename);
}
}
return originFilename;
}
/**
* 获取单元格的值
*
* @param cell 单元格对象
*
* @return 单元格的值
*/
public static Object getValue(Cell cell) {
CellType type = cell.getCellType();
switch (type) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue();
}
return cell.getNumericCellValue();
case ERROR:
return cell.getErrorCellValue();
case BOOLEAN:
return cell.getBooleanCellValue();
case BLANK:
case _NONE:
default:
return null;
}
}
public static String getStringValue(Cell cell) {
return getStringValue(cell, null);
}
public static String getStringValue(Cell cell, String defaultIfNull) {
try {
return cell.getStringCellValue();
} catch (NullPointerException e) {
return defaultIfNull;
} catch (Exception e) {
return StringUtil.toStringOrDefaultIfNull(getValue(cell), defaultIfNull);
}
}
public static double getNumericValue(Cell cell) {
return getNumericValue(cell, 0);
}
public static double getNumericValue(Cell cell, double defaultIfNull) {
try {
return cell.getNumericCellValue();
} catch (NullPointerException e) {
return defaultIfNull;
} catch (Exception e) {
Double value = DoubleUtil.toDouble(getValue(cell));
return value == null ? defaultIfNull : value;
}
}
/**
* 获取单元格的值,并转换
*
* @param cell 单元格
* @param converter 转换器
* @param 返回值类型
*
* @return 返回转换后的值
*/
public static T getValue(Cell cell, Function
© 2015 - 2025 Weber Informatics LLC | Privacy Policy