本文轉自 http://lingceng.iteye.com/blog/1820081/
Displaytag官網有1.0, 1.1, 1.2等,注意找到對應的版本。源碼和API可以在Maven庫中找到。
常規的使用不是問題,這里說說關於Excel導出的問題,中文亂碼,使用POI等。我使用的是Displaytag1.1。
基本導出功能
這種情況只需引入displaytag-1.1.jar。
設置column屬性media="html"將不會導出,media="excel"不會頁面顯示,默認既顯示又導出。
setProperty也可以寫在displaytag.properties中應用於所有表格。
<display:table name="test" export="true" id="currentRowObject"> <display:column property="id" title="ID" /> <display:column property="email" /> <display:column property="status" /> <display:column media="html" property="date" /> <display:setProperty name="export.excel" value="true" /> <display:setProperty name="export.excel.filename" value="export.xls" /> </display:table>
這時候導出的excel打開的時候office會報警,但是能夠打開,因為這不是正真的excel,只是csv改了后綴的純文本格式。可能出現中文亂碼,通過重載ExcelView來解決。
Class SimpleChineseExcelView extends ExcelView { public String getMimeType(){ //原代碼是return "application/vnd.ms-excel"; return "application/vnd.ms-excel;charset=gbk"; } }
修改displaytag.properties中對應條目:
export.excel.class=yourpackage.SimpleChineseExcelView
這樣就勉強能用了,只要能夠忍受每次都需要另存為excel來避免報警,不用中文文件名,不在bodycontent中使用中文。這樣的實現只能是差強人意。中文問題解決
使用POI
需要引入額外的displaytag-export-excel-1.1.jar,使用Maven解決依賴。
修改displaytag.properties中對應條目:
export.excel.class=org.displaytag.export.excel.ExcelHssfView
配置export filter:
<!--Configure the Filter in your web.xml:--> <filter> <filter-name>ResponseOverrideFilter</filter-name> <filter-class>org.displaytag.filter.ResponseOverrideFilter</filter-class> </filter> <!--And add mappings for urls the filter will intercept, for example:--> <filter-mapping> <filter-name>ResponseOverrideFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <filter-mapping> <filter-name>ResponseOverrideFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>
filter-mapping加在struts之前,acegi之后(如果有),放struts之后會出問題。
很好地解決各種中文問題,也是真正的excel。
實踐Hack:
項目中已經有了poi3.6,而displaytag-export-excel-1.1依賴的是poi3.0,版本太高,需要重新寫一個ExcelHssfView。其實很簡單,找到ExcelHssfView的源碼,刪除其中的所有的setEncoding方法,setEncoding方法在poi3.6中沒有。修改后的代碼如下,當然記得修改export.excel.class:
package com.lingceng; import java.io.OutputStream; import java.util.Calendar; import java.util.Date; import java.util.Iterator; import javax.servlet.jsp.JspException; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; 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.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.displaytag.Messages; import org.displaytag.exception.BaseNestableJspTagException; import org.displaytag.exception.SeverityEnum; import org.displaytag.export.BinaryExportView; import org.displaytag.model.Column; import org.displaytag.model.ColumnIterator; import org.displaytag.model.HeaderCell; import org.displaytag.model.Row; import org.displaytag.model.RowIterator; import org.displaytag.model.TableModel; /** * Excel exporter using POI HSSF. * @author Fabrizio Giustina * @author rapruitt * @version $Revision: 1.2 $ ($Author: fgiust $) */ public class MyExcelHssfView implements BinaryExportView { /** * TableModel to render. */ private TableModel model; /** * export full list? */ private boolean exportFull; /** * include header in export? */ private boolean header; /** * decorate export? */ private boolean decorated; /** * Generated sheet. */ private HSSFSheet sheet; /** * @see org.displaytag.export.ExportView#setParameters(TableModel, boolean, boolean, boolean) */ public void setParameters(TableModel tableModel, boolean exportFullList, boolean includeHeader, boolean decorateValues) { this.model = tableModel; this.exportFull = exportFullList; this.header = includeHeader; this.decorated = decorateValues; } /** * @return "application/vnd.ms-excel" * @see org.displaytag.export.BaseExportView#getMimeType() */ public String getMimeType() { return "application/vnd.ms-excel"; //$NON-NLS-1$ } /** * @see org.displaytag.export.BinaryExportView#doExport(OutputStream) */ public void doExport(OutputStream out) throws JspException { try { HSSFWorkbook wb = new HSSFWorkbook(); sheet = wb.createSheet("-"); int rowNum = 0; int colNum = 0; if (this.header) { // Create an header row HSSFRow xlsRow = sheet.createRow(rowNum++); HSSFCellStyle headerStyle = wb.createCellStyle(); headerStyle.setFillPattern(HSSFCellStyle.FINE_DOTS); headerStyle.setFillBackgroundColor(HSSFColor.BLUE_GREY.index); HSSFFont bold = wb.createFont(); bold.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); bold.setColor(HSSFColor.WHITE.index); headerStyle.setFont(bold); Iterator iterator = this.model.getHeaderCellList().iterator(); while (iterator.hasNext()) { HeaderCell headerCell = (HeaderCell) iterator.next(); String columnHeader = headerCell.getTitle(); if (columnHeader == null) { columnHeader = StringUtils.capitalize(headerCell.getBeanPropertyName()); } HSSFCell cell = xlsRow.createCell((short) colNum++); cell.setCellValue(columnHeader); cell.setCellStyle(headerStyle); //cell.setEncoding(HSSFCell.ENCODING_UTF_16); } } // get the correct iterator (full or partial list according to the exportFull field) RowIterator rowIterator = this.model.getRowIterator(this.exportFull); // iterator on rows while (rowIterator.hasNext()) { Row row = rowIterator.next(); HSSFRow xlsRow = sheet.createRow(rowNum++); colNum = 0; // iterator on columns ColumnIterator columnIterator = row.getColumnIterator(this.model.getHeaderCellList()); while (columnIterator.hasNext()) { Column column = columnIterator.nextColumn(); // Get the value to be displayed for the column Object value = column.getValue(this.decorated); HSSFCell cell = xlsRow.createCell((short) colNum++); //cell.setEncoding(HSSFCell.ENCODING_UTF_16); if (value instanceof Number) { Number num = (Number) value; cell.setCellValue(num.doubleValue()); } else if (value instanceof Date) { cell.setCellValue((Date) value); } else if (value instanceof Calendar) { cell.setCellValue((Calendar) value); } else { cell.setCellValue(escapeColumnValue(value)); } } } wb.write(out); } catch (Exception e) { throw new ExcelGenerationException(e); } } // patch from Karsten Voges /** * Escape certain values that are not permitted in excel cells. * @param rawValue the object value * @return the escaped value */ protected String escapeColumnValue(Object rawValue) { if (rawValue == null) { return null; } String returnString = ObjectUtils.toString(rawValue); // escape the String to get the tabs, returns, newline explicit as \t \r \n returnString = StringEscapeUtils.escapeJava(StringUtils.trimToEmpty(returnString)); // remove tabs, insert four whitespaces instead returnString = StringUtils.replace(StringUtils.trim(returnString), "\\t", " "); // remove the return, only newline valid in excel returnString = StringUtils.replace(StringUtils.trim(returnString), "\\r", " "); // unescape so that \n gets back to newline returnString = StringEscapeUtils.unescapeJava(returnString); return returnString; } /** * Wraps IText-generated exceptions. * @author Fabrizio Giustina * @version $Revision: 1.2 $ ($Author: fgiust $) */ static class ExcelGenerationException extends BaseNestableJspTagException { /** * D1597A17A6. */ private static final long serialVersionUID = 899149338534L; /** * Instantiate a new PdfGenerationException with a fixed message and the given cause. * @param cause Previous exception */ public ExcelGenerationException(Throwable cause) { super(ExcelHssfView.class, Messages.getString("ExcelView.errorexporting"), cause); //$NON-NLS-1$ } /** * @see org.displaytag.exception.BaseNestableJspTagException#getSeverity() */ public SeverityEnum getSeverity() { return SeverityEnum.ERROR; } } }
