poi解析excel,将每一行数据注入到对应的entity实体对象对象中

20190723更新一个bug

  1. 在getValueFromCell()方法中
    String typeName = expectClazz.getTypeName();
    变更为
    String typeName = expectClazz.getSimpleName();
  2. 同时增加支持类型限制,也就是其中的supportTypeList,表达了该工具类支持excel中的数据类型

贼好用的代码,直接上辽

依赖给上

<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.11</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.11</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.11</version>
		</dependency>
/**测试用的实体类**/
public class GameScene {
    public int id;
    public String name;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    @Override
    public String toString() {
        return "GameScene{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

//取出方法引用
public class Ref<T> {
    public T ref;

    public T getRef() {
        return ref;
    }

    public void setRef(T ref) {
        this.ref = ref;
    }
}

package org.sq.gameDemo.svr.common;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Row;
import org.sq.gameDemo.svr.game.skills.model.Skill;

import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class PoiUtil {

    public static List<String> supportTypeList =
            Arrays.asList("int", "Integer", "float", "Float", "long", "Long", "double", "Double", "String");

    /**
     * 主方法
     * @param fileName excel文件流
     * @param sheetNum 第sheetNum个表格
     * @param clazz 实体class
     * @return
     * @throws Exception
     */
    public static List readExcel(String fileName, int sheetNum, Class clazz) throws Exception{
        //1.读取Excel文档对象
        //将class的Field的名称<name, setName()>记录到map中
        Map<String, Method> setMethodMap = new HashMap<>();
        for (Field field : clazz.getDeclaredFields()) {
            String name = field.getName();
            if(supportTypeList.contains(field.getType().getSimpleName())) {
                try{
                    Method setMethod = clazz.getDeclaredMethod(
                            "set" + String.valueOf(name.charAt(0)).toUpperCase()+ field.getName().substring(1),
                            field.getType());
                    setMethodMap.put(name, setMethod);
                }catch (NoSuchMethodException e) {
                    continue;
                }

            }
        }

        ArrayList excelData = new ArrayList<>();
        HSSFWorkbook hssfWorkbook = null;
        try {
            File file = new File(fileName);
            InputStream resourceAsStream = PoiUtil.class.getClassLoader().getResourceAsStream(fileName);
            hssfWorkbook = new HSSFWorkbook(resourceAsStream);
            HSSFSheet sheet = hssfWorkbook.getSheetAt(sheetNum);
            int lastRowNum = sheet.getLastRowNum();
            //Ref为了将第一行标题取出来
            Ref<List> listRef = new Ref<>();
            getSingleRow(sheet, 0, setMethodMap, listRef, clazz);//<1,name>

            //将每一行的数据注入到class实例中并保存在list中
            for(int i = 1;i <= lastRowNum; i++) {
                try {
                    Object singleRow = getSingleRow(sheet, i, setMethodMap, listRef, clazz);
                    excelData.add(singleRow);
                }catch (Exception e) {
                    throw new Exception("该路径下 " + file.getPath() + " 文件内容有誤");
                }
            }
            return excelData;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据传入的clazz 将每一行的数据填充到clazz.instance的实例中,然后返回
     * @param sheet
     * @param rowNum 取第rownum行
     * @param setMethod class中所有属性对应set属性方法的map映射;譬如class类中 public String name; 就会有-> <name, setName()>
     * @param listRef 引用,从参数取方法中的某个局部变量的引用
     * @param clazz 实例类变量
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchFieldException
     */
    private static Object getSingleRow(HSSFSheet sheet, int rowNum, Map<String, Method> setMethod, Ref<List> listRef, Class clazz) throws Exception {
        HSSFRow row = sheet.getRow(rowNum);

        if(!checkRow(row, rowNum, setMethod)) {
            System.out.println("err: 第" + (rowNum + 1) + "行數據有误");
            throw new Exception("PoiUtil -> excel文件有誤");
        }

        //此次读取是否为标题行读取
        boolean titleRow = (rowNum == 0 && Objects.isNull(listRef.ref));
        List<Object> rowData = new ArrayList<>();
        Object instance = clazz.newInstance();
        int lastCellNum = row.getLastCellNum() & '\uffff'; //盗poi的...

        for(int j = 0; j < lastCellNum; j++) {
            HSSFCell cell = row.getCell(j);
            Object value;
            if(titleRow) {
                value = getValueFromCell(cell, String.class);
                rowData.add(j, value);
            } else {
                //实例化Class对象,并注入数据
                Field declaredField = clazz.getDeclaredField(String.valueOf(listRef.ref.get(j)));
                Class<?> type = declaredField.getType();
                value = getValueFromCell(cell, type);
                Method set = setMethod.get(listRef.ref.get(j));
                set.invoke(instance, value);
            }

        }
        if(titleRow) {
            listRef.ref = rowData;
        }
        return instance;
    }

    /**
     * 获取单元格内容
     * @param cell 单元格
     * @param expectClazz 期望的单元格内容的数据类型
     * @return
     */
    private static Object getValueFromCell(HSSFCell cell, Class expectClazz) {
        Object value = null;
        //**--更改**String typeName = expectClazz.getTypeName();
        String typeName = expectClazz.getSimpleName();

        switch (cell.getCellType()) {
            case HSSFCell.CELL_TYPE_STRING:
                value = cell.getStringCellValue();
                break;
            case HSSFCell.CELL_TYPE_NUMERIC:
                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    if (date != null) {
                        if(typeName.equals("String")) {
                            value = new SimpleDateFormat("yyyy-MM-dd").format(date);
                        }
                        if(typeName.equals("Date")) {
                            value = date;
                        }
                    } else {
                        value = null;
                    }
                } else {
                    Double cellValue = cell.getNumericCellValue();
                    value = new DecimalFormat("0").format(cellValue);
                    //做一个基本类型的兼容
                   if(typeName.equals("int") || typeName.equals("Integer")) {
                        value = cellValue.intValue();
                    }
                    if(typeName.equals("double") || typeName.equals("Double")) {
                        value = cellValue.doubleValue();
                    }
                    if(typeName.equals("float") || typeName.equals("Float")) {
                        value = cellValue.floatValue();
                    }
                    if(typeName.equals("long") || typeName.equals("Long")) {
                        value = cellValue.longValue();
                    }
                }
                break;
            case HSSFCell.CELL_TYPE_FORMULA:
                // 导入时如果为公式生成的数据则无值
                if (!cell.getStringCellValue().equals("")) {
                    value = cell.getStringCellValue();
                } else {
                    value = cell.getNumericCellValue() + "";
                }
                break;
            case HSSFCell.CELL_TYPE_BLANK:
                break;
            case HSSFCell.CELL_TYPE_ERROR:
                break;
            case HSSFCell.CELL_TYPE_BOOLEAN:
                value = cell.getBooleanCellValue();
                break;
            default:
                value = null;
        }
        return value;
    }


    private static boolean checkRow(Row row, int rowNum, Map<String, Method> setMethod) {
        int lastCellNum = row.getLastCellNum() & '\uffff'; //盗poi的...
        if(lastCellNum > setMethod.keySet().size()) {
            return false;
        }
        return true;
    }

      //-----------------------测试代码
    public static void main(String[] args) {
        try {
            List list = readExcel(new File("C:\\code\\sence.xls"), 0, GameScene.class);
            list.forEach(sence->{
                System.out.println(sence.toString());
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }




}




}

结果截图

在这里插入图片描述在这里插入图片描述


挺好用的其实…本着开源精神,特此贡献
|
|
|
|
author : kevins | qq : 276368974
|
|
|
|
end

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
您可以使用 Apache POI 库来操作 Excel 文件。具体来说,以下是实现您所描述的操作的大致步骤: 1. 读取 Excel 文件,并获取要复制的行的样式和格式。 2. 创建一个新的行,将获取的样式和格式应用到该行。 3. 将要插入的行插入到指定的位置。 4. 将新创建的行的数据复制到要插入的行。 5. 根据需要,合并单元格。 下面是一个简单的示例代码,可以帮助您更好地理解这一过程: ``` // 读取 Excel 文件 FileInputStream inputStream = new FileInputStream(new File("example.xlsx")); Workbook workbook = new XSSFWorkbook(inputStream); Sheet sheet = workbook.getSheetAt(0); // 获取要复制的行的样式和格式 Row sourceRow = sheet.getRow(0); CellStyle sourceStyle = sourceRow.getRowStyle(); short sourceHeight = sourceRow.getHeight(); int sourceNumMergedRegions = sheet.getNumMergedRegions(); // 创建新的行并应用样式和格式 Row newRow = sheet.createRow(2); newRow.setHeight(sourceHeight); newRow.setRowStyle(sourceStyle); // 插入新的行 sheet.shiftRows(2, sheet.getLastRowNum(), 1, true, true); // 复制数据到新的行 for (int i = 0; i < sourceRow.getLastCellNum(); i++) { Cell oldCell = sourceRow.getCell(i); Cell newCell = newRow.createCell(i); if (oldCell != null) { newCell.setCellValue(oldCell.getStringCellValue()); } } // 根据需要合并单元格 for (int i = 0; i < sourceNumMergedRegions; i++) { CellRangeAddress sourceRange = sheet.getMergedRegion(i); if (sourceRange.getFirstRow() == sourceRow.getRowNum()) { CellRangeAddress newRange = new CellRangeAddress(newRow.getRowNum(), newRow.getRowNum() + sourceRange.getLastRow() - sourceRange.getFirstRow(), sourceRange.getFirstColumn(), sourceRange.getLastColumn()); sheet.addMergedRegion(newRange); } } // 保存 Excel 文件 FileOutputStream outputStream = new FileOutputStream("example.xlsx"); workbook.write(outputStream); workbook.close(); outputStream.close(); ``` 请注意,这只是一个简单的示例,并且可能需要根据您的具体要求进行修改。此外,要使用 Apache POI 库,您需要在项目添加相应的依赖项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值