自定义表格注解
定义表格注解:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface ExcelField {
//排序
int sort();
//表头
String header();
}
实体类:
public class User {
@ExcelField(header="用户ID",sort=1)
private int id;
@ExcelField(header="用户姓名",sort=2)
private String name;
@ExcelField(header="用户性别",sort=4)
private String sex;
@ExcelField(header="用户年龄",sort=3)
private int age;
public User() {
super();
}
public User(int id, String name, String sex, int age) {
super();
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
如何通过上述的条件实现将数据导出到Excel表格?在此就需要先介绍导出Excel表格的相关java工具。
开发中经常会涉及到excel的处理,如导出Excel,导入Excel到数据库中,操作Excel目前有两个框架,一个是apache 的poi, 另一个是 Java Excel。在此只介绍apache的poi。
Apache POI 与 Java Excel
Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件。这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Office文件的开源库。它包含类和方法对用户输入数据或文件到MS Office文档进行解码。
Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。jxl 由于其小巧 易用的特点, 逐渐已经取代了 POI-excel的地位, 成为了越来越多的java开发人员生成excel文件的首选。
这里提供Java Excel的jxl.jar和Apache poi的下载:
http://download.csdn.net/download/yutao_struggle/10186699
poi引入的jar包:
poi-3.17.jar
poi-ooxml-3.17.jar
poi-ooxml-schemas-3.17.jar
commons-collectons4-4.1.jar
Apache POI 的常用类
- HSSF - 提供读写Microsoft Excel XLS格式档案的功能,它与微软Office97-2003版本兼容。
- XSSF - 提供读写Microsoft Excel OOXML XLSX XLS格式档案的功能,它与MS-Office版本2007或更高版本兼容。
- SXSSF - 与XSSF相同,提供大数据的读写。
- HWPF - 提供读写Microsoft Word DOC97格式档案的功能。
- XWPF - 提供读写Microsoft Word DOC2003格式档案的功能。
- HSLF - 提供读写Microsoft PowerPoint格式档案的功能。
- HDGF - 提供读Microsoft Visio格式档案的功能。
- HPBF - 提供读Microsoft Publisher格式档案的功能。
- HSMF - 提供读Microsoft Outlook格式档案的功能。
注意:旧版本的POI支持二进制文件格式,如DOC,XLS,PPT等,从版本3.5起,POI支持微软Office的OOXML文件格式,如DOCX,XLSX,PPTX等。
SXSSF
Excel中的工作簿、工作表、行、单元格中的关系:
- 一个Excel文件对应于一个workbook(如SXSSFWorkbook),
- 一个workbook可以有多个sheet(SXSSFSheet)组成,
- 一个sheet是由多个row(SXSSFRow)组成,
- 一个row是由多个cell(SXSSFFCell)组成
API
org.apache.poi.ss.usermodel.Workbook是创建和维护Excel工作簿的接口,他有三个实现:
- HSSFWorkbook : 这个类有读取和.xls 格式和写入Microsoft Excel文件的方法。它与微软Office97-2003版本兼容。
- XSSFWorkbook : 这个类有读写Microsoft Excel和OpenOffice的XML文件的格式.xls或.xlsx的方法。它与MS-Office版本2007或更高版本兼容。
- SXSSFWorkbook:提供大数据的读写。
与工作簿相似,对应的Sheet、Row、Cell等都有多个实现。
SXSSFWorkbook:工作簿,代表一个Excel 的整个文档
- SXSSFWorkbook() 创建一个工作簿
- SXSSFSheet getSheet(String sheetName) 通过名称获取Sheet
- SXSSFSheet getSheetAt(int index) 通过索引获取Sheet,索引从0开始
- int getNumberOfSheets() 获取sheet的个数
- setActiveSheet(int index) 设置默认选中的工作表
- write(OutputStream stream) 输出工作簿的输出流
- CellStyle createCellStyle() 获取样式
- Font createFont() 获取字体
- SXSSFSheet createSheet() 获取工作表
SXSSFSheet:工作表
SXSSFRow:行
SXSSFCell:单元格
SXSSFCellStyle:单元格样式
SXSSFFont:字体
SXSSFName:名称
SXSSFDataFormat :日期格式化
SXSSFHeader : Sheet的头部
SXSSFFooter :Sheet的尾部
SXSSFDateUtil :日期工具
SXSSFPrintSetup :打印设置
SXSSFErrorConstants:错误信息表
导出Excel实例
public class ExcelExport {
private SXSSFWorkbook wb; //工作簿
private Sheet sheet; //工作表
private Map<String,CellStyle> styles; //样式
private int rownum; //行数
private List<Object[]> annotationList; //注解集合
public ExcelExport(String title,Class<?> clazz){
this.wb = new SXSSFWorkbook();
this.sheet = wb.createSheet("user");
this.styles = createStyles(this.wb);
initialize(title,clazz);
}
/**
* @param title 标题
* @param clazz 对应实体类的class
*/
private void initialize(String title, Class<?> clazz) {
//反射获取所有字段及对应的注解
Field[] fields = clazz.getDeclaredFields();
this.annotationList = new ArrayList<>();
for(Field f : fields){
ExcelField ef = f.getAnnotation(ExcelField.class);
if(ef != null){
annotationList.add(new Object[]{ef,f});
}
}
//导入Excel列排序
Collections.sort(annotationList,new Comparator<Object[]>() {
@Override
public int compare(Object[] o1, Object[] o2) {
return new Integer(((ExcelField)o1[0]).sort()).compareTo(
new Integer(((ExcelField)o2[0]).sort()));
}
});
//表头集合
List<String> headList = new ArrayList<>();
for(Object[] objs : annotationList){
headList.add(((ExcelField)objs[0]).header());
}
//标题
if(title!=null && !"".equals(title)){
Row titleRow = this.sheet.createRow(rownum++);
Cell titleCell = titleRow.createCell(0);
//合并单元格,四个参数分别表示:first row,last row ,first column,last column
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, headList.size()-1));
//样式
titleCell.setCellStyle(this.styles.get("title"));
titleCell.setCellValue(title);
}
//创建表头
if(headList!=null) {
//创建一行
Row contentRow = this.sheet.createRow(rownum++);
for(int i=0;i<headList.size();i++){
//添加单元格
Cell contentCell = contentRow.createCell(i);
//设置单元格内容
contentCell.setCellValue(headList.get(i));
//设置样式
contentCell.setCellStyle(this.styles.get("header"));
}
}
}
/**
* 设置需要导出的数据
* @param dataList 数据集合
*/
public void setDataList(List dataList){
if(dataList != null && dataList.size() > 0){
Class clazz = dataList.get(0).getClass();
for (int i=0;i<dataList.size();i++) {
int index = 0;
//创建一行
Row dataRow = this.sheet.createRow(rownum++);
for(Object[] objs : annotationList) {
String fieldName = ((Field)objs[1]).getName();
String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
try {
Method method = clazz.getMethod(methodName, null);
String result = method.invoke(dataList.get(i),null).toString();
//创建单元格
Cell dataCell = dataRow.createCell(index++);
//设置样式
dataCell.setCellStyle(this.styles.get("data"));
//设置文本
dataCell.setCellValue(result);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
/*
* 将工作簿写入输出流
*/
public void write(OutputStream os){
try {
this.wb.write(os);
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param wb 工作簿
* @return 样式map集合
*/
private Map<String, CellStyle> createStyles(Workbook wb) {
Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
//标题样式
CellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
Font titleFont = wb.createFont();
titleFont.setFontName("Arial");
titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true);
style.setFont(titleFont);
styles.put("title", style);
//数据样式
style = wb.createCellStyle();
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
style.setFont(dataFont);
styles.put("data", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.LEFT);
styles.put("data1", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
styles.put("data2", style);
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.RIGHT);
styles.put("data3", style);
//表头样式
style = wb.createCellStyle();
style.cloneStyleFrom(styles.get("data"));
style.setAlignment(HorizontalAlignment.CENTER);
style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
Font headerFont = wb.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 10);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
style.setFont(headerFont);
styles.put("header", style);
return styles;
}
public static void main(String[] args) {
//模拟数据,实际应用返回数据库数据封装即可
List list = new ArrayList();
User user = new User(1,"zhang","男",23);
User user1 = new User(2,"wang","女",22);
list.add(user);
list.add(user1);
ExcelExport ex = new ExcelExport("用户表",User.class);
ex.setDataList(list);
FileOutputStream fos;
try {
fos = new FileOutputStream(new File("D:/user.xlsx"));
ex.write(fos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
由此可以通过注解注释相应的字段,选择性的导出部分字段,且可以通过sort来调整导出的列的顺序。有上述程序运行结果: