这两天公司让作一个报表,时间比较紧就用以前同事的代码,以前同事使用的 POI 开发的 , 我在开发的时候感受比较繁琐,特别是对“细胞”(cell)的设置,若是一个类里面要处处两个不一样的报表,那么你个组装过程将会变得异常的烦人, 即便把数据组装这部分抽取出来感受仍是很繁琐。下面就给你们推荐一种好的方法使用 XLSTransformer 来导出报表。可能个人语言不够华美不能打动让你使用XLSTransformer,下面我们就拿某公司现有的程序作个对比:html
一:使用POI 作的导出:java
java类中的 exportTradeIllegalDetails 方法:apache
/**安全
* 导出excel多线程
* @param parameter 查出来的list集合app
* @param outputStream函数
* @throws IOException工具
*/学习
public void exportTradeIllegalDetails(List<Map<String,Object>> parameter,ServletOutputStream outputStream) throws IOException {测试
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("余额变更明细" );
String[] headerColumns={ "操做日期" ,"用户id" ,"姓名" ,"手机号" ,"订单号" ,"解冻/冻结" ,"余额变更" ,"账号余额" ,"项目明细" ,"项目明细内容" };
ExcelUtil. generateHeader(workbook ,sheet,headerColumns);
HSSFCellStyle style = ExcelUtil. getCellStyle(workbook,false);
int rowNum = 0;
for(Map<String,Object> r : parameter){
rowNum++;
Row row = sheet.createRow(rowNum);
row.setHeightInPoints(25);
// 操做日期
int i=0;
Cell cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "time")));
//用户id 要加密
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "uid")));
//姓名
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "userName")));
//手机号
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "mobile")));
if(r.get("orderNo" )!=null && !r.get("orderNo" ).toString().equals("")){
//订单号
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "orderNo")));
} else if(r.get("contractCode" )!=null && !r.get("contractCode" ).toString().equals("")){
//合同号
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "contractCode")));
} else{
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue( "");
}
//解冻/冻结
cell = row.createCell(i++);
cell.setCellStyle(style);
if(disposeStrNull(r.get( "type")).equals("3" )||disposeStrNull(r.get( "type")).equals("0" )){
cell.setCellValue(disposeStrNull(r.get( "amount")));
} else{
cell.setCellValue( "0");
}
//余额变更
cell = row.createCell(i++);
cell.setCellStyle(style);
if(disposeStrNull(r.get( "type")).equals("1" )||disposeStrNull(r.get( "type")).equals("2" )){
cell.setCellValue(disposeStrNull(r.get( "amount")));
} else{
cell.setCellValue( "0");
}
//账号余额
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "totalAmount")));
//项目明细
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "proDetail")));
//项目明细内容
cell = row.createCell(i++);
cell.setCellStyle(style);
cell.setCellValue(disposeStrNull(r.get( "proConDetail")));
}
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
}
ExcelUtil:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
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.Row;
/**
* excel操做工具类
*
* @param <T>
*/
public class ExcelUtil {
public static HSSFCellStyle getCellStyle(HSSFWorkbook workbook,boolean isHeader){
HSSFCellStyle style = workbook.createCellStyle();
style.setBorderBottom(HSSFCellStyle.BORDER_THIN );
style.setBorderLeft(HSSFCellStyle.BORDER_THIN );
style.setBorderRight(HSSFCellStyle.BORDER_THIN );
style.setBorderTop(HSSFCellStyle.BORDER_THIN );
style.setLocked( true);
if (isHeader) {
style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND );
HSSFFont font = workbook.createFont();
font.setColor(HSSFColor.BLACK.index );
font.setFontHeightInPoints((short ) 12);
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD );
style.setFont(font);
}
return style;
}
public static void generateHeader(HSSFWorkbook workbook,HSSFSheet sheet,String[] headerColumns){
HSSFCellStyle style = getCellStyle(workbook,true);
Row row = sheet.createRow(0);
row.setHeightInPoints(30);
for(int i=0;i<headerColumns.length ;i++){
Cell cell = row.createCell(i);
String[] column = headerColumns[i].split("_#_" );
if(column.length ==1){
sheet.setColumnWidth(i, 3000);
} else{
sheet.setColumnWidth(i, Integer.valueOf(column[1]));
}
cell.setCellValue(column[0]);
cell.setCellStyle(style);
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> HSSFSheet creatAuditSheet(HSSFWorkbook workbook,String sheetName,
List<T> dataset,String[] headerColumns,String[] fieldColumns) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
HSSFSheet sheet = workbook.createSheet(sheetName);
sheet.protectSheet( "");
generateHeader(workbook,sheet,headerColumns);
HSSFCellStyle style = getCellStyle(workbook,false);
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd" );
int rowNum = 0;
for(T t:dataset){
rowNum++ ;
Row row = sheet.createRow(rowNum);
row.setHeightInPoints(25);
for(int i = 0; i < fieldColumns.length; i++){
String fieldName = fieldColumns[i] ;
String getMethodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
try {
Class clazz = t.getClass();
Method getMethod;
getMethod = clazz.getMethod(getMethodName, new Class[]{} );
Object value = getMethod.invoke(t, new Object[]{});
String cellValue = "";
if (value instanceof Date){
Date date = (Date)value;
cellValue = sd.format(date);
} else{
cellValue = null != value ? value.toString() : "" ;
}
Cell cell = row.createCell(i);
cell.setCellStyle(style);
cell.setCellValue(cellValue);
} catch (Exception e) {
}
}
}
return sheet;
}
}
若是如今又有一个新的报表需求而且和以前的半毛钱关系都没有的话,那么你将重复的写这三行代码
cell = row.createCell(i++); cell.setCellStyle(style); cell.setCellValue(disposeStrNull(r.get("uid")));
可能你抽取的更多代码可能会少点,若是报表的不少的话,这些依然很繁琐!下面就让 XLSTransformer 展现展现他的威力吧
二:XLSTransformer导出
2.1 ) 在使用以前,咱们先学习一下Transformer 这个类吧
javax.xml.transform
类 Transformer
java.lang.Object [object Object]
public abstract class
extends Object
此抽象类的实例可以将源树转换为结果树。
能够经过 TransformerFactory.newTransformer 方法获取此类的实例。而后可使用此实例处理来自不一样源的 XML,并将转换输出写入各类接收器。
在多线程同时运行时不能使用此类的对象。不一样线程能够同时使用不一样的 Transformers。
Transformer
能够屡次使用。能够在转换之间保留参数和输出属性。
构造方法摘要 | |
---|---|
protected |
Transformer() 默认构造方法受到有意保护。 |
方法摘要 | |
---|---|
abstract void |
clearParameters() 清除全部经过 setParameter 设置的参数。 |
abstract ErrorListener |
getErrorListener() 获取转换的实际错误事件处理程序。 |
abstract Properties |
getOutputProperties() 获取转换的输出属性的副本。 |
abstract String |
getOutputProperty(String name) 获取对转换器有效的输出属性。 |
abstract Object |
getParameter(String name) 获取经过 setParameter 显式设置的参数。 |
abstract URIResolver |
getURIResolver() 获取将用于解析在 document() 中使用的 URI 的对象。 |
void |
reset() 将此 Transformer 重置为其初始配置。 |
abstract void |
setErrorListener(ErrorListener listener) 设置转换的实际错误事件侦听器。 |
abstract void |
setOutputProperties(Properties oformat) 设置转换的输出属性。 |
abstract void |
setOutputProperty(String name, String value) 设置转换中实际的输出属性。 |
abstract void |
setParameter(String name, Object value) 添加一个转换参数。 |
abstract void |
setURIResolver(URIResolver resolver) 设置将用于解析在 document() 中使用的 URI 的对象。 |
abstract void |
transform(Source xmlSource, Result outputTarget) 将 XML Source 转换为 Result 。 |
从类 java.lang.Object 继承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
构造方法详细信息 |
---|
protected ()
默认构造方法受到有意保护。
方法详细信息 |
---|
public void ()
将此 Transformer
重置为其初始配置。
Transformer
被重置为经过 TransformerFactory.newTransformer()、TransformerFactory.newTransformer(Source source) 或 Templates.newTransformer() 建立它时的状态。reset()
的设计目标是容许重用现有 Transformer
,以节省与建立新 Transformer
有关的资源。
不保证重置的 Transformer
具备相同的 URIResolver 或 ErrorListener Object
,例如 Object.equals(Object obj)。但保证具备功能相同的 URIResolver
和 ErrorListener
。
抛出:
UnsupportedOperationException
- 当实现不能重写此方法时。
从如下版本开始:
1.5
public abstract void (Source xmlSource, Result outputTarget) throws TransformerException
将 XML Source
转换为 Result
。当实例化 Transformer
和对 Transformer
实例进行任何修改时,指定的转换行为由 TransformerFactory
的实际设置决定。
空 Source
表示为由 DocumentBuilder.newDocument() 构造的空文档。空 Source
的转换结果取决于转换行为;结果不总为空 Result
。
参数:
xmlSource
- 要转换的 XML 输入。
outputTarget
- 转换 xmlSource
的 Result
。
抛出:
TransformerException
- 若是转换过程当中发生不可恢复的错误。
public abstract void (String name, Object value)
添加一个转换参数。
以两部分字符串形式传递限定名称,即用花括号括起来的名称空间 URI,后跟本地名称。若是名称中有 null URL,则 String 只包含本地名称。应用程序能够经过测试安全地检查非 null URI,以查看名称的首字符是否为 '{' 字符。
例如,若是 URI 和本地名称是从经过 <xyz:foo xmlns:xyz="http://xyz.foo.com/yada/baz.html"/> 定义的元素获取的,则限定名称将为 "{http://xyz.foo.com/yada/baz.html}foo"。注意,不使用前缀。
参数:
name
- 参数名称,它能够以花括号({})中的名称空间 URI 开始。
value
- 值对象。它能够为任何有效的 Java 对象。处理器负责提供正确的对象 coersion,或只传递在扩展中使用的对象。
抛出:
NullPointerException
- 若是值为 null。
public abstract Object (String name)
获取经过 setParameter 显式设置的参数。
此方法不返回默认参数值,默认参数值直到在转换过程当中计算了节点上下文后才能肯定。
参数:
name
- 要获取的 Object
返回:
已经过 setParameter 设置的参数。
public abstract void ()
清除全部经过 setParameter 设置的参数。
public abstract void (URIResolver resolver)
设置将用于解析在 document() 中使用的 URI 的对象。
若是解析器参数为 null,则将清除 URIResolver 值,且转换器将再也不拥有解析器。
参数:
resolver
- 实现 URIResolver 接口的对象,或为 null。
public abstract URIResolver ()
获取将用于解析在 document() 中使用的 URI 的对象。
返回:
实现 URIResolver 接口的对象,或返回 null。
public abstract void (Properties oformat)
设置转换的输出属性。这些属性将重写经过 xsl:output 在 Templates 中设置的属性。
若是此函数的参数为 null,则移除任何之前设置的属性,且值将恢复为 templates 对象中定义的值。
以两部分字符串形式传递限定属性,即用花括号括起来的名称空间 URI,后跟本地名称。若是名称中有 null URL,则 String 只包含本地名称。应用程序能够经过测试安全地检查非 null URI,以查看名称的首字符是否为 '{' 字符。
例如,若是 URI 和本地名称是从经过 <xyz:foo xmlns:xyz="http://xyz.foo.com/yada/baz.html"/> 定义的元素获取的,则限定名称将为 "{http://xyz.foo.com/yada/baz.html}foo"。注意,不使用前缀。
若是任何参数键不能被识别且不是名称空间限定的,则抛出 IllegalArgumentException
。
参数:
oformat
- 将用于重写在实际转换中任何相同属性的输出属性集。
抛出:
IllegalArgumentException
- 当键没法识别且不是限定于名称空间的键时。
另请参见:
OutputKeys, Properties
public abstract Properties ()
获取转换的输出属性的副本。
返回的属性应包含由用户设置的属性,以及经过样式表设置的属性,且这些属性将 section 16 of the XSL Transformations (XSLT) W3C Recommendation 指定的默认属性做为“默认值”。由用户或经过样式表特定设置的属性应位于基本 Properties 列表中,而未特定设置的 XSLT 默认属性应位于默认的 Properties 列表中。所以,getOutputProperties().getProperty(String key) 将包含经过 setOutputProperty(java.lang.String, java.lang.String)、setOutputProperties(java.util.Properties) 设置的任何属性,或者在样式表或 默认属性中设置的任何属性,而 getOutputProperties().get(String key) 将只检索经过 setOutputProperty(java.lang.String, java.lang.String)、setOutputProperties(java.util.Properties) 显式设置的属性,或在样式表中显式设置的属性。
注意返回的 Properties 对象的变化将不影响转换器所包含的属性。
若是任何参数键不能被识别且不是名称空间限定的键,则属性将被忽略且不返回。换句话说,行为与 setOutputProperties 无关。
返回:
下一个实际转换中的输出属性集的副本。
另请参见:
OutputKeys, Properties, XSL Transformations (XSLT) Version 1.0
public abstract void (String name, String value) throws IllegalArgumentException
设置转换中实际的输出属性。
以两部分字符串形式传递限定属性名称,即用花括号括起来的名称空间 URI,后跟本地名称。若是名称中有 null URL,则 String 只包含本地名称。应用程序能够经过测试安全地检查非 null URI,以查看名称的首字符是否为 '{' 字符。
例如,若是 URI 和本地名称是从经过 <xyz:foo xmlns:xyz="http://xyz.foo.com/yada/baz.html"/> 定义的元素获取的,则限定名称将为 "{http://xyz.foo.com/yada/baz.html}foo"。注意,不使用前缀。
传递给 setOutputProperties(java.util.Properties) 的 Properties 对象不会受到调用此方法的影响。
参数:
name
- 指定了输出属性名称的非 null String,它能够是名称空间限定的。
value
- 输出属性的非 null 字符串值。
抛出:
IllegalArgumentException
- 若是不支持属性,且该属性没有限定于某一名称空间。
另请参见:
OutputKeys
public abstract String (String name) throws IllegalArgumentException
获取对转换器有效的输出属性。
若是已经使用 setOutputProperty(java.lang.String, java.lang.String) 设置了属性,则返回所设置的值。若是在样式表中显式地指定了属性,则返回所指定的值。若是使用默认属性值,即没有使用 setOutputProperty(java.lang.String, java.lang.String) 或在样式表中显式地设置了任何值,则结果将随实现以及输入样式表而改变。
参数:
name
- 指定了输出属性名称的非 null String,它能够是名称空间限定的。
返回:
输出属性的字符串值,若是找不到属性,则返回 null。
抛出:
IllegalArgumentException
- 若是不支持属性。
另请参见:
OutputKeys
public abstract void (ErrorListener listener) throws IllegalArgumentException
设置转换的实际错误事件侦听器。
参数:
listener
- 新错误侦听器。
抛出:
IllegalArgumentException
- 若是侦听器为 null。
public abstract ErrorListener ()
获取转换的实际错误事件处理程序。实现必须提供默认错误侦听器。
返回:
当前错误处理程序,它永远不该为 null。
2.2 ) 学习完Transformer 这个类咱们就来写一个Demo试试手吧!
package com.jhaso.action;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import net.sf.jxls.exception.ParsePropertyException;import net.sf.jxls.transformer.XLSTransformer;import org.apache.poi.openxml4j.exceptions.InvalidFormatException;import org.apache.poi.ss.usermodel.Workbook;import com.jhaso.model.ContReportModel;import com.jhaso.util.ExportImportUtil;import com.jhaso.util.FormatUtil;public class AgeContAction { public ContReportModel am = new ContReportModel(); public String contCode; private static String PATH = "D:/work/jhaso/JXLTest/src/com/jhaso/template/jxls_agent_report.xls"; private static String PATH2 = "D:/work/jhaso/JXLTest/src/com/jhaso/template/"; private static List<ContReportModel> list; public AgeContAction(){ init(); } private void init() { list = new ArrayList<ContReportModel>(); ContReportModel crm = new ContReportModel(); crm.setIndex(1); crm.setOperTimeView("2015-08-01 00:00:00"); crm.setName("铁臂金刀"); crm.setRecharge(1000.00); crm.setMargin(2000.00); crm.setRebate(3560.00); crm.setRefund(4560.00); crm.setCosts(3560.00); crm.setOperContent("铁臂金刀向郑州一百度充值"); list.add(crm); ContReportModel crm2 = new ContReportModel(); crm2.setIndex(2); crm2.setOperTimeView("2015-08-01 00:00:00"); crm2.setName("铁臂阿童木"); crm2.setRecharge(1500.00); crm2.setMargin(2500.00); crm2.setRebate(3860.00); crm2.setRefund(5590.00); crm2.setCosts(4560.00); crm2.setOperContent("铁臂阿童木向郑州一百度充值"); list.add(crm2); } /** * 导出excel */ public void toReportExcel(HttpServletRequest request, HttpServletResponse response) { // 导出数据 String srcFilePath = PATH; String destFilePath = ExportImportUtil.getDataTempFile( PATH2).getAbsoluteFile() + File.separator + new Date().getTime() + "_report.xls"; File detFile = new File(destFilePath); InputStream iputStream; try { iputStream = new FileInputStream(new File(PATH)); Map<String,Object> beanParams = new HashMap<String,Object>(); beanParams.put("operat", list); XLSTransformer transformer = new XLSTransformer(); Workbook wb = (Workbook) transformer.transformXLS(iputStream, beanParams); /* * 真实项目请打开注释 * response.setHeader( "Content-Disposition", "attachment;fileName="+ ExportImportUtil.generateFileName(request,FormatUtil.formatDate() + "合同报表.xls")); response.setContentType("application/vnd.ms-excel");*/ OutputStream os = response.getOutputStream(); wb.write(new FileOutputStream(destFilePath)); // 导出Excel os.flush(); iputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (ParsePropertyException e) { e.printStackTrace(); } catch (InvalidFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } detFile.delete(); System.out.println("成功"); }}