因项目原因,需要用Apache的POI读取excel文档中行数据及每行的图片,把行数据和图片作为一条记录保存到数据库中。网上搜索到的资料多数没法定位图片的位置,也就无法把图片关联到行数据中。在一国外的blog中看到一条思路,据此整理出可定位图片位置的代码(读取行文本的代码不是本文关注的各位看官可以自行找度娘解决),本例的目的是获取行所对应的图片数据,已在项目中部署,亲测可用。
POI版本: 3.11
excel类型:xls
以单个工作表为例,思路如下:
1. 获取sheet中的HSSFPatriarch
2. 根据HSSFPatriarch获取sheet中的所有形状(HSSFShape)
3. 遍历所有形状,并转换成图片(HSSFPicture)
4. 根据HSSFPicture获取图片定位信息
5. 绑定数据,返回绑定的数据信息
excel表中的图片是以常见的插入图片方式保存在格子中,插入对象的方式无法达到效果。
具体代码如下:
public Map<String, List<HSSFPictureData>> findAllPictureData(HSSFSheet sheet){
Map<String, List<HSSFPictureData>> dataMap = null;
//处理sheet中的图形
HSSFPatriarch hssfPatriarch = sheet.getDrawingPatriarch();
//获取所有的形状图
List<HSSFShape> shapes = hssfPatriarch.getChildren();
if(shapes.size()>0){
dataMap = new HashMap<String, List<HSSFPictureData>>();
List<HSSFPictureData> pictureDataList = null;
for(HSSFShape sp : shapes){
if(sp instanceof HSSFPicture){
//转换
HSSFPicture picture = (HSSFPicture)sp;
//获取图片数据
HSSFPictureData pictureData = picture.getPictureData();
//图形定位
if(picture.getAnchor() instanceof HSSFClientAnchor){
HSSFClientAnchor anchor = (HSSFClientAnchor)picture.getAnchor();
//获取图片所在行作为key值,插入图片时,默认图片只占一行的单个格子,不能超出格子边界
int row1 = anchor.getRow1();
String rowNum = String.valueOf(row1);
if(dataMap.get(rowNum)!=null){
pictureDataList = dataMap.get(rowNum);
}else{
pictureDataList = new ArrayList<HSSFPictureData>();
}
pictureDataList.add(pictureData);
dataMap.put(rowNum, pictureDataList);
// 测试部分
int row2 = anchor.getRow2();
short col1 = anchor.getCol1();
short col2 = anchor.getCol2();
int dx1 = anchor.getDx1();
int dx2 = anchor.getDx2();
int dy1 = anchor.getDy1();
int dy2 = anchor.getDy2();
System.out.println("row1: "+row1+" , row2: "+row2+" , col1: "+col1+" , col2: "+col2);
System.out.println("dx1: "+dx1+" , dx2: "+dx2+" , dy1: "+dy1+" , dy2: "+dy2);
}
}
}
}
System.out.println("********图片数量明细 START********");
int t=0;
if(dataMap!=null){
t=dataMap.keySet().size();
}
if(t>0){
for(String key : dataMap.keySet()){
System.out.println("第 "+key+" 行, 有图片: "+ dataMap.get(key).size() +" 张");
}
}else{
System.out.println("Excel表中没有图片!");
}
System.out.println("********图片数量明细 END ********");
return dataMap;
}
返回的是Map类型,行号为key,List为value,至此就可以知道每行对应的图片数据;HSSFPictureData中有获取二进制数据的API,方便使用各种IO操作,具体方法各位看官请自行查阅API本文不再讨论。