使用POI、Spring MVC導出EXCEL

1.POI工具類java

package com.lshaci.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPalette;
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.RegionUtil;

/**
 * 使用POI導出EXCEL
 * 
 * @author lshaci
 *
 */
public class ExcelExportUtilWithPOI {
	
	/**
	 * 使用POI建立Excel
	 * 
	 * @param sheetName				Excel標籤名字
	 * @param firstTitleName		一級標題名字(第一行合併單元格內)
	 * @param secondTitleNames		二級標題名字集合(第二行)
	 * @param secondTitleColumns	二級標題所跨列的集合
	 * @param columnHeaders			列標題集合(第三行)
	 * @param fieldNames			對象字段名集合
	 * @param datas					數據集合
	 * @param otherData				其它的數據(表格最後一行合併的單元格內)
	 * 
	 * @return	返回流信息
	 */
	public static <T> InputStream createWorkBook(String sheetName, String firstTitleName, List<String> secondTitleNames, List<Integer> secondTitleColumns,
			List<String> columnHeaders, List<String> fieldNames, List<T> datas, String otherData) {
		try (
				ByteArrayOutputStream os = new ByteArrayOutputStream();
			) {
			// 聲明一個工做薄
			HSSFWorkbook workbook = new HSSFWorkbook();
			// 建立一個sheet
			HSSFSheet sheet = workbook.createSheet(sheetName);
			// 設置列寬
			sheet.setDefaultColumnWidth(12);
			// 設置序號列的寬度
			sheet.setColumnWidth(0, 1500);
			
			// 設置一級標題行
			setFirstTitleRow(workbook, sheet, firstTitleName, columnHeaders.size());
			// 設置二級標題行
			setSecondTitleRows(workbook, sheet, secondTitleNames, secondTitleColumns);
			// 設置列的標題
			setColumnTitles(workbook, sheet, columnHeaders);
			List<String[]> rowDatas = javaBean2StringArrays(datas, fieldNames);
			// 設置表格中的內容
			setSheetRows(workbook, sheet, rowDatas);
			// 若是其它數據存在,則進行填充
			if (otherData != null && otherData != "") {
				setOtherDataRows(workbook, sheet, otherData, 3 + rowDatas.size(), columnHeaders.size());
			}
			
			workbook.write(os);
			return new ByteArrayInputStream(os.toByteArray());
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("建立excel表格出錯");
		}
		
	}
	
	/**
	 * 設置表格一級標題行
	 * 
	 * @param workbook			工做簿
	 * @param sheet				標籤
	 * @param firstTitleName	一級標題名稱
	 * @param size				一級標題所跨列數
	 */
	private static void setFirstTitleRow(HSSFWorkbook workbook, HSSFSheet sheet, String firstTitleName, int size) {
		HSSFRow row = sheet.createRow(0);
		row.setHeight((short) 1600);
		CellRangeAddress region = new CellRangeAddress(0, 0, 0, size);
		sheet.addMergedRegion(region);
		HSSFCell cell = row.createCell(0);
		cell.setCellValue(firstTitleName);
		cell.setCellStyle(createFirstTitleStyle(workbook));
		
		// 設置合併單元格的邊框
		setMergeCellBorder(region, sheet, workbook);
	}
	
	/**
	 * 建立一級標題樣式
	 * 
	 */
	private static HSSFCellStyle createFirstTitleStyle(HSSFWorkbook workbook) {
		// 生成一個樣式
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFPalette customPalette = workbook.getCustomPalette();  
		HSSFColor color = customPalette.findSimilarColor(102, 102, 153);
		// 設置這些樣式
		style.setFillForegroundColor(HSSFColor.WHITE.index);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// 生成一個字體
		HSSFFont font = workbook.createFont();
		font.setColor(color.getIndex());
		font.setFontHeightInPoints((short) 20);
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("華文楷體");
		// 把字體應用到當前的樣式
		style.setFont(font);
		style.setWrapText(true);	// 使用 \n 換行設置爲true
		
		return style;
	}
	
	/**
	 * 設置表格二級標題行
	 * 
	 * @param workbook				工做簿
	 * @param sheet					標籤
	 * @param secondTitleNames		二級標題名稱集合
	 * @param secondTitleColumns	二級標題所跨列數集合
	 */
	private static void setSecondTitleRows(HSSFWorkbook workbook, HSSFSheet sheet, List<String> secondTitleNames,
			List<Integer> secondTitleColumns) {
		if (secondTitleNames.isEmpty() || secondTitleColumns.isEmpty() || 
				secondTitleNames.size() != secondTitleColumns.size()) {
			throw new RuntimeException("二級標題名對應所跨的列數量不一致!");
		}
		HSSFRow row = sheet.createRow(1);
		row.setHeight((short) 400);
		for (int i = 0; i < secondTitleNames.size(); i++) {
			Integer now = secondTitleColumns.get(i) - 1;
			Integer last = i == 0 ? 0 : secondTitleColumns.get(i - 1);
			HSSFCell cell = row.createCell(last);;
			cell.setCellValue(secondTitleNames.get(i));
			cell.setCellStyle(createSecondTitleStyle(workbook));
			if (now > 0) {
				CellRangeAddress region = new CellRangeAddress(1, 1, last, last + now);
				sheet.addMergedRegion(region);
				
				// 設置合併單元格的邊框
				setMergeCellBorder(region, sheet, workbook);
			}
		}
	}

	/**
	 * 建立二級標題樣式
	 */
	private static HSSFCellStyle createSecondTitleStyle(HSSFWorkbook workbook) {
		// 生成一個樣式
		HSSFCellStyle style = workbook.createCellStyle();
		HSSFPalette customPalette = workbook.getCustomPalette();  
		HSSFColor color = customPalette.findSimilarColor(102, 102, 153);
		// 設置這些樣式
		style.setFillForegroundColor(HSSFColor.WHITE.index);
		// 設置表格邊框
		setBorder(style);
		
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// 生成一個字體
		HSSFFont font = workbook.createFont();
		font.setColor(color.getIndex());
		font.setFontHeightInPoints((short) 12);
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("微軟雅黑");
		// 把字體應用到當前的樣式
		style.setFont(font);
		
		return style;
	}
	/**
	 * 設置表格的列標題
	 * 
	 * @param workbook 	工做薄
	 * @param sheet		表格中的一個標籤頁
	 * @param headers	列標題名稱的字符串數組
	 * @throws ExcelHanlderException 
	 */
	private static void setColumnTitles(HSSFWorkbook workbook, HSSFSheet sheet, List<String> columnHeaders) {
		if (columnHeaders.isEmpty()) {
			throw new RuntimeException("列標題集合爲空!");
		}
		HSSFRow row = sheet.createRow(2);
		row.setHeight((short) 360);
		HSSFCellStyle columnTitleStyle = createColumnTitleStyle(workbook);
		for (int i = 0; i <= columnHeaders.size(); i++) {
			HSSFCell cell = row.createCell(i);
			String value = i == 0 ? "序號" : columnHeaders.get(i - 1);
			cell.setCellValue(value);
			cell.setCellStyle(columnTitleStyle);
		}
	}
	
	/**
	 * 建立列標題欄樣式
	 */
	private static HSSFCellStyle createColumnTitleStyle(HSSFWorkbook workbook) {
		// 生成一個樣式
		HSSFCellStyle style = workbook.createCellStyle();
		// 根據RGB獲取類似的顏色
		HSSFPalette customPalette = workbook.getCustomPalette();  
		HSSFColor color = customPalette.findSimilarColor(102, 102, 153);
		// 設置這些樣式
		style.setFillForegroundColor(HSSFColor.WHITE.index);
		setBorder(style);
		// 設置水平和垂直居中
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// 生成一個字體
		HSSFFont font = workbook.createFont();
		font.setColor(color.getIndex());
		font.setFontHeightInPoints((short) 10);
		font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("宋體");
		// 把字體應用到當前的樣式
		style.setFont(font);
		
		return style;
	}
	/**
	 * 設置表格中的內容
	 * 
	 * @param workbook 	工做薄
	 * @param sheet		表格中的一個標籤頁
	 * @param rows		內容字符串數組集合
	 * @throws ExcelHanlderException 
	 */
	private static void setSheetRows(HSSFWorkbook workbook, HSSFSheet sheet, List<String[]> rowDatas) {
		if (rowDatas.isEmpty()) {
			throw new RuntimeException("內容集合爲空!");
		}
		HSSFCellStyle contentStyle = createContentStyle(workbook);
		for (int i = 0; i < rowDatas.size(); i++) {
			HSSFRow row = sheet.createRow(3 + i);
			row.setHeight((short) 320);
			String[] rowData = rowDatas.get(i);
			for (int j = 0; j <= rowData.length; j++) {
				HSSFCell cell = row.createCell(j);
				String value = j == 0 ? (i + 1) + "" : rowData[j - 1];
				cell.setCellValue(value);
				cell.setCellStyle(contentStyle);
			}
		}
	}

	/**
	 * 建立表格內容樣式
	 * 
	 * @param workbook	工做薄
	 * @return
	 */
	private static HSSFCellStyle createContentStyle(HSSFWorkbook workbook) {
		// 生成一個樣式
		HSSFCellStyle style = workbook.createCellStyle();
		// 設置這些樣式
		style.setFillForegroundColor(HSSFColor.WHITE.index);
//		style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
		setBorder(style);
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
		style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
		// 生成一個字體
		HSSFFont font = workbook.createFont();
		font.setColor(HSSFColor.BLACK.index);
		font.setFontHeightInPoints((short) 10);
		font.setFontName("宋體");
		// 把字體應用到當前的樣式
		style.setFont(font);
		
		return style;
	}
	/**
	 * 設置合併單元格的邊框
	 * 
	 * @param region 	合併的單元格
	 * @param sheet		標籤
	 * @param workbook	工做簿
	 */
	private static void setMergeCellBorder(CellRangeAddress region, HSSFSheet sheet, HSSFWorkbook workbook) {
		RegionUtil.setBorderBottom(1, region, sheet, workbook);
		RegionUtil.setBorderLeft(1, region, sheet, workbook);
		RegionUtil.setBorderRight(1, region, sheet, workbook);
		RegionUtil.setBorderTop(1, region, sheet, workbook);
	}
	
	/**
	 * 設置表格邊框
	 * 
	 * @param style 表格樣式
	 */
	private static void setBorder(HSSFCellStyle style) {
		style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
		style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
		style.setBorderRight(HSSFCellStyle.BORDER_THIN);
		style.setBorderTop(HSSFCellStyle.BORDER_THIN);
	}
	
	/**
	 * 設置一些其它數據,在表格最後一行合併單元格內
	 * 
	 * @param workbook
	 * @param sheet
	 * @param otherData
	 * @param rowIndex
	 * @param size
	 */
	private static void setOtherDataRows(HSSFWorkbook workbook, HSSFSheet sheet, String otherData, int rowIndex, int size) {
		HSSFRow row = sheet.createRow(rowIndex);
		row.setHeight((short) 320);
		CellRangeAddress region = new CellRangeAddress(rowIndex, rowIndex, 0, size);
		sheet.addMergedRegion(region);
		HSSFCell cell = row.createCell(0);
		cell.setCellValue(otherData);
		HSSFCellStyle style = createContentStyle(workbook);
		style.setAlignment(HSSFCellStyle.ALIGN_LEFT);
		style.setWrapText(true);
		cell.setCellStyle(style);
		
		// 設置合併單元格的邊框
		setMergeCellBorder(region, sheet, workbook);
	}

	/**
	 * javaBean轉換爲String數組集合
	 * 
	 * @param datas		須要轉換的數據集合(對象類型,符合javaBean規範)
	 * @param fields	指定須要轉換的字段集合
	 * @return
	 * @throws SecurityException 
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	private static <T> List<String[]> javaBean2StringArrays(List<T> datas, List<String> fieldNames) 
			throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		if (datas.isEmpty()) {
			throw new RuntimeException("數據爲空!");
		}
		
		List<String[]> rows = new ArrayList<>();
		
		Class<?> clazz = datas.get(0).getClass();
		if (fieldNames.isEmpty()) {
			throw new RuntimeException("字段名爲空!");
		}
		
		Method[] methods = getMethods(clazz, fieldNames);
		
		for (T data : datas) {
			int length = methods.length;
			String[] row = new String[length];
			for (int i = 0; i < length; i++) {
				Object obj = methods[i].invoke(data);
				if (obj != null) {
					row[i] = obj.toString();
				} else {
					row[i] = "";
				}
			}
			rows.add(row);
		}
		return rows;
	}
	
	/**
	 * 根據字段名獲取get方法
	 * 
	 * @param clazz 		須要獲取get方法對象的Class
	 * @param fieldNames 	字段名字符串集合
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 */
	private static Method[] getMethods(Class<?> clazz, List<String> fieldNames) 
			throws NoSuchMethodException, SecurityException {
		int length = fieldNames.size();
		Method[] methods = new Method[length];
		for (int i = 0; i < length; i++) {
			String fieldName = fieldNames.get(i);
			String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
			methods[i] = clazz.getMethod(methodName);
		}
		return methods;
	}

}

2.controllerapache

@RequestMapping(value = "exportDoctorsSummary", method = RequestMethod.GET)
	public void exportDoctorsSummary(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String fileName = new String("文件名.xls".getBytes(), "iso-8859-1");
		InputStream is = service.createExcel();//TODO 本身實現
		// 設置response參數,能夠打開下載頁面
		response.reset();
		response.setContentType("application/vnd.ms-excel;charset=utf-8");
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
		ServletOutputStream out = response.getOutputStream();
		try (
			BufferedInputStream bis = new BufferedInputStream(is);
			BufferedOutputStream bos = new BufferedOutputStream(out);
		) {
			byte[] buff = new byte[2048];
			int bytesRead;
			// Simple read/write loop.
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (final IOException e) {
			throw e;
		} 
	}
相關文章
相關標籤/搜索