poi实现通用excel导出

本实例通过poi实现excel导出,实现会员数据的excle下载

0.导入maven依赖

		<!-- POI相关的包 -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.9</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.9</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.9</version>
		</dependency>

1.新建个实体SharedMember

/**
 */
package com.sml.sz.supplier.pojo;

import com.sml.sz.ExceVo;
import com.sml.sz.common.persistence.NewDataEntity;
import org.hibernate.validator.constraints.Length;

import java.util.Date;

/**
 * 会员共享Entity
 * 
 * @author xxx
 * @version 2018-10-15
 */
public class SharedMember{

	private static final long serialVersionUID = 1L;

	@ExceVo(name = "编号", sort = 1)
	private String number; // 编号

	@ExceVo(name = "姓名", sort = 2)
	private String name; // 姓名

	@ExceVo(name = "账号", sort = 3)
	private String account; // 账号

	@ExceVo(name = "来源", sort = 4)
	private String source; // 来源

	private String code; // 平台唯一编码

	@ExceVo(name = "添加时间", sort = 5)
	private Date createDate;// 添加时间

	public SharedMember() {
		super();
	}

	public SharedMember(String id) {
		super(id);
	}

	@Length(min = 1, max = 64, message = "编号长度必须介于 1 和 64 之间")
	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	@Length(min = 1, max = 255, message = "姓名长度必须介于 1 和 255 之间")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Length(min = 1, max = 64, message = "账号长度必须介于 1 和 64 之间")
	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	@Length(min = 1, max = 255, message = "来源长度必须介于 1 和 255 之间")
	public String getSource() {
		return source;
	}

	public void setSource(String source) {
		this.source = source;
	}

	@Length(min = 1, max = 30, message = "平台唯一编码长度必须介于 1 和 30 之间")
	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	@Override
	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(String date) {
		this.createDate = super.createDate;
	}

}

2.新建注解ExceVo

package com.sml.sz;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.TYPE })
public @interface ExceVo {

	/** 对应的列名称 */
	String name() default "";

	/** 列序号 */
	int sort();

	/** 字段类型对应的格式 */
	String format() default "";

	/** 是否需要校验 */
	boolean isCheck() default false;

	/** 校验字段长度 */
	int fieldLength() default 50;

	/** 校验是否可以为空 */
	boolean isEmpty() default true;
}

3.新建一个TestController

package com.sml.sz.supplier.controller;

import com.sml.sz.ExcelExportUtil;
import com.sml.sz.supplier.common.Message;
import com.sml.sz.supplier.pojo.SharedMember;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @author xxx
 * @ClassName TestController
 * @Description: todo
 * @date 2020/7/3 17:05
 * @Version 1.0
 */
public class TestController {

    /**
     * 会员导出
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "export", method = { RequestMethod.POST, RequestMethod.GET })
    public void list(HttpServletResponse response) throws IOException {
        response.setContentType("application/binary;charset=ISO8859_1");
        ServletOutputStream outputStream = response.getOutputStream();
        String fileName = new String(("会员列表").getBytes(), "ISO8859_1");
        // 组装附件名称和格式
        response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xlsx");
        //这里替换成自己的list就行
        List<SharedMember> sharedMembers = sharedMemberService.findList(new SharedMember());
        ExcelExportUtil<SharedMember> excelUtil = new ExcelExportUtil<SharedMember>(SharedMember.class);
        excelUtil.export(sharedMembers, outputStream);
    }
}

4.新建 ExcelExportUtil

package com.sml.sz;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.xssf.usermodel.*;

import javax.servlet.ServletOutputStream;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class ExcelExportUtil<T> {

	private Class claze;

	public ExcelExportUtil(Class claze) {
		this.claze = claze;
	}

	/**
	 * 基于注解导出 不需要自己封装每列的值
	 * 
	 * @param fileName
	 *            模板名称
	 * @param objs
	 *            导出实体集合
	 * @param rowIndex
	 *            excel第几行开始导出
	 */
	public void export(List<T> objs, ServletOutputStream outputStream) {
		// 带注解并排序好的字段
		List<Field> fieldList = getFieldList();
		// 创建一个workbook 对应一个excel应用文件
		XSSFWorkbook workBook = new XSSFWorkbook();
		// 在workbook中添加一个sheet,对应Excel文件中的sheet
		XSSFSheet sheet = workBook.createSheet("Sheet1");
		XSSFCellStyle headStyle = getHeadStyle(workBook);
		XSSFCellStyle bodyStyle = getBodyStyle(workBook);
		try {
			// 构建表头
			XSSFRow headRow = sheet.createRow(0);
			XSSFCell cell = null;
			for (int i = 0; i < fieldList.size(); i++) {
				cell = headRow.createCell(i);
				cell.setCellStyle(headStyle);
				Field field = fieldList.get(i);
				cell.setCellValue(getExcelHead(field));
			}
			// 构建表体数据
			for (int j = 0; j < objs.size(); j++) {
				XSSFRow bodyRow = sheet.createRow(j + 1);
				T t = objs.get(j);
				Class clazz = t.getClass();
				for (int k = 0; k < fieldList.size(); k++) {
					Field field = fieldList.get(k);
					PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
					// 获取值之前先把日期类型转化成string
					Map<String, Boolean> map = covertAttrType(field, t);
					Method getMethod = pd.getReadMethod();
					if (getMethod != null) {
						cell = bodyRow.createCell(k);
						cell.setCellStyle(bodyStyle);
						for (Map.Entry<String, Boolean> entry : map.entrySet()) {
							// 日期类型
							if (entry.getValue() == true) {
								cell.setCellValue(entry.getKey());
							} else {
								String stringCell=getMethod.invoke(t) == null ? "" : getMethod.invoke(t) + "";
								if(!StringUtils.isBlank(stringCell)){
									//如果excel内容是网络地址,需要单独处理,否则打不开excel
									if(stringCell.contains("https")){
										// 使用creationHelpper来创建XSSFHyperlink对象
										CreationHelper createHelper = workBook.getCreationHelper();
										XSSFHyperlink  link = (XSSFHyperlink) createHelper.createHyperlink(Hyperlink.LINK_URL);
										link.setAddress(stringCell);
										// 设置超链接
										cell.setHyperlink(link);
									}
									cell.setCellValue(stringCell);
								}
							}
						}
					}
				}
			}
			workBook.write(outputStream);
			outputStream.flush();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			try {
				outputStream.close();
			}
			catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 设置表头的单元格样式
	 * 
	 * @return
	 */
	public XSSFCellStyle getHeadStyle(XSSFWorkbook wb) {
		// 创建单元格样式
		XSSFCellStyle cellStyle = wb.createCellStyle();
		// 设置单元格的背景颜色为淡蓝色
		cellStyle.setFillForegroundColor(HSSFColor.PALE_BLUE.index);
		cellStyle.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
		// 设置单元格居中对齐
		cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		// 设置单元格垂直居中对齐
		cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		// 创建单元格内容显示不下时自动换行
		cellStyle.setWrapText(true);
		// 设置单元格字体样式
		XSSFFont font = wb.createFont();
		// 设置字体加粗
		font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("宋体");
		font.setFontHeight((short) 200);
		cellStyle.setFont(font);
		// 设置单元格边框为细线条
		cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);
		cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);
		cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);
		cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);
		return cellStyle;
	}

	/**
	 * 设置表体的单元格样式
	 * 
	 * @return
	 */
	public XSSFCellStyle getBodyStyle(XSSFWorkbook wb) {
		// 创建单元格样式
		XSSFCellStyle cellStyle = wb.createCellStyle();
		// 设置单元格居中对齐
		cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
		// 设置单元格垂直居中对齐
		cellStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
		// 创建单元格内容显示不下时自动换行
		cellStyle.setWrapText(true);
		// 设置单元格字体样式
		XSSFFont font = wb.createFont();
		// 设置字体加粗
		font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
		font.setFontName("宋体");
		font.setFontHeight((short) 200);
		cellStyle.setFont(font);
		// 设置单元格边框为细线条
		cellStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);
		cellStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);
		cellStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);
		cellStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);
		return cellStyle;
	}

	/**
	 * 获取带注解的字段 并且排序
	 * 
	 * @return
	 */
	private List<Field> getFieldList() {
		Field[] fields = getAllFields(this.claze);
		// 无序
		List<Field> fieldList = new ArrayList<Field>();
		// 排序后的字段
		List<Field> fieldSortList = new LinkedList<Field>();
		int length = fields.length;
		int sort = 0;
		Field field = null;
		// 获取带注解的字段
		for (int i = 0; i < length; i++) {
			field = fields[i];
			if (field.isAnnotationPresent(ExceVo.class)) {
				fieldList.add(field);
			}
		}
		// Assert.assertNotNull("未获取到需要导出的字段", fieldList);
		length = fieldList.size();
		for (int i = 1; i <= length; i++) {
			for (int j = 0; j < length; j++) {
				field = fieldList.get(j);
				ExceVo exceVo = field.getAnnotation(ExceVo.class);
				field.setAccessible(true);
				sort = exceVo.sort();
				if (sort == i) {
					fieldSortList.add(field);
					continue;
				}
			}
		}
		return fieldSortList;
	}

	/**
	 * 获取所有属性包括父类
	 * 
	 * @param object
	 * @return
	 */
	public static Field[] getAllFields(Class clazz) {
		List<Field> fieldList = new ArrayList<>();
		while (clazz != null) {
			fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
			clazz = clazz.getSuperclass();
		}
		Field[] fields = new Field[fieldList.size()];
		fieldList.toArray(fields);
		return fields;
	}

	/**
	 * 类型转换把date类型转为String
	 */
	public Map<String, Boolean> covertAttrType(Field field, T obj) {
		Map<String, Boolean> map = new HashMap<String, Boolean>();
		try {
			if (field.get(obj) == null) {
				map.put("", false);
				return map;
			}
			String type = field.getType().getSimpleName();
			if ("Date".equals(type)) {
				map.put(DateFormatUtils.format((Date) field.get(obj), "yyyy-MM-dd HH:mm:ss"), true);
				return map;
			} else {
				map.put(field.get(obj).toString(), false);
				return map;
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取excel表头信息
	 */
	public String getExcelHead(Field field) {
		if (null == field) {
			return null;
		}
		ExceVo exceVo = field.getAnnotation(ExceVo.class);
		return exceVo.name();
	}

}

5.大功告成~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值