.
.
.
.
.
主要內容:在 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/ 謝謝。