Excel

1 POI

  • Apache提供API给java对MicrosoftOffice格式文档的读和写的功能

  • HSSF:

    • Excel03版,最大行数65536;一次性从内存写入文档,效率快

    • 文件名后缀以.xls

  • XSSF:

    • Excel OOXML07版,无限制,能写入更多数据,效率慢;可能抛出内存溢出问题

    • 文件名后缀.xlsx

    • 优化:新的实现类SXSSF:效率快,占用内存少;会产生用来保存临时数据的临时文件,需要清理即workbook.dispose();

  • HWPF:Word

  • HSLF:PowerPoint

  • HDGF:Visio

  • 写:

     public static final String filePath = "E:\\Projects\\security\\";
     @Test
     void writeExcel() throws IOException {
         // 创建工作簿
         // Workbook workbook = new HSSFWorkbook();
         Workbook workbook = new XSSFWorkbook();
         // 创建工作表,表名默认sheet0
         Sheet sheet = workbook.createSheet("数据表");
         // 创建行列
         Row row1 = sheet.createRow(0);
         Cell cell11 = row1.createCell(0);
         cell11.setCellValue("第一行一列");
         Cell cell12 = row1.createCell(1);
         cell12.setCellValue("第一行第二列");
         Cell cell13 = row1.createCell(2);
         cell13.setCellValue(new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
         // 生成表(IO流)
         // FileOutputStream fileOutputStream = new FileOutputStream(filePath + "03版本Excel生成测试.xls");
         FileOutputStream fileOutputStream = new FileOutputStream(filePath + "07版本Excel生成测试.xlsx");
         workbook.write(fileOutputStream);
         // (SXSSFWorkbook)workbook.dispose(); // 清除临时文件
         fileOutputStream.close();
     }

  • 读:

     @Test
     void readExcel() throws IOException {
         // 获取文件流
         FileInputStream fileInputStream = new FileInputStream(filePath + "03版本Excel生成测试.xls");
         // 创建工作簿-将流转为Workbook对象
         Workbook workbook = new HSSFWorkbook(fileInputStream);
         // Workbook workbook = new XSSFWorkbook();
         // 得到工作表
         Sheet sheet = workbook.getSheetAt(0);
         // 得到行列
         Row row1 = sheet.getRow(0);
         Cell cell11 = row1.getCell(0);
         // 得到不同类型的数据
         String cell11Value = cell11.getStringCellValue();
         System.out.println(cell11Value);
         fileInputStream.close();
     }

  • 获取不同类型数据:

     private void readValue(Workbook workbook, Sheet sheet) {
         if (null != sheet) {
             // 表中所有行
             int numberOfRows = sheet.getPhysicalNumberOfRows();
             for (int rowNumber = 0; rowNumber < numberOfRows; rowNumber++) {
                 // 一般将标题行和实际内容行分开读取
                 Row row = sheet.getRow(0);
                 if (null != row) {
                     // 行的所有列
                     int cellCount = row.getPhysicalNumberOfCells();
                     for (int cellNumber = 0; cellNumber < cellCount; cellNumber++) {
                         Cell cell = row.getCell(cellNumber);
                         // 匹配列的数据类型
                         if (null != cell) {
                             CellType cellType = cell.getCellTypeEnum();
                             String cellValue = "";
                             switch (cellType) {
                                 case STRING:
                                     cellValue = cell.getStringCellValue();
                                     break;
                                 case BLANK:
                                     cellValue = "";
                                     break;
                                 case BOOLEAN:
                                     cellValue = String.valueOf(cell.getBooleanCellValue());
                                     break;
                                 case NUMERIC: // 数字,分为日期和普通数字
                                     if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                         Date dateCellValue = cell.getDateCellValue();
                                         cellValue = new DateTime(dateCellValue).toString("yyyy-MM-dd");
                                     } else {
                                         cell.setCellType(CellType.STRING);
                                         cellValue = cell.toString();
                                     }
                                     break;
                                 case FORMULA: // 特殊数据格式,如单元格存在计算公式
                                     FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
                                     String formula = cell.getCellFormula(); // 公式字符串
                                     // 公式计算结果
                                     CellValue evaluate = formulaEvaluator.evaluate(cell);
                                     cellValue = evaluate.formatAsString();
                                     break;
                                 case _NONE:
                                 case FORMULA:
                                 case ERROR:
                                 default:
                                     break;
                             }
                         }
                     }
                 }
             }
         }
     }

2 EasyExcel

  • Alibaba提供解析Excel的工具,简单,快速

  • POI写数据到Excel时,先将数据全部加载到内存,再写入文件;在数据庞大时可能导致内存溢出问题;而重写后的EasyExcel读一行写一行,避免了问题

  • 编写表头映射的实体类:

     @Data
     public class HeadData {
         @ExcelProperty("value = "姓名", index = "列索引") // 表头;而下面的字段值为这一列的数据
         private String name;
         @ExcelProperty("年龄")
         private String age;
         @ExcelIgnore // 或者类上用@ExcelIgnoreUnanoteated忽略此字段写入Excel
         private String ignore;
     }

  • 根据实体类设置数据:

    public List<User> getData() {
        List<User> userList = new ArrayList()<>;
        for (int i = 0; i < rowCount; i++) {
            User data = new User();
            data.setName("标题1下的数据" + i);
            data.setAge("标题2下的数据" + i);
            datas.add(data);
        }
        return datas;
    }

  • 把设置好的数据写入Excel:

    public void exportTemplate(HttpServletResponse response) {
        try {
            String fileName = URLEncoder.encode("XXX文件模板" + ExcelTypeEnum.XLSX.getValue(), "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType(MdediaType.APPLICATION_OCTET_STREAM_VALUE);
            // 导出一个空白模板文件
            EasyExcel.write(response.getOutputStream())
                .head(Collections.singletonList(Collections.singletonList("XXX")))
                .sheet("XXXX").doWrite(Collections.emptyList());
            
            // 导出实际数据
            EasyExcel.write(response.getOutputStream(), User.class)
    				.sheet("XXXX").doWrite(userList);
        } catch(IOException e) {
            ...
        }
    }

  • 数据读取:具体查看官方文档

    public void readData() {
        String fileName = filePath + "...xlsx";
        EasyExcel.read(fileName, User.class, new DemoDataListener).sheet().doRead();
    }

  • 日期格式或数字处理:可能遇到时间转换异常

    • 字段使用LocalDate或LocalDateTime类型

    • 日期字段少的,可直接使用注解@DataTimeFormat("yyyy-MM-dd HH:mm:ss")

    • 对数字的格式化(long类型太长,如果不格式化的话excel中会以科学计数法显示)则将数据改为字符串类型;或者使用注解@NumberFormat(value = "#");其他格式如"##.00"

    • 需要格式化的字段较多的,需要自定义实现alibaba.Converter转换器来对时间或数字进行转换

    • 调用EasyExcel.write(response.getOutputStream(), User.class).registerConverter(new LocalDtaTimeConverter()).sheet("...").doWrite(data);可以同时注册多个Converter

  • excel生成并DSM加密:文件名fileName,文件路径filePath;加密文件名(.dsm后缀)dsmFileName,加密文件路径dsmFilePath;结合上面的导出数据实例,在filePath上生成文件;加密则调用提供的加密API(如华为的makeDsmFile(filePath,dsmFilePath),生成加密文件);配合SFTP的文件上传下载,将文件上传到服务器;配合流,下载加密文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值