springMVC导出excel - poi操作

原创
2016/12/27 15:40
阅读数 325

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包下有很多的类,我这里考虑到兼容所以继承AbstractXlsView

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的方法中返回ModelAndView

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

5.总结

我在ExportExcelView 中使用了反射,断言,只导出public的属性,title可以配合前端指定需要导出的属性,比较适合大部分场景。后期想加入导出查询的条件,再就是使用注解类似@requestBody这样子的,如果你有想法和建议,希望你愿意和我分享

展开阅读全文
打赏
0
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部