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      * 将实体类的集合导出为&nbsp;Excel&nbsp;文件(POI方式)并发送到客户端<br>
  3      * 目前仅支持一个 sheet 页
  4      * @param response HttpServletResponse&nbsp;响应对象,用于将 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时,每一行的序列号相隔&nbsp;seqSetpLength&nbsp;个距离;<br>
 16      * 步长等于0时,每一行的序列号相同;<br>
 17      * 步长小于0时,每一行的序列号递减&nbsp;seqSetpLength&nbsp;个距离。
 18      * @param SHEET_NAME 第一个 sheet 页的名字<br>
 19      * 如果传入&nbsp;null&nbsp;或空字符串则默认为“第一页”。
 20      * @param fileName 文件名<br>
 21      * 文件名无需添加扩展名<br>
 22      * 如果传入&nbsp;null&nbsp;或空字符串则默认为当前时间的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/ 谢谢。

原文地址:https://www.cnblogs.com/0xcafebabe/p/2714017.html