ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java 上传Excel 文档解析成对象

2021-09-20 15:33:41  阅读:253  来源: 互联网

标签:Java String valueOf Excel entity field 文档 import null


日常开发过程中经常有需要上传Excel文档的需求,今天就给大家总结一篇比较好用的API接口。

1、首先引入jar

       <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>

2、工具类伪代码:

import com.google.common.collect.Maps;
import com.nandao.demo.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;

/**
 * @author wanghuainan
 * @date 2017/9/6 16:05
 */
@Slf4j
public class PoiUtil<T> {
    Class<T> clazz;

    /**
     * 有参构造函数
     * @param clazz
     */
    public PoiUtil(Class<T> clazz) {
        this.clazz = clazz;
    }

    public List<T> importExcel(Integer sheetIndex, MultipartFile file) throws Exception {
        int maxCol = 0;
        List<T> list = new ArrayList<T>();//定义范型的集合
        Workbook workbook = null;
        if (file.getOriginalFilename().endsWith("xls")) {
            workbook = new HSSFWorkbook(file.getInputStream());
        } else {
            workbook = new XSSFWorkbook(file.getInputStream());
        }
        if (sheetIndex == null) {
            sheetIndex = 0;
        }
        Sheet sheet = workbook.getSheetAt(sheetIndex);
        int rows = sheet.getPhysicalNumberOfRows();
        // 有数据时才处理
        if (rows > 0) {
            /**
             * 通过反射取出实体的每个参数
             */
            List<Field> allFields = getMappedFiled(clazz, null);

            // 定义一个map用于存放列的序号和field.
            Map<Integer, Field> fieldsMap = Maps.newHashMap();
            Row titleRow = sheet.getRow(0);
            for (Field field : allFields) {//遍历每个参数
                // 将有注解的field存放到map中.
                if (field.isAnnotationPresent(ExcelVOAttribute.class)) {//参数上是否有注解
                    /**
                     * 取出注解,并取出注解里面的参数,逐个匹配
                     */
                    ExcelVOAttribute attr = field.getAnnotation(ExcelVOAttribute.class);
                    // 获得列号
                    int col = getExcelCol(attr.column());
                    maxCol = Math.max(col, maxCol);
                    // 设置类的私有字段属性可访问.
                    field.setAccessible(true);
                    fieldsMap.put(col, field);
                    //校验标题必填列是否与模板一致
                    if (attr.required()) {
                        Cell cell = titleRow.getCell(col);
                        String title = null;
                        if (cell != null) {
                            title = cell.getStringCellValue();
                        }//校验标题和模版中是否一致
                        if (title == null || !title.trim().equals(attr.templateName())) {
                            throw new BizException(ResultCode.PARAM_ERROR.getCode(), "请检查导入模板,第" + (col + 1) + "列标题与模板不一致!");
                        }
                    }
                }
            }
            // 从第2行开始取数据,默认第一行是表头.
            for (int i = 1; i < rows; i++) {
                Row row = sheet.getRow(i);

                //判断空行
                if (isEmptyRow(row)) {
                    break;
                }

                int cellNum = maxCol;
                T entity = null;
                for (int j = 0; j <= cellNum; j++) {
                    Cell cell = row.getCell(j);
                    Field field = fieldsMap.get(j);
                    ExcelVOAttribute attr = field.getAnnotation(ExcelVOAttribute.class);
                    String filedName = attr.templateName();
                    Class<?> fieldType = field.getType();
                    if (cell == null) {
                        if (attr.required()) {
                            throw new BizException(ResultCode.PARAM_ERROR.getCode(), filedName + "不能为空,第" + (i + 1) + "行数据" + filedName + "为空!");
                        } else {
                            continue;
                        }
                    }
                    int cellType = cell.getCellType();
                    String c = "";
                    if (cellType == Cell.CELL_TYPE_NUMERIC) {
                        NumberFormat numberFormat = NumberFormat.getInstance();//防止数值转换成Doule小数点类型
                        // 不显示千位分割符,否则显示结果会变成类似1,234,567,890
                        numberFormat.setGroupingUsed(false);
                        if (String.valueOf(cell.getNumericCellValue()).indexOf("E") == -1) {
                            c = String.valueOf(numberFormat.format(cell.getNumericCellValue()));
                        } else {
                            if (String.valueOf(cell.getNumericCellValue()).indexOf("-") == -1) {
                                BigDecimal bd = new BigDecimal(String.valueOf(cell.getNumericCellValue()));
                                c = String.valueOf(bd.longValueExact());
                            } else {
                                BigDecimal bd = new BigDecimal(String.valueOf(cell.getNumericCellValue()));
                                c = bd.toString();
                            }
//                            c = String.valueOf(new DecimalFormat("#").format(cell.getNumericCellValue()));
                        }
                    } else if (cellType == Cell.CELL_TYPE_BOOLEAN) {
                        c = String.valueOf(cell.getBooleanCellValue()).trim();
                    } else {
                        c = cell.getStringCellValue().trim();
                    }

                    if (c == null || StringUtils.isEmpty(c)) {
                        if (attr.required()) {
                            throw new BizException(ResultCode.PARAM_ERROR.getCode(), filedName + "不能为空,第" + (i + 1) + "行数据" + filedName + "为空!");
                        } else {
                            continue;
                        }
                    }
                    try {
                        entity = (entity == null ? clazz.newInstance() : entity);
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    if (field == null) {
                        continue;
                    }
                    try {
                        // 取得类型,并根据对象类型设置值.
                        if (String.class == fieldType) {
                            field.set(entity, c);
                        } else if ((Integer.TYPE == fieldType)
                                || (Integer.class == fieldType)) {
                            field.set(entity, Integer.valueOf(c));
                        } else if ((Long.TYPE == fieldType)
                                || (Long.class == fieldType)) {
                            field.set(entity, Long.valueOf(c));
                        } else if ((Float.TYPE == fieldType)
                                || (Float.class == fieldType)) {
                            field.set(entity, Float.valueOf(c));
                        } else if ((Short.TYPE == fieldType)
                                || (Short.class == fieldType)) {
                            field.set(entity, Short.valueOf(c));
                        } else if ((Double.TYPE == fieldType)
                                || (Double.class == fieldType)) {
                            field.set(entity, Double.valueOf(c));
                        } else if (Character.TYPE == fieldType) {
                            if ((c != null) && (c.length() > 0)) {
                                field.set(entity, Character
                                        .valueOf(c.charAt(0)));
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new BizException(ResultCode.PARAM_ERROR.getCode(), "第" + (i + 1) + "行数据" + filedName + "格式非法,请检查EXCEL");
                    }
                }
                if (entity != null) {
                    list.add(entity);
                }
            }
        }
        return list;
    }
}

通过反射取参数的代码:

 
    private List<Field> getMappedFiled(Class clazz, List<Field> fields) {
        if (fields == null) {
            fields = new ArrayList<Field>();
        }

        Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段
        // 得到所有field并存放到一个list中.
        for (Field field : allFields) {
            if (field.isAnnotationPresent(ExcelVOAttribute.class)) {
                fields.add(field);
            }
        }
        if (clazz.getSuperclass() != null
                && !clazz.getSuperclass().equals(Object.class)) {
            getMappedFiled(clazz.getSuperclass(), fields);
        }

        return fields;
    }

 自定义注解:

/**
 * @author wanghuainan
 * @date 2017/9/6 16:10
 */
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target( { java.lang.annotation.ElementType.FIELD })
public @interface ExcelVOAttribute {

    /**
     * 导出到Excel中的名字.
     */
    String name() default "";

    /**
     * 下载模板中的名字.
     */
    String templateName() default "";

    /**
     * 配置列的名称,对应A,B,C,D....
     */
    String column();

    boolean required() default false;
    /**
     * 导出到Excel中的宽度.
     */
    String width() default "";

    /**
     * 提示信息
     */
    String prompt() default "";

    /**
     * 设置只能选择不能输入的列内容.
     */
    String[] combo() default {};

    /**
     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
     */
    boolean isExport() default true;
}

3、控制层的代码:

/**
     * 上传excel表格
     * @param file
     * @return
     */
    @RequestMapping("uploadExcel")
    public R uploadExcel(@RequestParam("file") MultipartFile file){
        /**
         * 通过有参构造函数创建工具类
         */
        PoiUtil<UserInfoVoTemplate> userVoTemplatePoi = new PoiUtil(UserInfoVoTemplate.class);
        List<UserInfoVoTemplate> userVoTemplateExcels = null;
        List<Long> userIdList = new ArrayList<>();
        try {
            /**
             * 正式取出excel中的内容生成list集合
             */
            userVoTemplateExcels = userVoTemplatePoi.importExcel(0, file);
            /**
             * 通过流式变成取某个参数和成集合
             */
            userIdList = userVoTemplateExcels.stream().map(u ->u.getUserId()).collect(Collectors.toList());
            log.info("上传的用户id:[{}]",userIdList.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.ok();
    }

定义的对象:

package com.nandao.demo.entity;

import com.nandao.demo.common.ExcelVOAttribute;
import lombok.Data;

import java.io.Serializable;

/**
 * @author wanghuainan
 * @date 2017/9/06
 */
@Data
public class UserInfoVoTemplate implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 用户id
     */
    @ExcelVOAttribute(templateName = "用户主键", name = "用户主键", column = "A", width = "4000", required = true)
    private Long userId;


}

集成结束,然后通过postman,就可以测试了,后期我们还会分享一篇关于生成Excel文档的文章,敬请期待!

标签:Java,String,valueOf,Excel,entity,field,文档,import,null
来源: https://blog.csdn.net/nandao158/article/details/120391252

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有