摘要 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