以前使用poi导出excel,每次都是使用API去一步步画出excel的样式,这种方法在遇到复杂的excel需求时,会浪费不少时间。后来决定尝试使用模板的方法进行导出,这样只须要关心要导出的数据便可,节省了不少时间。下面的代码封装了一些简单的API,包含了03和07格式的导出, 能知足基本需求,贴出来跟你们分享下,有兴趣的同窗也能够在此基础上扩展,和你们共享。java
代码已经分享到git@osc上啦,地址:http://git.oschina.net/carpo/carpo/tree/master/carpo.xlsgit
使用方法apache
poi-3.8-beta4-20110826.jar浏览器
poi-ooxml-3.8-beta4.jarxss
poi-ooxml-schemas-3.8-beta4.jaride
xmlbeans-2.6.0.jar函数
1.ExcelExp为抽象基类,定义了基本操做方法测试
package com.example; import java.io.IOException; import java.util.Map; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * * excel模板导出基类 * @since jdk1.6 * @date 2016-6-2 * */ public abstract class ExcelExp { protected XSSFWorkbook xssWb; protected XSSFSheet xssSheet; protected HSSFWorkbook hssWb; protected HSSFSheet hssSheet; /** * 设置页脚 */ public abstract void createFooter(); /** * * 插入行 * @param startRow * @param rows */ public abstract void insertRows(int startRow, int rows); /** * * 替换模板中变量 * @param map */ public abstract void replaceExcelData(Map<String, String> map); /** * 下载excel * @param response * @param filaName * @throws IOException */ public abstract void downloadExcel(HttpServletResponse response, String filaName) throws IOException; public XSSFWorkbook getXssWb() { return xssWb; } public void setXssWb(XSSFWorkbook xssWb) { this.xssWb = xssWb; } public XSSFSheet getXssSheet() { return xssSheet; } public void setXssSheet(XSSFSheet xssSheet) { this.xssSheet = xssSheet; } public HSSFWorkbook getHssWb() { return hssWb; } public void setHssWb(HSSFWorkbook hssWb) { this.hssWb = hssWb; } public HSSFSheet getHssSheet() { return hssSheet; } public void setHssSheet(HSSFSheet hssSheet) { this.hssSheet = hssSheet; } }
2.XssExcelExp为07格式(.xlsx)的实现类this
package com.example; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFFooter; import org.apache.poi.ss.usermodel.Footer; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * * excel导出类 * <p>处理.xlsx格式<p> * @since jdk1.6 * @date 2016-6-2 * */ public class XssExcelExp extends ExcelExp{ public XssExcelExp() { super(); } /** * 构造函数 * ExcelExp * @param filePath 文件路径,如com/test/template/test.xlsx * @param sheetNum 要操做的页签,0为第一个页签 * @throws IOException */ public XssExcelExp(String filePath, int sheetNum) throws IOException { URL resource = this.getClass().getClassLoader().getResource(filePath); InputStream is = new FileInputStream(resource.getFile()); xssWb = new XSSFWorkbook(is); xssSheet = xssWb.getSheetAt(sheetNum); } /** * 设置页脚 */ public void createFooter(){ Footer footer = xssSheet.getFooter(); footer.setRight("第" + HSSFFooter.page() + "页,共" + HSSFFooter.numPages() + "页"); } /** * * 插入行 * @param startRow * @param rows */ public void insertRows(int startRow, int rows){ int bottomRow = xssSheet.getLastRowNum(); if(startRow > bottomRow){ int n = startRow - bottomRow; for(int i = 1; i <= n; i++){ xssSheet.createRow(bottomRow + i); } } xssSheet.shiftRows(startRow, xssSheet.getLastRowNum(), rows, true, false); } /** * * 替换模板中变量 * @param map */ public void replaceExcelData(Map<String, String> map){ int rowNum = xssSheet.getLastRowNum(); for(int i = 0;i <= rowNum; i++){ XSSFRow row = xssSheet.getRow(i); if(row == null) continue; for(int j = 0;j < row.getPhysicalNumberOfCells();j++){ XSSFCell cell = row.getCell(j); if(cell == null) continue; String key = cell.getStringCellValue(); if(map.containsKey(key)){ cell.setCellValue(map.get(key)); } } } } /** * 下载excel * @param response * @param filaName * @throws IOException */ public void downloadExcel(HttpServletResponse response, String filaName) throws IOException{ String encodeFileName = URLEncoder.encode(filaName,"UTF-8"); response.addHeader("Content-Disposition","attachment;filename=" +encodeFileName); ServletOutputStream out = response.getOutputStream(); xssWb.write(out); out.flush(); out.close(); } }
3.HssExcelExp为03格式(.xls)的实现类spa
package com.example; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFFooter; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Footer; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * * excel导出类 * <p>处理.xls格式<p> * @since jdk1.6 * @date 2016-6-2 * */ public class HssExcelExp extends ExcelExp{ public HssExcelExp() { super(); } /** * 构造函数 * ExcelExp * @param filePath 文件路径,如com/test/template/test.xls * @param sheetNum 要操做的页签,0为第一个页签 * @throws IOException */ public HssExcelExp(String filePath, int sheetNum) throws IOException { URL resource = this.getClass().getClassLoader().getResource(filePath); InputStream is = new FileInputStream(resource.getFile()); hssWb = new HSSFWorkbook(is); hssSheet = hssWb.getSheetAt(sheetNum); } @Override public void createFooter() { Footer footer = hssSheet.getFooter(); footer.setRight("第" + HSSFFooter.page() + "页,共" + HSSFFooter.numPages() + "页"); } @Override public void downloadExcel(HttpServletResponse response, String filaName) throws IOException { String encodeFileName = URLEncoder.encode(filaName,"UTF-8"); response.addHeader("Content-Disposition","attachment;filename=" +encodeFileName); ServletOutputStream out = response.getOutputStream(); hssWb.write(out); out.flush(); out.close(); } @Override public void insertRows(int startRow, int rows) { int bottomRow = hssSheet.getLastRowNum(); if(startRow > bottomRow){ int n = startRow - bottomRow; for(int i = 1; i <= n; i++){ hssSheet.createRow(bottomRow + i); } } hssSheet.shiftRows(startRow, hssSheet.getLastRowNum(), rows, true, false); } @Override public void replaceExcelData(Map<String, String> map) { int rowNum = hssSheet.getLastRowNum(); for(int i = 0;i <= rowNum; i++){ HSSFRow row = hssSheet.getRow(i); if(row == null) continue; for(int j = 0;j < row.getPhysicalNumberOfCells();j++){ HSSFCell cell = row.getCell(j); if(cell == null) continue; String key = cell.getStringCellValue(); if(map.containsKey(key)){ cell.setCellValue(map.get(key)); } } } } }
基于不一样的excel格式去实例化不一样的实现类便可,调用指定的API可实现相应的功能,例如 添加页脚、插入行、为excel中的变量赋值等。如下面excel格式为例,里面存在变量xlsx_a、xlsx_b、
xlsx_c,要为变量赋值。在第三行要插入行,而后写入数据。
public static void main(String[] args) throws Exception { //传递模板地址和要操做的页签 ExcelExp excel = new XssExcelExp("com/example/template/test.xlsx", 0); //建立页脚,打印excel时显示页数 excel.createFooter(); //插入行 int startRow = 2;//起始行 int rows = 5;//插入行数 excel.insertRows(startRow, rows); //在插入的行中写入数据 wirteXssExcel(excel); //为模板中变量赋值 Map<String, String> map = new HashMap<String, String>(); map.put("xlsx_a", "2016-06-07 12:00:00"); map.put("xlsx_b", "测试"); map.put("xlsx_c", "12345"); excel.replaceExcelData(map); //导出,此处只封装了浏览器下载方式 //调用downloadExcel,返回输出流给客户端 String fileName = "export1.xlsx"; excel.downloadExcel(response, fileName); } public void wirteXssExcel(ExcelExp excel){ XSSFSheet sheet = excel.getXssSheet(); List list = new ArrayList(); for (int i = 0; i < list.size(); i++) { XSSFRow row = sheet.createRow(i+3); row.createCell(0).setCellValue(String.valueOf(i + 1)); row.createCell(1).setCellValue("111"); row.createCell(2).setCellValue("222"); row.createCell(3).setCellValue("333"); } } public void wirteHssExcel(ExcelExp excel){ HSSFSheet sheet = excel.getHssSheet(); List list = new ArrayList(); for (int i = 0; i < list.size(); i++) { HSSFRow row = sheet.createRow(i+3); row.createCell(0).setCellValue(String.valueOf(i + 1)); row.createCell(1).setCellValue("111"); row.createCell(2).setCellValue("222"); row.createCell(3).setCellValue("333"); } }
勘误
1.在使用中发现,插入行方法,在模板最后插入行时会报错( java.lang.IllegalArgumentException: firstMovedIndex, lastMovedIndex out of order ),现已修复,文中代码已更新。