简单封装POI导出excel

简单封装POI导出excel

Apache POI是一套根据Office Open XML标准(OOXML)和Microsoft OLE 2复合文档格式(OLE2)来处理各种文件格式的Java API,在应用中经常用来和Microsoft Office系列产品对接,在和excel对接是,需要处理excel繁琐的单元格,下面提供一个在Spring环境下导出excel的简单框架,减少对单元格的繁琐处理,减少重复搬砖,提高开发效率。

1. 依赖

	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi</artifactId>
		<version>3.14</version>
	</dependency>
	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi-ooxml</artifactId>
		<version>3.14</version>
	</dependency>

2. Excel导出配置

1) 导出excel的样式、数据配置文件

导出excel时,主要逻辑无非是将数据填充到excel单元格中,再设置单元格样式,封装POIexcel单元格的操作,只需要定义预先约定的配置文件,封装类再解析配置文件,得到被导出excel每行、每个单元格的数据,操作单元格,最后生成excel文件,返回给用户。

下面是约定的简单配置

<?xml version="1.0" encoding="UTF-8"?>
<excel name="export.xls">
	<sheet data-list="data1" desc="" field="examName">
		<title desc="" field="examName" border="thin" height="40" background-color="41" align="center" v-align="center" wrap="true" bold="bold" font-size="25" font-color="12" font-name="黑体"></title>
		<headers border="thin" height="25" background-color="43" align="center" v-align="center" wrap="true" bold="bold" font-size="20" font-name="宋体" >
			<column header="名称" field="examName" type="String" border="thin" width="30" height="20" background-color="" align="center" v-align="top" wrap="true" bold="" font-size="18" font-name="宋体"></column>
			<column header="测试1" field="schoolYear" type="String" border="thin" width="20" height="20" background-color="" align="right" v-align="center" wrap="true" bold="" font-size="18" font-name="宋体"></column>
			<column header="测试2" field="term" type="String" border="thin" width="40" height="20" background-color="" align="left" v-align="" wrap="bottom" bold="true" font-size="18" font-name="隶书"></column>
		</headers>
	</sheet>
	<sheet data-list="data1" desc="11111" field="examName">
		<title desc="but" field="examName" border="thin" height="40" background-color="41" align="center" v-align="center" wrap="true" bold="bold" font-size="25" font-color="12" font-name="黑体"></title>
		<headers border="thin" height="25" background-color="43" align="center" v-align="center" wrap="true" bold="bold" font-size="20" font-name="宋体" >
			<column header="名称" field="examName" type="String" border="thin" width="30" height="20" background-color="" align="center" v-align="top" wrap="true" bold="" font-size="18" font-name="宋体"></column>
			<column header="测试1" field="schoolYear" type="String" border="thin" width="20" height="20" background-color="" align="right" v-align="center" wrap="true" bold="" font-size="18" font-name="宋体"></column>
			<column header="测试2" field="term" type="String" border="thin" width="40" height="20" background-color="" align="left" v-align="" wrap="bottom" bold="true" font-size="18" font-name="隶书"></column>
		</headers>
	</sheet>
</excel>

2) 配置解析器

配置解析器ExcelConfigHelper负责解析导出配置,生成程序可读的导出excel配置ExcelConfigVO对象

public class ExcelConfigHelper {
	public static ExcelConfigVO GetExcelConfig(String configPath) {
		ExcelConfigVO config = new ExcelConfigVO();
		SAXReader reader = new SAXReader();
		try {
			Document doc = reader.read(new File(configPath));
			Element root = doc.getRootElement();

			config.setName(root.attributeValue("name"));

			List<SheetConfigVO> sheetList = new ArrayList<SheetConfigVO>();
			config.setSheetList(sheetList);

			Iterator<Element> si = root.elementIterator();
			while (si.hasNext()) {
				Element se = si.next();

				SheetConfigVO sc = new SheetConfigVO();
				sheetList.add(sc);

				sc.setDataList(se.attributeValue("data-list"));
				sc.setDesc(se.attributeValue("desc"));
				sc.setField(se.attributeValue("field"));

				Element te = se.element("title");
				if (null != te) {
					sc.setTitleStyle(getStyleConfig(te));
				}

				Element he = se.element("headers");
				if (null != he) {
					sc.setHeaderStyle(getStyleConfig(he));
				}
				List<ColumnConfigVO> columnList = new ArrayList<ColumnConfigVO>();
				sc.setColumnList(columnList);
				Iterator<Element> ci = he.elementIterator();
				while (ci.hasNext()) {

					Element ce = ci.next();
					ColumnConfigVO cc = getColumnConfig(ce);
					columnList.add(cc);

				}
			}
		} catch (DocumentException e) {

			e.printStackTrace();
		}
		return config;
	}

	private static StyleConfigVO getStyleConfig(Element e) {
		StyleConfigVO style = new StyleConfigVO();
		style.setField(e.attributeValue("field"));
		style.setDesc(e.attributeValue("desc"));
		style.setBorder(e.attributeValue("border"));
		style.setWidth(e.attributeValue("width"));
		style.setHeight(e.attributeValue("height"));
		style.setBgcolor(e.attributeValue("background-color"));
		style.setAlign(e.attributeValue("align"));
		style.setValign(e.attributeValue("v-align"));
		style.setWrap(e.attributeValue("wrap"));
		style.setBold(e.attributeValue("bold"));
		style.setFontSize(e.attributeValue("font-size"));
		style.setFontName(e.attributeValue("font-name"));
		style.setFontColor(e.attributeValue("font-color"));
		return style;
	}

	private static ColumnConfigVO getColumnConfig(Element e) {
		ColumnConfigVO c = new ColumnConfigVO();
		c.setField(e.attributeValue("field"));
		c.setHeader(e.attributeValue("header"));

		StyleConfigVO style = getStyleConfig(e);
		c.setStyle(style);
		return c;
	}
}

Excel配置类

ExcelConfigVO

public class ExcelConfigVO implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6669292508345659358L;

	private String name;

	private List<SheetConfigVO> sheetList;

SheetConfigVO

public class SheetConfigVO implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7809672890306591286L;

	private String dataList;

	private String desc;

	private String field;

	private StyleConfigVO titleStyle;

	private StyleConfigVO headerStyle;

	private List<ColumnConfigVO> columnList;

StyleConfigVO 

public class StyleConfigVO implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2747357536186545711L;

	private String desc;

	private String field;

	private String border;

	private String width;

	private String height;

	private String bgcolor;

	private String align;

	private String valign;

	private String wrap;

	private String bold;

	private String fontSize;

	private String fontName;

	private String fontColor;

ColumnConfigVO 

public class ColumnConfigVO implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5303919948113915294L;

	private String header;

	private String field;

	private StyleConfigVO style;

3. 根据配置和数据生成excel

Excel生成器ExcelExportHelper根据配置和数据生成excel


public class ExcelExportHelper {

	private static final Logger log = LoggerFactory.getLogger(ExcelExportHelper.class);

	public static HSSFWorkbook export(Map<String, Object> map, ExcelConfigVO config) {
		try {

			HSSFWorkbook hw = new HSSFWorkbook();

			int sheetIndex = 1;
			for (SheetConfigVO sc : config.getSheetList()) {

				// dataList数据集合,desc是sheet名称,field是sheet名称在数据集合中的字段,后面二者取一个
				String dataList = sc.getDataList();
				String desc = sc.getDesc();
				String field = sc.getField();
				List<Object> datas = (List<Object>) map.get(dataList);

				if (StringUtils.isEmpty(desc) && !CollectionUtils.isEmpty(datas) && !StringUtils.isEmpty(field)) {
					Object obj = datas.get(0);
					Field f = obj.getClass().getDeclaredField(field);
					f.setAccessible(true);
					desc = (String) f.get(obj);
				}

				if (StringUtils.isEmpty(desc)) {
					desc = "sheet" + sheetIndex;
				}

				HSSFSheet sheet = hw.createSheet(desc);

				if (null != sc.getTitleStyle()) {
					StyleConfigVO ts = sc.getTitleStyle();
					String tdesc = ts.getDesc();
					String tfield = ts.getField();

					if (StringUtils.isEmpty(tdesc) && !CollectionUtils.isEmpty(datas) && !StringUtils.isEmpty(tfield)) {
						Object obj = datas.get(0);
						Field f = obj.getClass().getDeclaredField(tfield);
						f.setAccessible(true);
						tdesc = (String) f.get(obj);
					}

					if (StringUtils.isEmpty(tdesc)) {
						tdesc = "title" + sheetIndex;
					}

					HSSFCellStyle titleStyle = getCellStyle(hw, ts);
					int rindex = 0;
					HSSFRow row = sheet.createRow(rindex++);
					if (!StringUtils.isEmpty(ts.getHeight())) {
						row.setHeightInPoints(Short.valueOf(ts.getHeight()));
					}
					HSSFCell cell = row.createCell(0);
					cell.setCellStyle(titleStyle);
					cell.setCellType(HSSFCell.CELL_TYPE_STRING);
					cell.setCellValue(desc);
					if (!CollectionUtils.isEmpty(sc.getColumnList()) && sc.getColumnList().size() > 1) {
						for (int i = 1; i < sc.getColumnList().size(); i++) {
							cell = row.createCell(i);
							cell.setCellStyle(titleStyle);
							cell.setCellType(HSSFCell.CELL_TYPE_STRING);
							cell.setCellValue("");
						}
						CellRangeAddress merge = new CellRangeAddress(rindex - 1, rindex - 1, 0,
								sc.getColumnList().size() - 1);
						sheet.addMergedRegion(merge);
					}

					StyleConfigVO hs = sc.getHeaderStyle();
					HSSFCellStyle headerstyle = getCellStyle(hw, hs);
					row = sheet.createRow(rindex++);
					if (!StringUtils.isEmpty(hs.getHeight())) {
						row.setHeightInPoints(Short.valueOf(hs.getHeight()));
					}

					Map<Integer, HSSFCellStyle> styleMap = new HashMap<Integer, HSSFCellStyle>();
					if (!CollectionUtils.isEmpty(sc.getColumnList())) {
						for (int i = 0; i < sc.getColumnList().size(); i++) {
							ColumnConfigVO column = sc.getColumnList().get(i);
							styleMap.put(i, getCellStyle(hw, column.getStyle()));

							cell = row.createCell(i);
							cell.setCellStyle(headerstyle);
							cell.setCellType(HSSFCell.CELL_TYPE_STRING);
							cell.setCellValue(column.getHeader());
							if (null != column.getStyle() && !StringUtils.isEmpty(column.getStyle().getWidth())) {
								sheet.setColumnWidth(i, Short.valueOf(column.getStyle().getWidth()) * 256);
							}

						}
					}

					for (Object obj : datas) {
						row = sheet.createRow(rindex++);
						for (int i = 0; i < sc.getColumnList().size(); i++) {

							ColumnConfigVO column = sc.getColumnList().get(i);

							if (i == 0 && !StringUtils.isEmpty(column.getStyle().getHeight())) {

								row.setHeightInPoints(Short.valueOf(column.getStyle().getHeight()));
							}
							styleMap.put(i, getCellStyle(hw, column.getStyle()));

							cell = row.createCell(i);
							cell.setCellStyle(styleMap.get(i));
							cell.setCellType(HSSFCell.CELL_TYPE_STRING);
							String val = "";
							Field f = obj.getClass().getDeclaredField(column.getField());
							f.setAccessible(true);
							val = (String) f.get(obj);
							cell.setCellValue(null == val ? "" : val);
						}
					}
				}

				sheetIndex++;
			}

			return hw;
		} catch (NoSuchFieldException e) {

			log.error("", e);
		} catch (SecurityException e) {

			log.error("", e);
		} catch (IllegalArgumentException e) {

			log.error("", e);
		} catch (IllegalAccessException e) {

			log.error("", e);
		}
		return null;
	}

	private static HSSFCellStyle getCellStyle(HSSFWorkbook hw, StyleConfigVO ts) {
		HSSFCellStyle titlestyle = hw.createCellStyle();
		HSSFFont titlefont = hw.createFont();

		if (!StringUtils.isEmpty(ts.getBold()) && "BOLD".equalsIgnoreCase(ts.getBold().trim())) {
			titlefont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
		}

		if (!StringUtils.isEmpty(ts.getFontName())) {
			titlefont.setFontName(ts.getFontName().trim());
		}

		if (!StringUtils.isEmpty(ts.getFontSize())) {
			titlefont.setFontHeightInPoints(Short.valueOf(ts.getFontSize()));
		}

		if (!StringUtils.isEmpty(ts.getFontColor())) {
			titlefont.setColor(Short.valueOf(ts.getFontColor()));
		}
		titlestyle.setFont(titlefont);

		if (!StringUtils.isEmpty(ts.getBorder())) {
			if ("THIN".equalsIgnoreCase(ts.getBorder().trim())) {
				titlestyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
				titlestyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
				titlestyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
				titlestyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
			} else if ("NONE".equalsIgnoreCase(ts.getBorder().trim())) {
				titlestyle.setBorderBottom(HSSFCellStyle.BORDER_NONE);
				titlestyle.setBorderLeft(HSSFCellStyle.BORDER_NONE);
				titlestyle.setBorderRight(HSSFCellStyle.BORDER_NONE);
				titlestyle.setBorderTop(HSSFCellStyle.BORDER_NONE);
			} else if ("DOUBLE".equalsIgnoreCase(ts.getBorder().trim())) {
				titlestyle.setBorderBottom(HSSFCellStyle.BORDER_DOUBLE);
				titlestyle.setBorderLeft(HSSFCellStyle.BORDER_DOUBLE);
				titlestyle.setBorderRight(HSSFCellStyle.BORDER_DOUBLE);
				titlestyle.setBorderTop(HSSFCellStyle.BORDER_DOUBLE);
			} else if ("DOTTED".equalsIgnoreCase(ts.getBorder().trim())) {
				titlestyle.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);
				titlestyle.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);
				titlestyle.setBorderRight(HSSFCellStyle.BORDER_DOTTED);
				titlestyle.setBorderTop(HSSFCellStyle.BORDER_DOTTED);
			} else if ("DASHED".equalsIgnoreCase(ts.getBorder().trim())) {
				titlestyle.setBorderBottom(HSSFCellStyle.BORDER_DASHED);
				titlestyle.setBorderLeft(HSSFCellStyle.BORDER_DASHED);
				titlestyle.setBorderRight(HSSFCellStyle.BORDER_DASHED);
				titlestyle.setBorderTop(HSSFCellStyle.BORDER_DASHED);
			} else if ("MEDIUM".equalsIgnoreCase(ts.getBorder().trim())) {
				titlestyle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM);
				titlestyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
				titlestyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
				titlestyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
			}
		}

		if (!StringUtils.isEmpty(ts.getAlign())) {
			String align = ts.getAlign().toUpperCase().trim();
			switch (align) {
			case "CENTER":
				titlestyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
			case "LEFT":
				titlestyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);
			case "RIGHT":
				titlestyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
			case "FILL":
				titlestyle.setAlignment(HSSFCellStyle.ALIGN_FILL);
			case "GENERAL":
				titlestyle.setAlignment(HSSFCellStyle.ALIGN_GENERAL);
			default:
				titlestyle.setAlignment(HSSFCellStyle.ALIGN_JUSTIFY);
			}

		}

		if (!StringUtils.isEmpty(ts.getValign())) {
			String valign = ts.getValign().toUpperCase().trim();
			switch (valign) {
			case "CENTER":
				titlestyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
			case "BOTTOM":
				titlestyle.setAlignment(HSSFCellStyle.VERTICAL_BOTTOM);
			case "TOP":
				titlestyle.setAlignment(HSSFCellStyle.VERTICAL_TOP);
			default:
				titlestyle.setAlignment(HSSFCellStyle.VERTICAL_JUSTIFY);
			}

		}

		if (!StringUtils.isEmpty(ts.getBgcolor())) {
			titlestyle.setFillForegroundColor(Short.valueOf(ts.getBgcolor()));
			titlestyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
		}

		if (!StringUtils.isEmpty(ts.getWrap())) {
			titlestyle.setWrapText(Boolean.valueOf(ts.getWrap()));
		}

		return titlestyle;
	}

	public static String getFileName(String fileName, ExcelConfigVO config) {
		if (StringUtils.isEmpty(fileName)) {
			fileName = config.getName();
		}

		if (StringUtils.isEmpty(fileName)) {
			fileName = "export.xls";
		}
		return fileName;
	}
}

4. 导出逻辑

1) 获取导出任务

导出任务接口,导出特定数据时需要实现接口,给配置解析器提供特定的配置,给excel生成器提供特定的数据。

public interface IExcelExportProcessor {

	/**
	 * 配置文件路径
	 * 
	 * @return
	 */
	public String getConfigPath();

	/**
	 * 导出文件名
	 * 
	 * @return
	 */
	public String getFilename();

	/**
	 * 查询数据
	 * 
	 * @param queryMap
	 *            查询参数
	 * @return 导出数据
	 */
	public Map<String, Object> getDatas(Map<String, Object> queryMap);
}

导出任务实现样例

@Component("excelExport.seat")
public class ExportSeatProcessor implements IExcelExportProcessor {

	private static final Logger log = LoggerFactory.getLogger(ExportSeatProcessor.class);

	@Override
	public String getConfigPath() {

		return "";
	}

	@Override
	public String getFilename() {

		return null;
	}

	@Override
	public Map<String, Object> getDatas(Map<String, Object> queryMap) {

		return null;
	}

}

2) 导出接口

导出接口根据请求参数得到导出任务Bean和数据请求参数,通过导出任务Bean获取导出配置,数据,导出文件名,再调用配置解析器,excel生成器,生成excel并返回。

RequestMapping(value = "/export", method = RequestMethod.GET)
	public void test(HttpServletRequest req, HttpServletResponse res) throws IOException {
		String processorName = req.getParameter("processor");

		if (StringUtils.isEmpty(processorName)) {
			res.getWriter().println("parameter error!");
			return;
		}

		IExcelExportProcessor processor = (IExcelExportProcessor) ExcelExportContext.getApplicationContext()
				.getBean(processorName);
		if (null == processor) {
			res.getWriter().println("parameter error!");
			return;
		}

		Map<String, Object> queryMap = getParameterMap(req);
		String fileName = processor.getFilename();
		String configPath = processor.getConfigPath();
		Map<String, Object> map = processor.getDatas(queryMap);

		ExcelConfigVO config = ExcelConfigHelper.GetExcelConfig(configPath);
		fileName = ExcelExportHelper.getFileName(fileName, config);

		HSSFWorkbook hw = ExcelExportHelper.export(map, config);
		res.setContentType("application/octet-stream");
		res.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO-8859-1"));
		OutputStream out = null;
		try {

			out = res.getOutputStream();
			hw.write(out);
		} catch (IOException e) {

			log.error("export excel error", e);
		} finally {
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				log.error("export excel error", e);
			}

		}
	}

http GET请求 url?processorName=xxx&name=xxx$yyy=xxx,增加导出数据查询参数,即可导出excel。


猜你喜欢

转载自blog.csdn.net/weihao_/article/details/76473089