java 使用POI操作Excel(2)----使用模板操作Excel

       上一节,介绍了基于Apache的POI对Excel基本读写操作.一般情况下使用我们使用CellStyle来修改样式,但是那样的话会显得等别麻烦.所有我们可以先自定义模板,然后从模板中读取样式即可.

下面是对模板操作的封装:

package gd.hz.poi.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

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.RichTextString;
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;

/**
 * 用于处理Excel写操作
 * @author lfd
 * 2013-11-25
 */
public class ExcelTemplate {
	//开始位置
	public final static String TEMPLATE_NAME = "datastart" ;
	//样式,用于要标志自定义的样式的列.
	public final static String STYLE = "style" ;
	//默认样式
	public final static String DEFALULT_STYLE = "defaultStyle" ;
	//序号,确定Excel是否需要样式.
	public final static String SERNUMS = "sernums" ;
	private int initRowIndxe ; //初始行
	private int initColIndex ; //初始列
	private int curRowIndex ;  //当前行
	private int curColIndex ;  //当前列
	private int lastRowInex ;  //最后一行
	private float defaultHeight ; // 默认行高
	private int serColIndex ; //序号行.
	private Workbook workbook = null ;
	private Sheet sheet = null ;
	private Row curRow = null ; //当前行
	//样式
	private Map<Integer,CellStyle> styles = null ;
	//默认样式
	private CellStyle defaultStyle = null ;
	//使用单例
	private static ExcelTemplate excel = new ExcelTemplate() ;
	
	private ExcelTemplate() {}
	public static ExcelTemplate getInstance() {
		return excel ;
	}
	
	/**
	 * 读取模板(从classpath中)
	 * @param path 模板路径
	 * @return ExcelTemplate
	 */
	public ExcelTemplate readTemplateClassPath(String calsspath) {
		try {
			workbook = WorkbookFactory.create(ExcelTemplate.class.getResourceAsStream(calsspath)) ;
			initTemplate() ;
		} catch (InvalidFormatException e) {
			e.printStackTrace();
			throw new RuntimeException("读取模板格式有错!请检查.") ;
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("读取模板文件不存在!请检查.") ;
		}
		return this ; 
	}
	
	/**
	 * 读取模板(从指定路径)
	 * @param path 模板路径
	 * @return ExcelTemplate
	 */
	public ExcelTemplate readTemplatePath(String path) {
		try {
			workbook = WorkbookFactory.create(new File(path)) ;
			initTemplate() ;
		} catch (InvalidFormatException e) {
			e.printStackTrace();
			throw new RuntimeException("读取模板格式有错!请检查.") ;
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("读取模板文件不存在!请检查.") ;
		}
		return this ; 
	}
	
	/**
	 * 创建新的一行
	 */
	public void creatNewRow() {
		//curRowIndex != initRowIndxe : 当前行本身是存在的,所以下移多余.
		if(lastRowInex > curRowIndex && curRowIndex != initRowIndxe) {
			sheet.shiftRows(curRowIndex, lastRowInex, 1, true, true) ;  //有的模板最后可能是日期或者姓名之类的非数据.所以要移动行.
			lastRowInex ++ ;
		}
		curRow = sheet.createRow(curRowIndex) ;
		curRow.setHeightInPoints(defaultHeight) ;
		curRowIndex ++ ;
		curColIndex = initColIndex ;
	}
	
	public void createNewCol(String value) {
		Cell cell = curRow.createCell(curColIndex) ;
		setStyle(cell) ;
		cell.setCellValue(value) ;
		curColIndex ++ ;
	}
	
	public void createNewCol(double value) {
		Cell cell = curRow.createCell(curColIndex) ;
		setStyle(cell) ;
		cell.setCellValue(value) ;
		curColIndex ++ ;
	}
	
	public void createNewCol(boolean value) {
		Cell cell = curRow.createCell(curColIndex) ;
		setStyle(cell) ;
		cell.setCellValue(value) ;
		curColIndex ++ ;
	}
	
	public void createNewCol(Date value) {
		Cell cell = curRow.createCell(curColIndex) ;
		setStyle(cell) ;
		cell.setCellValue(value) ;
		curColIndex ++ ;
	}
	
	public void createNewCol(Calendar value) {
		Cell cell = curRow.createCell(curColIndex) ;
		setStyle(cell) ;
		cell.setCellValue(value) ;
		curColIndex ++ ;
	}
	
	public void createNewCol(RichTextString value) {
		Cell cell = curRow.createCell(curColIndex) ;
		setStyle(cell) ;
		cell.setCellValue(value) ;
		curColIndex ++ ;
	}
	
	/**
	 * 根据#xxx替换模板中的其它样式.
	 * @param datas 要替换的数据
	 */
	public void replaceFind(Map<String, String> datas) {
		if(datas == null) return ;
		for(Row row : sheet) {
			for(Cell cell : row) {
				if(cell.getCellType() != Cell.CELL_TYPE_STRING) continue ;
				String value = cell.getStringCellValue().trim() ;
				if(value.startsWith("#")) {
					if(datas.containsKey(value.substring(1))) {
						cell.setCellValue(datas.get(value.substring(1))) ;
					}
				}
			}
		}
	}
	
	/**
	 * 插入序号
	 */
	public void insertSer() {
		int index = 1 ;
		Row row = null ;
		Cell cell = null ;
		for(int i = initRowIndxe; i < curRowIndex; i++) {
			row = sheet.getRow(i) ;
			cell = row.createCell(serColIndex) ;
			setStyle(cell) ;
			cell.setCellValue(index++) ;
		}
	}
	
	/**
	 * 输出文件,根据路径
	 * @param path 路径
	 */
	public void writeToFile(String path) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(path) ;
			workbook.write(fos) ;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException("找不到文件!请检查.") ;
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("文件输出异常!请检查.") ;
		} finally {
			try {
				if(fos != null) {
					fos.close() ;
					fos = null ;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 输出文件,根据流输出
	 * @param stream OutputStream
	 */
	public void writeToStream(OutputStream stream) {
		try {
			workbook.write(stream) ;
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("文件输出异常!请检查.") ;
		} finally {
			try {
				if(stream != null) {
					stream.close() ;
					stream = null ;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 初始化模板
	 */
	private void initTemplate() {
		sheet = workbook.getSheetAt(0) ;
		styles = new HashMap<Integer, CellStyle>() ;
		initConfigData() ;
		lastRowInex = sheet.getLastRowNum() ;
	}
	
	/**
	 * defaultStyles:获得默认样式(如果默认样式没有则使用开始样式)
	 * styles:获取自定义样式
	 * 
	 */
	private void initConfigData() {
		for(Row row : sheet) {
			for(Cell cell : row) {
				if(cell.getCellType() != Cell.CELL_TYPE_STRING) continue ;
				String value = cell.getStringCellValue().trim() ;
				//获取开始位置,初始化数据
				if(TEMPLATE_NAME.equals(value)) {
					initRowIndxe = cell.getRowIndex() ;
					initColIndex = cell.getColumnIndex() ;
					curRowIndex = initRowIndxe ;
					curColIndex = initColIndex ;
					defaultHeight = row.getHeightInPoints() ;
					if(defaultStyle == null) defaultStyle = cell.getCellStyle() ;
				}
				
				//获取defaultStyles,无论如何,当有设置defaultStyles都设置为defaultStyles
				if(DEFALULT_STYLE.equals(value)) defaultStyle = cell.getCellStyle() ;
				
				//获取自定义样式的列
				if(STYLE.equals(value)) {
					styles.put(cell.getColumnIndex(), cell.getCellStyle()) ;
				}
				
				//获取样式所在的列
				if(SERNUMS.equals(value)) serColIndex = cell.getColumnIndex() ;
			}
		}
	} 
	
	/**
	 * 设置样式
	 * @param cell Cell
	 */
	private void setStyle(Cell cell) {
		
		//当前列存在自定义样式时使用自定义样式,否则使用默认样式.
		if(styles.containsKey(curColIndex)) {
			cell.setCellStyle(styles.get(curColIndex)) ;
		} else {
			cell.setCellStyle(defaultStyle) ;
		}		
	}
}

基本原理是获取模板样式,记录自定义样式所在列的列号和样式,然后根据列号输出样式.

样式例子:

@Test
	public void testExcel() {
		ExcelTemplate excel = ExcelTemplate.getInstance().readTemplatePath("D:/Project/MAVEN_ANT/Poi_Template/excel/lilys.xls") ;
		excel.creatNewRow() ;
		excel.createNewCol("aaa") ;
		excel.createNewCol("111") ;
		excel.createNewCol("111") ;
		excel.createNewCol("111") ;
		excel.creatNewRow() ;
		excel.createNewCol("bbb") ;
		excel.createNewCol("222") ;
		excel.createNewCol("222") ;
		excel.createNewCol("222") ;
		excel.creatNewRow() ;
		excel.createNewCol("ccc") ;
		excel.createNewCol("333") ;
		excel.createNewCol("333") ;
		excel.createNewCol("333") ;
		excel.creatNewRow() ;
		excel.createNewCol("ddd") ;
		excel.createNewCol("444") ;
		excel.createNewCol("444") ;
		excel.createNewCol("444") ;
		excel.creatNewRow() ;
		excel.createNewCol("eee") ;
		excel.createNewCol("555") ;
		excel.createNewCol("555") ;
		excel.createNewCol("555") ;
		Map<String, String> datas = new HashMap<String, String>() ;
		datas.put("title", "拉斯维加斯") ;
		datas.put("date", new Date().toString()) ;
		datas.put("department", "百合科技人事部") ;
		excel.replaceFind(datas) ;
		excel.insertSer() ;
		excel.writeToFile("D:/poi.xls") ;
	}

下面是例子的源代码(Maven项目):

http://www.kuaipan.cn/file/id_129263676497613793.htm

相关推荐