POI 导出 Excel
.
.
.
.
.
主要内容:在 struts1 中使用 POI 将数据导出为 Excel 文档,并使客户端下载。
使用POI生成一个 Excel 文档非常简单,通过以下几步简单的操作便可以生成一个最简单的文档:
1 /** 2 * 生成 Excel 文档 3 * @param path 文档保存路径 4 * @param sheetName sheet 页名称 5 * @throws IOException 如果文件写出时遇到问题 6 */ 7 public void createExcel(String path, String sheetName) throws IOException { 8 // 创建工作簿对象 9 HSSFWorkbook hssfWorkBook = new HSSFWorkbook(); 10 // 创建 sheet 页 11 HSSFSheet sheet1 = hssfWorkBook.createSheet(); 12 // 处理中文 sheet 页名称 13 hssfWorkBook.setSheetName(0, sheetName, HSSFWorkbook.ENCODING_UTF_16); 14 // 创建行 15 HSSFRow row1 = sheet1.createRow(0); 16 // 创建单元格 17 HSSFCell cell1 = row1.createCell((short)0); 18 cell1.setEncoding(HSSFCell.ENCODING_UTF_16); 19 // 为单元格填充值 20 cell1.setCellValue("单元格中的内容文字"); 21 // 输出工作簿 22 FileOutputStream fos = new FileOutputStream(path); 23 // 将工作簿进行输出 24 hssfWorkBook.write(fos); 25 // 关闭输出流 26 fos.close(); 27 System.out.println("生成完成"); 28 }
如此简单,我们就创建了一个 Excel 文档,这个文档的第一个单元格中有我们要填入的内容。
经常我们需要将数据库或者从其它地方获取来的数据导出到 Excel 中,并不是这样简单的使用常量赋值,那么应该怎样处理呢?
其实都是差不多的,只要稍微变通变通,比如将常量变成变量或者集合之类的即可。
下面我做了一个相对通用的例子:
1 /** 2 * 将实体类的集合导出为 Excel 文件(POI方式)并发送到客户端<br> 3 * 目前仅支持一个 sheet 页 4 * @param response HttpServletResponse 响应对象,用于将 Excel 文件发送至客户端 5 * @param titleList 需要展示的列。<br> 6 * Key 值是对象的属性,大小写敏感,且首字母必须大写(即规则与 getter() 和 setter() 方法相同,无需添加 "get" 和 "set");<br> 7 * Value 值是显示在 Excel 中第一行的列头。 8 * @param CONTENT_LIST 需要展示的实体类的 List 集合 9 * @param SEQ_TITLE 序列号列标题 10 * @param SEQ_INDEX 序列号起始索引。<br> 11 * 该值小于0时无序列号列;<br> 12 * 该值等于0时排列在第一列,依此类推。 13 * @param SEQ_START_INDEX 序列号起始值 14 * @param SEQ_STEP_LENGTH 序列号步长<br> 15 * 步长大于0时,每一行的序列号相隔 seqSetpLength 个距离;<br> 16 * 步长等于0时,每一行的序列号相同;<br> 17 * 步长小于0时,每一行的序列号递减 seqSetpLength 个距离。 18 * @param SHEET_NAME 第一个 sheet 页的名字<br> 19 * 如果传入 null 或空字符串则默认为“第一页”。 20 * @param fileName 文件名<br> 21 * 文件名无需添加扩展名<br> 22 * 如果传入 null 或空字符串则默认为当前时间的Long值。 23 * 24 * @throws IOException 如果输出工作簿时出现异常 25 * @throws UnsupportedEncodingException 如果处理文件名中文编码时出现异常 26 * @throws IllegalArgumentException 如果获取需要展示的内容出现异常 27 * @throws SecurityException 如果获取实体类的方法失败 28 * @throws IllegalAccessException 如果获取需要展示的内容出现异常 29 * @throws InvocationTargetException 如果获取需要展示的内容出现异常 30 * @throws NoSuchMethodException 如果获取实体类的方法失败 31 * @author yuhuashi http://www.cnblogs.com/chuyuhuashi/ 2012-09-20 32 */ 33 void exportExcel(HttpServletResponse response, final Map<String, String> titleList, final List<?> CONTENT_LIST 34 , final String SEQ_TITLE, final int SEQ_INDEX, final int SEQ_START_INDEX, final int SEQ_STEP_LENGTH 35 , final String SHEET_NAME, final String fileName) 36 throws IOException, UnsupportedEncodingException 37 , IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { 38 39 // 创建工作簿对象 40 HSSFWorkbook hssfWorkBook = new HSSFWorkbook(); 41 // 创建 sheet 页 42 HSSFSheet sheet1 = hssfWorkBook.createSheet(); 43 // 默认的 sheet 页名称 44 final String DEFAULT_SHEET_NAME = "第一页"; 45 // 处理中文 sheet 页名称 46 hssfWorkBook.setSheetName(0, ((null == SHEET_NAME) || ("".equals(SHEET_NAME.trim()))) ? DEFAULT_SHEET_NAME : SHEET_NAME.trim(), HSSFWorkbook.ENCODING_UTF_16); 47 48 // 列数 49 final int TITLE_LIST_SIZE = titleList.size(); 50 final int COLUMN_COUNT = (SEQ_INDEX >= 0) ? (TITLE_LIST_SIZE + 1) : TITLE_LIST_SIZE; 51 // 设置单元格宽度 52 final short COLUMN_WIDTH = 22 * 256; // 单位是1/256个字符宽度 53 for(int i = 0, index = 0; i < COLUMN_COUNT; i++) { 54 sheet1.setColumnWidth((short)index++, COLUMN_WIDTH); 55 } 56 57 // 索引只能在 8~64 之间 58 // 首行背景颜色索引 59 final short FIRST_ROW_BACKGROUND_COLOR_INDEX = 9; 60 // 首行边框颜色索引 61 final short FIRST_ROW_BORDER_COLOR_INDEX = 10; 62 // 其它行背景颜色索引 63 final short OTHER_ROW_BACKGROUND_COLOR_INDEX = 11; 64 // 其它行边框颜色索引 65 final short OTHER_ROW_BORDER_COLOR_INDEX = 12; 66 67 HSSFPalette palette = hssfWorkBook.getCustomPalette(); 68 // 定义首行背景颜色 69 palette.setColorAtIndex(FIRST_ROW_BACKGROUND_COLOR_INDEX, (byte)(0xFF & 230), (byte)(0xFF & 245), (byte)(0xFF & 238)); 70 // 定义首行边框颜色 71 palette.setColorAtIndex(FIRST_ROW_BORDER_COLOR_INDEX, (byte)(0xFF & 0), (byte)(0xFF & 153), (byte)(0xFF & 102)); 72 // 定义其它行背景颜色 73 palette.setColorAtIndex(OTHER_ROW_BACKGROUND_COLOR_INDEX, (byte)(0xFF & 255), (byte)(0xFF & 255), (byte)(0xFF & 255)); 74 // 定义单元格边框颜色 75 palette.setColorAtIndex(OTHER_ROW_BORDER_COLOR_INDEX, (byte)(0xFF & 153), (byte)(0xFF & 153), (byte)(0xFF & 153)); 76 77 // 填充每一行的数据 78 for(int sequence = SEQ_START_INDEX, i = 0, j = CONTENT_LIST.size(); i < (j + 1); i++) { 79 // 创建行 80 HSSFRow row = sheet1.createRow(i); 81 82 int colIndex = 0; 83 List<HSSFCell> cellList = new ArrayList<HSSFCell>(); // 本行中所有的列(单元格) 84 85 // 设置单元格样式 86 HSSFCellStyle cellStyle=hssfWorkBook.createCellStyle(); 87 cellStyle.setWrapText(true); 88 cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 左右居中 89 cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 上下居中 90 // 设置单元格填充样式 91 cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); // SOLID_FOREGROUND 使用纯色填充前景颜色 92 93 for(int k = 0; k < COLUMN_COUNT; k++) { 94 // 创建单元格 95 HSSFCell cell = row.createCell((short)colIndex++); 96 // 处理单元格中文编码 97 cell.setEncoding(HSSFCell.ENCODING_UTF_16); 98 // 设置单元格内换行 99 cell.setCellStyle(cellStyle); 100 cellList.add(cell); 101 // 设置单元格边框 102 cellStyle.setBorderTop(HSSFCellStyle.SOLID_FOREGROUND); 103 cellStyle.setBorderLeft(HSSFCellStyle.SOLID_FOREGROUND); 104 cellStyle.setBorderRight(HSSFCellStyle.SOLID_FOREGROUND); 105 cellStyle.setBorderBottom(HSSFCellStyle.SOLID_FOREGROUND); 106 // 设置单元格边框颜色(除首行) 107 cellStyle.setTopBorderColor(OTHER_ROW_BORDER_COLOR_INDEX); 108 cellStyle.setLeftBorderColor(OTHER_ROW_BORDER_COLOR_INDEX); 109 cellStyle.setRightBorderColor(OTHER_ROW_BORDER_COLOR_INDEX); 110 cellStyle.setBottomBorderColor(OTHER_ROW_BORDER_COLOR_INDEX); 111 // 设置背景颜色索引(除首行) 112 cellStyle.setFillForegroundColor(OTHER_ROW_BACKGROUND_COLOR_INDEX); 113 } 114 115 // 为单元格填充值 116 // 首行 117 if(0 == i) { 118 row.setHeight((short)600); // 设置第一行的高度 119 // 设置首行背景颜色索引 120 cellStyle.setFillForegroundColor(FIRST_ROW_BACKGROUND_COLOR_INDEX); 121 // 设置首行单元格边框颜色索引 122 cellStyle.setTopBorderColor(FIRST_ROW_BORDER_COLOR_INDEX); 123 cellStyle.setLeftBorderColor(FIRST_ROW_BORDER_COLOR_INDEX); 124 cellStyle.setRightBorderColor(FIRST_ROW_BORDER_COLOR_INDEX); 125 cellStyle.setBottomBorderColor(FIRST_ROW_BORDER_COLOR_INDEX); 126 // 创建列头 127 Set<String> titlePropertySet = titleList.keySet(); 128 Iterator<String> itTitleProperty = titlePropertySet.iterator(); // 所有的 key,也就是对象中的属性名 129 for(int k = 0; k < COLUMN_COUNT; k++) { 130 // 添加序号列头 131 if(SEQ_INDEX == k) { 132 cellList.get(k).setCellValue(SEQ_TITLE); 133 } else { 134 if(itTitleProperty.hasNext()) { 135 cellList.get(k).setCellValue(titleList.get(itTitleProperty.next())); 136 } 137 } 138 cellList.get(k).setCellStyle(cellStyle); 139 } 140 continue; 141 } 142 Object dto = CONTENT_LIST.get((i - 1)); 143 // 为每一列赋值 144 Set<String> titlePropertySet = titleList.keySet(); 145 Iterator<String> itTitleProperty = titlePropertySet.iterator(); // 所有的 key,也就是对象中的属性名 146 for(int k = 0; k < COLUMN_COUNT; k++) { 147 // 填充序号 148 if(SEQ_INDEX == k) { 149 cellList.get(k).setCellValue(sequence); 150 // 累计步长 151 sequence += SEQ_STEP_LENGTH; 152 } else { 153 if(itTitleProperty.hasNext()) { 154 String key = itTitleProperty.next(); 155 Object obj = dto.getClass().getMethod("get" + key, new Class[]{}).invoke(dto, new Object[]{}); 156 // System.out.println("bx:" + key + "\t" + obj.getClass().toString() + "\t" + obj.toString()); 157 // 如果需要使列展示新的类型需要继续补充 158 // 处理日期类型字段 159 if(obj instanceof DateTime) { 160 cellList.get(k).setCellValue(new DateTime(((DateTime)obj).toString(), DateTime.YEAR_TO_SECOND).toString()); 161 } 162 // 处理 ArrayList 类型字段 163 else if (obj instanceof ArrayList) { 164 @SuppressWarnings("unchecked") 165 List<String> item = (List<String>) obj; 166 StringBuffer registNoBuffer = new StringBuffer(""); 167 for(String str : item) { 168 registNoBuffer.append(str + "\r\n"); 169 } 170 cellList.get(k).setCellValue(registNoBuffer.toString()); 171 } 172 // 处理字符串类型字段 173 else { 174 cellList.get(k).setCellValue(obj.toString()); 175 } 176 } 177 } 178 } 179 } 180 // 输出工作簿 181 // 这里使用的是 response 的输出流,如果将该输出流换为普通的文件输出流则可以将生成的文档写入磁盘等 182 OutputStream os = response.getOutputStream(); 183 // 这个是弹出下载对话框的关键代码 184 response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode((((null == fileName) || ("".equals(fileName.trim()))) ? ((new Date().getTime()) + "") : fileName.trim()) + ".xls", "utf-8")); 185 // 将工作簿进行输出 186 hssfWorkBook.write(os); 187 os.flush(); 188 // 关闭输出流 189 os.close(); 190 }
调用点也非常简单:
/* * response 响应对象 * nameLise 列头的名字的集合,Map 类型 * contentList 内容集合,每个元素是一个 JavaBean。也就是从数据库中或者其它地方获取来要导出的数据。 * fileName 浏览器弹出下载对话框时显示的文件名称 */ this.exportExcel(response, nameList, contentList, "序号", 0, 1, 1, null, fileName);
就先写到这里了,代码的注释也相对清晰全面,如有疑问请留言,欢迎高手指导。
原创内容,允许转载,请注明出处:http://www.cnblogs.com/chuyuhuashi/ 谢谢。
作者:dybai
出自:https://0xcafebabe.cnblogs.com
赞赏:3Ky9q5HVGpYseBPAUTvbJBvM3h3FQ3edqr(BTC)
本作品采用知识共享署名-相同方式共享 3.0 中国大陆许可协议进行许可。
欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
posted on 2012-10-07 14:20 0xCAFEBABE 阅读(4997) 评论(0) 编辑 收藏 举报