POI工具类 2016-12-09日项目中再次更新

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;
	}
	
	
	
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值