因工作需要,把上百个excel文件合并成一个excel文件。
失败方案一:一个输入流 + 一个输出流,循环读取源文件然后直接写入目标文件。
这种方案有个问题,流是无记忆的。同一个输入流,读取一个指针自动后移一位,但是不同的输入流,完全不知道上个流在做什么。最后的结果就是,目标文件的内容和循环中的最后一个源文件的内容相同....
方案二:为了让写入Excel的内容是接着上一次的位置继续写入的,选择使用HSSFWorkbook。
实现的思路是:在页面里,用户填写源文件地址、目标文件地址和目标文件名,提交后,后台先建立一个Excel目标文件,并且把目标文件和源文件都包装成HSSFWorkbook,然后迭代读取源文件的每个cell并将值存入到目标文件HSSFWorkbook对象中,最终数据写入到目标文件中。这样用户可以在填写的目标目标中找到合并文件。
不过在用HSSFWorkbook包装新创建的.xlsx目标文件时遇到了一个小问题:Unable to read entire header; 0 bytes read; expected 512 bytes,就是说包装对象没有没有表头。
问题语句:File file=File.createTempFile(targetPath+File.separator+fileName);
FileInputStream fis = new FileInputStream(file);
HSSFWorkbook targetWork = new HSSFWorkbook(fis);//出问题语句
所以直接创建的.xlsx是不能用HSSFWorkbook包装的,这种办法也不行。
方案三:在页面里,用户只填写源文件地址,提交后文件直接下载。后台不用再创建目标文件,直接把目标HSSFWorkbook对象写入到response流中。代码如下
import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; public void excelMerge(HttpServletResponse response, String sourcePath) throws Exception { // 创建HSSFWorkbook,暂时存放数据 HSSFWorkbook targetWork = new HSSFWorkbook(); HSSFSheet targetSheet = targetWork.createSheet("中石化预分配记录"); targetSheet.setDefaultColumnWidth(20); targetSheet.setDefaultRowHeightInPoints(20); // 记录targetWork新建行位置 int targetLineIndex = 0; // 获取样式集合 Map<String, CellStyle> styles = createStyles(targetWork); //设置标题行 Row titleRow = targetSheet.createRow(targetLineIndex++); titleRow.setHeightInPoints(30); Cell titleCell = titleRow.createCell(0); titleCell.setCellStyle(styles.get("header")); titleCell.setCellValue("合并文件" + CreateOrderID.getOrderNo()); targetSheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), 4)); // 设置表头行 Row headerRow = targetSheet.createRow(targetLineIndex++); headerRow.setHeightInPoints(16); List<String> headerList = new ArrayList<>(); headerList.add("卡号"); headerList.add("时间"); headerList.add("金额"); headerList.add("余额"); headerList.add("地址"); for (int i = 0; i < headerList.size(); i++) { Cell cell = headerRow.createCell(i); cell.setCellStyle(styles.get("title")); cell.setCellValue(headerList.get(i)); targetSheet.autoSizeColumn(i); } for (int i = 0; i < headerList.size(); i++) { int colWidth = targetSheet.getColumnWidth(i) * 5; targetSheet.setColumnWidth(i, colWidth < 3000 ? 3000 : colWidth); } HSSFWorkbook workbook; HSSFSheet sheet; File sourcePathFile = new File(sourcePath); for (File file : sourcePathFile.listFiles()) { if (file.isFile() && file.getName().endsWith(".xlsx")) { workbook = new HSSFWorkbook(new FileInputStream(file)); sheet = workbook.getSheetAt(0); for (int i = 2; i < sheet.getLastRowNum(); i++) { Row sourceRow = sheet.getRow(i); Row targetRow = targetSheet.createRow(targetLineIndex++); for (int j = 0; j < sourceRow.getLastCellNum(); j++) {//Cell Cell cell = sourceRow.getCell(j); switch (cell.getCellType()) { case Cell.CELL_TYPE_BLANK: break; case Cell.CELL_TYPE_STRING: System.out.println(); targetRow.createCell(j).setCellValue(cell.getStringCellValue()); break; case Cell.CELL_TYPE_NUMERIC: targetRow.createCell(j).setCellValue(cell.getNumericCellValue()); break; default: targetRow.createCell(j).setCellValue(cell.toString()); } } } } } response.reset(); response.setContentType("application/octet-stream; charset=utf-8"); response.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("合并文件" + CreateOrderID.getOrderNo() + ".xlsx")); targetWork.write(response.getOutputStream()); } // 工具方法,设置Excel表样式 private Map<String, CellStyle> createStyles(Workbook wb) { Map<String, CellStyle> styles = new HashMap<>(); CellStyle style = wb.createCellStyle(); style.setAlignment(CellStyle.ALIGN_CENTER); style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); Font titleFont = wb.createFont(); titleFont.setFontName("Arial"); titleFont.setFontHeightInPoints((short) 12); titleFont.setBoldweight(Font.BOLDWEIGHT_BOLD); style.setFont(titleFont); styles.put("title", style); style = wb.createCellStyle(); style.setVerticalAlignment(CellStyle.VERTICAL_CENTER); style.setBorderRight(CellStyle.BORDER_THIN); style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBorderLeft(CellStyle.BORDER_THIN); style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBorderTop(CellStyle.BORDER_THIN); style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setBorderBottom(CellStyle.BORDER_THIN); style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); Font dataFont = wb.createFont(); dataFont.setFontName("Arial"); dataFont.setFontHeightInPoints((short) 10); style.setFont(dataFont); styles.put("data", style); style = wb.createCellStyle(); style.setAlignment(CellStyle.ALIGN_LEFT); style.cloneStyleFrom(styles.get("data")); styles.put("data1", style); style = wb.createCellStyle(); style.cloneStyleFrom(styles.get("data")); style.setAlignment(CellStyle.ALIGN_CENTER); styles.put("data2", style); style = wb.createCellStyle(); style.cloneStyleFrom(styles.get("data")); style.setAlignment(CellStyle.ALIGN_RIGHT); styles.put("data3", style); style = wb.createCellStyle(); style.cloneStyleFrom(styles.get("data")); // style.setWrapText(true); style.setAlignment(CellStyle.ALIGN_CENTER); style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); style.setFillPattern(CellStyle.SOLID_FOREGROUND); Font headerFont = wb.createFont(); headerFont.setFontName("Arial"); headerFont.setFontHeightInPoints((short) 16); headerFont.setBoldweight(Font.BOLDWEIGHT_BOLD); headerFont.setColor(IndexedColors.WHITE.getIndex()); style.setFont(headerFont); styles.put("header", style); return styles; }