通用 excel 模板导入工具类

简介:

工具类支持 2003/2007 excel

主要根据 excel 模板上的某一行指定 Java bean 的属性列名,再使用 java 反射,进行实体对象的构造

使用者可以根据业务需要对该工具类自行扩展

模板样式:

java导入excel后公式精度丢失 java excel导入工具类_java导入excel后公式精度丢失


代码实现:

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by xiaofeng.he on 2018/06/22
 * poi 实现 excel 导入 工具类
 */
public class ImportExcelUtil {

    //正则表达式 用于匹配属性的第一个字母
    private static final String REGEX = "[a-zA-Z]";

    /**
     * Excel数据转 list
     * @param originUrl Excel表的所在路径
     * @param datePattern 日期格式 如"yyyy-MM-dd hh:mm:ss"
     * @param filedsIndex 模板定义的属性名的行位置
     * @param startRow 从第几行开始
     * @param endRow 到第几行结束 (0表示所有行;正数表示到第几行结束;负数表示到倒数第几行结束)
     * @param clazz 要返回的对象集合的类型
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> List<T> importExcel(String originUrl, String datePattern, int filedsIndex, int startRow, int endRow, Class<T> clazz) throws IOException {
        // 判断文件是否存在
        File file = new File(originUrl);
        if (!file.exists()) {
            throw new IOException("文件名为" + file.getName() + "Excel文件不存在!");
        }
        InputStream fis = new FileInputStream(file);

        return doImportExcel(fis, datePattern, filedsIndex, startRow, endRow, clazz);
    }

    /**
     * Excel数据转 list
     * @param inputStream Excel文件输入流
     * @param datePattern 日期格式 如"yyyy-MM-dd hh:mm:ss"
     * @param filedsIndex 模板定义的属性名的行位置
     * @param startRow 从第几行开始
     * @param endRow 到第几行结束 (0表示所有行;正数表示到第几行结束;负数表示到倒数第几行结束)
     * @param clazz 要返回的对象集合的类型
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> List<T> importExcel(InputStream inputStream, String datePattern, int filedsIndex, int startRow, int endRow, Class<T> clazz) throws IOException {
        return doImportExcel(inputStream, datePattern, filedsIndex, startRow, endRow, clazz);
    }

    /**
     * 真正实现
     * @param inputStream
     * @param datePattern
     * @param filedsIndex
     * @param startRow
     * @param endRow
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    private static <T> List<T> doImportExcel(InputStream inputStream, String datePattern, int filedsIndex, int startRow, int endRow, Class<T> clazz) throws IOException {
        Workbook wb;
        Sheet sheet;
        Row filedsRow = null;
        List<Row> rowList = new ArrayList<>();
        try {
            // 去读Excel
            // HSSFWorkbook wb = new HSSFWorkbook(fis);
            // 使用workbook 支持2003/2007
            wb = WorkbookFactory.create(inputStream);
            sheet = wb.getSheetAt(0);
            // 获取最后行号
            int lastRowNum = sheet.getLastRowNum();

            int rowLength = lastRowNum;
            if (endRow > 0) {
                rowLength = endRow;
            } else if (endRow < 0) {
                rowLength = lastRowNum + endRow;
            }

            // 获取属性列字段
            filedsRow = sheet.getRow(filedsIndex);
            // 循环读取
            Row row;
            for (int i = startRow; i <= rowLength; i++) {
                row = sheet.getRow(i);
                rowList.add(row);
            }

        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } catch (InvalidFormatException e1) {
            e1.printStackTrace();
        }

        return returnObjectList(datePattern, filedsRow, rowList, clazz);
    }

    /**
     * 功能:返回指定的对象集合
     */
    private static <T>List<T> returnObjectList(String datePattern, Row filedsRow, List<Row> rowList,Class<T> clazz) {
        List<T> objectList=new ArrayList<>();
        try {
            T obj;
            String attribute;
            String value;

            for (Row row : rowList) {
                obj = clazz.newInstance();
                for (int j = 0; j < filedsRow.getLastCellNum(); j++) {
                    attribute = getCellValue(filedsRow.getCell(j));
                    if (!attribute.equals("")) {
                        value = getCellValue(row.getCell(j));
                        setAttrributeValue(obj, attribute, value, datePattern);
                    }
                }
                objectList.add(obj);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return objectList;
    }

    /**
     * 功能:获取单元格的值
     */
    private static String getCellValue(Cell cell) {
        Object result = "";
        if (cell != null) {
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_STRING:
                    result = cell.getStringCellValue();
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    result = cell.getNumericCellValue();
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    result = cell.getBooleanCellValue();
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    result = cell.getCellFormula();
                    break;
                case Cell.CELL_TYPE_ERROR:
                    result = cell.getErrorCellValue();
                    break;
                case Cell.CELL_TYPE_BLANK:
                    break;
                default:
                    break;
            }
        }
        return result.toString();
    }

    /**
     * 功能:给指定对象的指定属性赋值
     */
    private static void setAttrributeValue(Object obj,String attribute,String value, String datePattern) {
        //得到该属性的set方法名
        String method_name = convertToMethodName(attribute,obj.getClass(),true);
        Method[] methods = obj.getClass().getMethods();
        for (Method method : methods) {
            /**
             * 因为这里只是调用bean中属性的set方法,属性名称不能重复
             * 所以set方法也不会重复,所以就直接用方法名称去锁定一个方法
             * (注:在java中,锁定一个方法的条件是方法名及参数)
             */
            if(method.getName().equals(method_name)) {
                Class<?>[] parameterC = method.getParameterTypes();
                try {
                    /**如果是(整型,浮点型,布尔型,字节型,时间类型),
                     * 按照各自的规则把value值转换成各自的类型
                     * 否则一律按类型强制转换(比如:String类型)
                     */
                    if(parameterC[0] == int.class || parameterC[0]==java.lang.Integer.class) {
                        if(value != null && value.length() > 0) {
                            value = value.substring(0, value.lastIndexOf("."));
                            method.invoke(obj,Integer.valueOf(value));
                        }

                        break;
                    } else if(parameterC[0] == long.class || parameterC[0]==java.lang.Long.class) {
                        if(value != null && value.length() > 0) {
                            value = value.substring(0, value.lastIndexOf("."));
                            method.invoke(obj,Long.valueOf(value));
                        }
                        break;
                    } else if(parameterC[0] == float.class || parameterC[0]==java.lang.Float.class) {
                        if(value != null && value.length() > 0) {
                            method.invoke(obj, Float.valueOf(value));
                        }
                        break;
                    } else if(parameterC[0] == double.class || parameterC[0]==java.lang.Double.class) {
                        if(value != null && value.length() > 0) {
                            method.invoke(obj, Double.valueOf(value));
                        }
                        break;
                    } else if(parameterC[0] == byte.class || parameterC[0]==java.lang.Byte.class) {
                        if(value != null && value.length() > 0) {
                            method.invoke(obj, Byte.valueOf(value));
                        }
                        break;
                    } else if(parameterC[0] == boolean.class|| parameterC[0]==java.lang.Boolean.class) {
                        if (value != null && value.length() > 0) {
                            method.invoke(obj, Boolean.valueOf(value));
                        }
                        break;
                    } else if(parameterC[0] == java.util.Date.class) {
                        if(value != null && value.length() > 0) {
                            SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
                            Date date=null;
                            try {
                                date=sdf.parse(value);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            method.invoke(obj,date);
                        }

                        break;
                    } else if(parameterC[0] == java.math.BigDecimal.class) {
                        if (value != null && value.length() > 0) {
                            method.invoke(obj, new BigDecimal(value));
                        }
                        break;
                    } else {
                        if (value != null && value.length() > 0) {
                            method.invoke(obj,parameterC[0].cast(value));
                        }
                        break;
                    }
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (SecurityException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 功能:根据属性生成对应的set/get方法
     */
    private static String convertToMethodName(String attribute,Class<?> objClass,boolean isSet) {
        /** 通过正则表达式来匹配第一个字符 **/
        Pattern p = Pattern.compile(REGEX);
        Matcher m = p.matcher(attribute);
        StringBuilder sb = new StringBuilder();
        /** 如果是set方法名称 **/
        if(isSet) {
            sb.append("set");
        } else {
            /** get方法名称 **/
            try {
                Field attributeField = objClass.getDeclaredField(attribute);
                /** 如果类型为boolean **/
                if(attributeField.getType() == boolean.class||attributeField.getType() == Boolean.class) {
                    sb.append("is");
                } else {
                    sb.append("get");
                }
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
        /** 针对以下划线开头的属性 **/
        if(attribute.charAt(0)!='_' && m.find()) {
            sb.append(m.replaceFirst(m.group().toUpperCase()));
        } else {
            sb.append(attribute);
        }
        return sb.toString();
    }

}

调用示例:

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

/**
 * Created by xiaofeng.he on 2018/06/22
 * 测试类
 */
public class APP {

    public static void main(String[] args) {
        String originUrl="D:\\doc\\prepayment_template.xls";
        int startRow=2;
        int endRow=-1;
        int filedsIndex = 0;
        List<ApRequisitionLine> linesList;
        try {
            linesList = ImportExcelUtil.importExcel(originUrl,"yyyy-MM-dd HH:mm:ss", filedsIndex, startRow, endRow, ApRequisitionLine.class);
            for (ApRequisitionLine lines : linesList) {
                System.out.println(lines);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static class ApRequisitionLine extends AA {
        @Id
        @GeneratedValue
        private Long requisitionLineId;

        @NotNull
        private Long requisitionId;

        @NotNull
        private Long lineNum;

        private String expenseTypeCode;

        private String soNumber;

        private Long soLineNum;

        private String poNumber;

        private Long poLineNum;

        private String parkNumber;

        private String projectNum;

        private String internalOrderNumber;

        private BigDecimal lineAmount;

        private BigDecimal baseLineAmount;

        private BigDecimal contractAmount;

        private BigDecimal prepayRatio;

        private String costcentreCode;

        private String profitCentre;

        private String factoryCode;

        private String customsDeclarationNum;

        private Long chargeAmount;

        private String drCrDirection;//借贷方向,HSS_GA_DR_CR_DIRECTION

        private String account;

        private String sgl;

        private String customerCode;

        private String comments;

        @Transient
        private String costcentreName;//成本中心名称

        @Transient
        private String profitCentreName;//利润中心名称

        @Transient
        private String companyCode;//公司编码

        @Transient
        private String sglMeaning;//sgl名称

        @Transient
        private String flexValueMeaning;//成本中心含义


        public void setRequisitionLineId(Long requisitionLineId) {
            this.requisitionLineId = requisitionLineId;
        }

        public Long getRequisitionLineId() {
            return requisitionLineId;
        }

        public void setRequisitionId(Long requisitionId) {
            this.requisitionId = requisitionId;
        }

        public Long getRequisitionId() {
            return requisitionId;
        }

        public void setLineNum(Long lineNum) {
            this.lineNum = lineNum;
        }

        public Long getLineNum() {
            return lineNum;
        }

        public void setExpenseTypeCode(String expenseTypeCode) {
            this.expenseTypeCode = expenseTypeCode;
        }

        public String getExpenseTypeCode() {
            return expenseTypeCode;
        }

        public void setSoNumber(String soNumber) {
            this.soNumber = soNumber;
        }

        public String getSoNumber() {
            return soNumber;
        }

        public void setSoLineNum(Long soLineNum) {
            this.soLineNum = soLineNum;
        }

        public Long getSoLineNum() {
            return soLineNum;
        }

        public void setPoNumber(String poNumber) {
            this.poNumber = poNumber;
        }

        public String getPoNumber() {
            return poNumber;
        }

        public void setPoLineNum(Long poLineNum) {
            this.poLineNum = poLineNum;
        }

        public Long getPoLineNum() {
            return poLineNum;
        }

        public void setParkNumber(String parkNumber) {
            this.parkNumber = parkNumber;
        }

        public String getParkNumber() {
            return parkNumber;
        }

        public void setProjectNum(String projectNum) {
            this.projectNum = projectNum;
        }

        public String getProjectNum() {
            return projectNum;
        }

        public void setInternalOrderNumber(String internalOrderNumber) {
            this.internalOrderNumber = internalOrderNumber;
        }

        public String getInternalOrderNumber() {
            return internalOrderNumber;
        }

        public BigDecimal getLineAmount() {
            return lineAmount;
        }

        public void setLineAmount(BigDecimal lineAmount) {
            this.lineAmount = lineAmount;
        }

        public BigDecimal getBaseLineAmount() {
            return baseLineAmount;
        }

        public void setBaseLineAmount(BigDecimal baseLineAmount) {
            this.baseLineAmount = baseLineAmount;
        }

        public BigDecimal getContractAmount() {
            return contractAmount;
        }

        public void setContractAmount(BigDecimal contractAmount) {
            this.contractAmount = contractAmount;
        }

        public BigDecimal getPrepayRatio() {
            return prepayRatio;
        }

        public void setPrepayRatio(BigDecimal prepayRatio) {
            this.prepayRatio = prepayRatio;
        }

        public void setCostcentreCode(String costcentreCode) {
            this.costcentreCode = costcentreCode;
        }

        public String getCostcentreCode() {
            return costcentreCode;
        }

        public void setProfitCentre(String profitCentre) {
            this.profitCentre = profitCentre;
        }

        public String getProfitCentre() {
            return profitCentre;
        }

        public void setFactoryCode(String factoryCode) {
            this.factoryCode = factoryCode;
        }

        public String getFactoryCode() {
            return factoryCode;
        }

        public void setCustomsDeclarationNum(String customsDeclarationNum) {
            this.customsDeclarationNum = customsDeclarationNum;
        }

        public String getCustomsDeclarationNum() {
            return customsDeclarationNum;
        }

        public void setChargeAmount(Long chargeAmount) {
            this.chargeAmount = chargeAmount;
        }

        public Long getChargeAmount() {
            return chargeAmount;
        }

        public String getDrCrDirection() {
            return drCrDirection;
        }

        public void setDrCrDirection(String drCrDirection) {
            this.drCrDirection = drCrDirection;
        }

        public void setAccount(String account) {
            this.account = account;
        }

        public String getAccount() {
            return account;
        }

        public void setSgl(String sgl) {
            this.sgl = sgl;
        }

        public String getSgl() {
            return sgl;
        }

        public void setCustomerCode(String customerCode) {
            this.customerCode = customerCode;
        }

        public String getCustomerCode() {
            return customerCode;
        }

        public void setComments(String comments) {
            this.comments = comments;
        }

        public String getComments() {
            return comments;
        }

        public String getCostcentreName() {
            return costcentreName;
        }

        public void setCostcentreName(String costcentreName) {
            this.costcentreName = costcentreName;
        }

        public String getProfitCentreName() {
            return profitCentreName;
        }

        public void setProfitCentreName(String profitCentreName) {
            this.profitCentreName = profitCentreName;
        }

        public String getCompanyCode() {
            return companyCode;
        }

        public void setCompanyCode(String companyCode) {
            this.companyCode = companyCode;
        }

        public String getSglMeaning() {
            return sglMeaning;
        }

        public void setSglMeaning(String sglMeaning) {
            this.sglMeaning = sglMeaning;
        }

        public String getFlexValueMeaning() {
            return flexValueMeaning;
        }

        public void setFlexValueMeaning(String flexValueMeaning) {
            this.flexValueMeaning = flexValueMeaning;
        }

        @Override
        public String toString() {
            return "ApRequisitionLines{" +
                    "requisitionLineId=" + requisitionLineId +
                    ", requisitionId=" + requisitionId +
                    ", lineNum=" + lineNum +
                    ", expenseTypeCode='" + expenseTypeCode + '\'' +
                    ", soNumber='" + soNumber + '\'' +
                    ", soLineNum=" + soLineNum +
                    ", poNumber='" + poNumber + '\'' +
                    ", poLineNum=" + poLineNum +
                    ", parkNumber='" + parkNumber + '\'' +
                    ", projectNum='" + projectNum + '\'' +
                    ", internalOrderNumber='" + internalOrderNumber + '\'' +
                    ", lineAmount=" + lineAmount +
                    ", baseLineAmount=" + baseLineAmount +
                    ", contractAmount=" + contractAmount +
                    ", prepayRatio=" + prepayRatio +
                    ", costcentreCode='" + costcentreCode + '\'' +
                    ", profitCentre='" + profitCentre + '\'' +
                    ", factoryCode='" + factoryCode + '\'' +
                    ", customsDeclarationNum='" + customsDeclarationNum + '\'' +
                    ", chargeAmount=" + chargeAmount +
                    ", drCrDirection='" + drCrDirection + '\'' +
                    ", account='" + account + '\'' +
                    ", sgl='" + sgl + '\'' +
                    ", customerCode='" + customerCode + '\'' +
                    ", comments='" + comments + '\'' +
                    ", costcentreName='" + costcentreName + '\'' +
                    ", profitCentreName='" + profitCentreName + '\'' +
                    ", companyCode='" + companyCode + '\'' +
                    ", sglMeaning='" + sglMeaning + '\'' +
                    ", flexValueMeaning='" + flexValueMeaning + '\'' +
                    '}';
        }
    }

    public static class AA {
        String aa;
    }
}