POI 匯出Excel 並且根據內容設定列寬自適應
package com.XXX; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import com.eos.system.annotation.Bizlet; import commonj.sdo.DataObject; public class ExcelExportUtil { /** * * Excel匯出 * @author RangoLan * @param criteriaEntity DataObject 獲取填充資料來源的查詢物件 * @param fileName 生成的檔名字首 * @param response HttpServletResponse響應 * @param colToProperty 表格列名和DataObject物件Property應的LinkedHashMap * @param datePattern 日期格式資料格式 * @param HttpServletRequest request 請求物件,用於無資料輸出時,內部跳轉 * @param backPage 執行查詢後無資料時返回畫面 */ @Bizlet("資料寫入Excel並生成下載") public static void exportExcel(String fileName,HttpServletRequest request,HttpServletResponse response,DataObject criteriaEntity,LinkedHashMap<String,String> colToProperty,String datePattern,String backPage) throws Exception { //根據查詢物件criteria填充資料來源 DataObject[] datas = (DataObject[])com.eos.foundation.database.DatabaseUtil.queryEntitiesByCriteriaEntity("default", criteriaEntity); if (datas != null && datas.length > 0) { if(datePattern==null){ datePattern = "yyyy-MM-dd"; } SXSSFWorkbook workbook = new SXSSFWorkbook(1000); /** 設定格式* */ workbook.setCompressTempFiles(true); // 表頭樣式 CellStyle headerStyle = workbook.createCellStyle(); //水平居中 headerStyle.setAlignment(CellStyle.ALIGN_CENTER); //垂直居中 headerStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //設定邊框 headerStyle.setBorderTop(CellStyle.BORDER_THIN); headerStyle.setBorderRight(CellStyle.BORDER_THIN); headerStyle.setBorderBottom(CellStyle.BORDER_THIN); headerStyle.setBorderLeft(CellStyle.BORDER_THIN); //設定顏色 headerStyle.setFillForegroundColor(HSSFColor.LIGHT_GREEN.index); headerStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); Font headerFont = workbook.createFont(); headerFont.setFontHeightInPoints((short) 12); headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); headerStyle.setFont(headerFont); // 單元格樣式 CellStyle cellStyle = workbook.createCellStyle(); cellStyle.setAlignment(CellStyle.ALIGN_CENTER); //垂直居中 cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); //設定邊框 cellStyle.setBorderTop(CellStyle.BORDER_THIN); cellStyle.setBorderRight(CellStyle.BORDER_THIN); cellStyle.setBorderBottom(CellStyle.BORDER_THIN); cellStyle.setBorderLeft(CellStyle.BORDER_THIN); //設定自動換行 cellStyle.setWrapText(true); //設定字型 Font cellFont = workbook.createFont(); cellFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); cellStyle.setFont(cellFont); //DataObject屬性Property陣列 String[] properties = new String[colToProperty.size()]; //表頭陣列 String[] headers = new String[colToProperty.size()]; int ii = 0; for (Iterator<String> iter = colToProperty.keySet().iterator();iter.hasNext();) { String fieldName = iter.next(); headers[ii] = fieldName; properties[ii] = colToProperty.get(fieldName); ii++; } // 遍歷集合資料,產生資料行,填充Excel int rowIndex = 0; Sheet sheet = null; for (DataObject data : datas) { if (rowIndex == 65535 || rowIndex == 0) { sheet = workbook.createSheet();// 如果資料超過了,則在第二頁顯示 Row headerRow = sheet.createRow(0);// 表頭 rowIndex=0 for (int i = 0; i < headers.length; i++) { headerRow.createCell(i).setCellValue(headers[i]); //設定表頭樣式 headerRow.getCell(i).setCellStyle(headerStyle); } rowIndex = 1;// 資料內容從 rowIndex=1開始 } //建立行 Row dataRow = sheet.createRow(rowIndex); for (int i = 0; i < properties.length; i++) { //建立單元格 Cell newCell = dataRow.createCell(i); Object o = data.get(properties[i]); String cellValue = ""; if (o == null) {//為空處理 cellValue = ""; } else if (o instanceof Date) {//日期格式化處理 cellValue = new SimpleDateFormat(datePattern).format(o); } else { cellValue = o.toString(); } //單元格賦值 newCell.setCellValue(cellValue); //單元格格式設定 newCell.setCellStyle(cellStyle); } rowIndex++; } OutputStream out = null; //設定自動列寬 for (int i = 0; i < headers.length; i++) { sheet.autoSizeColumn(i); sheet.setColumnWidth(i,sheet.getColumnWidth(i)*17/10); } try { out = response.getOutputStream(); fileName = fileName + "_" + new SimpleDateFormat("yyyyMMDDhh24mmssSSS") .format(System.currentTimeMillis()) + ".xlsx"; response.setContentType("application/x-msdownload"); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")); // 儲存報表檔案 workbook.write(out); } catch (IOException e) { e.printStackTrace(); } finally { try { if (out != null) out.close(); response.flushBuffer(); } catch (IOException e) { e.printStackTrace(); } } } else { // 無匯出資料 request.setAttribute("noDataToExport", "沒有資料可以匯出!"); request.getRequestDispatcher(backPage).forward(request, response); } }
強調的是設定自適應列寬:sheet.autoSizeColumn(i);只這樣設定是沒有很好的效果的。所以採取了以下兩步:
**1. sheet.autoSizeColumn(i);//先設定自動列寬
2. sheet.setColumnWidth(i,sheet.getColumnWidth(i)17/10);//設定列寬為自動列寬的1.7倍(當然不是嚴格的1.7倍,int的除法恕不再討論),這個1.6左右也可以,這是本人測試的經驗值*
經過本人測試,能夠將excel的列寬很好的更具單元格的內容進行設定。
poi生成excel整理(設定邊框/字型/顏色/加粗/居中/)
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFCellStyle setBorder = wb.createCellStyle();
一、設定背景色:
setBorder.setFillForegroundColor((short) 13);// 設定背景色
setBorder.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
二、設定邊框:
setBorder.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下邊框
setBorder.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左邊框
setBorder.setBorderTop(HSSFCellStyle.BORDER_THIN);//上邊框
setBorder.setBorderRight(HSSFCellStyle.BORDER_THIN);//右邊框
三、設定居中:
setBorder.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中
四、設定字型:
HSSFFont font = wb.createFont();
font.setFontName("黑體");
font.setFontHeightInPoints((short) 16);//設定字型大小
HSSFFont font2 = wb.createFont();
font2.setFontName("仿宋_GB2312");
font2.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗體顯示
font2.setFontHeightInPoints((short) 12);
setBorder.setFont(font);//選擇需要用到的字型格式
五、設定列寬:
sheet.setColumnWidth(0, 3766); //第一個引數代表列id(從0開始),第2個引數代表寬度值
六、設定自動換行:
setBorder.setWrapText(true);//設定自動換行
七、通過row 物件設定行高
HSSFRow row = sheet.createRow(0);
//heightInPoints 設定的值永遠是height屬性值的20倍
row.setHeightInPoints(20);
HSSFRow row1 = sheet.createRow(5);
row1.setHeight((short) (25 * 20));
八、設定預設寬度、高度值
HSSFSheet sheet2 = wb.createSheet("sheet2");
sheet2.setDefaultColumnWidth(20);
sheet2.setDefaultRowHeightInPoints(20);
九、設定cell寬度(通過sheet 物件,setColumnWidth設定cell的寬度)
HSSFSheet sheet = wb.createSheet("sheet1");
sheet.setColumnWidth(0, 20 * 256);
十、合併單元格:
Region region1 = new Region(0, (short) 0, 0, (short) 6);//引數1:行號 引數2:起始列號 引數3:行號 引數4:終止列號
//此方法在POI3.8中已經被廢棄,建議使用下面一個
CellRangeAddress region1 = new CellRangeAddress(rowNumber, rowNumber, (short) 0, (short) 11);
//引數1:起始行 引數2:終止行 引數3:起始列 引數4:終止列
但應注意兩個構造方法的引數不是一樣的,具體使用哪個取決於POI的不同版本。
sheet.addMergedRegion(region1);
目前用過的就這麼多,後續有新的會繼續新增。
十一、加邊框
HSSFCellStyle cellStyle= wookBook.createCellStyle();
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
cellStyle.setBorderBottom(HSSFCellStyle.BorderBORDER_MEDIUM);
cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
cellStyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
十二、字型顏色
Font font = wb.createFont();
font.setFontHeightInPoints((short) 12); // 字型高度
font.setFontName("宋體"); // 字型
font.setColor(HSSFColor.RED.index); //顏色
cellStyle.setFont(font);//選擇需要用到的字型格式