1. 程式人生 > >POI匯出Excel--合併單元格

POI匯出Excel--合併單元格

package com.test.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;
import javax.swing.JOptionPane;

import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;

/**
 * @author zhanghk
 */
public class ExcelUtil_Extend {
	/**
	 * @param fileName 檔名稱
	 * @param headers 表頭
	 * @param dataset 資料集
	 * @param isSortDataSet 是否對資料排序
	 * @param response HttpServletResponse
	 * @param mergeBasis 合併基準列 可選
	 * @param mergeCells 要合併的列 可選
	 * @param sumCellsMap 要求和的列 可選
	 * @param timeCells 時間列 可選
	 * @throws IOException
	 */
	public static void exportExelMerge(String fileName,final String[] headers,List<String[]> dataset,boolean isSortDataSet,HttpServletResponse response, final Integer[] mergeBasis, final Integer[] mergeCells, final Integer[] sumCells, final Integer[] timeCells) throws IOException{
		String title = "Sheet1";
		response.setContentType("application/vnd.ms-excel;charset=utf-8"); 
		response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
		
		createExcelMerge(title,headers,dataset,isSortDataSet,response.getOutputStream(),mergeBasis,mergeCells,sumCells,timeCells);
		
		response.setStatus(HttpServletResponse.SC_OK);
		response.flushBuffer();
	}
	
	/**
	 * @param title 檔名稱
	 * @param headers 表頭
	 * @param dataset 資料集
	 * @param isSortDataSet 是否對資料排序
	 * @param out OutputStream
	 * @param mergeBasis 合併基準列 可選
	 * @param mergeCells 要合併的列
	 * @param sumCells 要求和的列
	 * @param timeCells 時間列 可選
	 */
	public static void createExcelMerge(String title, final String[] headers,List<String[]> dataset,boolean isSortDataSet, OutputStream out, final Integer[] mergeBasis, final Integer[] mergeCells, final Integer[] sumCells, final Integer[] timeCells){
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet(title);
		
		sheet.setDefaultColumnWidth(15); // 設定表格預設列寬度為15個位元組  
		
		HSSFCellStyle headStyle = createHeadStyle(workbook); // 生成頭部樣式 
		HSSFCellStyle commonDataStyle = createCommonDataStyle(workbook); // 生成一般資料樣式  
		HSSFCellStyle numStyle = createNumStyle(workbook); //生成數字型別保留兩位小數樣式
		HSSFCellStyle sumRowStyle = createSumRowStyle(workbook); //生成合計行樣式

		if(headers == null || headers.length <= 0){
			return;
		}
		
		HSSFRow row = sheet.createRow(0); // 產生表格標題行  
		for (int i = 0; i < headers.length; i++) {
			HSSFCell cell = row.createCell(i);
			cell.setCellStyle(headStyle);
			HSSFRichTextString text = new HSSFRichTextString(headers[i]);
			cell.setCellValue(text);
		}
		
		if(isSortDataSet && mergeBasis != null && mergeBasis.length > 0){ //是否排序資料
			Collections.sort(dataset, new Comparator<String[]>() {
				public int compare(String[] o1, String[] o2) {
					String s1 = "";
					String s2 = "";
					for(int i = 0 ; i < mergeBasis.length ; i++){
						s1+=(o1[mergeBasis[i].intValue()]+Character.valueOf((char)127).toString());
						s2+=(o2[mergeBasis[i].intValue()]+Character.valueOf((char)127).toString());
					}
					if(timeCells != null && timeCells.length > 0){
						for(int i = 0 ; i < timeCells.length ; i++){
							s1+= o1[timeCells[i].intValue()];
							s2+= o2[timeCells[i].intValue()];
						}
					}
					if(s1.compareTo(s2) < 0){
						return -1;
					}else if(s1.compareTo(s2) == 0){
						return 0;
					}else{
						return 1;
					}
				}
	        });
		}
		// 遍歷集合資料,產生資料行  
		Iterator<String[]> it = dataset.iterator();  
		int index = 0;  
		while (it.hasNext()) {
			index++;  
			row = sheet.createRow(index);  
			String[] dataSources = it.next() ;
			for (int i = 0; i < dataSources.length; i++) {  
				HSSFCell cell = row.createCell(i);  
				cell.setCellStyle(commonDataStyle);
				cell.setCellValue(dataSources[i]);
			}
		}  
		try {  
			if(mergeBasis != null && mergeBasis.length > 0 && mergeCells != null && mergeCells.length > 0){
				for(int i = 0 ; i < mergeCells.length ; i++){
					mergedRegion(sheet,mergeCells[i],1,sheet.getLastRowNum(),workbook,mergeBasis);
				}
			}
			if(sumCells != null && sumCells.length > 0){
				createSumRow(sheet, row, headers, sumCells, sumRowStyle, numStyle);
			}
			workbook.write(out);  
		} catch (IOException e) {  
			e.printStackTrace();  
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 建立合計行
	 * @param sheet
	 * @param row
	 * @param headers
	 * @param sumCells
	 * @param sumRowStyle
	 * @param numStyle
	 */
	private static void createSumRow(HSSFSheet sheet , HSSFRow row , final String[] headers, final Integer[] sumCells , HSSFCellStyle sumRowStyle,HSSFCellStyle numStyle){
		row=sheet.createRow(sheet.getLastRowNum()+1);
		for (int i = 0; i < headers.length; i++) {
			HSSFCell cell = row.createCell(i);
			cell.setCellStyle(sumRowStyle);
		}
		for(int i = 1 ; i < sheet.getLastRowNum() ; i++){
			for(int j = 0 ; j < sumCells.length ; j++){
				sheet.getRow(i).getCell(sumCells[j]).setCellValue(Double.parseDouble(sheet.getRow(i).getCell(sumCells[j]).getStringCellValue()));
	            sheet.getRow(i).getCell(sumCells[j]).setCellStyle(numStyle);
			}
		}
		HSSFCell sumCell = row.getCell(0);
		sumCell.setCellValue("合計:");
		String sumFunctionStr = null;
		for(int i = 0 ; i < sumCells.length ; i++){
			sumFunctionStr = "SUM("+CellReference.convertNumToColString(sumCells[i])+"2:"+CellReference.convertNumToColString(sumCells[i])+sheet.getLastRowNum()+")";
			row.getCell(sumCells[i]).setCellFormula(sumFunctionStr);
		}
	}
	
	/**
	 * 合併單元格
	 * @param sheet
	 * @param cellLine
	 * @param startRow
	 * @param endRow
	 * @param workbook
	 * @param mergeBasis
	 */
	private static void mergedRegion(HSSFSheet sheet, int cellLine,int startRow, int endRow, HSSFWorkbook workbook, Integer[] mergeBasis) {
		HSSFCellStyle style = workbook.createCellStyle(); 			// 樣式物件  
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);	// 垂直  
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);				// 水平  
        String s_will = sheet.getRow(startRow).getCell(cellLine).getStringCellValue();  // 獲取第一行的資料,以便後面進行比較  
        int count = 0;  
        Set<Integer> set = new HashSet<Integer>();
        CollectionUtils.addAll(set, mergeBasis);
        for (int i = 2; i <= endRow; i++) {  
        	String s_current = sheet.getRow(i).getCell(cellLine).getStringCellValue();  
            if (s_will.equals(s_current)) { 
            	boolean isMerge = true;
            	if(!set.contains(cellLine)){//如果不是作為基準列的列 需要所有基準列都相同
	            	for(int j = 0 ; j < mergeBasis.length ; j++){
		            	if(!sheet.getRow(i).getCell(mergeBasis[j]).getStringCellValue()
		            			.equals(sheet.getRow(i-1).getCell(mergeBasis[j]).getStringCellValue())){
		            		isMerge = false;
		            	}
	            	}
            	}else{//如果作為基準列的列 只需要比較列號比本列號小的列相同
            		for(int j = 0 ; j < mergeBasis.length && mergeBasis[j] < cellLine ; j++){
		            	if(!sheet.getRow(i).getCell(mergeBasis[j]).getStringCellValue()
		            			.equals(sheet.getRow(i-1).getCell(mergeBasis[j]).getStringCellValue())){
		            		isMerge = false;
		            	}
	            	}
            	}
            	if(isMerge){
            		count++;
            	}else{
            		sheet.addMergedRegion(new CellRangeAddress( startRow, startRow+count,cellLine , cellLine));
            		startRow = i;  
                    s_will = s_current;
                    count = 0;
            	}
            } else {  
            	sheet.addMergedRegion(new CellRangeAddress( startRow, startRow+count,cellLine , cellLine));  
            	startRow = i;  
                s_will = s_current;
                count = 0;
            }  
            if (i == endRow && count > 0) {  
                sheet.addMergedRegion(new CellRangeAddress(startRow,startRow+count ,cellLine , cellLine));  
            }  
        }  
	}

	/**
	 * 標題單元格樣式
	 * @param workbook
	 * @return
	 */
	private static HSSFCellStyle createHeadStyle(HSSFWorkbook workbook){
		//標題單元格樣式
		HSSFCellStyle headStyle = workbook.createCellStyle();   
		headStyle.setFillForegroundColor(HSSFColor.SKY_BLUE.index);  
		headStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  
		headStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);  
		headStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);  
		headStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);  
		headStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);  
		headStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);  
		//標題單元格字型  
		HSSFFont headFont = workbook.createFont();  
		headFont.setColor(HSSFColor.VIOLET.index);  
		headFont.setFontHeightInPoints((short) 12);  
		headFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);  
		// 把字型應用到當前的樣式  
		headStyle.setFont(headFont);  
		return headStyle;
	}
	
	/**
	 * 合計行單元格樣式
	 * @param workbook
	 * @return
	 */
	private static HSSFCellStyle createSumRowStyle(HSSFWorkbook workbook){
		//合計行單元格樣式
		HSSFCellStyle sumRowStyle = workbook.createCellStyle();  
		sumRowStyle.setFillForegroundColor(HSSFColor.SKY_BLUE.index);  
		sumRowStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  
		sumRowStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);  
		sumRowStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);  
		sumRowStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);  
		sumRowStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);  
		sumRowStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); 
		sumRowStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));
		//合計行單元格字型  
		HSSFFont sumRowFont = workbook.createFont();  
		sumRowFont.setColor(HSSFColor.VIOLET.index);  
		sumRowFont.setFontHeightInPoints((short) 12);  
		sumRowFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);  
		// 把字型應用到當前的樣式  
		sumRowStyle.setFont(sumRowFont);	
		return sumRowStyle;
	}
	
	/**
	 * 普通資料單元格樣式 
	 * @param workbook
	 * @return
	 */
	private static HSSFCellStyle createCommonDataStyle(HSSFWorkbook workbook){
		//普通資料單元格樣式 
		HSSFCellStyle commonDataStyle = workbook.createCellStyle();  
		commonDataStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);  
		commonDataStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  
		commonDataStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);  
		commonDataStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);  
		commonDataStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);  
		commonDataStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);  
		commonDataStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);  
		commonDataStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);  
		//普通資料單元格字型  
		HSSFFont commonDataFont = workbook.createFont();  
		commonDataFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);  
		//把字型應用到當前的樣式  
		commonDataStyle.setFont(commonDataFont); 
		return commonDataStyle;
	}
	
	/**
	 * 自定義保留兩位小數數字單元格格式
	 * @param workbook
	 * @return
	 */
	private static HSSFCellStyle createNumStyle(HSSFWorkbook workbook){
		//自定義保留兩位小數數字單元格格式
		HSSFCellStyle numStyle = workbook.createCellStyle();  
		numStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);  
		numStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);  
		numStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);  
		numStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);  
		numStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);  
		numStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);  
		numStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);  
		numStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);  
		numStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0.00"));
		//自定義保留兩位小數數字單元格字型  
		HSSFFont numFont = workbook.createFont();  
		numFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);  
		//把字型應用到當前的樣式  
		numStyle.setFont(numFont); 
		return numStyle;
	}
	
	public static void main(String[] args) { 
        String[] headers =  { "大區", "部門", "金額", "數量", "日期" };  
        List<String[]> dataset = new ArrayList<String[]>();  
        dataset.add(new String[] {"華東", "部門3", "35", "1", "2015-01-01"});  
        dataset.add(new String[] {"華北", "部門1", "20", "1", "2015-01-02"});  
        dataset.add(new String[] {"華北", "部門2", "25", "1", "2015-01-03"});  
        dataset.add(new String[] {"華北", "部門5", "25", "1", "2015-01-04"});  
        dataset.add(new String[] {"華南", "部門1", "15", "1", "2015-01-05"});  
        dataset.add(new String[] {"華北", "部門3", "30", "1", "2015-01-06"});  
        dataset.add(new String[] {"華北", "部門3", "30", "1", "2015-01-07"});  
        dataset.add(new String[] {"華東", "部門1", "25", "1", "2015-01-08"});  
        dataset.add(new String[] {"華南", "部門4", "30", "1", "2015-01-09"});   
        dataset.add(new String[] {"華東", "部門2", "25", "1", "2015-01-10"});  
        dataset.add(new String[] {"華東", "部門2", "25", "1", "2015-01-11"});  
        dataset.add(new String[] {"華東", "部門3", "35", "1", "2015-01-12"});  
        dataset.add(new String[] {"華南", "部門1", "15", "1", "2015-01-13"});  
        dataset.add(new String[] {"華北", "部門6", "20", "1", "2015-01-14"});  
        dataset.add(new String[] {"華南", "部門2", "25", "1", "2015-01-15"});  
        dataset.add(new String[] {"華南", "部門2", "25", "1", "2015-01-16"});  
        dataset.add(new String[] {"華東", "部門1", "25", "1", "2015-01-17"});  
        dataset.add(new String[] {"華南", "部門8", "30", "1", "2015-01-18"});   
        dataset.add(new String[] {"華東", "部門2", "35", "1", "2015-01-01"});  
        dataset.add(new String[] {"華北", "部門1", "20", "1", "2015-01-02"});  
        dataset.add(new String[] {"華北", "部門11", "25", "1", "2015-01-03"});  
        dataset.add(new String[] {"華北", "部門2", "25", "1", "2015-01-04"});  
        dataset.add(new String[] {"華南", "部門1", "15", "1", "2015-01-05"});  
        dataset.add(new String[] {"華北", "部門4", "30", "1", "2015-01-06"});  
        dataset.add(new String[] {"華北", "部門3", "30", "1", "2015-01-07"});  
        dataset.add(new String[] {"華東", "部門9", "25", "1", "2015-01-08"});  
        dataset.add(new String[] {"華南", "部門3", "30", "1", "2015-01-09"});   
        dataset.add(new String[] {"華東", "部門12", "25", "1", "2015-01-10"});  
        dataset.add(new String[] {"華東", "部門2", "25", "1", "2015-01-11"});  
        dataset.add(new String[] {"華東", "部門12", "35", "1", "2015-01-12"});  
        dataset.add(new String[] {"華南", "部門1", "15", "1", "2015-01-13"});  
        dataset.add(new String[] {"華北", "部門11", "20", "1", "2015-01-14"});  
        dataset.add(new String[] {"華南", "部門21", "25", "1", "2015-01-15"});  
        dataset.add(new String[] {"華南", "部門2", "25", "1", "2015-01-16"});  
        dataset.add(new String[] {"華東", "部門15", "25", "1", "2015-01-17"});  
        dataset.add(new String[] {"華南", "部門3", "30", "1", "2015-01-18"});   
        dataset.add(new String[] {"華東", "部門3", "35", "1", "2015-01-01"});  
        dataset.add(new String[] {"華北", "部門17", "20", "1", "2015-01-02"});  
        dataset.add(new String[] {"華北", "部門22", "25", "1", "2015-01-03"});  
        dataset.add(new String[] {"華北", "部門2", "25", "1", "2015-01-04"});  
        dataset.add(new String[] {"華南", "部門1", "15", "1", "2015-01-05"});  
        dataset.add(new String[] {"華北", "部門2", "30", "1", "2015-01-06"});  
        dataset.add(new String[] {"華北", "部門3", "30", "1", "2015-01-07"});  
        dataset.add(new String[] {"華東", "部門1", "25", "1", "2015-01-08"});  
        dataset.add(new String[] {"華南", "部門8", "30", "1", "2015-01-09"});   
        dataset.add(new String[] {"華東", "部門2", "25", "1", "2015-01-10"});  
        dataset.add(new String[] {"華東", "部門2", "25", "1", "2015-01-11"});  
        dataset.add(new String[] {"華東", "部門3", "35", "1", "2015-01-12"});  
        dataset.add(new String[] {"華南", "部門7", "15", "1", "2015-01-13"});  
        dataset.add(new String[] {"華北", "部門1", "20", "1", "2015-01-14"});  
        dataset.add(new String[] {"華南", "部門2", "25", "1", "2015-01-15"});  
        dataset.add(new String[] {"華南", "部門2", "25", "1", "2015-01-16"});  
        dataset.add(new String[] {"華東", "部門9", "25", "1", "2015-01-17"});  
        dataset.add(new String[] {"華南", "部門3", "30", "1", "2015-01-18"});   
        try {  
            OutputStream out = new FileOutputStream("E://a.xls");  
            ExcelUtil_Extend.createExcelMerge("測試.xls", headers, dataset, true, out, new Integer[]{0,1}, new Integer[]{0,1}, new Integer[]{2,3}, new Integer[]{4});  
            out.close();  
            JOptionPane.showMessageDialog(null, "匯出成功!");  
            System.out.println("excel匯出成功!");  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }
	}
}