java 导出Excel 自定义Excel模版及表达式(毛坯)
2013-03-28 14:39
676 查看
为了满足用户Excel报表多变的需求,研究自定义Excel模版及表达式,通过表达式中的属性值 反射 找到对应的值。
初步研究
完成以下功能:
1、单元格一对一填值
2、单独一行表达式的循环
3、遍历多个list出多个表格
4、多个sheet
留下以下问题:
1、一个单元格 同时存在表达式和静态文本
2、一个单元格 同时存在两个以上表达式
4、如何在单独一行表达式的循环中加入静态文本框
3、如何控制多行级循环
现记录在此,供自己以后参考,要解决复杂报表问题,还有待优化
初步研究
完成以下功能:
1、单元格一对一填值
2、单独一行表达式的循环
3、遍历多个list出多个表格
4、多个sheet
留下以下问题:
1、一个单元格 同时存在表达式和静态文本
2、一个单元格 同时存在两个以上表达式
4、如何在单独一行表达式的循环中加入静态文本框
3、如何控制多行级循环
现记录在此,供自己以后参考,要解决复杂报表问题,还有待优化
public class ExcelExportAction<T extends AbstractDomain> extends AbstractAction<T> { // 第一个F表达式的行号 private int writeRowNum = -1;// 写list数据到excel中的行号 // private ExcelWorkCell[] excelTable ; private ExcelWorkTable excelTable = null; private int excelTableRow, excelTableCol;// 暂未使用 private boolean excelTableLoading = false;// 正在装载table中 暂未使用 private HSSFWorkbook workbook = null; private HSSFDataFormat df = null;// 单元格 格式化对象 /** * 根据模版导出 单个sheet * * @param filename * 导出的文件名 * @param param * 导出的数据参数 * @param templatePath * 模版路径 * @throws Exception */ public void export(String filename, Map<String, Object> param, String templatePath) throws Exception { init(filename, templatePath); buildSheet(0, param); printExcel(); } /** * 根据模版导出 多个sheet * * @param filename * 导出的文件名 * @param params * 导出的数据参数 数组序号与sheet序号匹配 * @param templatePath * 模版路径 * @throws Exception */ public void export(String filename, Map<String, Object>[] params, String templatePath) throws Exception { init(filename, templatePath); // 循环构建sheet for (int i = 0; i < params.length; i++) { buildSheet(i, params[i]); } printExcel(); } private void init(String filename, String templatePath) throws Exception { setResponseHeader(filename); FileInputStream fi = new FileInputStream(templatePath); POIFSFileSystem fs = new POIFSFileSystem(fi); workbook = new HSSFWorkbook(fs); df = workbook.createDataFormat(); } /** * 设置响应头 * * @param filename * 导出的文件名 */ public void setResponseHeader(String filename) throws Exception { // response.setContentType("application/msexcel;charset=UTF-8"); // //两种方法都可以 response.setContentType("application/octet-stream;charset=iso-8859-1"); response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(filename, "UTF-8")); // 客户端不缓存 response.addHeader("Pargam", "no-cache"); response.addHeader("Cache-Control", "no-cache"); } private void buildSheet(int sheetIndex, Map<String, Object> param) throws Exception { HSSFRow row = null;// 行 HSSFCell cell = null;// 列 // 2、取得Sheet if (sheetIndex > workbook.getNumberOfSheets() - 1) {// 如果sheet号大于excel的sheet数量 // 返回 return; } HSSFSheet sheet = workbook.getSheetAt(sheetIndex); // 3、遍历sheet 解析表达式 for (int i = 0; i <= sheet.getLastRowNum(); i++) {// 遍历行 base 0 row = sheet.getRow(i);// 取得行 if (row == null) { i++; continue; } for (int j = 0; j < row.getLastCellNum(); j++) {// 遍历列 base 1 cell = row.getCell(j); if (null != cell) { String cellValue = getValue(cell); // 判断是否为表达式 并 取字段名 Pattern pattern_ = Pattern .compile("\\$([PF])\\{(\\w+[\\.\\w]*)\\}"); Matcher matcher_ = pattern_.matcher(cellValue); if (matcher_.find()) { // 是表达式 // 创建单元格属性对象workcell 存放表达式的信息 ExcelWorkCell workcell = new ExcelWorkCell(); workcell.setHssfCell(cell); String fieldType = matcher_.group(1);// 字段类型 F P workcell.setParam(matcher_.group(2)); // 取表达式的其他信息 Pattern pattern = Pattern .compile("[.](\\w+)\\(([^)]+)\\)"); Matcher matcher = pattern.matcher(cellValue); while (matcher.find()) { // 存放到workcell中 PropertyUtils.setProperty(workcell, matcher .group(1), matcher.group(2)); } // 如果是F属性,则先存放在excelTable中,最后构建 if ("F".equals(fieldType)) { if (excelTable == null) { excelTable = new ExcelWorkTable(); excelTable.setDataName(workcell.getList()); writeRowNum = row.getRowNum(); } excelTable.add(workcell); // 记住第一个F属性的行号, 表格从此行开始写入,并将此行以下的内容往下移 // if (writeRowNum == -1) { // writeRowNum = row.getRowNum(); // } } else {// 如果是p属性,则立即构建 buildCell(cell, workcell, param.get(workcell .getParam())); } } else {// 不是表达式 保留原单元格 } } } // 一行循环完 如果excelTable不为空 那么循环构建表格 if (excelTable != null) { List data = (ArrayList) param.get(excelTable.getDataName()); if (writeRowNum + 1 <= sheet.getLastRowNum()) { sheet.shiftRows(writeRowNum + 1, sheet.getLastRowNum(), data.size() - 1, true, false); } // 根据data遍历出表格 for (int dataIndex = 0; dataIndex < data.size(); dataIndex++) { Object t = data.get(dataIndex); HSSFRow wirteRow = sheet.createRow(writeRowNum); for (ExcelWorkCell workcell : excelTable) { // 创建新的单元格 HSSFCell writeCell = wirteRow.createCell(workcell .getHssfCell().getColumnIndex()); // 将原始单元格的样式 赋给 新的单元格 writeCell.setCellStyle(workcell.getHssfCell() .getCellStyle()); // 构建新的单元格 buildCell(writeCell, workcell, getProperty(t, workcell .getParam())); // 根据groupby 合并单元格 行级别 if (StringUtils.isNotBlank(workcell.getGroupby())) { // 如果为第一条数据 或者 本条数据的groupby对应值与前一条数据的groupby对应值不相同 // 那么创建region if (dataIndex == 0 || !getProperty(t, workcell.getGroupby()) .equals( getProperty( data .get(dataIndex - 1), workcell .getGroupby()))) { int dataIndexInner = -1; // 从本条数据开始往后遍历 取groupby对应值相同的记录数dataIndexInner for (dataIndexInner = dataIndex + 1; dataIndexInner < data .size(); dataIndexInner++) { if (!getProperty(t, workcell.getGroupby()) .equals( getProperty( data .get(dataIndexInner), workcell .getGroupby()))) { break; } } // 创建 dataIndexInner - dataIndex - 1 合并行的region CellRangeAddress newRegion = new CellRangeAddress( writeRowNum, writeRowNum + (dataIndexInner - dataIndex - 1), workcell.getHssfCell().getColumnIndex(), workcell.getHssfCell().getColumnIndex()); sheet.addMergedRegion(newRegion); } } } writeRowNum++; } // 表格构建完毕 表格对象置为null writeRowNum置为-1 以便存储下一张table excelTable = null; writeRowNum = -1; i = i + data.size() - 1;// 行指针移到新表格以后 继续遍历行 } } } /** * 获取参数的值 * * @param o * 如果o为map 则从map里取值 否则反射从对象o中取值 * @param param * @return * @throws Exception */ private Object getProperty(Object o, String param) throws Exception { if (o instanceof Map) { Map<String, Object> map = (HashMap<String, Object>) o; return map.get(param); } else { return PropertyUtils.getProperty(o, param); } } /** * 构建新的单元格 * * @param cell * 新单元格 * @param workcell * 新单元格属性对象 * @param object * 新单元格的值对象 */ private void buildCell(HSSFCell cell, ExcelWorkCell workcell, Object object) { // 处理type 字段类型 比如时间data或金额currency if (StringUtils.isBlank(workcell.getType())) {// 如果没有type 直接toString() cell.setCellValue(transNull(object)); } else if ("number".equals(workcell.getType())) {// 如果是number 以数字格式输出 if (object != null) { cell.setCellValue(Double.parseDouble(object.toString())); } } else if ("date".equals(workcell.getType())) {// 如果是date 进行format if (StringUtils.isBlank(workcell.getFormat())) {// 如果format为空 // 默认yyyy-MM-dd workcell.setFormat("yyyy-MM-dd"); } if (object != null) { cell.setCellValue(new SimpleDateFormat(workcell.getFormat()) .format(object)); // Calendar cal = Calendar.getInstance(); // cal.setTime((Date)object); // cell.setCellValue(cal); } } else if ("currency".equals(workcell.getType())) {// 如果是currency // 进行format 并以数字格式输出 if (StringUtils.isBlank(workcell.getFormat())) {// 如果format为空 workcell.setFormat("#,##0.00"); } if (object != null) { cell.setCellValue(Double.parseDouble(object.toString())); } } else {// 其他不支持的type 直接toString() 可扩展 cell.setCellValue(transNull(object)); } // 处理format 数据格式 // cell.getCellStyle().setDataFormat(df.getFormat("General"));//常规 if (StringUtils.isNotBlank(workcell.getFormat())) {// 如果format不为空 // 设置format格式 cell.getCellStyle().setDataFormat( df.getFormat(workcell.getFormat())); } } /** * 输出xls文件 * * @throws Exception */ private void printExcel() throws Exception { workbook.write(response.getOutputStream()); response.getOutputStream().flush(); response.getOutputStream().close(); } /** * 将对象转换为字符串 如果对象为null 返回"" * * @param o * @return */ private String transNull(Object o) { if (o == null) { return ""; } else { return o.toString(); } } /** * 返回单元格的字符串值 * * @param hssfCell * @return */ private String getValue(HSSFCell hssfCell) { if (hssfCell.getCellType() == hssfCell.CELL_TYPE_BOOLEAN) { return String.valueOf(hssfCell.getBooleanCellValue()); } else if (hssfCell.getCellType() == hssfCell.CELL_TYPE_NUMERIC) { return String.valueOf(hssfCell.getNumericCellValue()); } else { return String.valueOf(hssfCell.getStringCellValue()); } } }
相关文章推荐
- JAVA使用POI根据模版导出EXCEL
- java导出excel,自定义列与行
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- Java自定义导出Excel
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- java jsp JXL调用模版导出Excel
- java jsp JXL调用模版导出Excel
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- NPOI 按模版导出到Excel 自定义列映射
- JAVA使用POI根据模版导出EXCEL
- JAVA使用POI根据模版导出EXCEL
- <转>java jsp JXL调用模版导出Excel
- JAVA使用POI根据模版导出EXCEL