1. 程式人生 > >POI 匯出Excel 並且根據內容設定列寬自適應

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);//選擇需要用到的字型格式