package com.rufengda.tms.biz.util.poiexcel; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * 通过新家class类一样,在选择新家的时候 * 选择新建@Annotation 即可 * 当新建的Annotation之后需要进行策略注解 * @Retention(RetentionPolicy.RUNTIME) * @Retention指明其策略 * RetentionPolicy.RUNTIME 指明其策略是 运行时策略 * @author wanghaiyang * @verion time 2015/12/28 15:00:00 * */ @Retention(RetentionPolicy.RUNTIME) public @interface ExcelResources { //声明策略的值 String title(); //声明一个order值,并且其默认值为9999 int order() default 9999; }
package com.rufengda.tms.biz.util.poiexcel; /** * 此类主要用于获取User中 Annotation 中的 title,order * @author wanghaiyang * @version 2015/12/28 16:38 * */ public class ExcelHeader implements Comparable<ExcelHeader> { private String tilte; private int order; private String methodName; public ExcelHeader() { // TODO Auto-generated constructor stub } public ExcelHeader(String tilte, int order, String methodName) { super(); this.tilte = tilte; this.order = order; this.methodName = methodName; } public String getTilte() { return tilte; } public void setTilte(String tilte) { this.tilte = tilte; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } /** * 用于对ExcelHeader进行排序 * */ public int compareTo(ExcelHeader o) { return this.order > o.order ? 1 : (this.order < o.order ? -1 : 0); } @Override public String toString() { return "ExcelHeader [tilte=" + tilte + ", order=" + order+ ", methodName=" + methodName + "]"; } }
package com.rufengda.tms.biz.util.poiexcel; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import javax.management.RuntimeErrorException; import org.apache.commons.lang3.StringUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; 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; /** * * @author wanghaiyang * @version 2015/12/28 16:38 * */ //创建Excel模版类,用于来加载模版Excel表 @SuppressWarnings("unused") public class ExcelTemplate { // 创建模版标示符 private static final String DATA_LINE = "datas"; //excel样式标示符 private static final String DEFAULT_STYLE="defaultStyles"; private static final String STYLE="styles"; //样式容器、用于装载第几列所在的样式 private Map<Integer, CellStyle> styles; // 声明Wrokbook private Workbook workbook; //声明sheet表格 private Sheet sheet; //声明row private Row currRow; //声明最后一行数据 private int lastRowIndex; //初始化行的下标 private int initRowIndex; //初始化列的下标 private int initCollIndex; //当前行的下标 private int currRowIndex; //当前列的下标 private int currCollIndex; //excel默认样式 private CellStyle defaultStyle; //设置默认行高样式 private float rowHeight; //用于记录sernums序列号列列的坐标 private int colSernums; // single模式 private static ExcelTemplate excelTemplate = new ExcelTemplate(); private ExcelTemplate() { } public static ExcelTemplate getInstance() { return excelTemplate; } /** 第一步、读取相应模版文档,该方法通过classpath方式读取模版*/ public void readExcelTemplateByClassPath(String path) { try { workbook = WorkbookFactory.create(ExcelTemplate.class.getResourceAsStream(path)); //初始化模版 initTemplate(); } catch (InvalidFormatException e) { e.printStackTrace(); throw new RuntimeException("Excel模版格式不正确!"); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Excel模版不存在!"); } } /**第二种读取模版方式、通过path来继续读取*/ public void readExcelTemplateByPath(String path) { try { workbook = WorkbookFactory.create(new File(path)); //初始化模版 initTemplate(); sheet.setDefaultColumnWidth(20); //创建行 createNewRow(); } catch (InvalidFormatException e) { e.printStackTrace(); throw new RuntimeException("Excel模版格式不正确!"); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("Excel模版不存在!"); } } //初始化模版 private void initTemplate(){ //得到模版中第一个sheet表格 sheet=workbook.getSheetAt(0); //初始化配置信息 initConfigData(); //获取最后一行的数据坐标 lastRowIndex=sheet.getLastRowNum(); //初始化完成,创建一行 //currRow=sheet.getRow(currRowIndex); //createNewRow(); } //初始化模版中的数据信息找到标识符的坐标 private void initConfigData() { boolean isFind=false; boolean isFindSernums=false; for (Row row : sheet) { //如果找到对应的数据就结束 if(isFind) break; for (Cell cell : row) { //如果当前行的数据类型不是字符串类型就继续,因为我们在excel模版中设置的是datas是字符串类型 if(cell.getCellType()!=Cell.CELL_TYPE_STRING) continue; //获取到当前单元格的值 String cellValue=cell.getStringCellValue().trim(); //找序列号的标示符sernums if(cellValue.equals("sernums")){ colSernums=cell.getColumnIndex(); isFindSernums=true; } if(cellValue.equals("datas")){ //获取当前单元格行的坐标 initRowIndex=cell.getRowIndex(); //获取当前单元格列的坐标 initCollIndex=cell.getColumnIndex(); currRowIndex=initRowIndex; currCollIndex=initCollIndex; //获取默认行高 rowHeight=row.getHeightInPoints(); //初始化模版样式 initStyles(); isFind=true; break; } } } //最后检查一下在初始化数据的时候有没有找到,如果没找到就初始化序列号 initSernums(); } //将模版样式初始化数据加载到styles容器中 private void initStyles() { //初始化样式容器 styles= new HashMap<Integer, CellStyle>(); for (Row row : sheet) { for (Cell cell : row) { if(cell.getCellType()!=Cell.CELL_TYPE_STRING) continue; String cellValue=cell.getStringCellValue().trim(); //如果当前列的值等于defaultstyles设置成默认样式 if(DEFAULT_STYLE.equals(cellValue)){ defaultStyle=cell.getCellStyle(); } if(STYLE.equals(cellValue)){ styles.put(cell.getColumnIndex(), cell.getCellStyle()); } } } } //初始化模版sernums序列号的坐标 private void initSernums() { for (Row row : sheet) { for (Cell cell : row) { //如果当前行的数据类型不是字符串类型就继续,因为我们在excel模版中设置的是sernums是字符串类型 if(cell.getCellType()!=Cell.CELL_TYPE_STRING) continue; //获取到当前单元格的值 String cellValue=cell.getStringCellValue().trim(); if(cellValue.equals("sernums")){ //获取到序列号sernums的坐标 colSernums=cell.getColumnIndex(); } } } } //用于替换一些常量固定的值 public void replaceConstant(Map<String, String> datas){ //数据常量如果为空就不进行替换 if(null==datas) return; for (Row row : sheet) { for (Cell cell : row) { String cellValue=cell.getStringCellValue().trim(); //如果当前模版中式#开头就是我们所需要替换的常量 if (cellValue.startsWith("#")) { //如果datas数据中包含有我们的值就进行常量设置 String key = cellValue.substring(1); if (datas.containsKey(key)) { cell.setCellValue(datas.get(key)); } } } } } //创建行 public void createNewRow() { if(lastRowIndex>=currRowIndex && currRowIndex>initRowIndex){ //移动下一行 sheet.shiftRows(currRowIndex, lastRowIndex, 1, true, true); lastRowIndex++; } currRow=sheet.createRow(currRowIndex); //设置行高 currRow.setHeightInPoints(rowHeight); //下一行 currRowIndex++; //当创建到下一行的单元格的列就应该是初始化的列的坐标 currCollIndex=initCollIndex; } //创建列,并为当前单元格赋值 public void createCell(String cellValue){ Cell cell=currRow.createCell(currCollIndex); cell.setCellValue(cellValue); if (null!=styles && styles.size()>0) setCellStyle(cell); //到下一个单元格 currCollIndex++; } //插入序列号 public void insertSernums(){ int index=1; Row row=null; Cell cell= null; for (int i = initRowIndex; i < currRowIndex; i++) { //得到当前行 row=sheet.getRow(i); cell=row.createCell(colSernums); setCellStyle(cell); cell.setCellValue(index++); } } //设置样式 public void setCellStyle(Cell cell){ //设置的时候将样式添加进去 cell.setCellStyle(styles.containsKey(currCollIndex)?styles.get(currCollIndex):defaultStyle); } //将数据到处到Excel中 public void writeFilePath(String filePath){ FileOutputStream fos=null; try { fos= new FileOutputStream(new File(filePath)); workbook.write(fos); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException("写入的文件不存在!"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException("写入流失败!"); }finally{ try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void writeStream(OutputStream os){ try { workbook.write(os); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); throw new RuntimeException("写入流失败!"); }finally{ try { os.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package com.rufengda.tms.biz.util.poiexcel; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Timestamp; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.DataFormat; 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.xssf.usermodel.XSSFWorkbook; /** * * @author wanghaiyang * @version 2015/12/28 16:38 * */ public class ExcelUtil { private static ExcelUtil excelUtil = new ExcelUtil(); private ExcelUtil() { }; public static ExcelUtil getInstance() { return excelUtil; } /**通过excel模版的方式,将数据对象导入到Excel中 * @param template :excel的模板 * @param outPath:文件输出路径 输出到那里 * @param objs:数据列表、用于要输出的数据对象 * @param constantMap:用于输出一些特殊的一些常量 如#tiltle=标题 * @param clz:导入那个,其通过反射机制实现 * @param isclassPath:是否通过classpath的加载方式进行加载excel模版 * */ @SuppressWarnings("rawtypes") public void exportObjToExcelByTemplate(String template,String outPath,List objs,Map constantMap,Class clz,boolean isclassPath){ ExcelTemplate excelTemplate=HanderExcelByTemplate(template, objs, constantMap, clz, isclassPath); excelTemplate.writeFilePath(outPath); } /**通过excel模版的方式,将数据对象导入到Excel中 * @param template :excel的模板 * @param os:通过输出流 * @param objs:数据列表、用于要输出的数据对象 * @param constantMap:用于输出一些特殊的一些常量 如#tiltle=标题 * @param clz:导入那个,其通过反射机制实现 * @param isclassPath:是否通过classpath的加载方式进行加载excel模版 * */ @SuppressWarnings("rawtypes") public void exportObjToExcelByTemplate(String template,OutputStream os,List objs,Map constantMap,Class clz,boolean isclassPath){ ExcelTemplate excelTemplate=HanderExcelByTemplate(template, objs, constantMap, clz, isclassPath); excelTemplate.writeStream(os); } /**不通过excel模版的方式,直接将数据对象导入到Excel中 * @param :excel的模板 * @param outPath:文件输出路径 输出到那里 * @param objs:数据列表、用于要输出的数据对象 * @param :用于输出一些特殊的一些常量 如#tiltle=标题 * @param clz:导入那个,其通过反射机制实现 * @param isXssF:true=2007excel,false=2003excel * */ @SuppressWarnings("rawtypes") public void exportObjToExcel(String outPath,List objs,Class clz,boolean isXssF){ FileOutputStream fos=null; try { fos= new FileOutputStream(new File(outPath)); Workbook workbook=HanderExcel(objs, clz, isXssF); workbook.write(fos); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /**不通过excel模版的方式,直接将数据对象导入到Excel中 * @param :excel的模板 * @param os:输出流 * @param objs:数据列表、用于要输出的数据对象 * @param :用于输出一些特殊的一些常量 如#tiltle=标题 * @param clz:导入那个,其通过反射机制实现 * @param isXssF:true=2007excel,false=2003excel * */ @SuppressWarnings("rawtypes") public void exportObjToExcel(OutputStream os,List objs,Class clz,boolean isXssF){ try { Workbook workbook=HanderExcel(objs, clz, isXssF); workbook.write(os); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /**不通过excel模版的方式,直接将数据对象导入到Excel中 * @param :excel的模板 * @param os:输出流 * @param objs:数据列表、用于要输出的数据对象 * @param :用于输出一些特殊的一些常量 如#tiltle=标题 * @param clz:导入那个,其通过反射机制实现 * @param isXssF:true=2007excel,false=2003excel * @author ksea:该方法基于属性注解 * */ @SuppressWarnings("rawtypes") public void exportObjToExcelByField(OutputStream os,List objs,Class clz,boolean isXssF){ try { Workbook workbook=HanderExcelByField(objs, clz, isXssF); workbook.write(os); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /**不通过excel模版的方式,直接将数据对象导入到Excel中 * @param :excel的模板 * @param os:输出流 * @param objs:数据列表、用于要输出的数据对象 * @param sheetTitleMap:sheet名称 * @param :用于输出一些特殊的一些常量 如#tiltle=标题 * @param :导入那个,其通过反射机制实现 * @param isXssF:true=2007excel,false=2003excel * desc:2016-7-22日项目实际中需求,批量导出,数据列与明细 * */ @SuppressWarnings("rawtypes") public void exportObjToExcel(OutputStream os,Map<Integer, List> objs,Map<Integer, Object> sheetTitleMap,Map<Integer, Class> classMap,boolean isXssF){ try { Workbook workbook=HanderExcel(objs,sheetTitleMap,classMap, isXssF); workbook.write(os); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /**通过excel模版的方式,来处理excel,该方法需要提供Excel的模版,并进行在excel中添加模版标识符 * @param template :excel的模板 * @param objs:数据列表、用于要输出的数据对象 * @param constantMap:用于输出一些特殊的一些常量 如#tiltle=标题 * @param clz:导入那个,其通过反射机制实现 * @param isclassPath:是否通过classpath的加载方式进行加载excel模版 * */ @SuppressWarnings({ "rawtypes", "unchecked" }) private ExcelTemplate HanderExcelByTemplate(String template,List objs,Map constantMap,Class clz,boolean isclassPath){ //读取模版 ExcelTemplate excelTemplate= ExcelTemplate.getInstance(); if(isclassPath){ //通过classpath方式读取模版 excelTemplate.readExcelTemplateByClassPath(template); }else{ //通过path方式读取模版 excelTemplate.readExcelTemplateByPath(template); } List<ExcelHeader> headers=getExcelHeader(clz); //对list进行排序 Collections.sort(headers); //将其标题项写入到excel中:用户标识、用户名称、用户昵称、用户年龄 //创建一行 //excelTemplate.createNewRow(); //将标题插入到当前行中 for (ExcelHeader excelHeader : headers) { excelTemplate.createCell(excelHeader.getTilte()); } //开始写入对应数据,ExcelHeader是排序的,因此根据ExcelHeader进行插入 //这里插入是通过反射机制进行 if(null!=objs && objs.size()>0){ for ( Object obj : objs) { //首先创建一行 excelTemplate.createNewRow(); for (ExcelHeader excelHeader : headers) { try { //通过之前保存在excelHeader中的get方法得到相对应的方法 Method method=clz.getMethod(excelHeader.getMethodName()); //获取返货类型 String returnName=method.getReturnType().getName(); //如果这里是时间类型进行时间格式化 if (returnName.equals("java.util.Date") || returnName.equals("java.sql.Date") || returnName.equals("java.sql.Timestamp")){ //通过反射得到对象对应的值 Object returnValue=method.invoke(obj); excelTemplate.createCell(String.valueOf(returnValue==null?"": MessageFormat.format("{0,date,yyyy-MM-dd HH:mm:ss}",returnValue))); } else{ //通过反射得到对象对应的值 Object returnValue=method.invoke(obj); excelTemplate.createCell(String.valueOf(returnValue==null?"":returnValue)); } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //用于替换一些特殊常量字符 if(null!=constantMap && constantMap.size()>0) excelTemplate.replaceConstant(constantMap); return excelTemplate; } /** * HanderExcel该方法不通过加载模版的方式,而是直接将对象数据数据写入到excel * @param objs 要写入的对象集合 * @param clz 写入的对象 * isXssF判定是否是2003excel还是2007excel * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * * */ @SuppressWarnings({ "rawtypes", "unchecked" }) private Workbook HanderExcel(List objs,Class clz,boolean isXssF) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ Workbook workbook=null; if(isXssF){ //创建2007excel后缀是.xlsx workbook= new XSSFWorkbook(); }else{ //创建2003excel后缀是.xls workbook=new HSSFWorkbook(); } //创建sheet Sheet sheet=workbook.createSheet(); //设置默认列宽度与高度 sheet.setDefaultColumnWidth(20); //sheet.setDefaultRowHeight(Short.parseShort("5")); //得到第一行,在excel中第一行第一列的坐标是(0,0) Row row= sheet.createRow(0); //获取传入数据的标题,其就是annotation List<ExcelHeader> excelHeaders=getExcelHeader(clz); //对头部数据进行排序 Collections.sort(excelHeaders); //将表头插入到第一行 for (int i=0;i<excelHeaders.size();i++) { Cell cell=row.createCell(i); cell.setCellValue(excelHeaders.get(i).getTilte()); } //数据不为空的时候执行 if(null!=objs && objs.size()>0){ /** * 设置时间类型样式,该样式创建不能放在循环中,否则会报异常 * java.lang.IllegalStateException: The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook */ CellStyle cellStyle= workbook.createCellStyle(); DataFormat format=workbook.createDataFormat(); cellStyle.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm:ss")); //插入对象数据 for (int i = 0; i < objs.size(); i++) { Object obj=objs.get(i); //新建一行 Row dataRow=sheet.createRow(i+1); for (int j = 0; j < excelHeaders.size(); j++) { ExcelHeader e=excelHeaders.get(j); //得到对应的get方法 Method method=clz.getMethod(e.getMethodName()); try { Object objectName=method.getReturnType().getName(); String value=String.valueOf(method.invoke(obj)); //将对应的值插入进去 if(objectName.equals("java.sql.Timestamp")|| objectName.equals("java.sql.Date") || objectName.equals("java.util.Date")){ Cell cell=dataRow.createCell(j); if(value==null||value.equals("null")){ cell.setCellValue(""); }else{ Object dateValue=method.invoke(obj); if(objectName.equals("java.sql.Timestamp")) cell.setCellValue((java.sql.Timestamp)dateValue); else if(objectName.equals("java.sql.Date")) cell.setCellValue((java.sql.Date)dateValue); else if(objectName.equals("java.util.Date")) cell.setCellValue((java.util.Date)dateValue); cell.setCellStyle(cellStyle); } } else{ dataRow.createCell(j).setCellValue(value==null||value.equals("null")?"":value); } } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } return workbook; } /** * HanderExcel该方法不通过加载模版的方式,而是直接将对象数据数据写入到excel * @param objs 要写入的对象集合 * @param clz 写入的对象 * isXssF判定是否是2003excel还是2007excel * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @author ksea:该方法基于注解 * */ @SuppressWarnings({ "rawtypes", "unchecked" }) private Workbook HanderExcelByField(List objs,Class clz,boolean isXssF) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ Workbook workbook=null; if(isXssF){ //创建2007excel后缀是.xlsx workbook= new XSSFWorkbook(); }else{ //创建2003excel后缀是.xls workbook=new HSSFWorkbook(); } //创建sheet Sheet sheet=workbook.createSheet(); //得到第一行,在excel中第一行第一列的坐标是(0,0) Row row= sheet.createRow(0); //获取传入数据的标题,其就是annotation List<ExcelHeader> excelHeaders=getExcelHeaderByField(clz); //对头部数据进行排序 Collections.sort(excelHeaders); //将表头插入到第一行 for (int i=0;i<excelHeaders.size();i++) { Cell cell=row.createCell(i); cell.setCellValue(excelHeaders.get(i).getTilte()); } //数据不为空的时候执行 if(null!=objs && objs.size()>0){ /** * 设置时间类型样式,该样式创建不能放在循环中,否则会报异常 * java.lang.IllegalStateException: The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook */ CellStyle cellStyle= workbook.createCellStyle(); DataFormat format=workbook.createDataFormat(); cellStyle.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm:ss")); //插入对象数据 for (int i = 0; i < objs.size(); i++) { Object obj=objs.get(i); //新建一行 Row dataRow=sheet.createRow(i+1); for (int j = 0; j < excelHeaders.size(); j++) { ExcelHeader e=excelHeaders.get(j); //得到对应的get方法 Method method=clz.getMethod(e.getMethodName()); try { Object objectName=method.getReturnType().getName(); String value=String.valueOf(method.invoke(obj)); //将对应的值插入进去 if(objectName.equals("java.sql.Timestamp")|| objectName.equals("java.sql.Date") || objectName.equals("java.util.Date")){ Cell cell=dataRow.createCell(j); if(value==null||value.equals("null")){ cell.setCellValue(""); }else{ Object dateValue=method.invoke(obj); if(objectName.equals("java.sql.Timestamp")) cell.setCellValue((java.sql.Timestamp)dateValue); else if(objectName.equals("java.sql.Date")) cell.setCellValue((java.sql.Date)dateValue); else if(objectName.equals("java.util.Date")) cell.setCellValue((java.util.Date)dateValue); cell.setCellStyle(cellStyle); } } else{ dataRow.createCell(j).setCellValue(value==null||value.equals("null")?"":value); } } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } return workbook; } /** * HanderExcel该方法不通过加载模版的方式,而是直接将对象数据数据写入到excel * objs 要写入的对象集合 * clz 写入的对象 * isXssF判定是否是2003excel还是2007excel * @throws SecurityException * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * desc:2016-7-22日项目中实际需求扩展导出数据列表与明细 * 特别说明:Map<String, Object> objs,Map<String, Object> sheetTitleMap,Map<String, Class> clzs三个map的key必须保持一致 * 后台处理是根据map的key来进行设置值,因此每个对象的key必须一直,并且key一定是,1,2,3之类的key * */ @SuppressWarnings({ "rawtypes", "unchecked" }) private Workbook HanderExcel(Map<Integer, List> objMap,Map<Integer, Object> sheetTitleMap,Map<Integer, Class> classMap,boolean isXssF) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ Workbook workbook=null; if(isXssF){ //创建2007excel后缀是.xlsx workbook= new XSSFWorkbook(); }else{ //创建2003excel后缀是.xls workbook=new HSSFWorkbook(); } if(null!=sheetTitleMap && sheetTitleMap.size()>0){ for (Integer key : sheetTitleMap.keySet()) { //创建sheet并设置对应的sheet名称 Sheet sheet=workbook.createSheet(); workbook.setSheetName(key, String.valueOf(sheetTitleMap.get(key))); //得到第一行,在excel中第一行第一列的坐标是(0,0) Row row= sheet.createRow(0); //获取传入数据的标题,其就是annotation List<ExcelHeader> excelHeaders=getExcelHeaderByField(classMap.get(key)); //对头部数据进行排序 Collections.sort(excelHeaders); //将表头插入到第一行 for (int i=0;i<excelHeaders.size();i++) { Cell cell=row.createCell(i); cell.setCellValue(excelHeaders.get(i).getTilte()); } //数据不为空的时候执行 List list=objMap.get(key); if(null!=list && list.size()>0){ /** * 设置时间类型样式,该样式创建不能放在循环中,否则会报异常 * java.lang.IllegalStateException: The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook */ CellStyle cellStyle= workbook.createCellStyle(); DataFormat format=workbook.createDataFormat(); cellStyle.setDataFormat(format.getFormat("yyyy-MM-dd HH:mm:ss")); //插入对象数据 for (int i = 0; i < list.size(); i++) { Object obj=list.get(i); //新建一行 Row dataRow=sheet.createRow(i+1); for (int j = 0; j < excelHeaders.size(); j++) { ExcelHeader e=excelHeaders.get(j); //得到对应的get方法 Method method=classMap.get(key).getMethod(e.getMethodName()); try { Object objectName=method.getReturnType().getName(); String value=String.valueOf(method.invoke(obj)); //将对应的值插入进去 if(objectName.equals("java.sql.Timestamp")|| objectName.equals("java.sql.Date") || objectName.equals("java.util.Date")){ Cell cell=dataRow.createCell(j); if(value==null||value.equals("null")){ cell.setCellValue(""); }else{ Object dateValue=method.invoke(obj); if(objectName.equals("java.sql.Timestamp")) cell.setCellValue((java.sql.Timestamp)dateValue); else if(objectName.equals("java.sql.Date")) cell.setCellValue((java.sql.Date)dateValue); else if(objectName.equals("java.util.Date")) cell.setCellValue((java.util.Date)dateValue); cell.setCellStyle(cellStyle); } } else{ dataRow.createCell(j).setCellValue(value==null||value.equals("null")?"":value); } } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } } } return workbook; } /**通过反射机制,得到在对应类中的注解,该方法通过注解在get上*/ @SuppressWarnings("rawtypes") public List<ExcelHeader> getExcelHeader(Class clz){ List<ExcelHeader> headers= new ArrayList<ExcelHeader>(); Method[] methods=clz.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { //获取当前方法 Method method=methods[i]; //获取方法名称、我们所有的注解都是注解在get方法的,因此只需要获取get有关的方法 String methodName=method.getName(); if(methodName.startsWith("get")){ //获取到get方法中对应的注解 ExcelResources er=method.getAnnotation(ExcelResources.class); //当一个类中存在有些字段的get未添加annotation 就不进行添加 if(er!=null) headers.add(new ExcelHeader(er.title(), er.order(), methodName)); } } return headers; } /**通过反射机制,得到在对应类中的注解,该方法通过注解在属性上上*/ @SuppressWarnings("rawtypes") public List<ExcelHeader> getExcelHeaderByField(Class clz){ List<ExcelHeader> headers= new ArrayList<ExcelHeader>(); //Method[] methods=clz.getDeclaredMethods(); Field[] fields=clz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { //获取当前属性 Field field=fields[i]; String methodName=field.getName(); methodName="get"+methodName.substring(0, 1).toUpperCase()+methodName.substring(1); //获取到field中对应的注解 ExcelResources er=field.getAnnotation(ExcelResources.class); //当一个类中存在有些字段的get未添加annotation 就不进行添加 if(er!=null) headers.add(new ExcelHeader(er.title(), er.order(),methodName)); } return headers; } //-------------------------以上是写入excel的方法、以下是将数据从excel中读出来---------- @SuppressWarnings("rawtypes") public List<Object> readExcelToObjectByClassPath(String classPath,Class clz,int readLine,int tailLine){ Workbook workbook=null; try { workbook=WorkbookFactory.create(ExcelUtil.class.getResourceAsStream(classPath)); return handlerExcelToObject(workbook, clz, readLine,tailLine); } catch (InvalidFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @SuppressWarnings("rawtypes") public List<Object> readExcelToObjectByPath(String path,Class clz,int readLine,int tailLine){ Workbook workbook=null; try { workbook=WorkbookFactory.create(new File(path)); return handlerExcelToObject(workbook, clz, readLine,tailLine); } catch (InvalidFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @SuppressWarnings("rawtypes") public List<Object> readExcelToObjectByClassPath(String classPath,Class clz){ return readExcelToObjectByClassPath(classPath, clz, 0,0); } /*** * 该方法默认从0行开始读取数据 * @param path * @param clz */ @SuppressWarnings("rawtypes") public List<Object> readExcelToObjectByPath(String path,Class clz){ return readExcelToObjectByPath(path, clz, 0,0); } /** * desc:该方法用于处理excel、读取excel中的数据并将转换成clz对应的类 * @param workbook * @param clz * @param readLine 从第几行开始读取 * @param tailLine 尾部有几行不需要读取 */ @SuppressWarnings("rawtypes") private List<Object> handlerExcelToObject(Workbook workbook,Class clz,int readLine,int tailLine){ List<Object> objects= new ArrayList<Object>(); try { Sheet sheet=workbook.getSheetAt(0); Row row=sheet.getRow(readLine); Map<Integer,String> maps=getExcelHeaderMap(row, clz); /*** * i = readLine+1说明、第一行读取的时标题行、因此读取数据应从标题的下一行开始 readLine+1 * sheet.getLastRowNum()-tailLine 说明:总共需要读取的行数-不需要读取的行数=需要读取的行数 */ for (int i = readLine+1; i <sheet.getLastRowNum()-tailLine; i++) { //实例化对应的对象 Object obj= clz.newInstance(); //得到当前行 Row currRow=sheet.getRow(i); //循环当前行所有列的数据 for (Cell cell : currRow) { //当前列的坐标 int currColIndex=cell.getColumnIndex(); //得到当前列对应的方法名称 String methodName= maps.get(currColIndex); /** * 此处用java反射机制进行方法的反射,由于如果对象有int,date之类的参数,在这里反射就不是特别好用 * 因此这里可以在maven配置 * * <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.2</version> </dependency> beanutils的依赖用beantils来进行 * */ //注意这里如果方法的参数是Integer或者Date或者其他类型需要做判定,而我这里属性全部都定义成String类型的 // Method method=clz.getMethod(methodName, String.class); //通过反射将单元格对应的值、调用对象的setXXX方法实现对数据的添加 //method.invoke(obj, cell.getStringCellValue()); /** * BeanUtils.copyProperty(obj, methodName, method); * 说明 obj对象 * methodName方法 在beantuils这里只要提供属性名称即可 若 方法名setUserName这里只需要时username * * */ methodName=methodName.substring(3); methodName=methodName.substring(0,1).toLowerCase()+methodName.substring(1); BeanUtils.copyProperty(obj, methodName, cell.getStringCellValue()); } //将添加到集合中去 objects.add(obj); } } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return objects; } /*** * * @param titleRow 标题行 * @param clz * @return Map<Integer, String> 对应列所对应的方法 */ @SuppressWarnings("rawtypes") private Map<Integer, String> getExcelHeaderMap(Row titleRow,Class clz){ //首先获取类上上面所注解的标题 List<ExcelHeader> headers=getExcelHeader(clz); //用于存储某一列所对应的方法的值 Map<Integer, String> maps= new HashMap<Integer, String>(); //根据header列表找到对应的数据列表 for (ExcelHeader excelHeader : headers) { for (Cell cell : titleRow) { if(cell.getStringCellValue().trim().equals(excelHeader.getTilte())){ //找到当前列所对应的值将存储起来,而这里我们是得到get方法,需要获取set方法,为对象设置 maps.put(cell.getColumnIndex(), excelHeader.getMethodName().replace("get", "set")); break; } } } return maps; } }
POI工具类 2016-12-09日项目中再次更新
最新推荐文章于 2024-08-07 23:48:20 发布