Apache-POI的基本使用

前言

很多时候,一个软件应用程序需要生成Microsoft Excel文件格式的报告。有时,一个应用程序甚至希望将Excel文件作为输入数据。例如,一个公司开发的应用程序将财务部门需要所有输出生成自己的Excel。
任何Java程序员愿意将MS Office文件的输出,可以使用预定义和只读API来做到。
这个人写的挺不错的可以看看 https://www.cnblogs.com/huajiezh/p/5467821.html

什么是Apache POI?

  • Apache POI是一种流行的API,它允许程序员使用Java程序创建,修改和显示MS Office文件。这由Apache软件基金会开发使用Java分布式设计或修改Microsoft Office文件的开源库。它包含类和方法对用户输入数据或文件到MS Office文档进行解码。
  • 下载地址 http://poi.apache.org/

Apache POI组件说明

Apache POI包含类和方法,来将MS Office所有OLE 2文档复合。此API组件的列表如下。

  1. POIFS (较差混淆技术实现文件系统) : 此组件是所有其他POI元件的基本因素。它被用来明确地读取不同的文件。
  2. HSSF (可怕的电子表格格式) : 它被用来读取和写入MS-Excel文件的xls格式。
  3. XSSF (XML格式) : 它是用于MS-Excel中XLSX文件格式。
  4. HPSF (可怕的属性设置格式) : 它用来提取MS-Office文件属性设置。
  5. HWPF (可怕的字处理器格式) : 它是用来读取和写入MS-Word的文档扩展名的文件。
  6. XWPF (XML字处理器格式) : 它是用来读取和写入MS-Word的docx扩展名的文件。
  7. HSLF (可怕的幻灯片版式格式) : 它是用于读取,创建和编辑PowerPoint演示文稿。
  8. HDGF (可怕的图表格式) : 它包含类和方法为MS-Visio的二进制文件。
  9. HPBF (可怕的出版商格式) : 它被用来读取和写入MS-Publisher文件。

创建 并 将数据写入 xls文件

    //创建 excel 并写入数据到文件
    @Test
    public void test1() throws IOException {
        String[] rowHeads = {"id", "name", "gender", "hobby", "birthday"};//定义第一行的数据
        //1. 创建工作薄
        HSSFWorkbook book = new HSSFWorkbook();
        //2. 创建第一个 sheet【工作表】对象并设置sheet的名字
        HSSFSheet sheet = book.createSheet("学生信息");
//        sheet.getWorkbook().setSheetName(0,"学生信息"); //设置第一个工作表的名字
        //3. 创建第一行,【从0开始】标题
        HSSFRow row = sheet.createRow(0);
        //4. 创建行的单元格
        for (int i = 0; i < rowHeads.length; i++) {
            //创建的单元格
            HSSFCell cell = row.createCell(i);
            //设置设置单元格内容
            cell.setCellValue(rowHeads[i]);
        }
        //5. 创建写入数据
        String[] data = new String[rowHeads.length];
        List<Student> list = new ArrayList<>();
        //创建student 数据
        // public Student(Integer id, String name, Integer gender, String hobby, Date birthday)
        for (int i = 0; i <= 10; i++) {
            list.add(new Student(i + 1,
                    UUID.randomUUID().toString().substring(0, 4),
                    (int) (Math.random() * 2),
                    UUID.randomUUID().toString().substring(0, 4),
                    new Date()));
        }
        //数据写入到 【工作表 0】文件中
        for (int i = 0; i < list.size(); i++) {
            //创建行单元格设置参数【第一行已经有数据了】
            HSSFRow row1 = sheet.createRow(i + 1);
            Student temp = list.get(i);//获取写入的对象,准备写入数据
            //设置单元格内容,重载
            row1.createCell(0).setCellValue(temp.getId());
            row1.createCell(1).setCellValue(temp.getName());
            row1.createCell(2).setCellValue(temp.getGender());
            row1.createCell(3).setCellValue(temp.getHobby());
            //日期格式化
            HSSFCellStyle style = book.createCellStyle(); //创建单元格样式
            //设置 日期格式化的风格
            style.setDataFormat(book.createDataFormat().getFormat("yyyy-MM-dd"));
            //创建行的单元格
            HSSFCell cell = row1.createCell(4);
            cell.setCellStyle(style);//设置样式
            cell.setCellValue(temp.getBirthday());//设置内容
            //row1.createCell(4).setCellValue(temp.getBirthday()); //日期没有格式化
        }
        //6. 把 book写入到目的文件中
        String path = "E:\\sample.xls";
        book.write(new File(path));
        book.close();
        System.out.println("写入成功");
    }

image

根据指定文件读取 xls文件并封装成 java对象

    //读取 excel文件,把 excel中数据每行读成一个对象
    //规则:工作表必须是类名,第一列必须是属性名
    @Test
    public void tese2() throws IOException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        File file = new File("E:\\sample.xls");//文件路径
        String sheetName = "学生信息"; //工作表名
        Class clazz = Student.class;//要保存的Java 对象名

        //1. 创建工作薄:读取源文件
        HSSFWorkbook book = new HSSFWorkbook(new FileInputStream(file));
        //2. 根据工作表名获取一个工作表
        HSSFSheet sheet = book.getSheet(sheetName);
        //3. 获取第一行:列标题 对应的类的属性名
        HSSFRow row = sheet.getRow(0);
        //创建一个数组存储属性名
        ArrayList<String> fieldName = new ArrayList<>();
        Iterator<Cell> iterator = row.cellIterator();
        while (iterator.hasNext()) {
            Cell temp = iterator.next();
            //存储第一行的信息,对象的成员变量
            fieldName.add(temp.getStringCellValue());
        }
//        System.out.println(fieldName);//[id, name, sex, hubby, birthday]
        //遍历其他行并封装对象
        ArrayList<Object> list = new ArrayList<>();
//        System.out.println(sheet.getLastRowNum());//11 最后的位置
        //注意第一行 不是 !!!!
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            //获取改行对象
            HSSFRow tempRow = sheet.getRow(i);
            //每一行对应一个 Java实体对象
            Object transientObj = clazz.newInstance();
            for (short j = 0; j < tempRow.getLastCellNum(); j++) {
                //xls 文件的类型    _NONE(-1),NUMERIC(0),STRING(1),FORMULA(2),BLANK(3),BOOLEAN(4), ERROR(5);
                HSSFCell tempCell = tempRow.getCell(j); //获取每一行的每一个单元格
                CellType type = tempCell.getCellType(); //获取每一个单元格的类型
                Object fieldValue;//设置一个参数用来定义该 单元格的类型
                //处理类型
                if (type == CellType.BOOLEAN) {
                    fieldValue = tempCell.getBooleanCellValue();
                } else if (type == CellType.NUMERIC) {
                    fieldValue = tempCell.getNumericCellValue();
                } else {
                    fieldValue = tempCell.getStringCellValue();
                    System.out.println("value" + fieldValue);
                    System.out.println("type:" + type);
                }

                //给需要实例化的对象 进行字段赋值
                Field field = clazz.getDeclaredField(fieldName.get(j));
                field.setAccessible(true);//暴力访问
                fieldValue = changeValue(field, fieldValue);
                field.set(transientObj, fieldValue);
            }
            list.add(transientObj);
        }
        book.close();
        //打印对象
        System.out.println(list);
    }

    //把 value转换成 field对应的类型
    private static Object changeValue(Field field, Object value) {
        Class type = field.getType();
        if (type == int.class || type == Integer.class) {
            return (int) ((double) value);
        }
        if (type == short.class || type == Short.class) {
            return (short) ((double) value);
        }
        if (type == byte.class || type == Byte.class) {
            return (byte) ((double) value);
        }
        if (type == long.class || type == Long.class) {
            return (long) ((double) value);
        }
        if (type == float.class || type == Float.class) {
            return (float) ((double) value);
        }
        if (type == java.util.Date.class) {
            return new Date((long) ((double) value));
        }
        return value;
    }

读取 excel工具类

import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.ss.usermodel.*;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ Auther: hwj
 * @ Date: 2019/8/8 16:52
 * @ Description: 读取excel工具类
 */
public class ExcelReaderUtil {

    /**
     * @methodName: readExcel 读取excel工具类
     * @param: [is, tClass]  传入的实体类,成员变量类型只能是基本类型和字符串
     * @return: java.util.List<T>
     * @auther: hwj
     * @date: 2019/8/9 11:24
     * @Description: 读取excel文件, 将其转换为javabean
     */
    public static <T> List<T> readExcel2Bean(InputStream is, Class<T> tClass)
            throws IOException, IllegalAccessException, InstantiationException, ParseException {
        List<List<String>> list = ExcelReaderUtil.readExcel(is);
        //-----------------------遍历数据到实体集合开始-----------------------------------
        List<T> listBean = new ArrayList<T>();
        Field[] fields = tClass.getDeclaredFields();
        T uBean = null;
        for (int i = 1; i < list.size(); i++) {// i=1是因为第一行不要
            uBean = (T) tClass.newInstance();
            List<String> listStr = list.get(i);
            for (int j = 0; j < listStr.size(); j++) {
                if (j >= fields.length) {
                    break;
                }
                Field field = fields[j];
                String datastring = listStr.get(j);
                field.setAccessible(true);
                if (datastring.length() > 0) {
                    Class<?> type = field.getType();
                    // 只支持8中基本类型和String类型 如有其他类型 请自行添加[添加日期]
                    if (type == String.class) {
                        field.set(uBean, datastring);
                    } else if (type == Integer.class || type == int.class) {
                        field.set(uBean, Integer.parseInt(datastring));
                    } else if (type == Double.class || type == double.class) {
                        field.set(uBean, Double.parseDouble(datastring));
                    } else if (type == Float.class || type == float.class) {
                        field.set(uBean, Float.parseFloat(datastring));
                    } else if (type == Long.class || type == long.class) {
                        field.set(uBean, Long.parseLong(datastring));
                    } else if (type == Boolean.class || type == boolean.class) {
                        field.set(uBean, Boolean.parseBoolean(datastring));
                    } else if (type == Short.class || type == short.class) {
                        field.set(uBean, Short.parseShort(datastring));
                    } else if (type == Byte.class || type == byte.class) {
                        field.set(uBean, Byte.parseByte(datastring));
                    } else if (type == Character.class || type == char.class) {
                        field.set(uBean, datastring.charAt(0));
                    } else if (type == Date.class) {
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                        field.set(uBean, format.parse(datastring));
                    }
                }
            }
            listBean.add(uBean);
        }
        return listBean;
    }

    /**
     * Excel读取 操作,返回内容
     */
    private static List<List<String>> readExcel(InputStream is)
            throws IOException {
        Workbook wb = null;
        try {
            wb = WorkbookFactory.create(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        /** 得到第一个sheet */
        assert wb != null;
        Sheet sheet = wb.getSheetAt(0);
        /** 得到Excel的行数 */
        int totalRows = sheet.getPhysicalNumberOfRows();
        /** 得到Excel的列数 */
        int totalCells = 0;
        if (totalRows >= 1 && sheet.getRow(0) != null) {
            totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        }
        List<List<String>> dataLst = new ArrayList<List<String>>();
        /** 循环Excel的行 */
        for (int r = 0; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            if (row == null)
                continue;
            List<String> rowLst = new ArrayList<String>();
            /** 循环Excel的列 */
            for (int c = 0; c < totalCells; c++) {
                Cell cell = row.getCell(c);
                String cellValue = "";
                if (null != cell) {
                    HSSFDataFormatter hSSFDataFormatter = new HSSFDataFormatter();
                    cellValue = hSSFDataFormatter.formatCellValue(cell);
                }
                rowLst.add(cellValue);
            }
            /** 保存第r行的第c列 */
            dataLst.add(rowLst);
        }
        return dataLst;
    }
}

创建 excel工具类

  • 自己写的有一个问题,如果集合中数据 属性有为 null则报空指针异常。
import org.apache.poi.hssf.usermodel.*;
import java.io.File;
import java.lang.reflect.Field;
import java.util.*;


/**
 * @author zhaokuii11@163.com
 * @create 2021-11-16 22:11
 * @Description 解析数据 编程 excel 文件
 */
public class ExcelCreateUtil {
    /**
     * 存储数据 map<类型,数据>
     */
    private static Map<Class<?>, List<?>> MAP = new HashMap<>();

    /**
     * 添加数据
     *
     * @param clazz 类型
     * @param list  数据
     */
    public static void mapPut(Class<?> clazz, ArrayList<?> list) {
        MAP.put(clazz, list);
    }


    /**
     * @param path 路径+文件的名字
     * @return 创建了几个 工作薄
     * @throws Exception
     */
    public static Integer createExcel(String path) throws Exception {
        File file = new File(path);
        if (!file.exists() && file.isDirectory()) {
            file.mkdirs(); //如果文件不存在就创建
        }

        if (MAP.size() > 0) {
            //创建工作薄
            HSSFWorkbook workbook = new HSSFWorkbook();
            Set<Class<?>> keySet = MAP.keySet();//所有的 字节码文件
            keySet.forEach(key -> {
                //System.out.println(key);
                //创建第一个工作表:【下标0】
                HSSFSheet sheet = workbook.createSheet(key.getSimpleName());

                //创建行 一行一个对象 第一行是对象的属性名
                HSSFRow heat = sheet.createRow(0);
                Field[] fields = key.getDeclaredFields();
                for (int i = 0; i < fields.length; i++) {
                    //System.out.println(fields[i].getName());
                    heat.createCell(i).setCellValue(fields[i].getName());
                }
                final int[] count = {1};
                MAP.get(key).forEach(instance -> { //instance 集合循环对象
                    //创建单元格 下标+1
                    HSSFRow row = sheet.createRow(count[0]);
                    //写入数据
                    Field[] fieldRow = key.getDeclaredFields();
                    for (int i = 0; i < fieldRow.length; i++) {
                        Field field = fieldRow[i];
                        field.setAccessible(true);

                        try {
                            Class<?> type = field.getType(); //类型
                            Object value = field.get(instance);//值
                            //只能设置 date double boolean string

                            //只设置了包装类
                            if (type == Integer.class || type == Byte.class || type == Short.class || type == Long.class || type == Float.class) {
                                //integer 不能转为 double 类型
                                row.createCell(i).setCellValue(Double.parseDouble(value.toString()));
                            } else if (type == String.class) {
                                row.createCell(i).setCellValue(value.toString());
                            } else if (type == Date.class) {
                                //日期类型封装
                                HSSFCellStyle style = workbook.createCellStyle();
                                style.setDataFormat(workbook.createDataFormat().getFormat("yyyy年MM月dd日"));
                                HSSFCell cell = row.createCell(i);
                                cell.setCellStyle(style);
                                cell.setCellValue((Date) value);
                            } else if (type == Boolean.class) {
                                row.createCell(i).setCellValue((Boolean) value);
                            } else {
                                //其他类型不进行判断直接 toString 返回
                                row.createCell(i).setCellValue(value.toString());
                            }
                            //row.createCell(i).setCellValue(value);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }

                    }
                    count[0]++;
                });
            });

            workbook.write(file);
            workbook.close();
            return MAP.size();
        }
        return -1;
    }

}

其他
其他参考资料 https://blog.csdn.net/Q36_524/article/details/115185218

posted @ 2021-11-16 20:46  MikiKawai  阅读(315)  评论(0编辑  收藏  举报