一、POI导出报表要用到的包

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

二、POI常用类说明

class

declare

HSSFWorkbook

Excel的文档对象(考虑到对以前老版本格式为.xls的excel的兼容性,以下的实例用HSSF,而不采用XSSF)

HSSFSheet

Excel中的表单

HSSFRow

Excel中的行

HSSFCell

Excel中的元素单元

HSSFFont

Excel元素的字体

HSSFDataFormat

格子单元的日期格式

HSSFHeader

Excel文档工作表的页眉

HSSFFooter

Excel文档表的页脚

HSSFCellStyle

格子单元样式(HSSF对应旧的xls格式,XSSF对应新的xlsx格式,SXSSF是在XSSF的基础上,支持导出大批量的excel数据。)【POI HSSFColor 颜色索引对照表】

HSSFDateUtil


日期

HSSFPrintSetup

打印

POI快速入门教程,POI有三种API

  • POI-HSSF,HSSF是POI项目的Excel '97-2007’文件格式的纯Java实现
  • POI-XSSF,XSSF是POI Project的Excel 2007 OOXML(.xlsx)文件格式的纯Java实现
  • SXSSF,3.8-beta3以来,SXSSF是XSSF的API兼容流式扩展,用于在必须生成非常大的电子表格时使用,并且堆空间有限。

简单的说,HSSF对应旧的xls格式,XSSF对应新的xlsx格式,SXSSF是在XSSF的基础上,支持导出大批量的excel数据。

要使用POI,要知道以下关键代码

//创建工作簿,对应整个xlsx文件
XSSFWorkbook workbook = new XSSFWorkbook();

//创建sheet,对应excel的单个sheet
XSSFSheet sheet = workbook.createSheet("sheet1");

//创建行,对应excel中的一行
XSSFRow row = sheet.createRow(0)

//创建单元格,对应row中的一格
XSSFCell cell = row.createCell(0);

//单元格设置值
cell.setCellValue("cell");

//单元格设置样式
cell.setCellStyle(style);

其中style要从workbook中创建,简单的style示例

XSSFCellStyle style = workbook.createCellStyle();
//居中
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
//border
style.setBorderLeft(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
style.setBorderRight(BorderStyle.THIN);
style.setBorderBottom(BorderStyle.THIN);

将workbook保存到文件

FileOutputStream file = new FileOutputStream("example.xlsx");
workbook.write(file);
file.close();

三、简单示例

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;


/**
 * 导出报表工具类
 */
public class ExportExcelUtil {
    /**
     *
     * @param title 标题
     * @param headers  表头
     * @param values  表中元素
     * @return
     */
    public static HSSFWorkbook getHSSFWorkbook(String title, String headers[], String [][] values){

        //创建一个HSSFWorkbook,对应一个Excel文件
        HSSFWorkbook hssfWorkbook = new HSSFWorkbook();

        //在workbook中添加一个sheet,对应Excel文件中的sheet
        HSSFSheet hssfSheet = hssfWorkbook.createSheet(title);

        //创建标题合并行
        hssfSheet.addMergedRegion(new CellRangeAddress(0,(short)0,0,(short)headers.length - 1));

        //设置标题样式
        HSSFCellStyle style = hssfWorkbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);   //设置居中样式
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置标题字体
        Font titleFont = hssfWorkbook.createFont();
        titleFont.setFontHeightInPoints((short) 14);
        style.setFont(titleFont);

        //设置值表头样式 设置表头居中
        HSSFCellStyle hssfCellStyle = hssfWorkbook.createCellStyle();
        hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);   //设置居中样式
        hssfCellStyle.setBorderBottom(BorderStyle.THIN);
        hssfCellStyle.setBorderLeft(BorderStyle.THIN);
        hssfCellStyle.setBorderRight(BorderStyle.THIN);
        hssfCellStyle.setBorderTop(BorderStyle.THIN);

        //设置表内容样式
        //创建单元格,并设置值表头 设置表头居中
        HSSFCellStyle style1 = hssfWorkbook.createCellStyle();
        style1.setBorderBottom(BorderStyle.THIN);
        style1.setBorderLeft(BorderStyle.THIN);
        style1.setBorderRight(BorderStyle.THIN);
        style1.setBorderTop(BorderStyle.THIN);

        //产生标题行
        HSSFRow hssfRow = hssfSheet.createRow(0);
        HSSFCell cell = hssfRow.createCell(0);
        cell.setCellValue(title);
        cell.setCellStyle(style);



        //产生表头
        HSSFRow row1 = hssfSheet.createRow(1);
        for (int i = 0; i < headers.length; i++) {
            HSSFCell hssfCell = row1.createCell(i);
            hssfCell.setCellValue(headers[i]);
            hssfCell.setCellStyle(hssfCellStyle);
        }

        //创建内容
        for (int i = 0; i <values.length; i++){
            row1 = hssfSheet.createRow(i +2);
            for (int j = 0; j < values[i].length; j++){
                //将内容按顺序赋给对应列对象
                HSSFCell hssfCell = row1.createCell(j);
                hssfCell.setCellValue(values[i][j]);
                hssfCell.setCellStyle(style1);
            }
        }
        return hssfWorkbook;
    }
}

四、注解实现工具类

1、HSSF模式97-2007Excel

(1)标题注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * 标题注解类
 * @author tangyb
 * @date 2020/03/27
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAnnotation {
    // excel导出时标题显示的名字,如果没有设置Annotation属性,将不会被导出和导入
    public String exportName();
}
(2)数据实体类
import java.util.Date;

/**
 * 数据实体类
 * @author tangyb
 * @date 2020/03/27
 */
public class Testpojo {
    @ExcelAnnotation(exportName = "用户名")
    String username;
    @ExcelAnnotation(exportName = "登录名")
    String loginname;
    @ExcelAnnotation(exportName = "年龄")
    Integer age;
    @ExcelAnnotation(exportName = "收入")
    Long money;
    @ExcelAnnotation(exportName = "时间")
    Date createtime;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getLoginname() {
        return loginname;
    }

    public void setLoginname(String loginname) {
        this.loginname = loginname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Long getMoney() {
        return money;
    }

    public void setMoney(Long money) {
        this.money = money;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
}
(3)单元格样式
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;

/**
 * Excel单元格样式
 * @author tangyb
 * @date 2020/03/27
 */
public class ExcelStyle {
    /**
     * 表格标题单元格样式
     * @param workbook
     * @param style
     * @return
     */
    public static HSSFCellStyle setHeadStyle(HSSFWorkbook workbook, HSSFCellStyle style) {
        // 设置背景色
        style.setFillForegroundColor(HSSFColor.LIGHT_CORNFLOWER_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        // 设置边框
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
        // 设置单元格的中心水平对齐-居中
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 设置单元格的垂直对齐类型-居中
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 生成字体
        HSSFFont font = workbook.createFont();
        // 设置字体类型
        font.setFontName("微软雅黑");
        // 设置字体大小
        font.setFontHeightInPoints((short) 10);
        // 粗体字体
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;

    }

    /**
     * 表格主体单元格样式
     * @param workbook
     * @param style
     * @return
     */
    public static HSSFCellStyle setbodyStyle(HSSFWorkbook workbook, HSSFCellStyle style) {
        // 设置背景色
        // style.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
        // style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        // 设置边框
        style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 下边框
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框
        // 生成字体
        HSSFFont font = workbook.createFont();
        // 字体类型
        font.setFontName("微软雅黑");
        // 设置字体大小
        font.setFontHeightInPoints((short) 9);
        // 普通字体
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;
    }
}
(4)导入工具类
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 导入工具类
 * 
 * @author tangyb
 * @date 2020/03/27
 */
public class ImportExcel<T> {
    Class<T> clazz;

    public ImportExcel(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Collection<T> importExcel(File file, String... pattern) {
        Collection<T> dist = new ArrayList<T>();
        try {
            /**
             * 类反射得到调用方法
             */
            // 得到目标目标类的所有的字段列表
            Field filed[] = clazz.getDeclaredFields();
            // 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中
            Map<String, Method> fieldmap = new HashMap<String, Method>();
            // 循环读取所有字段
            for (int i = 0; i < filed.length; i++) {
                Field f = filed[i];
                // 得到单个字段上的Annotation
                ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
                // 如果标识了Annotationd的话
                if (exa != null) {
                    // 构造设置了Annotation的字段的Setter方法
                    String fieldname = f.getName();
                    String setMethodName = "set" + fieldname.substring(0, 1).toUpperCase()
                            + fieldname.substring(1);
                    // 构造调用的method,
                    Method setMethod = clazz.getMethod(setMethodName, new Class[] {f.getType()});
                    // 将这个method以Annotaion的名字为key来存入。
                    fieldmap.put(exa.exportName(), setMethod);
                }
            }
            /**
             * excel的解析开始
             */
            // 将传入的File构造为FileInputStream;
            FileInputStream in = new FileInputStream(file);
            // // 得到工作表
            Workbook book = null;
            try {
                book = new XSSFWorkbook(in);
            } catch (Exception ex) {
                book = new HSSFWorkbook(in);
            }
            // HSSFWorkbook book = new HSSFWorkbook(in);
            // // 得到第一页
            // HSSFSheet sheet = (HSSFSheet) book.getSheetAt(0);
            Sheet sheet = book.getSheetAt(0);
            // // 得到第一面的所有行
            Iterator<Row> row = sheet.rowIterator();

            /**
             * 标题解析
             */
            // 得到第一行,也就是标题行
            Row title = row.next();
            // 得到第一行的所有列
            Iterator<Cell> cellTitle = title.cellIterator();
            // 将标题的文字内容放入到一个map中。
            Map<Integer, String> titlemap = new HashMap<Integer, String>();
            // 从标题第一列开始
            int i = 0;
            // 循环标题所有的列
            while (cellTitle.hasNext()) {
                Cell cell = cellTitle.next();
                String value = cell.getStringCellValue();
                titlemap.put(i, value);
                i = i + 1;
            }
            /**
             * 解析内容行
             */
            // 用来格式化日期的DateFormat
            SimpleDateFormat sf;
            if (pattern.length < 1) {
                sf = new SimpleDateFormat("yyyy-MM-dd");
            } else
                sf = new SimpleDateFormat(pattern[0]);
            while (row.hasNext()) {
                // 标题下的第一行
                Row rown = row.next();

                // 行的所有列
                Iterator<Cell> cellbody = rown.cellIterator();
                // 得到传入类的实例
                T tObject = clazz.newInstance();
                int k = 0;
                // 遍历一行的列
                while (cellbody.hasNext()) {
                    Cell cell = cellbody.next();
                    // 这里得到此列的对应的标题
                    String titleString = (String) titlemap.get(k);
                    // 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值
                    if (fieldmap.containsKey(titleString)) {
                        Method setMethod = (Method) fieldmap.get(titleString);
                        // 得到setter方法的参数
                        Type[] ts = setMethod.getGenericParameterTypes();
                        // 只要一个参数
                        String xclass = ts[0].toString();
                        // 判断参数类型

                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        if (xclass.equals("class java.lang.String")) {
                            setMethod.invoke(tObject, cell.getStringCellValue());
                        } else if (xclass.equals("class java.util.Date")) {
                            setMethod.invoke(tObject, sf.parse(cell.getStringCellValue()));
                        } else if (xclass.equals("class java.lang.Boolean")) {
                            Boolean boolname = true;
                            if (cell.getStringCellValue().equals("否")) {
                                boolname = false;
                            }
                            setMethod.invoke(tObject, boolname);
                        } else if (xclass.equals("class java.lang.Integer")) {
                            setMethod.invoke(tObject, new Integer(cell.getStringCellValue()));
                        }

                        else if (xclass.equals("class java.lang.Long")) {
                            setMethod.invoke(tObject, new Long(cell.getStringCellValue()));
                        }
                    }
                    // 下一列
                    k = k + 1;
                }
                dist.add(tObject);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return dist;
    }

    public static void main(String[] args) {
        ImportExcel<Testpojo> test = new ImportExcel<Testpojo>(Testpojo.class);
        File file = new File("D:\\testOne.xls");
        Long befor = System.currentTimeMillis();
        List<Testpojo> result = (ArrayList<Testpojo>) test.importExcel(file);

        Long after = System.currentTimeMillis();
        System.out.println("此次操作共耗时:" + (after - befor) + "毫秒");
        for (int i = 0; i < result.size(); i++) {
            Testpojo testpojo = result.get(i);
            System.out.println("导入的信息为:" + testpojo.getLoginname() + "----" + testpojo.getAge()
                    + "---" + testpojo.getMoney() + "-----" + testpojo.getCreatetime());
        }

        System.out.println("共转化为List的行数为:" + result.size());
    }
}
(5)导出工具类
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;


/**
 * 导出工具类
 * @author tangyb
 * @date 2020/03/27
 */
public class ExportExcel<T> {
	//格式化日期
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * 
	 * @param title 标题
	 * @param dataset 集合
	 * @param out  输出流
	 */
	public void exportExcel(String title, Collection<T> dataset,
			OutputStream out) {
		// 声明一个工作薄
		try {
			//首先检查数据看是否是正确的
			Iterator<T> its = dataset.iterator();
			if(dataset==null||!its.hasNext()||title==null||out==null)
			{
				throw new Exception("传入的数据不对!");
			}
			//取得实际泛型类
			T ts = (T) its.next();
			Class<? extends Object> tCls = ts.getClass();
			HSSFWorkbook workbook = new HSSFWorkbook();
			// 生成一个表格
			HSSFSheet sheet = workbook.createSheet(title);
			// 设置表格默认列宽度为15个字节
			sheet.setDefaultColumnWidth(15);
			// 生成一个样式
			HSSFCellStyle style = workbook.createCellStyle();
			// 设置标题样式
			style = ExcelStyle.setHeadStyle(workbook, style);
			
			// 生成一个样式
            HSSFCellStyle style2 = workbook.createCellStyle();
            // 设置主体样式
            style2 = ExcelStyle.setbodyStyle(workbook, style2);

			// 得到所有字段
			Field filed[] = ts.getClass().getDeclaredFields();
			// 标题
			List<String> exportfieldtile = new ArrayList<String>();
			// 导出的字段的get方法
			List<Method> methodObj = new ArrayList<Method>();
			// 遍历整个filed
			for (int i = 0; i < filed.length; i++) {
				Field f = filed[i];
				ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
				// 如果设置了annottion
				if (exa != null) {
					String exprot = exa.exportName();
					// 添加到标题
					exportfieldtile.add(exprot);
					// 添加到需要导出的字段的方法
					String fieldname = f.getName();
					String getMethodName = "get"
							+ fieldname.substring(0, 1).toUpperCase()
							+ fieldname.substring(1);
					
					Method getMethod = tCls.getMethod(getMethodName,
							new Class[] {});
					
					
					methodObj.add(getMethod);
				}
			}
			// 产生表格标题行
			HSSFRow row = sheet.createRow(0);
			for (int i = 0; i < exportfieldtile.size(); i++) {
				HSSFCell cell = row.createCell(i);
				cell.setCellStyle(style);
				HSSFRichTextString text = new HSSFRichTextString(
						exportfieldtile.get(i));
				cell.setCellValue(text);
			}

	
			int index = 0;
			
			// 循环整个集合
			
			while (its.hasNext()) {
				//从第二行开始写,第一行是标题
				index++;
				row = sheet.createRow(index);
				T t = (T) its.next();
				for (int k = 0; k < methodObj.size(); k++) {
					HSSFCell cell = row.createCell(k);
					cell.setCellStyle(style2);
					Method getMethod=methodObj.get(k);
					Object value = getMethod.invoke(t, new Object[] {});
					String textValue = getValue(value);
					cell.setCellValue(textValue);
				}

			}
			workbook.write(out);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public String getValue(Object value) {
		String textValue = "";
		if (value == null)
			return textValue;

		if (value instanceof Boolean) {
			boolean bValue = (Boolean) value;
			textValue = "是";
			if (!bValue) {
				textValue = "否";
			}
		} else if (value instanceof Date) {
			Date date = (Date) value;
		
			textValue = sdf.format(date);
		} else
			textValue = value.toString();

		return textValue;
	}

	public static void main(String[] args) throws Exception {
		
		//构造一个模拟的List来测试,实际使用时,这个集合用从数据库中查出来
		List<Testpojo> list = new ArrayList<Testpojo>();
		for (int i = 0; i < 5000; i++) {
			Testpojo pojo = new Testpojo();
			pojo.setLoginname("登录名"+i);
			pojo.setUsername("用户名"+i);
			pojo.setMoney(new Long(1000+i));
			pojo.setCreatetime(new Date());
		    pojo.setAge(28);
			list.add(pojo);
		}
		//构造输出对象,可以从response输出,直接向用户提供下载
		OutputStream out = new FileOutputStream("D:\\testOne.xls");
		//开始时间
		Long l = System.currentTimeMillis();
		//注意
		ExportExcel<Testpojo> ex = new ExportExcel<Testpojo>();
		//
		ex.exportExcel("测试", list, out);
		out.close();
		//结束时间
		Long s = System.currentTimeMillis();
		System.out.println("总共耗时:" + (s - l));
	}
}

2、XSSF模式2007Excel

(1)标题注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


/**
 * 标题注解类
 * @author tangyb
 * @date 2020/03/27
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelAnnotation {
    // excel导出时标题显示的名字,如果没有设置Annotation属性,将不会被导出和导入
    public String exportName();
}
(2)数据实体类
import java.util.Date;

/**
 * 数据实体类
 * @author tangyb
 * @date 2020/03/27
 */
public class Testpojo {
    @ExcelAnnotation(exportName = "用户名")
    String username;
    @ExcelAnnotation(exportName = "登录名")
    String loginname;
    @ExcelAnnotation(exportName = "年龄")
    Integer age;
    @ExcelAnnotation(exportName = "收入")
    Long money;
    @ExcelAnnotation(exportName = "时间")
    Date createtime;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getLoginname() {
        return loginname;
    }

    public void setLoginname(String loginname) {
        this.loginname = loginname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Long getMoney() {
        return money;
    }

    public void setMoney(Long money) {
        this.money = money;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }
}
(3)单元格样式
import java.awt.Color;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


/**
 * Excel单元格样式
 * @author tangyb
 * @date 2020/03/27
 */
public class ExcelStyle {
    /**
     * 表格标题单元格样式
     * @param workbook
     * @param style
     * @return
     */
    public static XSSFCellStyle setHeadStyle(XSSFWorkbook workbook, XSSFCellStyle style) {
        // 设置背景色
        style.setFillForegroundColor(new XSSFColor(new Color(255,255,255)));
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 设置边框
        style.setBorderBottom(XSSFCellStyle.BORDER_THIN); // 下边框
        style.setBorderRight(XSSFCellStyle.BORDER_THIN);// 右边框
        style.setBorderLeft(XSSFCellStyle.BORDER_THIN);// 左边框
        style.setBorderTop(XSSFCellStyle.BORDER_THIN);// 上边框
        // 设置单元格的中心水平对齐-居中
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 设置单元格的垂直对齐类型-居中
        style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 生成字体
        XSSFFont font = workbook.createFont();
        // 设置字体类型
        font.setFontName("微软雅黑");
        // 设置字体大小
        font.setFontHeightInPoints((short) 10);
        // 粗体字体
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;

    }

    /**
     * 表格主体单元格样式
     * @param workbook
     * @param style
     * @return
     */
    public static XSSFCellStyle setbodyStyle(XSSFWorkbook workbook, XSSFCellStyle style) {
        // 设置背景色
        // style.setFillForegroundColor(new XSSFColor(new Color(255,255,255)));
        // style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        // 设置边框
        style.setBorderBottom(XSSFCellStyle.BORDER_THIN); // 下边框
        style.setBorderRight(XSSFCellStyle.BORDER_THIN);// 右边框
        style.setBorderLeft(XSSFCellStyle.BORDER_THIN);// 左边框
        style.setBorderTop(XSSFCellStyle.BORDER_THIN);// 上边框
        // 生成字体
        XSSFFont font = workbook.createFont();
        // 字体类型
        font.setFontName("微软雅黑");
        // 设置字体大小
        font.setFontHeightInPoints((short) 9);
        // 普通字体
        font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
        // 把字体应用到当前的样式
        style.setFont(font);
        return style;
    }
}
(4)导入工具类
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 导入工具类
 * 
 * @author tangyb
 * @date 2020/03/27
 */
public class ImportExcel<T> {
    Class<T> clazz;

    public ImportExcel(Class<T> clazz) {
        this.clazz = clazz;
    }

    public Collection<T> importExcel(File file, String... pattern) {
        Collection<T> dist = new ArrayList<T>();
        try {
            /**
             * 类反射得到调用方法
             */
            // 得到目标目标类的所有的字段列表
            Field filed[] = clazz.getDeclaredFields();
            // 将所有标有Annotation的字段,也就是允许导入数据的字段,放入到一个map中
            Map<String, Method> fieldmap = new HashMap<String, Method>();
            // 循环读取所有字段
            for (int i = 0; i < filed.length; i++) {
                Field f = filed[i];
                // 得到单个字段上的Annotation
                ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
                // 如果标识了Annotationd的话
                if (exa != null) {
                    // 构造设置了Annotation的字段的Setter方法
                    String fieldname = f.getName();
                    String setMethodName = "set" + fieldname.substring(0, 1).toUpperCase()
                            + fieldname.substring(1);
                    // 构造调用的method,
                    Method setMethod = clazz.getMethod(setMethodName, new Class[] {f.getType()});
                    // 将这个method以Annotaion的名字为key来存入。
                    fieldmap.put(exa.exportName(), setMethod);
                }
            }
            /**
             * excel的解析开始
             */
            // 将传入的File构造为FileInputStream;
            FileInputStream in = new FileInputStream(file);
            // // 得到工作表
            Workbook book = null;
            try {
                book = new XSSFWorkbook(in);
            } catch (Exception ex) {
                book = new HSSFWorkbook(in);
            }
            // HSSFWorkbook book = new HSSFWorkbook(in);
            // // 得到第一页
            // HSSFSheet sheet = (HSSFSheet) book.getSheetAt(0);
            Sheet sheet = book.getSheetAt(0);
            // // 得到第一面的所有行
            Iterator<Row> row = sheet.rowIterator();

            /**
             * 标题解析
             */
            // 得到第一行,也就是标题行
            Row title = row.next();
            // 得到第一行的所有列
            Iterator<Cell> cellTitle = title.cellIterator();
            // 将标题的文字内容放入到一个map中。
            Map<Integer, String> titlemap = new HashMap<Integer, String>();
            // 从标题第一列开始
            int i = 0;
            // 循环标题所有的列
            while (cellTitle.hasNext()) {
                Cell cell = cellTitle.next();
                String value = cell.getStringCellValue();
                titlemap.put(i, value);
                i = i + 1;
            }
            /**
             * 解析内容行
             */
            // 用来格式化日期的DateFormat
            SimpleDateFormat sf;
            if (pattern.length < 1) {
                sf = new SimpleDateFormat("yyyy-MM-dd");
            } else
                sf = new SimpleDateFormat(pattern[0]);
            while (row.hasNext()) {
                // 标题下的第一行
                Row rown = row.next();

                // 行的所有列
                Iterator<Cell> cellbody = rown.cellIterator();
                // 得到传入类的实例
                T tObject = clazz.newInstance();
                int k = 0;
                // 遍历一行的列
                while (cellbody.hasNext()) {
                    Cell cell = cellbody.next();
                    // 这里得到此列的对应的标题
                    String titleString = (String) titlemap.get(k);
                    // 如果这一列的标题和类中的某一列的Annotation相同,那么则调用此类的的set方法,进行设值
                    if (fieldmap.containsKey(titleString)) {
                        Method setMethod = (Method) fieldmap.get(titleString);
                        // 得到setter方法的参数
                        Type[] ts = setMethod.getGenericParameterTypes();
                        // 只要一个参数
                        String xclass = ts[0].toString();
                        // 判断参数类型

                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        if (xclass.equals("class java.lang.String")) {
                            setMethod.invoke(tObject, cell.getStringCellValue());
                        } else if (xclass.equals("class java.util.Date")) {
                            setMethod.invoke(tObject, sf.parse(cell.getStringCellValue()));
                        } else if (xclass.equals("class java.lang.Boolean")) {
                            Boolean boolname = true;
                            if (cell.getStringCellValue().equals("否")) {
                                boolname = false;
                            }
                            setMethod.invoke(tObject, boolname);
                        } else if (xclass.equals("class java.lang.Integer")) {
                            setMethod.invoke(tObject, new Integer(cell.getStringCellValue()));
                        }

                        else if (xclass.equals("class java.lang.Long")) {
                            setMethod.invoke(tObject, new Long(cell.getStringCellValue()));
                        }
                    }
                    // 下一列
                    k = k + 1;
                }
                dist.add(tObject);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return dist;
    }

    public static void main(String[] args) {
        ImportExcel<Testpojo> test = new ImportExcel<Testpojo>(Testpojo.class);
        File file = new File("D:\\testOne.xls");
        Long befor = System.currentTimeMillis();
        List<Testpojo> result = (ArrayList<Testpojo>) test.importExcel(file);

        Long after = System.currentTimeMillis();
        System.out.println("此次操作共耗时:" + (after - befor) + "毫秒");
        for (int i = 0; i < result.size(); i++) {
            Testpojo testpojo = result.get(i);
            System.out.println("导入的信息为:" + testpojo.getLoginname() + "----" + testpojo.getAge()
                    + "---" + testpojo.getMoney() + "-----" + testpojo.getCreatetime());
        }

        System.out.println("共转化为List的行数为:" + result.size());
    }
}
(5)导出工具类
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


/**
 * 导出工具类
 * @author tangyb
 * @date 2020/03/27
 */
public class ExportExcel<T> {
	//格式化日期
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * 
	 * @param title 标题
	 * @param dataset 集合
	 * @param out  输出流
	 */
	public void exportExcel(String title, Collection<T> dataset,
			OutputStream out) {
		// 声明一个工作薄
		try {
			//首先检查数据看是否是正确的
			Iterator<T> its = dataset.iterator();
			if(dataset==null||!its.hasNext()||title==null||out==null)
			{
				throw new Exception("传入的数据不对!");
			}
			//取得实际泛型类
			T ts = (T) its.next();
			Class<? extends Object> tCls = ts.getClass();
			XSSFWorkbook workbook = new XSSFWorkbook();
			// 生成一个表格
			XSSFSheet sheet = workbook.createSheet(title);
			// 设置表格默认列宽度为15个字节
			sheet.setDefaultColumnWidth(15);
			// 生成一个样式
			XSSFCellStyle style = workbook.createCellStyle();
			// 设置标题样式
			style = ExcelStyle.setHeadStyle(workbook, style);
			
			// 生成一个样式
			XSSFCellStyle style2 = workbook.createCellStyle();
            // 设置主体样式
            style2 = ExcelStyle.setbodyStyle(workbook, style2);

			// 得到所有字段
			Field filed[] = ts.getClass().getDeclaredFields();
			// 标题
			List<String> exportfieldtile = new ArrayList<String>();
			// 导出的字段的get方法
			List<Method> methodObj = new ArrayList<Method>();
			// 遍历整个filed
			for (int i = 0; i < filed.length; i++) {
				Field f = filed[i];
				ExcelAnnotation exa = f.getAnnotation(ExcelAnnotation.class);
				// 如果设置了annottion
				if (exa != null) {
					String exprot = exa.exportName();
					// 添加到标题
					exportfieldtile.add(exprot);
					// 添加到需要导出的字段的方法
					String fieldname = f.getName();
					String getMethodName = "get"
							+ fieldname.substring(0, 1).toUpperCase()
							+ fieldname.substring(1);
					
					Method getMethod = tCls.getMethod(getMethodName,
							new Class[] {});
					methodObj.add(getMethod);
				}
			}
			// 产生表格标题行
			XSSFRow row = sheet.createRow(0);
			for (int i = 0; i < exportfieldtile.size(); i++) {
			    XSSFCell cell = row.createCell(i);
				cell.setCellStyle(style);
				XSSFRichTextString text = new XSSFRichTextString(
						exportfieldtile.get(i));
				cell.setCellValue(text);
			}
            
			int index = 0;
			
			// 循环整个集合
			
			while (its.hasNext()) {
				//从第二行开始写,第一行是标题
				index++;
				row = sheet.createRow(index);
				T t = (T) its.next();
				for (int k = 0; k < methodObj.size(); k++) {
				    XSSFCell cell = row.createCell(k);
					cell.setCellStyle(style2);
					Method getMethod=methodObj.get(k);
					Object value = getMethod.invoke(t, new Object[] {});
					String textValue = getValue(value);
					cell.setCellValue(textValue);
				}

			}
			workbook.write(out);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public String getValue(Object value) {
		String textValue = "";
		if (value == null)
			return textValue;

		if (value instanceof Boolean) {
			boolean bValue = (Boolean) value;
			textValue = "是";
			if (!bValue) {
				textValue = "否";
			}
		} else if (value instanceof Date) {
			Date date = (Date) value;
		
			textValue = sdf.format(date);
		} else
			textValue = value.toString();

		return textValue;
	}

	public static void main(String[] args) throws Exception {
		
		//构造一个模拟的List来测试,实际使用时,这个集合用从数据库中查出来
		List<Testpojo> list = new ArrayList<Testpojo>();
		for (int i = 0; i < 5000; i++) {
			Testpojo pojo = new Testpojo();
			pojo.setLoginname("登录名"+i);
			pojo.setUsername("用户名"+i);
			pojo.setMoney(new Long(1000+i));
			pojo.setCreatetime(new Date());
		    pojo.setAge(28);
			list.add(pojo);
		}
		//构造输出对象,可以从response输出,直接向用户提供下载
		OutputStream out = new FileOutputStream("D:\\testOne.xlsx");
		//开始时间
		Long l = System.currentTimeMillis();
		//注意
		ExportExcel<Testpojo> ex = new ExportExcel<Testpojo>();
		//
		ex.exportExcel("测试", list, out);
		out.close();
		//结束时间
		Long s = System.currentTimeMillis();
		System.out.println("总共耗时:" + (s - l));
	}
}

五、POI 非侵入式设计工具类

poi-easyexcel.zip

github地址