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/ 謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM