springMVC導出excel - poi操做

1.說明

須要導出excel,沒有想到springMVC已經將poi匹配進來,表示贊前端

2.poi的mavn

<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-excelant</artifactId>
  <version>xxx</version>
</dependency>

3.繼承視圖類

在org.springframework.web.servlet.view.document包下有不少的類,我這裏考慮到兼容因此繼承AbstractXlsViewjava

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.tools.ant.util.DateUtils;
import org.springframework.web.servlet.view.document.AbstractXlsView;

public class ExportExcelView extends AbstractXlsView {
	/**
	 * 填充的數據
	 */
	public static String DATA_LIST = "dataList";
	/**
	 * 標題頭,定義的內容爲LinkedHashMap<String, String><br>
	 * 示例:LinkedHashMap<"name", "名字">
	 */
	public static String TITLE_MAP = "titleMap";

	@Override
	protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		response.setHeader("content-disposition", "attachment;filename=export.xls");
		@SuppressWarnings("rawtypes")
		List datas = (List) model.get(DATA_LIST);
		// 獲取頭
		@SuppressWarnings("unchecked")
		LinkedHashMap<String, String> titles = (LinkedHashMap<String, String>) model.get(TITLE_MAP);
		// 建立一個工做表sheet
		Sheet sheet = workbook.createSheet("導出數據");
		if (null == datas || datas.isEmpty()) {
			// 空數據
			if (null != titles && !titles.isEmpty()) {
				// 有標題
				this.writeTitle(sheet, titles);
			}
			return;
		}

		if (null == titles || titles.isEmpty()) {
			titles = this.getTitle(datas.get(0));
		}

		this.writeTitle(sheet, titles);
		this.writeDataList(sheet, titles, datas);

	}

	/**
	 * 寫title
	 */
	private void writeTitle(Sheet sheet, LinkedHashMap<String, String> titles) {
		Row row = sheet.createRow(0);
		Cell cell = null;
		int i = 0;
		for (Entry<String, String> entry : titles.entrySet()) {
			cell = row.createCell(i);
			cell.setCellValue(entry.getValue());
			i++;
		}
	}

	/**
	 * 寫dataList
	 */
	private void writeDataList(Sheet sheet, LinkedHashMap<String, String> titles,
			@SuppressWarnings("rawtypes") List Datas) {

		Row row;
		Class<? extends Object> class1;
		Cell cell;
		Method method;

		int i = 1;
		for (Object object : Datas) {
			class1 = object.getClass();
			row = sheet.createRow(i++);
			int y = 0;
			for (Entry<String, String> entry : titles.entrySet()) {
				cell = row.createCell(y++);
				// 反射獲取其值
				try {
					method = class1.getDeclaredMethod("get" + toUpperCase4Index(entry.getKey()));
					Object invoke = method.invoke(object);
					cell.setCellValue(formatValue(invoke));
				} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
						| InvocationTargetException e) {
					// e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 格式化數據值
	 * 
	 * @param invoke
	 * @return
	 */
	private String formatValue(Object invoke) {

		if (invoke instanceof Date) {
			Date new_name = (Date) invoke;
			return DateUtils.format(new_name, "yyyy-MM-dd HH:mm:ss");
		}

		return invoke + "";
	}

	/**
	 * 獲取屬性名稱爲標題
	 * 
	 * @param object
	 * @return
	 */
	private LinkedHashMap<String, String> getTitle(Object object) {
		LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<>();
		Class<? extends Object> class1 = object.getClass();
		Field[] declaredFields = class1.getDeclaredFields();
		@SuppressWarnings("unused")
		Method method;
		for (Field field : declaredFields) {
			String fieldName = field.getName();
			try {
				method = class1.getDeclaredMethod("get" + toUpperCase4Index(fieldName));
				// 若是不存在公開的get方法,則不加入標題
				linkedHashMap.put(fieldName, fieldName);
			} catch (NoSuchMethodException | SecurityException e) {
				// TODO Auto-generated catch block
				// e.printStackTrace();
			}

		}
		return linkedHashMap;
	}

	/**
	 * 首字母大寫
	 * 
	 * @param string
	 * @return
	 */
	private String toUpperCase4Index(String string) {
		char[] methodName = string.toCharArray();
		methodName[0] = toUpperCase(methodName[0]);
		return String.valueOf(methodName);
	}

	/**
	 * 字符轉成大寫
	 * 
	 * @param chars
	 * @return
	 */
	private char toUpperCase(char chars) {
		if (97 <= chars && chars <= 122) {
			chars ^= 32;
		}
		return chars;
	}

}

4.使用

在springMVC的方法中返回ModelAndViewweb

ModelAndView ret = new ModelAndView();
		ret.setView(new ExportExcelView());
		ret.getModel().put(ExportExcelView.DATA_LIST, blogList);
		return ret;

5.總結

我在ExportExcelView 中使用了反射,斷言,只導出public的屬性,title能夠配合前端指定須要導出的屬性,比較適合大部分場景。後期想加入導出查詢的條件,再就是使用註解相似@requestBody這樣子的,若是你有想法和建議,但願你願意和我分享spring

相關文章
相關標籤/搜索