当前位置: 代码迷 >> 报表 >> “Java+POI+模板”1:打造复杂Excel 报表
  详细解决方案

“Java+POI+模板”1:打造复杂Excel 报表

热度:498   发布时间:2016-04-29 01:58:58.0
“Java+POI+模板”一:打造复杂Excel 报表

1 设计思路

Java 对于Excel 的操作一般借助于POI 类库,由于有些报表的表头比较复杂,直接用POI 控制报表的生成比较困难,这时可以先制作Excel 报表模板,而后再通过Java 调用POI 函数将用户数据写入到Excel 报表模板,最后导出到新的目标文件即可。

2 设计步骤

2.1 初始步骤

2.1.1创建Excel 报表模板

根据需要设计出Excel 报表,并保存为default.xls。如下图所示。



2.1.2创建ExcelTemplate类

/** * 该类实现了基于模板的导出 * 如果要导出序号,需要在excel中定义一个标识为sernums * 如果要替换信息,需要传入一个Map,这个map中存储着要替换信息的值,在excel中通过#来开头 * 要从哪一行那一列开始替换需要定义一个标识为datas * 如果要设定相应的样式,可以在该行使用styles完成设定,此时所有此行都使用该样式 * 如果使用defaultStyls作为表示,表示默认样式,如果没有defaultStyles使用datas行作为默认样式 */public class ExcelTemplate {        private ExcelTemplate() {	}	public static ExcelTemplate getInstance() {		return et;	}}

?下面是以后要用到的一些变量和常量

/**	 * 数据行标识	 */	public final static String DATA_LINE = "datas";	/**	 * 默认样式标识	 */	public final static String DEFAULT_STYLE = "defaultStyles";	/**	 * 行样式标识	 */	public final static String STYLE = "styles";	/**	 * 插入序号样式标识	 */	public final static String SER_NUM = "sernums";	private static ExcelTemplate et = new ExcelTemplate();		private Workbook wb;		private Sheet sheet;	/**	 * 数据的初始化列数	 */	private int initColIndex;	/**	 * 数据的初始化行数	 */	private int initRowIndex;	/**	 * 当前列数	 */	private int curColIndex;	/**	 * 当前行数	 */	private int curRowIndex;	/**	 * 当前行对象	 */	private Row curRow;	/**	 * 最后一行的数据	 */	private int lastRowIndex;	/**	 * 默认样式	 */	private CellStyle defaultStyle;	/**	 * 默认行高	 */	private float rowHeight;	/**	 * 存储某一方所对于的样式	 */	private Map<Integer,CellStyle> styles;	/**	 * 序号的列	 */	private int serColIndex;

?

2.2 读取excel报表模板的数据

/**	 * 1、读取相应的模板文档	 */	public ExcelTemplate readTemplateByClasspath(String path){		try {			wb=WorkbookFactory.create(ExcelTemplate.class.getResourceAsStream(path));			initTemplate();		} catch (InvalidFormatException e) {			e.printStackTrace();			throw new RuntimeException("InvalidFormatException, please check.");		} catch (IOException e) {			e.printStackTrace();			throw new RuntimeException("The template is not exist, please check.");		}		return this;	}		public ExcelTemplate readTemplateByPath(String path){		try {			wb=WorkbookFactory.create(new File(path));		} catch (InvalidFormatException e) {			e.printStackTrace();			throw new RuntimeException("InvalidFormatException, please check.");		} catch (IOException e) {			e.printStackTrace();			throw new RuntimeException("The template is not exist, please check.");		}		return this;	}

?在读取报表模板的时候会初始化模板,记录模板的样式,插入数据的位置

private void initTemplate(){		sheet=wb.getSheetAt(0);		initConfigData();		lastRowIndex = sheet.getLastRowNum();		curRow=sheet.getRow(curRowIndex);	}/**	 * 循环遍历,找到有datas字符的那个单元,记录initColIndex,initRowIndex,curColIndex,curRowIndex	 * 调用initStyles()方法	 * 在寻找datas字符的时候会顺便找一下sernums,如果有则记录其列号serColIndex;如果没有则调用initSer()方法,重新循环查找	 */	private void initConfigData() {		boolean findData=false;		boolean findSer = false;		for(Row row : sheet){			if(findData) break;			for(Cell c: row){				if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue;				String str=c.getStringCellValue().trim();				if(str.equals(SER_NUM)){					serColIndex=c.getColumnIndex();					findSer=true;				}				if(str.equals(DATA_LINE)){					initColIndex=c.getColumnIndex();					initRowIndex=row.getRowNum();					curColIndex=initColIndex;					curRowIndex=initRowIndex;					findData=true;					break;				}			}		}		if(!findSer){			initSer();		}		initStyles();	}/**	 * 初始化序号位置	 */	private void initSer() {		for(Row row:sheet) {			for(Cell c:row) {				if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue;				String str = c.getStringCellValue().trim();				if(str.equals(SER_NUM)) {					serColIndex = c.getColumnIndex();				}			}		}	}		/**	 * 初始化样式信息	 */	private void initStyles(){		styles = new HashMap<Integer, CellStyle>();		for(Row row:sheet) {			for(Cell c:row) {				if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue;				String str = c.getStringCellValue().trim();				if(str.equals(DEFAULT_STYLE)) {					defaultStyle = c.getCellStyle();					rowHeight=row.getHeightInPoints();				}				if(str.equals(STYLE)||str.equals(SER_NUM)) {					styles.put(c.getColumnIndex(), c.getCellStyle());				}			}		}	}

?

2.3 新建excel并向其写数据

public void writeToFile(String filepath){		FileOutputStream fos=null;		try {			fos=new FileOutputStream(filepath);			wb.write(fos);		} catch (FileNotFoundException e) {			e.printStackTrace();			throw new RuntimeException("写入的文件不存在"+e.getMessage());		} catch (IOException e) {			e.printStackTrace();			throw new RuntimeException("写入数据失败"+e.getMessage());		} finally{			if(fos!=null)				try {					fos.close();				} catch (IOException e) {					e.printStackTrace();				}		}	}

?

2.4 实现Excel公共模板的第一步(实现了数据插入)

下面是创建单元格的方法,以及重载方法

public void createCell(String value){		Cell c =curRow.createCell(curColIndex);		setCellStyle(c);		c.setCellValue(value);		curColIndex++;	}	public void createCell(int value) {		Cell c = curRow.createCell(curColIndex);		setCellStyle(c);		c.setCellValue((int)value);		curColIndex++;	}	public void createCell(Date value) {		Cell c = curRow.createCell(curColIndex);		setCellStyle(c);		c.setCellValue(value);		curColIndex++;	}	public void createCell(double value) {		Cell c = curRow.createCell(curColIndex);		setCellStyle(c);		c.setCellValue(value);		curColIndex++;	}	public void createCell(boolean value) {		Cell c = curRow.createCell(curColIndex);		setCellStyle(c);		c.setCellValue(value);		curColIndex++;	}        public void createCell(Calendar value) {		Cell c = curRow.createCell(curColIndex);		setCellStyle(c);		c.setCellValue(value);		curColIndex++;	}

上面的方法会调用setCellStyle方法来设置单元格样式

/**	 * 设置某个单元格的样式	 * @param c	 */	private void setCellStyle(Cell c) {		if(styles.containsKey(c.getColumnIndex())) {			c.setCellStyle(styles.get(c.getColumnIndex()));		} else {			c.setCellStyle(defaultStyle);		}	}

?createNewRow方法用于创建新的行,新的行的位置位于curRowIndex,从curRowIndex到lastRowIndex的所有行会自动向下移动一行。

public void createNewRow(){		if(lastRowIndex>curRowIndex&&curRowIndex!=initRowIndex) {			sheet.shiftRows(curRowIndex, lastRowIndex, 1,true,true);			lastRowIndex++;		}		curRow = sheet.createRow(curRowIndex);		curRow.setHeightInPoints(rowHeight);		curRowIndex++;		curColIndex=initColIndex;	}

2.5 实现增加序号

/**	 * 插入序号,会自动找相应的序号标示的位置完成插入	 */	public void insertSer() {		int index = 1;		Row row = null;		Cell c = null;		for(int i=initRowIndex;i<curRowIndex;i++) {			row = sheet.getRow(i);			c = row.createCell(serColIndex);			setCellStyle(c);			c.setCellValue(index++);		}	}

?2.6?替换模板中#开头的值

/**	 * 根据map替换相应的常量,通过Map中的值来替换#开头的值	 * @param datas	 */	public void replaceFinalData(Map<String,String> datas) {		if(datas==null) return;		for(Row row:sheet) {			for(Cell c:row) {				if(c.getCellType()!=Cell.CELL_TYPE_STRING) continue;				String str = c.getStringCellValue().trim();				if(str.startsWith("#")) {					if(datas.containsKey(str.substring(1))) {						c.setCellValue(datas.get(str.substring(1)));					}				}			}		}	}

?3实现步骤

@Test	public void test01() {		ExcelTemplate et = ExcelTemplate.getInstance()					.readTemplateByClasspath("/excel/default.xls");		et.createNewRow();		et.createCell("1111111");		et.createCell("aaaaaaaaaaaa");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("222222");		et.createCell("bbbbb");		et.createCell("b");		et.createCell("dbbb");		et.createNewRow();		et.createCell("3333333");		et.createCell("cccccc");		et.createCell("a1");		et.createCell(12333);		et.createNewRow();		et.createCell("4444444");		et.createCell("ddddd");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell(112);		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell("a2a2");		et.createNewRow();		et.createCell("555555");		et.createCell("eeeeee");		et.createCell("a1");		et.createCell("a2a2");		Map<String,String> datas = new HashMap<String,String>();		datas.put("title","测试用户信息");		datas.put("date","2012-06-02 12:33");		datas.put("dep","昭通师专财务处");		et.replaceFinalData(datas);		et.insertSer();		et.writeToFile("d:/test/poi/test01.xls");	}

?4 最后结果



?

  相关解决方案