若依POI(Excel)模块探究
Posted 卷王2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了若依POI(Excel)模块探究相关的知识,希望对你有一定的参考价值。
若依POI(Excel)模块探究
POI是一个java操作Excel的工具包
POI中的对象
工作薄对象WorkBook
WorkBook
对象的实现类有3个:
HSSFWorkbook(03版Excel,最多只有65536行,导入导出速度快)
XSSFWorkbook(07版Excel,支持百万数据的导入导出,导入导出速度慢)
SXSSFWorkbook(07版Excel升级版,会在过程中生成中间文件,导入导出速度快)
工作表对象Sheet
行对象Row
单元格对象Cell
最基础的demo
需要的maven依赖
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
导出demo
@Test
public void SimplePIO() throws IOException
String path = "E:\\\\java代码\\\\POI练习代码\\\\output\\\\";
//新建工作簿
Workbook workbook = new SXSSFWorkbook();
//用工作簿来新建工作表
Sheet sheet = workbook.createSheet(String.valueOf(0));
//用工作表新建行
Row row = sheet.createRow(0);
//用行新建单元格
Cell cell = row.createCell(0);
//向单元格中写入值
cell.setCellValue("666");
Row row1 = sheet.createRow(1);
//向第二行的100列添加元素
for (int i = 0; i < 100; i++)
row1.createCell(i).setCellValue(i);
//用输出流创建一个文件
OutputStream out = new FileOutputStream(path+"test.xlsx");
//将工作簿的内容写在Excel中,输出
workbook.write(out);
out.close();
导入demo
将实体类转化为Excel
java中的注解类
想自定义注解类,先要了解JDK自带的注解
@Target 注解
功能:指明了修饰的这个注解的使用范围,即被描述的注解可以用在哪里。
ElementType的取值包含以下几种:
- TYPE:类,接口或者枚举
- FIELD:域,包含枚举常量
- METHOD:方法
- PARAMETER:参数
- CONSTRUCTOR:构造方法
- LOCAL_VARIABLE:局部变量
- ANNOTATION_TYPE:注解类型
- PACKAGE:包
@Retention 注解
功能:指明修饰的注解的生存周期,即会保留到哪个阶段。
RetentionPolicy的取值包含以下三种:
- SOURCE:源码级别保留,编译后即丢弃。
- CLASS:编译级别保留,编译后的class文件中存在,在jvm运行时丢弃,这是默认值。
- RUNTIME: 运行级别保留,编译后的class文件中存在,在jvm运行时保留,可以被反射调用。
@Documented 注解
功能:指明修饰的注解,可以被例如javadoc此类的工具文档化,只负责标记,没有成员取值。
@Inherited注解
功能:允许子类继承父类中的注解。
注意!:
@interface意思是声明一个注解,方法名对应参数名,返回值类型对应参数类型。
在若依中,将实体类转化为Excel的思路:
1.编写一个注解类Excel
思路:
通过注解类中的函数和内部类,就可以通过注解中的参数,向注解类中传值;注解类中的函数和内部类,在使用时都是用来传参数
package com.yutao.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
import com.yutao.common.utils.poi.ExcelHandlerAdapter;
/**
* 自定义导出Excel数据注解
*
* @author yutao
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
/**
* 导出时在excel中排序
*/
public int sort() default Integer.MAX_VALUE;
/**
* 导出到Excel中的名字.
*/
public String name() default "";
/**
* 日期格式, 如: yyyy-MM-dd
*/
public String dateFormat() default "";
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
public String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出类型(0数字 1字符串)
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出时在excel中每个列的高度 单位为字符
*/
public double height() default 14;
/**
* 导出时在excel中每个列的宽 单位为字符
*/
public double width() default 16;
/**
* 文字后缀,如% 90 变成90%
*/
public String suffix() default "";
/**
* 当值为空时,字段的默认值
*/
public String defaultValue() default "";
/**
* 提示信息
*/
public String prompt() default "";
/**
* 设置只能选择不能输入的列内容.
*/
public String[] combo() default ;
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
public boolean isExport() default true;
/**
* 另一个类中的属性名称,支持多级获取,以小数点隔开
*/
public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/**
* 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
*/
public Align align() default Align.AUTO;
/**
* 自定义数据处理器
*/
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
* 自定义数据处理器参数
*/
public String[] args() default ;
public enum Align
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
this.value = value;
public int value()
return this.value;
/**
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
Type type() default Type.ALL;
public enum Type
ALL(0), EXPORT(1), IMPORT(2);
private final int value;
Type(int value)
this.value = value;
public int value()
return this.value;
public enum ColumnType
NUMERIC(0), STRING(1), IMAGE(2);
private final int value;
ColumnType(int value)
this.value = value;
public int value()
return this.value;
2.编写注解工具类ExcelUtils
整体思路与模块划分:
1.类的成员变量,即Excel文件对象中的属性
/**
* Excel sheet最大行数,默认65536
*/
public static final int sheetSize = 65536;
/**
* 工作表名称
*/
private String sheetName;
/**
* 导出类型(EXPORT:导出数据;IMPORT:导入模板)
*/
private Excel.Type type;
/**
* 工作薄对象
*/
private Workbook wb;
/**
* 工作表对象
*/
private Sheet sheet;
/**
* 样式列表
*/
private Map<String, CellStyle> styles;
/**
* 导入导出数据列表
*/
private List<T> list;
/**
* 注解列表
*/
private List<Object[]> fields;
/**
* 当前行号
*/
private int rownum;
/**
* 标题
*/
private String title;
/**
* 最大高度
*/
private short maxHeight;
/**
* 统计列表
*/
private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
/**
* 数字格式
*/
private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
/**
* 实体对象
*/
public Class<T> clazz;
2.操作注解,从成员变量上的自定义注解中获取信息
操作的关键就是反射类中的几个方法
java中注解相关的操作
总结来说,有以下几个常用方法:
getDeclaredFields() | 返回该类中所有成员变量的Field | |
getDeclaredAnnotations() | 返回该元素上方所有注解的数组 | |
getDeclaredMethods() | 返回该类中所有成员方法的Field | |
isAnnotationPresent() | 如果此元素上有指定类型的注释,则返回true,否则返回false。该方法主要用于方便地访问标记注释。 这个方法返回的真值相当于:getAnnotation(annotationClass) != null | |
/**
* 获取字段注解信息
*/
public List<Object[]> getFields()
List<Object[]> fields = new ArrayList<Object[]>();
List<Field> tempFields = new ArrayList<>();
tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
for (Field field : tempFields)
// 单注解
if (field.isAnnotationPresent(Excel.class))
Excel attr = field.getAnnotation(Excel.class);
if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type))
field.setAccessible(true);
fields.add(new Object[] field, attr );
// 多注解
if (field.isAnnotationPresent(Excels.class))
Excels attrs = field.getAnnotation(Excels.class);
Excel[] excels = attrs.value();
for (Excel attr : excels)
if (attr != null && (attr.type() == Excel.Type.ALL || attr.type() == type))
field.setAccessible(true);
fields.add(new Object[] field, attr );
return fields;
3.导出模块
导出的关键就是如何填写每行,每个单元格的数据,在填写的过程中,会调用到其他规定格式的函数
解析实体对象中的每个属性值
/**
* 以类的属性的get方法方法形式获取值
*
* @param o
* @param name
* @return value
* @throws Exception
*/
private Object getValue(Object o, String name) throws Exception
if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
Class<?> clazz = o.getClass();
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
o = field.get(o);
return o;
/**
* 获取bean中的属性值
*
* @param vo 实体对象
* @param field 字段
* @param excel 注解
* @return 最终的属性值
* @throws Exception
*/
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
Object o = field.get(vo);
if (StringUtils.isNotEmpty(excel.targetAttr()))
String target = excel.targetAttr();
if (target.contains("."))
String[] targets = target.split("[.]");
for (String name : targets)
o = getValue(o, name);
else
o = getValue(o, target);
return o;
将单个实体类中每个属性字段,填入每行的对应单元格中
public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
Cell cell = null;
try
// 设置行高
row.setHeight(maxHeight);
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
if (attr.isExport())
// 创建cell
cell = row.createCell(column);
int align = attr.align().value();
cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : "")));
// 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr);
String dateFormat = attr.dateFormat();
String readConverterExp = attr.readConverterExp();
String separator = attr.separator();
String dictType = attr.dictType();
if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator以上是关于若依POI(Excel)模块探究的主要内容,如果未能解决你的问题,请参考以下文章