package com.cabletech.common.excel.exports; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; 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.Region; import org.dom4j.Element; import org.springframework.util.CollectionUtils; import com.cabletech.common.excel.ExcelStyleUtils; import com.cabletech.common.xmlparse.ParseXmlTools; /** * Excel导出公共功能抽象类 * * @author 杨隽 2012-02-15 创建 * @author 杨隽 2012-02-16 修改writeCellData方法支持获取数据的后期处理并添加processDataValue抽象方法 * @author 杨隽 2012-02-16 添加“XML配置文件中<constant>元素列表”变量 * @author 杨隽 2012-02-16 添加“XML配置文件中<style>元素列表”变量 * @author 杨隽 2012-02-16 * 添加“EXCEL工作表默认标题样式”、“EXCEL工作表默认数据列标题样式”、“EXCEL工作表默认数据单元格样式”变量 * @author 杨隽 2012-02-16 添加“EXCEL工作表特定样式集合Map”变量 * @author 杨隽 2012-02-16 提取initWorkbook()方法 * @author 杨隽 2012-02-16 * 添加initTableMap方法、setConstant方法、setStyles方法和getCellStyle方法 * @author 杨隽 2012-02-24 去除getWorkbook()方法,并添加outExcelFile()方法 * */ public abstract class ExcelExport { private Logger logger = Logger.getLogger("ExportExport"); // 获取数据对象属性值的方法名称 private static final String GET_VALUE_METHOD_NAME = "getValue"; // 标题所在行索引 private static final int TITLE_ROW_INDEX = 0; // 标题设置列索引 private static final int TITLE_CELL_INDEX = 0; // 数据标题列所在行索引 private static final int DATA_SUBJECT_ROW_INDEX = 1; // 数据导入开始行索引 private static final int DATA_START_ROW_INDEX = 2; // XML配置文件的解析工具业务服务 @Resource(name = "parseXmlTools") private ParseXmlTools parseXmlTools; // XML配置文件中<root>节点 private Element root; // XML配置文件中<column>元素列表 @SuppressWarnings("rawtypes") private List elements; // XML配置文件中<constant>元素列表 private Element constant; // XML配置文件中<style>元素列表 @SuppressWarnings("rawtypes") private List styles; // EXCEL工作表对象 private HSSFWorkbook workbook; // EXCEL工作表中数据表对象 private HSSFSheet sheet; // EXCEL工作表特定样式集合Map private Map<String, HSSFCellStyle> styleMap; // EXCEL工作表默认标题样式 private HSSFCellStyle defaultTitleStyle; // EXCEL工作表默认数据列标题样式 private HSSFCellStyle defaultSubjectStyle; // EXCEL工作表默认数据单元格样式 private HSSFCellStyle defaultCellStyle; /** * 根据数据列表导出Excel * * @param list * List 输入的数据列表 */ @SuppressWarnings("rawtypes") public void exportExcelData(List list) { root = parseXmlTools.getImportXmlElement(getExportXmlId()); elements = root.elements(ParseXmlTools.COLUMN_ELEMENT_KEY); setConstant(); if (CollectionUtils.isEmpty(elements)) { return; } if (CollectionUtils.isEmpty(list)) { return; } initWorkbook(); writeTitle(elements.size()); writeSubject(); writeCellData(list); } /** * 初始化数据值表 * * @return Map<String, String> 数据值表 */ @SuppressWarnings("rawtypes") public Map<String, String> initTableMap() { Map<String, String> map = new HashMap<String, String>(); if (constant == null) { return map; } List elements = constant.elements(ParseXmlTools.PROP_ELEMENT_KEY); if (CollectionUtils.isEmpty(elements)) { return map; } for (int i = 0; i < elements.size(); i++) { Element element = (Element) elements.get(i); String key = element.attributeValue(ParseXmlTools.ID_ATTRBUTE_KEY); String value = element.getTextTrim(); map.put(key, value); } return map; } /** * 向响应输出流中输出Excel文件 * * @param out * OutputStream 响应输出流 * @throws IOException */ public void outExcelFile(OutputStream out) throws IOException { workbook.write(out); } /** * 设置导出文件使用的常量配置节点 */ private void setConstant() { if (!CollectionUtils.isEmpty(root .elements(ParseXmlTools.CONSTANT_ELEMENT_KEY))) { constant = (Element) root.elements( ParseXmlTools.CONSTANT_ELEMENT_KEY).get(0); } } /** * 初始化工作表对象并设置默认的标题、数据列标题和单元格样式 */ private void initWorkbook() { workbook = new HSSFWorkbook(); defaultTitleStyle = ExcelStyleUtils.getTitleStyle(workbook); defaultSubjectStyle = ExcelStyleUtils.getSubjectStyle(workbook); defaultCellStyle = ExcelStyleUtils.getCommonCellStyle(workbook); setStyles(); } /** * 设置Excel表格的特定样式集合Map */ private void setStyles() { styleMap = new HashMap<String, HSSFCellStyle>(); styles = root.elements(ParseXmlTools.STYLE_ELEMENT_KEY); if (CollectionUtils.isEmpty(styles)) { return; } for (int i = 0; i < styles.size(); i++) { HSSFCellStyle style = ExcelStyleUtils.getCommonCellStyle(workbook); Element element = (Element) styles.get(i); String key = (String) element .attributeValue(ParseXmlTools.ID_ATTRBUTE_KEY); ExcelStyleUtils.setFontStyle(style, element, workbook); styleMap.put(key, style); } } /** * 写入Excel工作表的标题 * * @param size * int 标题所占列数 */ @SuppressWarnings("deprecation") private void writeTitle(int size) { // TODO Auto-generated method stub String title = root .attributeValue(ParseXmlTools.EXCEL_TITLE_ATTRIBUTE_KEY); sheet = workbook.createSheet(title); sheet.addMergedRegion(new Region(TITLE_ROW_INDEX, (short) TITLE_CELL_INDEX, TITLE_ROW_INDEX, (short) (TITLE_CELL_INDEX + size - 1))); HSSFRow row = sheet.createRow(TITLE_ROW_INDEX); HSSFCell cell = row.createCell(TITLE_CELL_INDEX); HSSFCellStyle style = getCellStyle(root, defaultTitleStyle); cell.setCellStyle(style); cell.setCellValue(title); } /** * 写入Excel工作表数据列标题 */ private void writeSubject() { // TODO Auto-generated method stub HSSFRow row = sheet.createRow(DATA_SUBJECT_ROW_INDEX); for (int i = 0; i < elements.size(); i++) { Element element = (Element) elements.get(i); String colIndex = element .attributeValue(ParseXmlTools.COL_INDEX_ATTRIBUTE_KEY); String subject = element .attributeValue(ParseXmlTools.SUBJECT_ATTRIBUTE_KEY); int columnIndex = Integer.parseInt(colIndex); sheet.autoSizeColumn(columnIndex); HSSFCell cell = row.createCell(columnIndex); HSSFCellStyle style = getStyle(element, defaultSubjectStyle, ParseXmlTools.SUBJECT_STYLE_ID_ATTRIBUTE_KEY); cell.setCellStyle(style); cell.setCellValue(subject); } } /** * 写入Excel工作表的数据信息 * * @param list * List 输入的数据信息 */ @SuppressWarnings("rawtypes") private void writeCellData(List list) { // TODO Auto-generated method stub for (int i = 0; i < list.size(); i++) { HSSFRow row = sheet.createRow(DATA_START_ROW_INDEX + i); Object object = list.get(i); for (int j = 0; j < elements.size(); j++) { Element element = (Element) elements.get(j); String methodName = element .attributeValue(ParseXmlTools.DATA_METHOD_NAME_ATTRIBUTE_KEY); String value = getValue(object, element); value = processDataValue(value, methodName); HSSFCell cell = getCell(row, element); HSSFCellStyle style = getCellStyle(element, defaultCellStyle); cell.setCellStyle(style); cell.setCellValue(value); } } } /** * 根据数据对象和配置文件中的数据属性配置信息读取数据的属性值 * * @param object * Object 数据对象 * @param element * Element 配置文件中的数据属性配置信息 * @return String 数据的属性值 */ @SuppressWarnings({ "rawtypes", "unchecked" }) private String getValue(Object object, Element element) { // TODO Auto-generated method stub String propertyName = element .attributeValue(ParseXmlTools.PROPERTY_NAME_ATTRIBUTE_KEY); String className = root .attributeValue(ParseXmlTools.ENTITY_ATTRIBUTE_KEY); Object value = ""; try { Class clazz = Class.forName(className); Method method = clazz.getMethod(GET_VALUE_METHOD_NAME, Object.class, String.class); value = method.invoke(null, object, propertyName); } catch (Exception ex) { logger.error("读取数据的属性值出错:", ex); } return value.toString(); } /** * 根据配置文件中的数据属性配置信息设置数据属性单元格的格式 * * @param row * HSSFRow 数据所在行信息 * @param element * Element 配置文件中的数据属性配置信息 * @return HSSFCell 数据属性单元格 */ private HSSFCell getCell(HSSFRow row, Element element) { String colIndex = element .attributeValue(ParseXmlTools.COL_INDEX_ATTRIBUTE_KEY); int columnIndex = Integer.parseInt(colIndex); sheet.autoSizeColumn(columnIndex); HSSFCell cell = row.createCell(columnIndex); return cell; } /** * 根据XML配置元素的style-id指定样式编号获取特定的样式,默认为缺省样式 * * @param element * Element XML配置元素 * @param defaultStyle * HSSFCellStyle 缺省样式 * @return HSSFCellStyle 单元格的样式 */ private HSSFCellStyle getCellStyle(Element element, HSSFCellStyle defaultStyle) { return getStyle(element, defaultStyle, ParseXmlTools.STYLE_ID_ATTRIBUTE_KEY); } /** * 根据XML配置元素的指定样式属性名字所指定样式编号获取特定的样式,默认为缺省样式 * * @param element * Element XML配置元素 * @param defaultStyle * HSSFCellStyle 缺省样式 * @param styleIdKey * String XML配置样式的样式属性名字 * @return HSSFCellStyle 单元格的样式 */ private HSSFCellStyle getStyle(Element element, HSSFCellStyle defaultStyle, String styleIdKey) { HSSFCellStyle style = defaultStyle; String styleId = element.attributeValue(styleIdKey); if (StringUtils.isNotBlank(styleId)) { style = styleMap.get(styleId); } return style; } /** * 获取导出Excel配置XML文件的id * * @return String 导出Excel配置XML文件的id */ public abstract String getExportXmlId(); /** * 进行获取后的数据后期处理(使用XML文件中配置的数据转换方法将数据库中存放的属性KEY值转换成输出Excel文件中的VALUE值) * * @param value * String 获取后的数据 * @param methodName * String 获取数据处理的调用方法名称 * @return String 后期处理后的数据 */ public abstract String processDataValue(String value, String methodName); }