Excel文件(xls/xlsx)轉(zhuǎn)JavaBean工具的實(shí)現(xiàn)

摘要 Excel文件轉(zhuǎn)換為javabean一般用Apache POI工具,這個(gè)工具是專門操作微軟辦辦公軟件的。雖然比較簡單,但是比較費(fèi)時(shí)費(fèi)力,沒有提供xlsToBean這樣給力的方法。這次正好有這個(gè)需求,看了同事們的方法~~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("行數(shù)為零");
        }
        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;
    }

這只是其中一個(gè)javabean的轉(zhuǎn)換方法。所在類里面目前有10個(gè)左右的轉(zhuǎn)換方法,但是代碼已經(jīng)有484行。這個(gè)項(xiàng)目才剛起步,到后期豈不是要幾千行上萬行?

首先說說我的想法,直接看偽代碼比較清楚

File file = new File(excel文件); 

WorkBook wb = new Workbook(file); //excel文件轉(zhuǎn)換文檔對象

Row row = wb.getSheet(0).getRow(行號);//讀取excel一行數(shù)據(jù)
//其實(shí)到這里,一行數(shù)據(jù)就是一個(gè)JavaBean

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

Object[] arr = new Object[cols];

//遍歷這行的每一個(gè)單元格,然后把單元格取到的數(shù)據(jù)添加到數(shù)組arr
for(int i = 0 ;i<cols;i++){
  Cell cell = row.getCell(i);
  arr[i] = cell.getCellValue();
}

//ok~到此為止我們把一行數(shù)據(jù)插入到了數(shù)組。那么接下來如何把數(shù)組填充到一個(gè)javabean呢?
//我的想法:數(shù)組的下標(biāo)與javabean屬性對應(yīng)起來。就可以利用反射將數(shù)組的元素一一設(shè)置到j(luò)avabean。

看我的代碼,不BB

ExcelCell.java 注解

/** 
* @ClassName: ExcelCell 
* @Description: 實(shí)體字段與excel列號關(guān)聯(lián)的注解
* @author albert
*  
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelCell {
    int col();
    Class<?> Type() default String.class;
}

Excel 文件

商品名 單位 規(guī)格 生產(chǎn)廠家
感冒靈顆粒 3片/盒 貴州百靈

excel文件總共有4列,那么序號0-3;

Goods.java 實(shí)體類

這里要給實(shí)體類屬性添加注解,以便與Excel 列號對應(yīng)

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

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

  @ExcelCell(col=2)
  private String format; //規(guī)格

  @ExcelCell(col=3)
  private String factory;//生產(chǎn)廠家
}

最重要的工具類: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就這么規(guī)定的
            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 官網(wǎng)就可以下載 http://poi.apache.org/download.html#POI-3.16

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,939評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內(nèi)容