基于POI 框架自己封装一个Excel通用读写小工具

在我们日常开发中,经常会遇到读写excel的需求。或者生成一个excel文件给用户,或者读取解析上传的excel文件。
在写过几次读写excel的代码后,我发现其实在读写excel的时候,大部分代码都是一样的,只要具体读写某一行的代码有区别。于是,就打算自己写一个Excel通用读写小工具。以后只需要写一个具体读写行的代码就可以了。这里将具体读/写 excel行 的方法抽象成一个接口,然后在读写excel的通用方法中调用它。使用的时候,只需要传入对应的读/写 的具体实现,和相关的数据/文件就可以了。具体代码如下:

github 地址:https://github.com/wsJava/excel-util

定一个 读和写 Row(行)的接口

读取接口 Reader 和 读取结果ReadResult

读取excel的接口就一个read方法,但返回结果是一个封装过的ReadResult,这个类除了持有读取结果外,还包括下一步操作(如继续读取、退出、跳过该行等),使得调用方能根据自己的需求决定读取方式。注意,如果该方法中抛出异常需要自行处理,结合ReadResult能很容易控制读取流程。

/**
 * 读取excel的接口
 */
public interface Reader<T> {

    /**
     * 读取 excel 行,注意如遇到空行 row 可能为 null, 请自行处理。
     * 另外请自行处理方法中抛出的异常,并决定后续操作;若该方法抛出异常,不做任何处理直接向上抛出。
     *
     * @param row excel 的行对象,可能为 null
     * @return ReadResult 持有读取行得到的数据对象,并决定下一步操作,直接退出,跳过该行,继续读,读取本行后退出
     */
    ReadResult<T> read(Row row);
}

/**
 * 读取的结果
 */
public class ReadResult<T> {
    private T value;
    private ReadOperatorEnum curOperator;
    // 省略一些方法
}
写excel的接口 Writer 和默认实现

Writer包含两个方法,一个用户获取列名,另一个则是将对象写入excel行。getHeader() 默认返回null,即没有列名。并且提供了一个默认的实现,使用字段名作为列名,调用所有定义字段的toString以String格式写入excel。

/**
 * 写excel行的接口
 */
public interface Writer<T> {

    /**
     * 获取表格头部字段,即每列的列名,顺序应该和 write 中的顺序保持一致,默认没有列名。需要列名请重写该方法
     *
     * @return 列名数组,如果返回 {@code null} 则不会添加列名
     */
    default String[] getHeaders() {
        return null;
    }

    /**
     * 将对象写入Excel表格的一行中
     *
     * @param row Excel 行对象
     * @param t   需要写入的对象
     */
    void write(Row row, T t);

    /**
     * 提供的一个默认的 Excel writer,将对象所有的定义字段(不包括继承的)写入表格,以字段名为列名,表格内的值为 String类型
     *
     * @param tClass 数据的类对象
     * @param <T>    数据类型
     * @return writer
     */
    static <T> Writer<T> defaultWriter(Class<T> tClass) {
        Objects.requireNonNull(tClass, "tClass must not be null");
        final Field[] fields = tClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
        }

        return new Writer<T>() {
            @Override
            public String[] getHeaders() {
                String[] headers = new String[fields.length];
                for (int i = 0; i < fields.length; i++) {
                    headers[i] = fields[i].getName();
                }
                return headers;
            }

            @Override
            public void write(Row row, T t) {
                String[] headers = getHeaders();
                for (int i = 0; i < headers.length; i++) {
                    Cell cell = row.createCell(i, CellType.STRING);
                    try {
                        cell.setCellValue(String.valueOf(fields[i].get(t)));
                    } catch (IllegalAccessException ignored) {
                    }
                }
            }
        };
    }
}

ExcelUtil 通用工具类

这主要提供两个功能,读取excel获取list 对象;将list对象写入excel。这里只贴出核心的处理流程。具体代码可以看我的github仓库;

public static <T> List<T> readExcel(Workbook workbook, int sheetIndex, int startRow, Reader<T> reader) {
 	Objects.requireNonNull(workbook, "workbook must not be null");
    Objects.requireNonNull(reader, "reader must not be null");
    Sheet sheet = workbook.getSheetAt(sheetIndex);
    List<T> list = new ArrayList<>(sheet.getLastRowNum());

    for (int rowIndex = startRow; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
        Row row = sheet.getRow(rowIndex);
        ReadResult<T> result = reader.read(row);

        ReadOperatorEnum curOperator = result.curOperator();
        switch (curOperator) {
            case CONTINUE:
                list.add(result.get());
                break;
            case SKIP:
                break;
            case ADD_EXIT:
                list.add(result.get());
            case EXIT:
                return list;
        }

    }
    return list;
}

public static <T> void writeExcelToWorkbook(List<T> data, Workbook workbook, int sheetIndex, int startRow, Writer<T> writer) {
    Objects.requireNonNull(data, "data must not be null");
    Objects.requireNonNull(workbook, "workbook must not be null");
    Objects.requireNonNull(writer, "writer must not be null");

    Sheet sheet = getOrCreateSheet(workbook, sheetIndex);
    String[] headers = writer.getHeaders();

    if (headers != null) {
        Row header = sheet.createRow(startRow++);
        for (int i = 0; i < headers.length; i++) {
            Cell cell = header.createCell(i);
            cell.setCellValue(headers[i]);
        }
    }

    for (T t : data) {
        Row row = sheet.createRow(startRow++);
        writer.write(row, t);
    }
}

使用示例

这里使用上面的工具,先生成一个excel文件,然后再从excel中读取数据。

public class ExcelUtilTest{
	public static void main(String[] args) throws IOException {
	//        ExcelUtil.addDataToExcelFile(getStudent(), new File("student.xlsx"), 2, 9, Writer.defaultWriter(Student.class));
	  File file = ExcelUtil.writeNewExcel(getStudent(), "student.xlsx", Writer.defaultWriter(Student.class));
	
		// 有需要可以在这里加一个异常捕获
	    List<Student> students = ExcelUtil.readExcel(file, 0, 1, ExcelUtilTest::readStudent);
	
	    System.out.println(students);
	}
	
	private static ReadResult<Student> readStudent(Row row) {
	    if (row == null) {
	        return ReadResult.skip();
	    }
	    // 读取到第6行就退出
	    if (row.getRowNum() > 5) {
	        return ReadResult.exit();
	    }
	
	    // 如果id读取报错,就说明excel格式不正确,捕获异常,添加相关信息,继续抛出
	    Integer id;
	    try {
	         id = ExcelReadUtils.getIntFromCellDefaultNull(row.getCell(0));
	    } catch (Exception e) {
	        throw new RuntimeException("excel 读取异常,当前行号:"+row.getRowNum(), e);
	    }
	    // 姓名这格不存在就默认null
	    String s = ExcelReadUtils.getStrFromCellDefaultNull(row.getCell(1));
	    return ReadResult.add(new Student(id, s));
	}

	private static List<Student> getStudent() {
        List<Student> list = new ArrayList<>(100);
        for (int i = 0; i < 10; i++) {
            list.add(new Student(i, "stu-"+i));
        }
        return list;
    }


    static class Student{
        Integer id;
        String name;
        public Student(Integer id, String name) {
            this.id = id;
            this.name = name;
        }

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Excel POI封装(文件+示范代码) package org.excel.service; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import javax.jws.WebService; import org.apache.poi.hssf.usermodel.*; import org.excel.data.DataType; import org.excel.data.DealForeign; import org.excel.data.ExcelImport; import org.excel.data.impl.StInStatusImpl; import org.excel.data.impl.StuClassImportImpl; import org.excel.data.impl.StuEducationImpl; import org.excel.data.impl.StuImprotDataImpl; import org.excel.data.impl.StuInClassImportImpl; import org.excel.data.impl.StuWorkStatusImpl; import org.excel.manager.Util; import org.excel.model.ExcelMap; import org.excel.xml.ExcelXmlParse; import net.sourceforge.jtds.jdbcx.JtdsDataSource; @WebService public class ExcelServiceImpl implements IExcelService { String tableName = ""; public static Integer suc = 0; public static Integer fail = 0; StringBuilder insert = new StringBuilder( " insert into {tableName} {column} values {values}"); /** Excel表格数据 */ public List<HashMap> readExcel(String excelName, Integer sheetIndex, String startPoint, String endPoint) throws Exception { FileInputStream inputStream = null; inputStream = new FileInputStream(excelName); HSSFWorkbook workbook = new HSSFWorkbook(inputStream); HSSFSheet sheet = workbook.getSheetAt(sheetIndex); String[] sc = null;// 开始坐标 String[] ec = null;// 结束坐标 int startRow = 0;// 默认开始行数 int endRoe = sheet.getPhysicalNumberOfRows();// 默认结束行 int startLine = 0;// 默认开始列 int endLine = 0;// 结束列 if (startPoint != null && endPoint != null) { sc = startPoint.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值