1. 程式人生 > >導出Excel工具類(一個主表多個明細表)

導出Excel工具類(一個主表多個明細表)

導出 excel 選擇

①ExcelData.java(Excel數據封裝類)

package com.kentra.util;

import java.util.List;
import java.util.Map;
/**
 * 
 * 描述:為導出Excel文件封裝數據
 * 封裝Excel文件數據註意事項:
 * 1.heads(標題行):是一個字符串, 標題與標題之間以逗號分隔如:hears="學號,姓名,性別"
 * 2.data: 表示:主數據集合,data是個字符串集合,包含了所有主數據,集合中的一個字符串元素就是Excel表格中的一行記錄;
 * 列數據項與列數項之間用冒號分隔, 如果某個列數據項值為空, 就用null代替,如: data.add("001:老李:null:15056786789:null");
 * 3.assoceData 關聯數據集合,主數據集合的字符串元素的下標在關聯數據集合就是對應的關聯數據.是個雙list集合字符串,包含了所有主數據的關聯數據集合,
 * 它的每一個元素就是某一行主數據的關聯數據集合,如果主表數據沒有關聯數據,那麽它的關聯數據,就用null代替
 * 4.widthAndHeiht map的key 表示列的位置,map的value 表示列的寬度, 如:widthAndHeiht.put(3, 5000); 第4列寬度為5000英寸
 * 5.length 合並單元格的個數
 * @author sunxuefeng 2017年7月28日 下午5:13:35
 * @version 1.0
 */

public class ExcelData {

    private String                excelName;    // Excel文件名稱
    private String                sheetName;    // 工作表的名稱
    private String                heads;        // 標題行
    private List<String>          data;         // 主數據
    private Map<Integer, Integer> widthAndHeiht;// 單元格的寬高,如:xSheet.setColumnWidth(10,1000);
                                                // 10表示:map的key, //
                                                // 10,1000表示:map的value
    private List<List<String>>    assoceData;   // 關聯數據行,一張主表對應一個從表,當有多個明細表的時候,那麽就全部拼接到這個從表中即可。
    private int                   length;       // 合並單元格的個數 沒有就不用填



    public String getHeads() {
        return heads;
    }



    public void setHeads(String heads) {
        this.heads = heads;
    }



    public int getLength() {
        return length;
    }



    public void setLength(int length) {
        this.length = length;
    }



    public List<List<String>> getAssoceData() {
        return assoceData;
    }



    public void setAssoceData(List<List<String>> assoceData) {
        this.assoceData = assoceData;
    }



    public String getExcelName() {
        return excelName;
    }



    public void setExcelName(String excelName) {
        this.excelName = excelName;
    }



    public String getSheetName() {
        return sheetName;
    }



    public void setSheetName(String sheetName) {
        this.sheetName = sheetName;
    }



    public List<String> getData() {
        return data;
    }



    public void setData(List<String> data) {
        this.data = data;
    }



    public Map<Integer, Integer> getWidthAndHeiht() {
        return widthAndHeiht;
    }



    public void setWidthAndHeiht(Map<Integer, Integer> widthAndHeiht) {
        this.widthAndHeiht = widthAndHeiht;
    }

}

②ExportExcelUtils.java(導出工具類)

package com.kentra.util;

import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 
 * 描述:導出excel文件模板
 * 
 * @author sunxuefeng 2017年7月28日 上午11:20:48
 * @version 1.0
 */
public class ExportExcelUtils {
    private static final Logger LOG = Logger.getLogger(ExportExcelUtils.class);



    /**
     * 
     * 描述:輸出Excel文件
     * 
     * @param response
     * @param excelData
     *            為導出Excel文件封裝數據
     * @author sunxuefeng 2017年7月31日 上午9:58:10
     * @version 1.0
     * @throws Exception
     */
    public static void exportFile(HttpServletResponse response, ExcelData excelData) {
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            response.setHeader("Content-disposition",
                    "attachment; filename = " + URLEncoder.encode(excelData.getExcelName() + ".xlsx", "UTF-8"));
            response.setContentType("application/octet-streem");
            List<List<String>> assoceData = excelData.getAssoceData();
            XSSFWorkbook workbook = null;
            if (assoceData != null && assoceData.size() > 0) {
                workbook = setSheetContent(excelData);
            } else {
                workbook = setSheetContentNO(excelData);
            }
            workbook.write(outputStream);
        } catch (Exception e) {
            LOG.error("Excel文件導出失敗:" + e.getMessage());
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }



    /**
     * 
     * 描述: set Sheet標題行
     * 
     * @param xWorkbook
     * @param xSheet
     * @param headers標題行
     * @author sunxuefeng 2017年7月28日 下午1:13:36
     * @version 1.0
     */
    private static void setSheetHeader(XSSFWorkbook xWorkbook, XSSFSheet xSheet, String headers) {
        // 設置樣式
        CellStyle cs = xWorkbook.createCellStyle();
        // 設置水平垂直居中
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        // 設置字體
        Font headerFont = xWorkbook.createFont();
        headerFont.setFontHeightInPoints((short) 12);
        headerFont.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        headerFont.setFontName("宋體");
        cs.setFont(headerFont);
        cs.setWrapText(false);// 是否自動換行
        XSSFRow xRow0 = xSheet.createRow(0);
        String[] header = headers.split(",");
        for (int i = 0, length = header.length; i < length; i++) {
            XSSFCell xCell = xRow0.createCell(i);
            xCell.setCellStyle(cs);
            xCell.setCellValue(header[i]);
        }
    }



    /***
     * 
     * 描述: 設置Sheet頁內容(有關聯數據)
     * 
     * @param excelData
     * @return
     * @author sunxuefeng 2017年7月31日 上午9:59:24
     * @version 1.0
     */
    private static XSSFWorkbook setSheetContent(ExcelData excelData) {
        XSSFWorkbook xWorkbook = new XSSFWorkbook();
        XSSFSheet xSheet = xWorkbook.createSheet(excelData.getSheetName());
        Map<Integer, Integer> map = excelData.getWidthAndHeiht();
        CellStyle cs = xWorkbook.createCellStyle(); // 設置樣式
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        cs.setWrapText(true); // 是否自動換行。加入\n 就會換行, eg:電子科技大學2 \n 北京大學
        setSheetHeader(xWorkbook, xSheet, excelData.getHeads());
        if (map != null && map.size() > 0) { // 設置單元格的寬高
            for (Integer key : map.keySet()) {
                xSheet.setColumnWidth(key, map.get(key));
            }
        }
        List<String> data = excelData.getData();
        List<List<String>> assoceDatas = excelData.getAssoceData();
        if (data != null && data.size() > 0) {
            int l = 0, ii = 0;
            for (int i = 0; i < data.size(); i++) {
                List<String> assoceData = assoceDatas.get(i);
                int assoceDataSize = 0;
                boolean assoceDataFlag = false;
                if (assoceData != null && assoceData.size() > 0) {
                    assoceDataSize = assoceData.size();
                    assoceDataFlag = true;
                    if (i == 0) {
                        ii = 0;
                        l = assoceDataSize;
                    } else {
                        ii = l;
                        l += assoceDataSize;
                    }
                } else {
                    if (i == 0) {
                        ii = 0;
                        l = 1;
                    } else {
                        ii = l;
                        l += 1;
                    }
                }
                for (int k = ii, m = 0, lengths = l; k < lengths; k++, m++) {// 控制行行:
                    XSSFRow xRow = xSheet.createRow(k + 1);
                    int j = 0;
                    j = setValue(j, 0, data.get(i), xRow, cs);// 設置主數據
                    int length = data.get(i).split(":").length;
                    if (assoceDataFlag) {
                        setValue(j, length, assoceData.get(m), xRow, cs);// 設置關聯數據
                    }
                }
                if (assoceDatas.size() >= 1) { // 合並單元格
                    for (int m = 0; m < excelData.getLength(); m++) {
                        if (assoceDataFlag) {
                            int endRows = xSheet.getLastRowNum();
                            int startRow = endRows - assoceDataSize + 1;
                            xSheet.addMergedRegion(new CellRangeAddress(startRow, endRows, m, m));
                        }
                    }
                }
            }
        }
        return xWorkbook;
    }



    /***
     * 
     * 描述: 設置Sheet頁內容(無關聯數據)
     * 
     * @param excelData
     * @return
     * @author sunxuefeng 2017年7月31日 上午9:59:24
     * @version 1.0
     */
    private static XSSFWorkbook setSheetContentNO(ExcelData excelData) throws Exception {
        XSSFWorkbook xWorkbook = new XSSFWorkbook();
        XSSFSheet xSheet = xWorkbook.createSheet(excelData.getSheetName());
        Map<Integer, Integer> map = excelData.getWidthAndHeiht();
        CellStyle cs = xWorkbook.createCellStyle(); // 設置樣式
        cs.setAlignment(CellStyle.ALIGN_CENTER);
        cs.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
//        cs.setWrapText(false); // 是否自動換行
        cs.setWrapText(true); // 是否自動換行
        setSheetHeader(xWorkbook, xSheet, excelData.getHeads());
        if (map != null && map.size() > 0) { // 設置單元格的寬
            for (Integer key : map.keySet()) {
                xSheet.setColumnWidth(key, map.get(key));
            }
        }
        List<String> data = excelData.getData();
        if (data != null && data.size() > 0) {
            for (int i = 0; i < data.size(); i++) {
                XSSFRow xRow = xSheet.createRow(i + 1);
                int j = 0;
                j = setValue(j, 0, data.get(i), xRow, cs);// 設置主數據
            }
        }
        return xWorkbook;
    }



    /**
     * 
     * 描述:為單元格設置值
     * 
     * @author sunxuefeng 2017年8月1日 上午9:45:36
     * @version 1.0
     */
    private static int setValue(int j, int i, String data, XSSFRow xRow, CellStyle cs) {
        String[] strings = data.split(":");
        for (; j < strings.length + i; j++) {
            String dString = strings[j - i];
            if (dString != null && !dString.equals("") && !dString.equals("null")) {
                XSSFCell xCell = xRow.createCell(j);
                xCell.setCellStyle(cs);
                xCell.setCellValue(dString);
            }
        }
        return j;
    }
}

③導出示例(當有多個明細表時,都拼接到從表後面)

/**
	 *測試導出員工
	 * 
	 */
	@RequestMapping(value="/ExportExcel")
	public void ExportExcel(HttpServletResponse response)throws Exception{
		ExcelData excelData = new ExcelData();
		excelData.setExcelName("員工信息表");
		excelData.setSheetName("員工信息表");
		excelData.setHeads("序號,姓名,性別,年齡,學校,畢業年份,學分,家庭成員,年齡");
		//列寬
		Map<Integer, Integer> widthAndHeiht = new HashMap<>();
		widthAndHeiht.put(0, 2000);
		widthAndHeiht.put(1, 3000);
		widthAndHeiht.put(2, 3000);
		widthAndHeiht.put(4, 8000);
		excelData.setWidthAndHeiht(widthAndHeiht);
		//主表
		String data1 = "1,李建波,null,26";
		String data2 = "2,李雨鋒,男,20";
		String data3 = "3,魏文瑩,null,null";
		List<String> data = new ArrayList<>();
		data.add(data1);
		data.add(data2);
		data.add(data3);
		excelData.setData(data);
		//合並單元格	
		excelData.setLength(2);
		//關聯明細表
		List<List<String>>    assoceData = new ArrayList<>();
		//教育明細
		String jioayu1 = "四川大學,2017,5,父親,60";
		String jioayu2 = "電子科技大學,2015,4,母親,55";
		String jioayu33 = "null,null,null,妻子,25";
		List<String> jiaoyulist1 = new ArrayList<>();
		jiaoyulist1.add(jioayu1);
		jiaoyulist1.add(jioayu2);
		jiaoyulist1.add(jioayu33);
		String jioayu3 = "四川大學2,2017,null";
		String jioayu4 = "電子科技大學2 \n 北京大學,2015,4";
		List<String> jiaoyulist2 = new ArrayList<>();
		jiaoyulist2.add(jioayu3);
		jiaoyulist2.add(jioayu4);
		//
		assoceData.add(jiaoyulist1);
		assoceData.add(null);
		assoceData.add(jiaoyulist2);
		excelData.setAssoceData(assoceData);
		//導出
		ExportExcelUtils.exportFile(response, excelData);
		
	}

註意事項:

導出Excel的時候,我們可能需要某一個單元格中的內容自動換行,那麽我們可以在需要換行的地方拼接一個 “\n” 那麽導出數據就會換行。

該工具類主要是為了導出員工信息表。一個主表多個明細表。比如一個員工有多條工作經歷,有多個家庭成員,有多個證件等。

(二)、如何手動實現頁面可選擇特定字段導出。

我們的思路是頁面勾選哪幾個字段,我們就拼接哪幾個字段然後導出。表頭名字來自於選擇的復選框的text();內容則通過每個字段對應的value值作為下標去從一條記錄(數組)中去獲取對應下標的值,然後進行拼接字符串。

技術分享

<div style="padding-top:10px">
		<div>
		<!-- 修改,將span加在了後面-->
		<input type="checkbox" value="1" name="staffinfo_checkbox"/><span>部門</span>
		<input type="checkbox" value="2" name="staffinfo_checkbox"/><span>姓名</span>
		<input type="checkbox" value="3" name="staffinfo_checkbox"/><span>性別</span>
		<input type="checkbox" value="4" name="staffinfo_checkbox"/><span>手機號</span>
		<input type="checkbox" value="5" name="staffinfo_checkbox"/><span>民族</span>
		<input type="checkbox" value="6" name="staffinfo_checkbox"/><span>籍貫</span>				
		<input type="checkbox" value="7" name="staffinfo_checkbox"/><span>出生地</span>
		<input type="checkbox" value="8" name="staffinfo_checkbox"/><span>出生日期</span>
		<input type="checkbox" value="9" name="staffinfo_checkbox"/><span>年齡</span>
</div>


本文出自 “JianBo” 博客,轉載請與作者聯系!

導出Excel工具類(一個主表多個明細表)