在用java 写数据库应用的时候, 通常会生成各种报表,而这些报表可能会被导出为各种格式的文件,比如Excel文档,pdf 文档等等. 今天先做了一个生成Excel 文档的例子,主要解决以下问题:
生成 Excel 文档.
保护生成Excel文档,设置密码访问.
自动对生成的Excel 文档第一行标题栏设置成filter 过滤形式, 方便用户使用.
用 apache POI 生成 Excel 文档公用类
package com.yihaomen.poi.sample; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; /** * Excel util, create excel sheet, cell and style. * @param <T> generic class. */ public class ExcelUtil<T> { public HSSFCellStyle getCellStyle(HSSFWorkbook workbook,boolean isHeader){ HSSFCellStyle style = workbook.createCellStyle(); style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); style.setLocked(true); if (isHeader) { style.setFillForegroundColor(HSSFColor.GREY_25_PERCENT.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); HSSFFont font = workbook.createFont(); font.setColor(HSSFColor.BLACK.index); font.setFontHeightInPoints((short) 12); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); style.setFont(font); } return style; } public void generateHeader(HSSFWorkbook workbook,HSSFSheet sheet,String[] headerColumns){ HSSFCellStyle style = getCellStyle(workbook,true); Row row = sheet.createRow(0); row.setHeightInPoints(30); for(int i=0;i<headerColumns.length;i++){ Cell cell = row.createCell(i); String[] column = headerColumns[i].split("_#_"); sheet.setColumnWidth(i, Integer.valueOf(column[1])); cell.setCellValue(column[0]); cell.setCellStyle(style); } } @SuppressWarnings({ "rawtypes", "unchecked" }) public HSSFSheet creatAuditSheet(HSSFWorkbook workbook,String sheetName,List<T> dataset,String[] headerColumns,String[] fieldColumns) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { HSSFSheet sheet = workbook.createSheet(sheetName); sheet.protectSheet(""); generateHeader(workbook,sheet,headerColumns); HSSFCellStyle style = getCellStyle(workbook,false); SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd"); int rowNum = 0; for(T t:dataset){ rowNum++ ; Row row = sheet.createRow(rowNum); row.setHeightInPoints(25); for(int i = 0; i < fieldColumns.length; i++){ String fieldName = fieldColumns[i] ; String getMethodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); try { Class clazz = t.getClass(); Method getMethod; getMethod = clazz.getMethod(getMethodName, new Class[]{} ); Object value = getMethod.invoke(t, new Object[]{}); String cellValue = ""; if (value instanceof Date){ Date date = (Date)value; cellValue = sd.format(date); }else{ cellValue = null != value ? value.toString() : ""; } Cell cell = row.createCell(i); cell.setCellStyle(style); cell.setCellValue(cellValue); } catch (Exception e) { } } } return sheet; } }
这一个公用的类,主要生成Excel的头,正文,以及Excel 文档的样式。看方法名称基本就可以知道这个方法是干什么用的.
写一个测试类测试生成Excel文档
package com.yihaomen.poi.test; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import com.yihaomen.poi.sample.ExcelUtil; import com.yihaomen.poi.sample.User; public class PoiTest { /*excel column formate:column_#_width, excel中每一列的名称*/ public static final String[] USER_RECORES_COLUMNS = new String[]{ "User Name_#_3000", "Address_#_7000" }; /*the column will display on xls files. must the same as the entity fields.对应上面的字段.*/ public static final String[] USER_RECORES_FIELDS = new String[]{ "name","address" }; public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException { List<User> users = new ArrayList<User>(); for(int i=0; i<10;i++){ User u = new User(); u.setAddress("address :" + i); u.setName("name: "+ i); u.setAge(i); users.add(u); } //实际项目中,这个list 估计是从数据库中得到的 HSSFWorkbook workbook = new HSSFWorkbook(); ExcelUtil<User> userSheet = new ExcelUtil<User>(); userSheet.creatAuditSheet(workbook, "user sheet xls", users, USER_RECORES_COLUMNS, USER_RECORES_FIELDS); FileOutputStream fileOut = new FileOutputStream("d:/yihaomen_user_test.xls"); workbook.write(fileOut); fileOut.close(); } }
这里直接保存文件到 D 盘下面,主要是为了自己测试方便. 另外还需要一个测试需要的
实体类 User.java:
package com.yihaomen.poi.sample; public class User { private String name; private int age; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
运行测试类,生成Excel 文档如下:
生成的文档,你是不能修改的,原因很简单,设置了一个空密码,虽然是空密码,Excel 还是会出现提示,当然你可以直接解保护. 实现的主要代码是在 ExcelUtil 中的 creatAuditSheet 方法中的:
sheet.protectSheet(""); // 设置了一个空的密码
如果要实现第一行标题自动过滤怎么处理呢,可以在上面提到的方法中加入如下代码:
char[] endChar = Character.toChars( 'A' + (headerColumns.length - 1) ); String rangeAddress = "A1:" + String.valueOf(endChar) + "1"; sheet.setAutoFilter(CellRangeAddress.valueOf(rangeAddress));
这样就能实现自动过滤了