ET-----ExcelTool,Excel业务快速处理框架

1.ET简介

    在大型企业系统中,有一个必不可少的业务,就是--报表。为了阅读、处理方便,报表通常都是以excel的文件形式进行存储的。所幸的是已经有大佬开发了一个用于处理excel的框架--jxl。既然有了jxl,为什么还要开发ET?第一,jxl虽然已经把api封装的很好了,但是对于业务层还是不太友好的,我要实现一个业务,需要很多步骤的api调用,故此,写一个更高层次的封装,更贴近业务;第二,本人太闲了,顺便当练练手,虽然写的很差= =。

    源码地址:https://github.com/a1104321118/ET

2.ET设计思想

    打开excel,发现它和什么很像?没错,数据库啊。所以说ET的设计思想就是来源于数据库,虽然它很简单。首先,数据库的表有很多列,每一个列都有列名。所以我们可以把excel也看成很多列,把第一行的都设置成类名。进一步,数据库的表一般都对应着实体类。所以我们可以把excel也对应成实体类。这不正是Mybatis的设计思想吗?

3.ET-demo

    首先,看一个excel,这是我们的原始数据,第一行就是“列名”,下面的几行是数据:

    164042_qxJI_3582320.png

    再看一个实体类:

public class Person {

    private String name;
    private String gender;
    private String age;
    private String state;

    //getter/setter
    ....
}

    其中,excel的列名和Person实体类的属性名是映射关系。

    接下来看ET的使用方法:

public class Main {

    public static void main(String[] args) {
        //文件输入输出路径
        String filePath = "D:\\idea\\MyProjects\\ET\\src\\main\\java\\resources\\test.xls";
        String outFilePath = "D:\\idea\\MyProjects\\ET\\src\\main\\java\\resources\\test-result.xls";

        ExcelTool excelTool = new ExcelTool(filePath);

        //读数据
        List<Person> peopleList = excelTool.readData(Person.class);

        //修改数据
        for (Person person : peopleList){
            System.out.println(person);
            person.setState("SUCCESS");
        }

        //写数据
        excelTool.writeData(peopleList, outFilePath);

    }
}

    运行结果:

164518_ZJhp_3582320.png

    至此,可以看出ET有多简单了把。

4.ET-源码解析

    其实ET的源码非常简单,最核心的思想,就是把excel的列名,和Person类的属性名进行映射,并实例出person对象。怎么做?反射。直接贴出源码,注释非常详细:

package com.hr.et.tool;

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by hr on 2017/08/03.
 *
 */
public class ExcelTool {

    //读取文件
    private Workbook workbook = null;
    //写文件
    private WritableWorkbook writableWorkbook = null;


    /**
     * 初始化工具,需要传入文件路径
     * @param filePath
     * @throws IOException
     * @throws BiffException
     */
    public ExcelTool(String filePath){
        File file = new File(filePath);
        if(!file.isFile() || !file.exists()){
            try {
                throw new FileNotFoundException("文件不存在");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        try {
            this.workbook = Workbook.getWorkbook(file);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (BiffException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取全部数据
     * @param clazz
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T> List<T> readData(Class<T> clazz){
        try {
            return readData(clazz, 1, 0);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取数据,从 begin 开始,数量为num
     * @param clazz
     * @param begin
     * @param num
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T> List<T> readData(Class<T> clazz, int begin, int num) throws IllegalAccessException, InstantiationException {
        List<T> result = new ArrayList<>();

        Sheet sheet = this.workbook.getSheet(0);

        //获得所有列名
        List<String> cloumnNames = new ArrayList<>();
        int cloumns = sheet.getColumns();
        for (int i=0; i<cloumns; i++){
            cloumnNames.add(sheet.getCell(i, 0).getContents());
        }

        //获得该类的属性
        Field[] fields = clazz.getDeclaredFields();

        int rows = sheet.getRows();
        begin = begin <= 0 ? begin+1 : begin;
        int end = (begin + num) > rows ? rows : (begin + num);
        if(num == 0){
            end = rows;
        }

        for (int i=begin; i<end; i++){//对每一行数据进行处理
            Cell[] row = sheet.getRow(i);//获得这一行的数据
            T t = clazz.newInstance(); //通过反射实例化泛型对象
            for (int j=0; j<row.length; j++){//对这一行的数据进行一个一个处理
                String thisCloumnName = cloumnNames.get(j);//先获得列名
                for (Field field : fields){
                    if(thisCloumnName.equals(field.getName())){//当列名和这个属性的名称一样时,认为他们相互映射
                        field.setAccessible(true);
                        field.set(t, row[j].getContents());//设置属性值
                    }
                }
            }
            result.add(t);
        }

        workbook.close();

        return result;
    }

    /**
     * 写数据
     * @param data
     * @param <T>
     */
    public <T> void writeData(List<T> data, String outFilePath) {

        //判断数据有效性
        if(null == data || data.size() == 0){
            return;
        }

        if(null == outFilePath || outFilePath.equals("")){
            return;
        }

        WritableSheet sheet = null;
        File file = new File(outFilePath);
        try {
            this.writableWorkbook = Workbook.createWorkbook(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sheet = this.writableWorkbook.createSheet("result", 0);

        //写入标题,顺序是fields的顺序
        T t = data.get(0);
        Field[] fields = t.getClass().getDeclaredFields();
        Label[] head = new Label[fields.length];
        for (int i=0; i<fields.length; i++){
            head[i] = new Label(i, 0, fields[i].getName());
        }
        writeLine(sheet, head);//先把Person的属性都写入excel的第一行

        //写入数据
        try {
            for (int i = 0; i < data.size(); i++) {//开始写list里面的数据
                T result = data.get(i);
                for (int j = 0; j < fields.length; j++) {//逐个写属性

                    Field field = result.getClass().getDeclaredField(fields[j].getName());
                    field.setAccessible(true);
                    String s = (String)field.get(result);
                    sheet.addCell(new Label(j, i+1, s));

                }
            }
        }catch (NoSuchFieldException | WriteException | IllegalAccessException e) {
            e.printStackTrace();
        }

        try {
            this.writableWorkbook.write();
            this.writableWorkbook.close();
        } catch (WriteException | IOException e) {
            e.printStackTrace();
        }


    }

    private void writeLine(WritableSheet sheet, Label[] data){

        try {
            for (int i = 0; i < data.length; i++) {
                sheet.addCell(data[i]);
            }
        } catch (WriteException e) {
            e.printStackTrace();
        }

    }

}

    main方法

public static void main(String[] args) {
        //文件输入输出路径
        String filePath = "D:\\idea\\MyProjects\\ET\\src\\main\\java\\resources\\test.xls";
        String outFilePath = "D:\\idea\\MyProjects\\ET\\src\\main\\java\\resources\\test-result.xls";

        ExcelTool excelTool = new ExcelTool(filePath);

        //读数据
        List<Person> peopleList = excelTool.readData(Person.class);

        //修改数据
        for (Person person : peopleList){
            System.out.println(person);
            person.setState("SUCCESS");
        }

        //写数据
        excelTool.writeData(peopleList, outFilePath);

}

5.注意事项

    5.1不要把读取的文件和写入的文件搞成同一个文件!!!

        不要把读取的文件和写入的文件搞成同一个文件!!!

        不要把读取的文件和写入的文件搞成同一个文件!!!

        否则报错时,原数据会被覆盖,造成数据丢失。

    5.2目前只有String类型

        确实,这个东西只写了一下午,还有很多东西没有完善,但是一般的功能业务足够了。以后有空再研究一下int,date这些东西能不能映射成功。

6.其它

    转载请附上原文地址:https://my.oschina.net/u/3582320/blog/1501527

    源码地址:https://github.com/a1104321118/ET

    欢迎大家留言讨论。

转载于:https://my.oschina.net/u/3582320/blog/1501527

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值