大多时候会出现需要导出excel的功能,利用poi可以实现简单的导出,可以说poi的功能非常强大可以做到细节的定制化操作,但相对于在office操作excel,利用poi完全生成excel会显得非常复杂,细节代码会特别多。在这个时候我们可以事先利用offfice制定好一个模版文件,在利用jxls来通过模版文件来实现复杂excel的导出。
模版的制作和一般excel的编写是一样的,在需要填充的网格利用{}来进行取出java中传进来的变量值,如图:
在java中:
InputStream is =getFileInputStream(templateFileName);//获取模板输入流
XLSTransformer transformer = new XLSTransformer();
HSSFWorkbook resultWorkbook =transformer.transformMultipleSheetsList(is,prints/*要打印的list*/,
sheetNames/*sheet的名称list*/, "print"/*excel的bean名称*/, new HashMap(), 0);
在excel中,jxls会将要打印的list通过我们定义的bean名称取出进行遍历,在源码中
public HSSFWorkbook transformMultipleSheetsList(InputStream is, List objects, List newSheetNames, String beanName, Map beanParams, int startSheetNum) throws ParsePropertyException {
HSSFWorkbook hssfWorkbook = null;
try {
if (beanParams != null && ((Map)beanParams).containsKey(beanName)) {
throw new IllegalArgumentException("Selected bean name '" + beanName + "' already exists in the bean map");
}
if (beanName == null) {
throw new IllegalArgumentException("Bean name must not be null");
}
if (beanParams == null) {
beanParams = new HashMap();
}
POIFSFileSystem fs = new POIFSFileSystem(is);
hssfWorkbook = new HSSFWorkbook(fs);
for(int sheetNo = 0; sheetNo < hssfWorkbook.getNumberOfSheets(); ++sheetNo) {
String spreadsheetName = hssfWorkbook.getSheetName(sheetNo);
if (!this.isSpreadsheetToRemove(spreadsheetName)) {
if (this.isSpreadsheetToRename(spreadsheetName)) {
hssfWorkbook.setSheetName(sheetNo, this.getSpreadsheetToReName(spreadsheetName));
}
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(sheetNo);
if (startSheetNum == sheetNo && objects != null && !objects.isEmpty()) {
for(int i = 0; i < objects.size(); ++i) {
Object bean = objects.get(i);
String beanKey = beanName;
if (i != 0) {
beanKey = beanName + i;
HSSFSheet newSheet = hssfWorkbook.createSheet((String)newSheetNames.get(i));
Util.copySheets(newSheet, hssfSheet, beanName, beanKey);
Util.copyPageSetup(newSheet, hssfSheet);
Util.copyPrintSetup(newSheet, hssfSheet);
} else {
hssfWorkbook.setSheetName(sheetNo, (String)newSheetNames.get(i));
}
((Map)beanParams).put(beanKey, bean);//在此次将我们传入的list通过map的形式放入beanParams
}
}
} else {
hssfWorkbook.removeSheetAt(sheetNo);
--sheetNo;
}
}
} catch (IOException var16) {
var16.printStackTrace();
}
if (hssfWorkbook != null) {
for(int i = 0; i < hssfWorkbook.getNumberOfSheets(); ++i) {
Util.setPrintArea(hssfWorkbook, i);
}
}
this.transformWorkbook(hssfWorkbook, (Map)beanParams);//通过模板和beanParams生产excel
return hssfWorkbook;
}
在excel中通过beanParams的Map形式来进行取值,有点类似于freemarker语法,但不同于freemarker
在此事例中,我定义了一个类(domain)来存放list,类的形式如下(即要打印的list的元素是以下类)
public class ExcelPrintDomain implements Serializable {
private List lista = new ArrayList();
private Object domaina;
private ServletContext context;
private int pageNo;
public ExcelPrintDomain() {
}
public ExcelPrintDomain(ServletContext context) {
this.context = context;
}
public void addDomain(Object obj) {
this.domains.add(obj);
}
public void addLista(Object obj) {
this.lista.add(obj);
}
public int getPageNo() {
return this.pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public List getLista() {
return this.lista;
}
public void setLista(List lista) {
this.lista = lista;
}
public Object getDomaina() {
return this.domaina;
}
public void setDomaina(Object domaina) {
this.domaina = domaina;
}
}
所以在模板中${print.domaina.orgName}代表的是取出domain里面的domaina里面的key为orgName的value值,
${print.lista.ec01002}代表的是在遍历中取出domain中的lista包含的Map里面的key为ec01002的value值。
来源:oschina
链接:https://my.oschina.net/u/4303080/blog/4225547