zoukankan      html  css  js  c++  java
  • ApachePOI的基本使用

    前言

    很多时候,一个软件应用程序需要生成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

  • 相关阅读:
    Web安全测试
    性能测试---并发用户计算
    浅谈软件性能测试中关键指标的监控与分析
    fiddler抓包——IOS
    Linux下查看CPU型号,内存大小,硬盘空间,进程等的命令(详解)
    windows 升级pip
    java 使用Iterator 迭代器遍历AList、Set、Map
    springboot 封装redis工具类
    idea 取消@Autowired 不建议字段注入的警告
    查看服务器相关
  • 原文地址:https://www.cnblogs.com/zk2020/p/15563510.html
Copyright © 2011-2022 走看看