POI操作Excel导入和导出

Apache的POI组件是Java操作Microsoft Office办公套件的强大API,当中对Word,Excel和PowperPoint都有支持,当然使用较多的还是Excel。由于Word和PowerPoint用程序动态操作的应用较少。那么本文就结合POI来介绍一下操作Excel的方法。

 

这里介绍两种方法实现excel的操作。代码都有凝视,能够非常清楚的看懂,一种是循环遍历excel表格。这个要自己定位一个excel的起点。第二种是通过java反射机制实现的,依据表头来实现映射。

详细代码例如以下:

第一种:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;



import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.util.Region;


public class ExcelUtils {
	
	/**
	 * 读取EXCEL
	 * @param firstrow 从第几行開始读取
	 * @return 读取后返回数组
	 */
	@SuppressWarnings("deprecation")
	public static String[][] importExcel(File file, int firstrow)
			throws FileNotFoundException, IOException {
		List<String[]> result = new ArrayList<String[]>();
		int rowSize = 0;
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(
				file));
		POIFSFileSystem fs = new POIFSFileSystem(in);
		HSSFWorkbook wb = new HSSFWorkbook(fs);
		HSSFCell cell = null;
		for (int sheetIndex = 0; sheetIndex < wb.getNumberOfSheets(); sheetIndex++) {
			HSSFSheet st = wb.getSheetAt(sheetIndex);
			for (int rowIndex = firstrow; rowIndex <= st.getLastRowNum(); rowIndex++) {
				HSSFRow row = st.getRow(rowIndex);
				if (row == null) {
					continue;
				}
				int tempRowSize = row.getLastCellNum() + 1;
				if (tempRowSize > rowSize) {
					rowSize = tempRowSize;
				}
				String[] values = new String[rowSize];
				Arrays.fill(values, "");
				boolean hasValue = false;

				for (short columnIndex = 0; columnIndex <= row.getLastCellNum(); columnIndex++) {
					String value = "";
					cell = row.getCell(columnIndex);
					if (cell != null) {
						switch (cell.getCellType()) {
						case HSSFCell.CELL_TYPE_STRING://读取的格式为字符串
							value = cell.getStringCellValue();
							break;
						case HSSFCell.CELL_TYPE_NUMERIC://读取的格式为数组
							//假设格式为日期格式,自己定义格式输出
							if (HSSFDateUtil.isCellDateFormatted(cell)) {
								Date date = cell.getDateCellValue();
								if (date != null) {
									value = new SimpleDateFormat("yyyy-MM-dd")
											.format(date);
								} else {
									value = "";
								}
							} else {
								//假设格式为数值,自己定义格式输出
								value = new DecimalFormat().format(cell
										.getNumericCellValue());
							}
							break;
						case HSSFCell.CELL_TYPE_FORMULA:
							// 导入时假设为公式生成的数据则无值
							value = "";
							break;
							// 导入时假设为空
						case HSSFCell.CELL_TYPE_BLANK:
							break;
						case HSSFCell.CELL_TYPE_ERROR:
							value = "";
							break;
							// 导入时假设为BOOLEAN型 自己定义格式输出
						case HSSFCell.CELL_TYPE_BOOLEAN:
							value = (cell.getBooleanCellValue() == true ? "Y"
									: "N");
							break;
						default:
							value = "";
						}
					}

					values[columnIndex] = rightTrim(value);
					hasValue = true;
				}

				if (hasValue) {
					result.add(values);
				}
			}

			in.close();
			String[][] returnArray = new String[result.size()][rowSize];
			for (int i = 0; i < returnArray.length; i++) {
				returnArray[i] = (String[]) result.get(i);
			}
			return returnArray;
		}
		return null;

	}

	/**
	 * 去掉字符串右边的空格
	 * 
	 * @param str 要处理的字符串
	 * @return 处理后的字符串
	 */
	public static String rightTrim(String str) {
		if (str == null) {
			return "";
		}
		int length = str.length();
		for (int i = length - 1; i >= 0; i--) {
			if (str.charAt(i) != 0x20) {
				break;
			}
			length--;
		}
		return str.substring(0, length);
	}
	
/**
	 * 创建通用EXCEL头部
	 * 
	 * @param headString 头部显示的字符
	 * @param colSum 该报表的列数
	 */
	@SuppressWarnings("deprecation")
	public void createNormalHead(String headString, int colSum,HSSFSheet sheet,HSSFWorkbook wb) {
	    
		HSSFRow row1 = sheet.createRow(0);

		// 设置第一行
		HSSFCell cell = row1.createCell(0);
		row1.setHeight((short) 800);

		// 定义单元格为字符串类型
		cell.setCellType(HSSFCell.ENCODING_UTF_16);
		cell.setCellValue(new HSSFRichTextString(headString));

		// 指定合并区域
		sheet.addMergedRegion(new Region(0, (short) 0, 0, (short) colSum));

		HSSFCellStyle cellStyle = wb.createCellStyle();

		cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 指定单元格居中对齐
		cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 指定单元格垂直居中对齐
		//cellStyle.setWrapText(true);// 指定单元格自己主动换行

		// 设置单元格字体
		HSSFFont font = wb.createFont();
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("宋体");
		font.setFontHeight((short) 300);
		cellStyle.setFont(font);

		cell.setCellStyle(cellStyle);
	}
	
	/**
	 * 创建通用报表第二行的格式
	 * 
	 */
	public HSSFCellStyle getCellStyle(HSSFWorkbook wb) {
		// 创建单元格样式
 		HSSFCellStyle cellStyle = wb.createCellStyle();
 		// 指定单元格居中对齐
 		cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
 		// 指定单元格垂直居中对齐
 		cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
 		// 指定当单元格内容显示不下时自己主动换行
 		//cellStyle.setWrapText(true);
 		// 设置单元格字体
 		HSSFFont font = wb.createFont();
 		font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
 		font.setFontName("宋体");
 		font.setFontHeight((short) 200);
 		//font.setFontHeightInPoints((short) 22);
 		cellStyle.setFont(font);
 		return cellStyle;

	}
	
}

另外一种:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
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.util.CellRangeAddress;

public class ExcelUtil<T> {
	/**
	 * 从excel导入,返回一个list集合
	 * 
	 * @author 
	 * @param file
	 *            导入的excel文件
	 * @param pattern
	 * @return
	 * */
	Class<T> clazz;

	public ExcelUtil(Class<T> clazz) {
		this.clazz = clazz;
	}

	@SuppressWarnings("unchecked")
	public Collection<T> importExcel(File file, String... pattern)
			throws Exception {
		Collection<T> dist = new ArrayList<T>();
		try {
			/**
			 * 类反射得到调用方法
			 */
			// 得到目标目标类的全部的字段列表
			Field filed[] = clazz.getDeclaredFields();
			// 将全部标有Annotation的字段。也就是同意导入数据的字段,放入到一个map中
			Map fieldmap = new HashMap();
			// 循环读取全部字段
			for (int i = 0; i < filed.length; i++) {
				Field f = filed[i];
				// 得到单个字段上的Annotation
				ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
				// 假设标识了Annotationd的话
				if (exa != null) {
					// 构造设置了Annotation的字段的Setter方法
					String fieldname = f.getName();
					String setMethodName = "set"
							+ fieldname.substring(0, 1).toUpperCase()
							+ fieldname.substring(1);
					// 构造调用的method,
					Method setMethod = clazz.getMethod(setMethodName,
							new Class[] { f.getType() });
					// 将这个method以Annotaion的名字为key来存入。

fieldmap.put(exa.exportName(), setMethod); } } /** * excel的解析開始 */ // 将传入的File构造为FileInputStream; FileInputStream in = new FileInputStream(file); // // 得到工作表 HSSFWorkbook book = new HSSFWorkbook(in); // // 得到第一页 HSSFSheet sheet = book.getSheetAt(0); // // 得到第一面的全部行 Iterator<Row> row = sheet.rowIterator(); /** * 标题解析 */ // 得到第一行。也就是标题行 Row title = row.next(); // 得到第一行的全部列 Iterator<Cell> cellTitle = title.cellIterator(); // 将标题的文字内容放入到一个map中。 Map titlemap = new HashMap(); // 从标题第一列開始 int i = 0; // 循环标题全部的列 while (cellTitle.hasNext()) { Cell cell = cellTitle.next(); String value = cell.getStringCellValue(); // 还是把表头trim一下 value = value.trim(); titlemap.put(i, value); i = i + 1; } /** * 解析内容行 */ // 用来格式化日期的DateFormat SimpleDateFormat sf; if (pattern.length < 1) { sf = new SimpleDateFormat("yyyy-MM-dd"); } else sf = new SimpleDateFormat(pattern[0]); while (row.hasNext()) { // 标题下的第一行 Row rown = row.next(); // 行的全部列 Iterator<Cell> cellbody = rown.cellIterator(); // 得到传入类的实例 T tObject = clazz.newInstance(); int k = 0; // 遍历一行的列 while (cellbody.hasNext()) { Cell cell = cellbody.next(); // 这里得到此列的相应的标题 String titleString = (String) titlemap.get(k); // 假设这一列的标题和类中的某一列的Annotation同样,那么则调用此类的的set方法,进行设值 if (fieldmap.containsKey(titleString)) { Method setMethod = (Method) fieldmap.get(titleString); // 得到setter方法的參数 Type[] ts = setMethod.getGenericParameterTypes(); // 仅仅要一个參数 String xclass = ts[0].toString(); // 推断參数类型 try { switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC: // 数字 if (xclass.equals("class java.lang.String")) { if ((cell.getNumericCellValue() + "") .indexOf(".") > 0) { setMethod .invoke(tObject, (cell.getNumericCellValue() + "") .substring( 0, (cell.getNumericCellValue() + "") .lastIndexOf("."))); } } else if (xclass .equals("class java.lang.Integer")) { setMethod.invoke(tObject, (int) cell.getNumericCellValue()); } else if (xclass.equals("int")) { setMethod.invoke(tObject, (int) cell.getNumericCellValue()); } break; case HSSFCell.CELL_TYPE_STRING: // 字符串 if (xclass.equals("class java.lang.Integer")) { setMethod.invoke(tObject, Integer.parseInt(cell .getStringCellValue())); } else if (xclass .equals("class java.lang.String")) { setMethod.invoke(tObject, cell .getStringCellValue().trim()); } else if (xclass.equals("int")) { int temp = Integer.parseInt(cell .getStringCellValue()); setMethod.invoke(tObject, temp); } break; case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean Boolean boolname = true; if (cell.getStringCellValue().equals("否")) { boolname = false; } setMethod.invoke(tObject, boolname); break; case HSSFCell.CELL_TYPE_FORMULA: // 公式 System.out.print(cell.getCellFormula() + " "); break; case HSSFCell.CELL_TYPE_BLANK: // 空值 System.out.println(" "); break; case HSSFCell.CELL_TYPE_ERROR: // 故障 System.out.println(" "); break; default: System.out.print("未知类型 "); break; } } catch (Exception e) {// 转换出错 e.printStackTrace(); } } // 下一列 k = k + 1; } dist.add(tObject); } } catch (Exception e) { e.printStackTrace(); // 将异常抛出去 throw e; } return dist; } // 格式化日期 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); /** * 导出到excel中去, * * @author Administrator * @param title * excel的工作表名 * @param fileName * excel 文件名称 * @param dateset * 导出的数据集合 * @param out * 输出流 * @throws IOException */ @SuppressWarnings({ "static-access" }) public void exportExcel(String title, String fileName, List<T> dataset, String totalMoney, HttpServletResponse response) throws IOException { OutputStream out = response.getOutputStream();// 取得输出流 response.reset();// 清空输出流 response.setContentType("application/ms-excel;charset=GB2312"); response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("gb2312"), "iso8859-1") + ".xls"); // 声明一个工作薄 try { HSSFWorkbook workbook = new HSSFWorkbook(); // 首先检查数据看是否是正确的 if (dataset == null || dataset.size() == 0 || title == null || out == null) { throw new Exception("传入的数据不正确!"); } // 取得实际泛型类 T ts = (T) dataset.get(0); Class<?> tCls = ts.getClass(); // 生成一个表格 HSSFSheet sheet = workbook.createSheet(title); // 设置表格默认列宽度为15个字节 sheet.setDefaultColumnWidth(15); // 生成一个样式 HSSFCellStyle style = workbook.createCellStyle(); // 设置标题样式 style = this.setHeadStyle(workbook, style); // 得到全部字段 Field filed[] = ts.getClass().getDeclaredFields(); // 标题 List<String> exportfieldtile = new ArrayList<String>(); // 导出的字段的get方法 List<Method> methodObj = new ArrayList<Method>(); // 遍历整个filed for (int i = 0; i < filed.length; i++) { Field f = filed[i]; ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class); // 假设设置了annottion if (exa != null) { String exprot = exa.exportName(); // 加入到标题 exportfieldtile.add(exprot); // 加入到须要导出的字段的方法 String fieldname = f.getName(); String getMethodName = "get" + fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1); Method getMethod = tCls.getMethod(getMethodName, new Class[] {}); methodObj.add(getMethod); } } sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, exportfieldtile .size() - 1)); HSSFRow titleRow = sheet.createRow(0); HSSFCell titleCell = titleRow.createCell(0); titleCell.setCellValue(title); titleCell.setCellStyle(this.setTitleStyle(workbook, workbook.createCellStyle())); // 产生表格标题行 HSSFRow row = sheet.createRow(1); for (int i = 0; i < exportfieldtile.size(); i++) { HSSFCell cell = row.createCell(i); cell.setCellStyle(style); HSSFRichTextString text = new HSSFRichTextString( exportfieldtile.get(i)); cell.setCellValue(text); } int index = 1; // 循环整个list for (int j = 0; j < dataset.size(); j++) { // 从第二行開始写,第一行是标题 T t = (T) dataset.get(j); row = sheet.createRow(index + 1); for (int k = 0; k < methodObj.size(); k++) { HSSFCell cell = row.createCell(k); Method getMethod = methodObj.get(k); Object value = getMethod.invoke(t, new Object[] {}); String textValue = getValue(value); cell.setCellValue(textValue); } index++; } //总的项目笔数 HSSFRow totalNumRow = sheet.createRow(index + 2); HSSFCell totalNumCellTitle = totalNumRow.createCell(0); totalNumCellTitle.setCellStyle(setStatStyle(workbook, workbook.createCellStyle())); totalNumCellTitle.setCellValue("项目笔数"); HSSFCell totalNumCell = totalNumRow.createCell(1); totalNumCell.setCellStyle(setStatStyle(workbook, workbook.createCellStyle())); totalNumCell.setCellValue(dataset.size()); //总金额 HSSFRow totalMoneyRow = sheet.createRow(index + 3); HSSFCell totalMoneyCellTitle = totalMoneyRow.createCell(0); totalMoneyCellTitle.setCellStyle(setStatStyle(workbook, workbook.createCellStyle())); totalMoneyCellTitle.setCellValue("总金额"); HSSFCell totalMoneyCell = totalMoneyRow.createCell(1); totalMoneyCell.setCellStyle(setStatStyle(workbook, workbook.createCellStyle())); totalMoneyCell.setCellValue(totalMoney + "万元"); workbook.write(out); } catch (Exception e) { e.printStackTrace(); } } public String getValue(Object value) { String textValue = ""; if (value == null) return textValue; if (value instanceof Boolean) { boolean bValue = (Boolean) value; textValue = "是"; if (!bValue) { textValue = "否"; } } else if (value instanceof Date) { Date date = (Date) value; textValue = sdf.format(date); } else textValue = value.toString(); return textValue; } /** * 初始化导出的excel标题的样式 * */ public static HSSFCellStyle setTitleStyle(HSSFWorkbook workbook, HSSFCellStyle style) { style.setFillForegroundColor(HSSFColor.WHITE.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 生成字体 HSSFFont font = workbook.createFont(); font.setColor(HSSFColor.BLACK.index); font.setFontHeightInPoints((short) 16); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 把字体应用到当前的样样式 style.setFont(font); return style; } /** * 统计部分的样式 * @param workbook * @param style * @return */ public static HSSFCellStyle setStatStyle(HSSFWorkbook workbook, HSSFCellStyle style) { style.setFillForegroundColor(HSSFColor.WHITE.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style.setBorderBottom(HSSFCellStyle.BORDER_NONE); style.setBorderLeft(HSSFCellStyle.BORDER_NONE); style.setBorderRight(HSSFCellStyle.BORDER_NONE); style.setBorderTop(HSSFCellStyle.BORDER_NONE); style.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 生成字体 HSSFFont font = workbook.createFont(); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 把字体应用到当前的样样式 style.setFont(font); return style; } /** * 初始化导出的excel样式 * */ public static HSSFCellStyle setHeadStyle(HSSFWorkbook workbook, HSSFCellStyle style) { style.setFillForegroundColor(HSSFColor.SKY_BLUE.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 生成字体 HSSFFont font = workbook.createFont(); font.setColor(HSSFColor.VIOLET.index); font.setFontHeightInPoints((short) 12); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 把字体应用到当前的样样式 style.setFont(font); return style; } public static HSSFCellStyle setbodyStyle(HSSFWorkbook workbook, HSSFCellStyle style2) { style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index); style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style2.setBorderBottom(HSSFCellStyle.BORDER_THIN); style2.setBorderLeft(HSSFCellStyle.BORDER_THIN); style2.setBorderRight(HSSFCellStyle.BORDER_THIN); style2.setBorderTop(HSSFCellStyle.BORDER_THIN); style2.setAlignment(HSSFCellStyle.ALIGN_CENTER); style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 生成字体 HSSFFont font2 = workbook.createFont(); font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); // 把字体应用到当前的样样式 style2.setFont(font2); return style2; } }



import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 用于Excel导出时给每一个pojo对象的字段加入字段名称,作为excel的表头
 * 
 * */
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)  
public @interface ExcelAnnotation {  
    // excel导出时标题显示的名字,假设没有设置Annotation属性,将不会被导出和导入  
    public String exportName();  
}




posted @ 2017-04-27 16:50  lytwajue  阅读(242)  评论(0编辑  收藏  举报