Excel导入在实际的开发中,经常会用到,可是我们往往需要研究一番这个Excel表格的结构才能够着手写Excel导入的代码,而这份代码有不能够复用,常常导致一表一码的情况,为了提高开发效率,因此写了些代码和解决思路
大前提
每一份Excel表格都有唯一标示某列或某行业务含义的标示,例如列名,某单元格特定字符。
很明显根据某些特定标示,我是能够知道哪个单元格是我想要的数据
解决思路
1.如何让程序根据某一字段标识与导入实体类字段存在对应关系,找出数据所在位置?
例如给出如下对应关系(参照上图教学进度的,给出如下配置)
List fields = new ArrayList<>();
//公用字段
fields.add(new ImportField("课程名称","name"));
fields.add(new ImportField("专业","major"));
fields.add(new ImportField("年级","grade"));
fields.add(new ImportField("班级","classes"));
//多值字段
fields.add(new ImportField("授课方式","type",true,1,0));
fields.add(new ImportField("授课教师","teacher",true,1,0));
fields.add(new ImportField("授课内容","content",true,1,0));
fields.add(new ImportField("上课地点","address",true,1,0));
fields.add(new ImportField("周次","week",true,1,0));
fields.add(new ImportField("星期","day",true,1,0));
fields.add(new ImportField("节次","scope",true,1,0));
2.如何通过给定的映射关系遍历Sheet和得到某一标识所在行和列?
首先我们需要定义一个导入配置,然后程序就是根据这一个导入配置去取数据
例如给出如下实体类
public class ImportField {
//别名
private String alias;
//数据库字段名称或者实体类名称
private String name;
//是否多个
private boolean isMulti = false;
//行偏移量
private int xOffset=0;
//列偏移量
private int yOffset=0;
//起始行
private int row;
//起始列
private int col;
//多值属性记录数
private int multiCount = 0;
//是否分析得到起始行列位置
private boolean isComplete = false;
public ImportField() {
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public boolean isMulti() {
return isMulti;
}
public void setMulti(boolean multi) {
isMulti = multi;
}
public int getxOffset() {
return xOffset;
}
public void setxOffset(int xOffset) {
this.xOffset = xOffset;
}
public int getyOffset() {
return yOffset;
}
public void setyOffset(int yOffset) {
this.yOffset = yOffset;
}
//计算所在列是需要加上行偏移量
public int getRow() {
return row+xOffset;
}
public void setRow(int row) {
this.row = row;
}
//计算所在列是需要加上列偏移量
public int getCol() {
return col+yOffset;
}
public void setCol(int col) {
this.col = col;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ImportField(String alias, String name, boolean isMulti, int xOffset, int yOffset) {
this.alias = alias;
this.name = name;
this.isMulti = isMulti;
this.xOffset = xOffset;
this.yOffset = yOffset;
}
public ImportField(String alias, String name) {
this.alias = alias;
this.name = name;
}
public void setPosition(int row, int col){
this.col = col;
this.row = row;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public void getNextRow(){
this.row ++;
}
public void addMultiCount(){
this.multiCount++;
}
public int getMultiCount() {
return multiCount;
}
遍历Excel得到标识位置所在行列
//分析即将导入的文件
/**
* HashMap中包含
*List fields
*HSSFSheet
*/
private static HashMap analysisExcel(
InputStream inputStream, List fields)
throws IOException,FormatException{
HashMap analysisResult = new HashMap<>();
int progress = 0;//扫描进度
HSSFWorkbook hssfWorkbook = new HSSFWorkbook(inputStream);
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(0);//默认获取第一个
if (hssfSheet == null) {
throw new FormatException("读取模板文件为空!");
}
for (int rowNum = 1; rowNum <= hssfSheet.getLastRowNum(); rowNum++) {
HSSFRow hssfRow = hssfSheet.getRow(rowNum);
if(hssfRow == null){
continue;
}
for(int colNum = 0; colNum
3.读取数据,返回指定实体类集合
通过以上的遍历,可以得到含有行列位置的导入配置和一个Sheet对象
//导入excel
private static List
4.通过上面的读取可以得到List
net.sf.dozer
dozer
5.5.1
然后简单封装一下
public class BeanMapper {
private static DozerBeanMapper dozer = new DozerBeanMapper();
public BeanMapper() {
}
public static T map(Object source, Class destinationClass) {
return dozer.map(source, destinationClass);
}
public static List mapList(Collection sourceList, Class destinationClass) {
ArrayList destinationList = Lists.newArrayList();
Iterator i$ = sourceList.iterator();
while(i$.hasNext()) {
Object sourceObject = i$.next();
Object destinationObject = dozer.map(sourceObject, destinationClass);
destinationList.add(destinationObject);
}
return destinationList;
}
public static void copy(Object source, Object destinationObject) {
dozer.map(source, destinationObject);
}
}
然后一句话转完
List
总结
第一次用markdown写文章,感觉倍爽,代码应该还有不完善的地方,其实最好的方式是自定义一个注解,然后加上校验,可是由于知识水平的限制,暂时没有什么进展。
完整的代码
https://github.com/Mygraduate/Supervisor_Java.git