背景
1:你excel是不是用挺多的
2:还好,阿里那套用的多
1:那你有知道怎么读取图片吗,像下面这种
2:不知道,自己百度
1:百度都是用原始poi写的,没有工具啊,好复杂又不能通用,你有没有工具
2:没有,不想搞
1:请你吃饭,弄一个呗
2:行吧,试试整一个
说明
废话不多说,下面将直接放代码,缺少包请自行下载
代码可以直接复制使用
有问题可以评论留言,看到就回
代码
这里用的是EasyExcel的ExcelProperty注解,你也可以自己定义注解
ExcelUtils工具
/**
* 读取,可读取图片,需调用imgCallback()方法对图片进行处理并返回路径(不支持CSV文件导入,因为csv暂时无法处理图片)
*
* @param stream 输入流
* @param callBack imgCallback()方法图片处理后返回的路径
* @param headRowCount 表头的行数(比如有些表格存在多行头,T为bean对象时无效,为Map时生效),
* (当T为Map时, headRowCount不传默认为1,第一行是表头; 当T为bean对象时根据ExcelProperty配置字段计算)
* @param heads 默认null,重新设置表头,且clazz的表头失效,只对T为bean对象生效,(特别注意: heads的表头顺序与clazz的字段顺序必须保持一致,否则bean赋值可能出错)
*/
public static <T> List<T> excelImageRead(InputStream stream, Class<T> clazz, Integer headRowCount, List<List<String>> heads, ImageCallBack callBack) throws Exception {
Workbook workbook = WorkbookFactory.create(stream); // 支持2003版本和2007版本
Sheet sheet = workbook.getSheetAt(0); // 只处理第一个表
// 如果是SXSSFWorkbook类型,转XSSFWorkbook类型,否则sheet.getRow可能为空
if (workbook instanceof SXSSFWorkbook) {
SXSSFWorkbook sxssfWorkbook = (SXSSFWorkbook) workbook;
sheet = sxssfWorkbook.getXSSFWorkbook().getSheetAt(workbook.getSheetIndex(sheet));
}
ExcelTools.handleExcelImage(sheet, callBack); // 处理图片
return ExcelTools.saveRowData(sheet, clazz, headRowCount, heads); // 存储并返回数据
}
自定义ExcelTools工具
public class ExcelTools {
/**
* 处理图片
*
* @param sheet excel表
* @param callBack 回调处理
*/
public static void handleExcelImage(Sheet sheet, ImageCallBack callBack) throws Exception {
if (Objects.nonNull(callBack) && Objects.nonNull(sheet.getDrawingPatriarch())) {
for (Shape shape : sheet.getDrawingPatriarch()) {
ClientAnchor anchor = (ClientAnchor) shape.getAnchor();
int row1 = anchor.getRow1(); // 获取行编号: getRow2():获取图片右下角行号 getRow1():获取图片左上角行号
short col1 = anchor.getCol1();// 获取列编号: getCol2():获取图片右下角列号 getCol1():获取图片左上角列号
if (row1 > sheet.getLastRowNum()) {
throw new Exception("图片位置错误(" + row1 + "," + col1 + ")");
}
if (shape instanceof Picture) {
Picture picture = (Picture) shape;
PictureData pictureData = picture.getPictureData();
String url = callBack.imgCallback(pictureData); // 调用回调处理
Row row = Objects.isNull(sheet.getRow(row1)) ? sheet.createRow(row1) : sheet.getRow(row1);
Cell cell = Objects.isNull(row.getCell(col1)) ? row.createCell(col1) : row.getCell(col1);
List<String> urls;
if (StringUtils.isNotBlank(cell.getStringCellValue())) {
try {
urls = JsonUtils.getJsonToList(cell.getStringCellValue(), String.class);
} catch (Exception e) {
urls = new ArrayList<>();
}
} else {
urls = new ArrayList<>();
}
urls.add(url);
cell.setCellValue(JsonUtils.getBeanToJson(urls));
}
}
}
}
/**
* 保存并返回数据
*
* @param headRowCount 表头的行数(比如有些表格存在多行的头,T为bean对象时无效,为Map时生效), (当T为Map时, headRowCount不传默认为1,第一行是表头; 当T为bean对象时根据ExcelProperty配置字段计算)
* @param newHeads 默认null,重新设置表头,且clazz的表头失效,只对T为bean对象生效,(特别注意: heads的表头顺序与clazz的字段顺序必须保持一致,否则bean赋值可能出错)
*/
public static <T> List<T> saveRowData(Sheet sheet, Class<T> clazz, Integer headRowCount, List<List<String>> newHeads) throws Exception {
List<T> list = new ArrayList<>();
Map<Integer, List<String>> cellHeadMap = new HashMap<>(); // 列-头
Map<String, Field> headFieldMap = getHeadFieldMap(clazz, newHeads); // 头-字段
// 多行头数(存在多行头)
int headCount;
if (Objects.isNull(headFieldMap)) {
headCount = Objects.isNull(headRowCount) ? 1 : headRowCount;
} else {
headCount = headFieldMap.keySet().stream().map(k -> JsonUtils.getJsonToList(k, String.class)).filter(Objects::nonNull).map(List::size).reduce(Integer::max).orElse(1);
}
// 分析每一行
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (Objects.isNull(row)) continue;
T t = null; // 声明对象
boolean existContent = false; // 存在内容
int rowNum = row.getRowNum(); // 从0开始
// headCount行以内都是表头
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext() && rowNum < headCount) {
Cell cell = cellIterator.next();
DataFormatter dataFormatter = new DataFormatter();
String val = dataFormatter.formatCellValue(cell);
List<String> heads = cellHeadMap.getOrDefault(cell.getColumnIndex(), new ArrayList<>());
heads.add(val);
cellHeadMap.put(cell.getColumnIndex(), heads);
}
if (rowNum >= headCount) {
int hs = cellHeadMap.size(); // 头数量
for (int cn = 0; cn < hs; cn++) {
t = Objects.isNull(t) ? clazz.getDeclaredConstructor().newInstance() : t;
Cell cell = row.getCell(cn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
List<String> heads = cellHeadMap.get(cell.getColumnIndex()); // 获取表头字段名称
DataFormatter dataFormatter = new DataFormatter();
String val = dataFormatter.formatCellValue(cell);
if (StringUtils.isBlank(val)) {
continue;
}
// bean
if (Objects.nonNull(headFieldMap)) {
Field field1 = headFieldMap.get(JsonUtils.getBeanToJson(heads)); // 为bean时获取表头对应的bean字段
if (Objects.nonNull(field1)) {
field1.set(t, val); // 为字段赋值
existContent = StringUtils.isNotBlank(val) || existContent; // 内容是否存在
}
}
// map
if (Map.class.isAssignableFrom(clazz)) {
Method put = clazz.getMethod("put", Object.class, Object.class);
put.invoke(t, String.join(",", heads), val);
existContent = StringUtils.isNotBlank(val) || existContent; // 内容是否存在
}
}
}
// 收集数据
if (Objects.nonNull(t)) {
list.add(t);
}
}
return list;
}
/**
* 获取map<excel头,字段>
*/
private static <T> Map<String, Field> getHeadFieldMap(Class<T> clazz, List<List<String>> heads) {
if (Map.class.isAssignableFrom(clazz)) {
return null;
}
// 存储注解位置-字段
Map<String, Field> indexMap = new HashMap<>(); // 字段-对象属性
Field[] fields = clazz.getDeclaredFields();
// 新表头
if (!CollectionUtils.isEmpty(heads)) {
// 取表头行数
int max = heads.stream().map(List::size).reduce(Integer::max).orElse(0);
for (int i = 0; i < heads.size(); i++) {
List<Field> fs = Arrays.stream(fields).filter(field -> field.isAnnotationPresent(ExcelProperty.class)).collect(Collectors.toList());
List<String> value = new ArrayList<>(heads.get(i));
// 不足时最后一个往后填充
while (value.size() < max) {
value.add(value.get(value.size() - 1));
}
if (i < fs.size()) {
Field field = fs.get(i);
if (field.isAnnotationPresent(ExcelProperty.class)) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
System.out.println(excelProperty);
field.setAccessible(true); // 设置私有字段可赋值
indexMap.put(JsonUtils.getBeanToJson(value), field);
}
}
}
} else {
// 取表头行数
int max = Arrays.stream(fields).filter(field -> field.isAnnotationPresent(ExcelProperty.class))
.map(field -> field.getAnnotation(ExcelProperty.class).value().length).reduce(Integer::max).orElse(0);
for (Field field : fields) {
if (field.isAnnotationPresent(ExcelProperty.class)) {
field.setAccessible(true); // 设置私有字段可赋值
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
// 没设置值或者设了一个空串时按字段名称处理
int vl = excelProperty.value().length;
List<String> value = vl == 0 || vl == 1 && "".equals(excelProperty.value()[0]) ? Stream.of(field.getName()).collect(Collectors.toList())
: Stream.of(excelProperty.value()).collect(Collectors.toList());
// 不足时最后一个往后填充
while (value.size() < max) {
value.add(value.get(value.size() - 1));
}
indexMap.put(JsonUtils.getBeanToJson(value), field);
}
}
}
return indexMap;
}
}
ImageCallBack 回调
/**
* 图片回调
*/
public interface ImageCallBack {
/**
* 导入或上传或读excel时处理:图片回调
*
* @param pictureData 图片数据
* @return 图片处理后的路径
*/
String imgCallback(PictureData pictureData) throws Exception;
}
测试
@GetMapping("/test2")
@ApiOperation(value = "测试excel图片导入", notes = "测试excel图片导入")
public JsonReturn test2(@RequestParam("file") MultipartFile file) throws Exception {
List<User> users = ExcelUtils.excelImageRead(file.getInputStream(), User.class, 1, null, pictureData -> "此处处理图片逻辑,如上传后返回路径等");
return JsonReturn.ok(users);
}
@GetMapping("/test3")
@ApiOperation(value = "测试excel图片导入", notes = "测试excel图片导入")
public JsonReturn test3(@RequestParam("file") MultipartFile file) throws Exception {
List<List<String>> heads = Stream.of("A", "B", "C", "D", "E", "F", "G").map(Collections::singletonList).collect(Collectors.toList()); //此处可以自定义表头,则User表头注解失效
List<User> users = ExcelUtils.excelImageRead(file.getInputStream(), User.class, 1, heads, pictureData -> "此处处理图片逻辑");
return JsonReturn.ok(users);
}
/**
* 测试可用的对象,可删
*/
@HeadStyle(fillForegroundColor = 1)
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@ExcelProperty(value = {"商品名称"})
private String name;
@ExcelProperty(value = {"商品图片"})
private String img;
//get set方法自己写。。。
}
写完了,又不想写了,写文章真累啊!!!!
相关内容:
https://blog.csdn.net/jingxin_123/article/details/138522876