Excel文件(xls/xlsx)转JavaBean工具的实现

摘要 Excel文件转换为javabean一般用Apache POI工具,这个工具是专门操作微软办办公软件的。虽然比较简单,但是比较费时费力,没有提供xlsToBean这样给力的方法。这次正好有这个需求,看了同事们的方法~~Orz给跪。既然是程序猿,那么就不要用人力解决问题,而是用算法解决它,所以还是直接写工具,方便自己,也方便他人。

先看看同事的方法

public static List<JavaBean> getListByExcel(String file) throws BiffException, IOException, MyException{
        List<JavaBean> list=new ArrayList<JavaBean>();
        Workbook rwb=Workbook.getWorkbook(new File(file));
        Sheet rs=rwb.getSheet("商品");
        if(rs==null) {
            throw new MyException("行数为零");
        }
        int rows=rs.getRows();
        for (int i = 1; i < rows; i++) {
            if(rs.getCell(0, i).getContents()==null||rs.getCell(0, i).getContents().equals("")) {
                break;
            }
            String name=rs.getCell(1, i).getContents();
            String format=rs.getCell(2, i).getContents();
            String unit=rs.getCell(3, i).getContents();
            String factory=rs.getCell(4, i).getContents();
            String price=rs.getCell(5, i).getContents();
            String conversion=rs.getCell(6, i).getContents();
            String tname=rs.getCell(7, i).getContents();
            String tformat=rs.getCell(8, i).getContents();
            String tunit=rs.getCell(9, i).getContents();
            String tfactory=rs.getCell(10, i).getContents();
            String tprice=rs.getCell(11, i).getContents();
            String tendGoodsId=rs.getCell(12, i).getContents();
            String goodsId=rs.getCell(13, i).getContents();
            String factoryId=(rs.getCell(14, i).getContents()==null||rs.getCell(14, i).getContents().equals(""))?"0":rs.getCell(14, i).getContents();
            GoodsEntity a = new GoodsEntity();
            a.setName(name);
            a.setFormat(format);
            a.setUnit(unit);
            a.setFactory(factory);
            a.setPrice(price);
            a.setTend_goodsId(tendGoodsId);
            a.setGoodsId(goodsId);
            a.setFactoryId(factoryId);
            a.setUuId(UUID.randomUUID().toString());
            a.setTfactory(tfactory);
            a.setTformat(tformat);
            a.setTname(tname);
            a.setTunit(tunit);
            a.setConversion(conversion);
            a.setTprice(tprice);
            list.add(a);
        }
        return list;
    }

这只是其中一个javabean的转换方法。所在类里面目前有10个左右的转换方法,但是代码已经有484行。这个项目才刚起步,到后期岂不是要几千行上万行?

首先说说我的想法,直接看伪代码比较清楚

File file = new File(excel文件); 

WorkBook wb = new Workbook(file); //excel文件转换文档对象

Row row = wb.getSheet(0).getRow(行号);//读取excel一行数据
//其实到这里,一行数据就是一个JavaBean

int cols = row.getLastCellNum();//获取最后一列的列号

Object[] arr = new Object[cols];

//遍历这行的每一个单元格,然后把单元格取到的数据添加到数组arr
for(int i = 0 ;i<cols;i++){
  Cell cell = row.getCell(i);
  arr[i] = cell.getCellValue();
}

//ok~到此为止我们把一行数据插入到了数组。那么接下来如何把数组填充到一个javabean呢?
//我的想法:数组的下标与javabean属性对应起来。就可以利用反射将数组的元素一一设置到javabean。

看我的代码,不BB

ExcelCell.java 注解

/** 
* @ClassName: ExcelCell 
* @Description: 实体字段与excel列号关联的注解
* @author albert
*  
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelCell {
    int col();
    Class<?> Type() default String.class;
}

Excel 文件

商品名 单位 规格 生产厂家
感冒灵颗粒 3片/盒 贵州百灵

excel文件总共有4列,那么序号0-3;

Goods.java 实体类

这里要给实体类属性添加注解,以便与Excel 列号对应

public class Goods{
  @ExcelCell(col=0)
  private String name; //商品名

  @ExcelCell(col=1)
  private String unit; //单位

  @ExcelCell(col=2)
  private String format; //规格

  @ExcelCell(col=3)
  private String factory;//生产厂家
}

最重要的工具类:ExcelConvert.java

/**
 * 
 */
package com.sy.utils;

/** 
* @ClassName: ExcelConveter 
* @Description: 
* @author albert
* @date 2017年5月5日 下午1:19:56 
*  
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
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;

import com.sy.exceptions.MyException;

public class ExcelConveter {
    
    public static Workbook readFile(File file) throws MyException {
        try {
            //xls和xlsx必须不同的处理类,POI就这么规定的
            if (file.getName().toLowerCase().endsWith(".xls")) {
                return readFileHSSF(new FileInputStream(file));
            } else {
                return readFileXSSF(new FileInputStream(file));
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(e.getMessage());
        }
    }
    //HSSF*是处理xls格式的,XSSF是处理xlsx格式文件
    private static Workbook readFileHSSF(InputStream stream) throws MyException, IOException {
        try {
            return new HSSFWorkbook(stream);
        } catch (IOException e) {
            e.printStackTrace();
            throw new MyException(e.getMessage());
        } finally {
            stream.close();
        }
    }

    private static Workbook readFileXSSF(InputStream stream) throws MyException, IOException {
        try {
            return new XSSFWorkbook(stream);
        } catch (IOException e) {
            e.printStackTrace();
            throw new MyException(e.getMessage());
        } finally {
            stream.close();
        }
    }

    public static Workbook readFile(String path) throws MyException {
        File file = new File(path);
        if (!file.exists())
            throw new MyException("文件不存在");
        if (!file.isFile())
            throw new MyException("不是合法的文件");
        return readFile(file);
    }

    public static Sheet readSheet(HSSFWorkbook workbook, Integer index) {
        return workbook.getSheetAt(index);
    }

    public static Object[] convertArrayByRow(Row row) {
        int cols = row.getLastCellNum();
        Object[] arr = new Object[cols];
        for (int i = 0; i < cols; i++) {
            Cell cell = row.getCell(i);
            if (cell == null)
                continue;
            if (cell.getCellTypeEnum() == CellType.STRING) {
                arr[i] = cell.getStringCellValue();
            } else if (cell.getCellTypeEnum() == CellType.NUMERIC) {
                arr[i] = cell.getNumericCellValue();
            } else {

            }
        }
        return arr;
    }

    public static <T extends Object> T convertBeanFromArray(Object[] arr, Class<T> clazz) throws MyException {
        T entity;
        try {
            entity = clazz.newInstance();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (!field.isAnnotationPresent(ExcelCell.class))
                    continue;

                field.setAccessible(true);
                ExcelCell anno = field.getAnnotation(ExcelCell.class);
                Class<?> cellType = anno.Type();
                Integer col = anno.col();

                if (col >= arr.length)
                    continue;
                if (arr[col] == null)
                    continue;
                if (cellType == null) {
                    field.set(entity, arr[col]);
                } else {
                    field.set(entity, numericByStr(cellType, arr[col]));
                }
            }
            return entity;
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(e.getMessage());
        }
    }

    public static <T extends Object> Object numericByStr(Class<T> clazz, Object param) {
        if (param == null)
            return null;
        String arg = String.valueOf(param);
        if (clazz.isAssignableFrom(Double.class)) {
            return Double.valueOf(arg);
        } else if (clazz.isAssignableFrom(Long.class)) {
            Double d = Double.valueOf(arg);
            return d.longValue();
        } else if (clazz.isAssignableFrom(Integer.class)) {
            return Integer.valueOf(arg);
        } else {
            return arg;
        }
    }

    public static <T> List<T> getBean(String path, Class<T> clazz) throws MyException {
        List<T> list = new ArrayList<T>();
        Workbook book = readFile(path);
        for (int i = 1; i <= book.getSheetAt(0).getLastRowNum(); i++) {
            Object[] arr = convertArrayByRow(book.getSheetAt(0).getRow(i));
            T t = convertBeanFromArray(arr, clazz);
            list.add(t);
        }
        return list;
    }

    public static <T> List<T> getBean(File file, Class<T> clazz) throws MyException {
        List<T> list = new ArrayList<T>();
        Workbook book = readFile(file);
        for (int i = 1; i <= book.getSheetAt(0).getLastRowNum(); i++) {
            Object[] arr = convertArrayByRow(book.getSheetAt(0).getRow(i));
            T t = convertBeanFromArray(arr, clazz);
            list.add(t);
        }
        return list;
    }

    public static <T> List<T> getBean(InputStream stream, String excelType, Class<T> clazz)
            throws MyException, IOException {
        Workbook book;
        if (excelType.equals("xls")) {
            book = readFileHSSF(stream);
        } else {
            book = readFileXSSF(stream);
        }
        List<T> list = new ArrayList<T>();
        for (int i = 1; i <= book.getSheetAt(0).getLastRowNum(); i++) {
            Object[] arr = convertArrayByRow(book.getSheetAt(0).getRow(i));
            T t = convertBeanFromArray(arr, clazz);
            list.add(t);
        }
        return list;
    }
}

使用方法:就这么一行,有没有很简单?

List<Goods> list = ExcelConveter.getBean('excel文件路径', Barcode.class);

所需jar包在apache 官网就可以下载 http://poi.apache.org/download.html#POI-3.16

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容