Java文件解析:Excel解析

news2024/9/25 9:38:14

文章目录

  • 一、前言
  • 二、POI 和 easyExcel
    • 1.1概念
    • 1.2xls和xlsx区别
    • 1.3文档
    • 1.4Excel概念
  • 二、常用场景
  • 三、内存问题
  • 四、POI的使用
    • 4.1创建一个空项目
    • 4.2引入pom依赖
    • 4.3workbook的三个实现类
    • 4.4写的实现
    • 4.4读的实现
    • 4.5POI常用的包
  • 五、EasyExcel的使用
    • 5.1创建一个空项目
    • 5.2引入pom依赖
    • 5.3写的实现
    • 5.4读的实现

一、前言

在日常的开发中,做报表开发的时候,经常会用到Excel导入数据或者导出数据到Excel里,在java中,通常用到第三方提供的技术来进行Excel文件的读写。

第三方提供的有:Apache POI、JXL、Alibaba EasyExcel。

下面介绍Apache POI和Alibaba EasyExcel。

二、POI 和 easyExcel

1.1概念

apache POI:开放源码式函数库。POI提供API给java程序堆Microsoft office格式档案读和写的功能。比较复杂。

Alibaba easyExcel:Java解析Excel工具,对POI做出优化,比较简单使用。

1.2xls和xlsx区别

xls(03)最大行数:65536。

xlsx(07) 最大行数:无限。

1.3文档

POI文档:https://poi.apache.org/

easyExcel官方文档:https://www.yuque.com/easyexcel/doc

1.4Excel概念

1.工作簿:

2.工作表:

3.行:

4.列:

5.单元格:3和4组成

二、常用场景

  • 将用户信息导出为excel表格(导出数据)

  • 将本地Excel表中的数据上传到服务器里(数据上传)

三、内存问题

POI:100w数据先加载到内存(会oom),再一次性写入文件。

EasyExcel:读取通过文件形式,一行一行的解析 ,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。 。

在这里插入图片描述

四、POI的使用

4.1创建一个空项目

4.2引入pom依赖

<!--        poi开始-->
<!--        xls-03-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
<!--        xls-07-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
<!--        poi结束-->
<!--        日期格式化工具-->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.4</version>
        </dependency>
<!--        test-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

4.3workbook的三个实现类

在这里插入图片描述

4.4写的实现

生成 Excel文件步骤:

  1. 创建WorkBook,一个WorkBook代表一个Excel文件

  2. 以输出流的形式创建出Excel文件

  3. 调用createSheet(0)创建工作簿

  4. 调用createRow(0)创建行

  5. 调用createCell(0)创建单元格

  6. 调用setCellValue()完成对单元格内容的写入

  7. 调用write()方法,将Workbook对象中包含的数据,通过输出流,生成Excel文件

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @Author: shen
 * @CreateTime: 2022-01-03  22:47
 * @Description: poi写
 */
public class ExcelWriteTest {

    @Test
    public void Test1() throws IOException {
        //文件路径
        String filePath="C:\\Users\\Administrator\\Desktop\\excel文件\\";
        //excel名称
        String excelName03 = "xiaoshen数据统计表03.xls";
        String excelName07 = "xiaoshen数据统计表07.xlsx";
        //sheet页名称
        String sheetName = "xiaoshen数据统计表";

        //1.创建工作簿:03 xls
        Workbook workbook = new HSSFWorkbook();
        //1.创建工作簿:07 xlsx
        Workbook workbook1 = new XSSFWorkbook();
        //1.升级版创建工作簿:07 xlsx
        Workbook workbook2 = new SXSSFWorkbook();
        //2.通过文件输出流生成excel文件
        FileOutputStream fileOutputStream = new FileOutputStream(filePath + excelName03);
        //new ExcelWriteTest().testWrite07BigData(workbook,sheetName,fileOutputStream);
        new ExcelWriteTest().testWrite03(workbook,sheetName,fileOutputStream);
    }

    private   void testWrite03 (Workbook workbook,String sheetName,FileOutputStream fileOutputStream)throws IOException{
        //2.创建一个工作表
        Sheet sheet = workbook.createSheet(sheetName);
        //3.创建行
        Row row1 = sheet.createRow(0);
        //4.创建一个单元格
        Cell cell11 = row1.createCell(0);
        cell11.setCellValue("今日学习数量");

        Cell cell12 = row1.createCell(1);
        cell12.setCellValue(666);
        //第二行
        Row row2 = sheet.createRow(1);
        Cell cell21 = row2.createCell(0);
        cell21.setCellValue("时间");

        Cell cell22 = row2.createCell(1);
        String time = new DateTime().toString("yyyy-MM-dd HH:mm:ss");
        cell22.setCellValue(time);

        //输出
        workbook.write(fileOutputStream);
        //关闭流
        fileOutputStream.flush();
        fileOutputStream.close();
        System.out.println("xiaoshen统计表o3生成完毕!");
    }


    public  void testWrite07BigData (Workbook workbook,String sheetName,FileOutputStream fileOutputStream)throws IOException{
        //时间
        long start = System.currentTimeMillis();
        Sheet sheet = workbook.createSheet(sheetName);
        //写入数据
        for (int rownum = 0; rownum < 65536; rownum++) {
            Row row = sheet.createRow(rownum);
            for (int cellNum = 0; cellNum < 10; cellNum++) {
                Cell cell = row.createCell(cellNum);
                cell.setCellValue(cellNum);
            }
        }
        System.out.println("over");
        //输出
        workbook.write(fileOutputStream);
        //关闭流
        fileOutputStream.flush();
        fileOutputStream.close();
        //清除临时文件
        ((SXSSFWorkbook)workbook).dispose();
        System.out.println("xiaoshen统计表o3生成完毕!");
        long end = System.currentTimeMillis();

        System.out.println("执行时间:"+(end-start)/1000 +"分");
    }
}

4.4读的实现

读取Excel 步骤:

  1. 以输入流的形式获取到excel文件

  2. 创建WorkBook,传入该输入流

  3. 调用getSheetAt(0),获取到工作簿

  4. 调用getRow()获取到行

  5. getCell()获取到单元格

  6. 调用getStringCellValue()获取到String的类型的值,调用getNumericCellValue()获取到double类型的值

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.joda.time.DateTime;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;

/**
 * @Author: shen
 * @CreateTime: 2022-01-03  22:47
 * @Description: poi读
 */
public class ExcelReadTest {

    @Test
    public void test1() throws IOException {
        //文件路径
        String filePath="C:\\Users\\Administrator\\Desktop\\excel文件\\";
        //excel名称:03
        String excelName="xiaoshen数据统计表03.xls";
        //创建文件输入流对象
        FileInputStream fileInputStream = new FileInputStream(filePath + excelName);
        //文件输入流读取excel
        //new ExcelReadTest().testCellType03(fileInputStream);
        new ExcelReadTest().testRead03(fileInputStream);
    }

    private void testRead03 (FileInputStream fileInputStream)throws IOException{
        //读取流中的工作簿:03-xls
        //XSSFWorkbook-07-xlsx、SXSSFWorkbook-07-xlsx
        Workbook workbook = new HSSFWorkbook(fileInputStream);

        //获取第一张工作表
        Sheet sheet = workbook.getSheetAt(0);
        //获取第一行
        Row row = sheet.getRow(0);
        //获取第一行的第一列单元格
        Cell cell = row.getCell(0);

        //注意:cell.getStringCellValue()获取字符串
        //日常开发中的问题:需要判断不同类型的数据
        System.out.println(cell.getStringCellValue());
        Cell cell1 = row.getCell(1);
        System.out.println(cell1.getNumericCellValue());

        //关闭流
        fileInputStream.close();
    }

    private void testCellType03 (FileInputStream fileInputStream)throws IOException{
        //读取流中的工作簿
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        //获取工作表
        Sheet sheet = workbook.getSheetAt(0);
        //获取总行数
        int rowCount = sheet.getPhysicalNumberOfRows();
        for (int rowNum = 0; rowNum < rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row != null ){
                //第一行有多少列
                int cellCount = row.getPhysicalNumberOfCells();
                for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                    Cell cell = row.getCell(cellNum);
                    if (cell != null){
                        //匹配列的数据类型
                        CellType cellType = cell.getCellType();
                        switch (cellType){
                            case STRING://字符串
                                System.out.print(cell.getStringCellValue());
                                break;
                            case NUMERIC://数字:日期或者数字
                                if (HSSFDateUtil.isCellDateFormatted(cell)){//日期
                                    Date date = cell.getDateCellValue();
                                    System.out.print(new DateTime(date).toString());
                                }else {//数字
                                    cell.setCellType(CellType.STRING);
                                    System.out.print(cell.toString());
                                }
                                break;
                            case BOOLEAN://布尔
                                System.out.print(cell.getBooleanCellValue());
                                break;
                            case BLANK://空白
                                break;
                            case FORMULA://公式
                                //拿到计算公式
                                FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
                                String cellFormula = cell.getCellFormula();
                                //计算
                                CellValue cellValue = formulaEvaluator.evaluate(cell);
                                String value = cellValue.formatAsString();
                                System.out.println(value);
                                break;
                            case ERROR:
                                System.out.print("错误类型!");
                                break;
                            default:
                        }
                    }
                }
                System.out.println();
           }
        }
        //关闭流
        fileInputStream.close();
    }
}

4.5POI常用的包

HSSF - 提供读写Microsoft Excel XLS格式档案的功能。

XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。

HWPF - 提供读写Microsoft Word DOC格式档案的功能。

HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

HDGF - 提供读Microsoft Visio格式档案的功能。

HPBF - 提供读Microsoft Publisher格式档案的功能。

HSMF - 提供读Microsoft Outlook格式档案的功能。

五、EasyExcel的使用

github地址:https://github.com/alibaba/easyexcel

easyExcel地址:https://easyexcel.opensource.alibaba.com/docs/current/

5.1创建一个空项目

5.2引入pom依赖

<!--        easyExcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>compile</scope>
        </dependency>
    <!--解决log4j冲突问题-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
    <!--        test-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>

5.3写的实现

生成excel文件使用的是EasyExcel中的write()方式,需要的是文件路径,和写入内容的类型。下面演示到的类型为:DemoData类型。

DemoData类:

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.metadata.data.WriteCellData;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
/**
 * @Author: shen
 * @CreateTime: 2022-01-04  11:36
 * @Description: easyExcel实体类
 */
@Getter
@Setter
@EqualsAndHashCode
@ContentRowHeight(100)//图片高度
@ColumnWidth(100 / 8)//图片宽度
public class DemoData {
    private File file;
    private InputStream inputStream;
    private byte[] byteArray;
    /**
     * 字符串起前面加上"自定义:"三个字:注解上使用converter属性即可
     * @ExcelProperty()代表列头单元格的内容
     */
    @ExcelProperty(value = "字符串标题",index = 0)
    private String string;

    @ExcelProperty(value = "日期标题",index = 1)
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    private Date date;

    @ExcelProperty(value = "数字标题",index = 2)
    @NumberFormat("¥#,###")//注解@NumberFormat()代表单元格格式
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;

    /**
     * 根据url导出
     */
    private URL url;
    /**
     * 根据文件导出 并设置导出的位置。
     */
    private WriteCellData<Void> writeCellDataFile;
    /**
     *超链接
     */
    private WriteCellData<String> hyperlink;
    /**
     * 备注
     */
    private WriteCellData<String> commentData;
    /**
     * 公式
     */
    private WriteCellData<String> formulaData;
    /**
     * 指定单元格的样式。当然样式 也可以用注解等方式。
     */
    private WriteCellData<String> writeCellStyle;
}

EasyexcelWriteTest类:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.*;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.fastjson.JSON;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.Test;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Author: shen
 * @CreateTime: 2022-01-04  11:40
 * @Description: Easyexcel写入测试
 */
public class EasyexcelWriteTest {
    String filePath="C:\\Users\\Administrator\\Desktop\\excel文件" + File.separator +"simpleWrite.xlsx";

    String imagePath = "C:\\Users\\Administrator\\Desktop\\image" + File.separator + "1.png";

    @Test
    public void simpleWrite() {
        new EasyexcelWriteTest().Write1(filePath);//简单写入excel
        //new EasyexcelWriteTest().Write2(filePath);//根据不同的对象写入excel
    }

    @Test
    public void imageWrite()  {
        //try-with-resource
        try(InputStream inputStream = new FileInputStream(new File(imagePath))) {
            ArrayList<DemoData> list = ListUtils.newArrayList();

            DemoData demoData = new DemoData();
            //放入图片类型,实际开发只要选择一种
            //1
            demoData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));
            //2
            demoData.setFile(new File(imagePath));
            //3
            demoData.setString(imagePath);
            //4
            demoData.setInputStream(inputStream);
            //5
            //demoData.setUrl(new URL(  "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg"));
            //这里将随机选择一种方式:

            WriteCellData<Void> imageWriteCellData = new WriteCellData<>();
            imageWriteCellData.setType(CellDataTypeEnum.STRING);
            imageWriteCellData.setStringValue("额外放一些文字");
            //放入图片:ImageData是alibaba提供的
            List<ImageData> imageList = new ArrayList<>();
            ImageData imageData = new ImageData();
            //放入二进制图片
            imageData.setImage(FileUtils.readFileToByteArray(new File(imagePath)));
            //设置图片类型
            imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
            //设置图片的上下左右
            imageData.setTop(5);
            imageData.setBottom(5);
            imageData.setLeft(5);
            imageData.setRight(40);
            //设置图片的位置:起点相对于单元格为0
            imageData.setRelativeFirstRowIndex(0);
            imageData.setRelativeFirstColumnIndex(0);
            imageData.setRelativeLastColumnIndex(1);
            imageList.add(imageData);
            //writeCellData设置图片数据
            imageWriteCellData.setImageDataList(imageList);


            //设置超链接
            WriteCellData<String> hyperlinkWriteCellData = new WriteCellData<>("百度网站");
            HyperlinkData hyperlinkData = new HyperlinkData();
            hyperlinkData.setAddress("https://www.baidu.com");
            hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);
            hyperlinkWriteCellData.setHyperlinkData(hyperlinkData);
            demoData.setHyperlink(hyperlinkWriteCellData);


            //设置备注:备注xiaoshen
            WriteCellData<String> commentWriteCellData = new WriteCellData<>("备注的单元格");
            CommentData commentData = new CommentData();
            commentData.setAuthor("xiao shen");
            commentData.setRichTextStringData(new RichTextStringData("这是一个备注"));
            commentWriteCellData.setCommentData(commentData);
            demoData.setCommentData(commentWriteCellData);

            //设置公式:替换字符串中的1为2
            WriteCellData<String> formulaWriteCellData = new WriteCellData<>();
            FormulaData formulaData = new FormulaData();
            formulaData.setFormulaValue("REPLACE(123456789,1,1,2)");
            formulaWriteCellData.setFormulaData(formulaData);
            demoData.setFormulaData(formulaWriteCellData);

            //设置单元格样式:背景绿色、字符串
            WriteCellData<String> styleWriteCellData = new WriteCellData<>("单元格样式");
            WriteCellStyle writeCellStyle = new WriteCellStyle();
            writeCellStyle.setFillBackgroundColor(IndexedColors.GREEN.getIndex());
            writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
            styleWriteCellData.setWriteCellStyle(writeCellStyle);
            styleWriteCellData.setType(CellDataTypeEnum.STRING);
            demoData.setWriteCellStyle(styleWriteCellData);


            list.add(demoData);
            //写入数据
            EasyExcel.write(filePath,DemoData.class).sheet(0).doWrite(list);
            System.out.println("写入完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author: shen
     * @date: 2022/01/12 0:40
     * @description: web中的写
     * @param response
     * @return:
     **/

    //@GetMapping("downloadFailedUsingJson")
    public void  webWrite(HttpServletResponse response) throws IOException {
        try {
            // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder
                    .encode("测试", "UTF-8")
                    .replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            //设置不关闭流
            EasyExcel.write(response.getOutputStream(), DemoData.class)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("模板")
                    .doWrite(data());
        }catch (Exception e){
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }

    }
    /*
     * @author: shen
     * @date: 2022/01/05 10:18
     * @description:写入数据方法
     * @param: fileName :文件路径
     * @return: void
     **/
    private  void Write1(String fileName){
        // 写法1 JDK8+
        HashSet<String> set = new HashSet<>();
        set.add("date");

        //EasyExcel写入数据
        EasyExcel.write(fileName, DemoData.class)// 指定以DemoData.class去写到fileName文件路径下。
                .excelType(ExcelTypeEnum.XLSX)// Excel的格式:xlsx
                .sheet(0,"模板")// sheet页的名称为模板
                .excludeColumnFieldNames(set)//忽略set集合的字段
                .head(head())//动态插入头部标题
                .doWrite(() -> {//写入的数据
                    return data();//这里可以去数据查询
                });
    }

    private void Write2(String fileName){
        // 写法2
        // 这里 需要指定写用哪个class去写
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {
            for (int i = 0; i < 5; i++) {
                // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
                //每个sheet页存的对象不同。
                WriteSheet writeSheet = EasyExcel.writerSheet(i,"模板"+i)
                        .head(DemoData2.class)
                        .build();
                excelWriter.write(data(), writeSheet);
            }
        }
    }
    /*
     * @author: shen
     * @date: 2022/01/5 10:14
     * @description:通用数据生成方法
     * @param:
     * @return: java.util.List<com.shenxm.easyexcel.utils.DemoData>
     **/
    private List<DemoData> data() {
        List<DemoData> list = ListUtils.newArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

    private List<List<String>> head() {
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> head0 = new ArrayList<String>();
        head0.add("字符串" + System.currentTimeMillis());
        List<String> head1 = new ArrayList<String>();
        head1.add("数字" + System.currentTimeMillis());
        List<String> head2 = new ArrayList<String>();
        head2.add("日期" + System.currentTimeMillis());
        list.add(head0);
        list.add(head1);
        list.add(head2);
        return list;
    }
}

5.4读的实现

DemoData类: 提供读取数据的对象类

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.metadata.data.WriteCellData;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

/**
 * @Author: shen
 * @CreateTime: 2022-01-04  11:36
 * @Description: easyExcel实体类
 */
@Getter
@Setter
@EqualsAndHashCode
@ContentRowHeight(100)//图片高度
@ColumnWidth(100 / 8)//图片宽度
public class DemoData {
    private File file;
    private InputStream inputStream;
    private byte[] byteArray;
    /**
     * 字符串起前面加上"自定义:"三个字:注解上使用converter属性即可
     * @ExcelProperty()代表列头单元格的内容
     */
    @ExcelProperty(value = "字符串标题",index = 0)
    private String string;

    @ExcelProperty(value = "日期标题",index = 1)
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    private Date date;

    @ExcelProperty(value = "数字标题",index = 2)
    @NumberFormat("¥#,###")//注解@NumberFormat()代表单元格格式
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;

    /**
     * 根据url导出
     */
    private URL url;
    /**
     * 根据文件导出 并设置导出的位置。
     */
    private WriteCellData<Void> writeCellDataFile;
    /**
     *超链接
     */
    private WriteCellData<String> hyperlink;
    /**
     * 备注
     */
    private WriteCellData<String> commentData;
    /**
     * 公式
     */
    private WriteCellData<String> formulaData;
    /**
     * 指定单元格的样式。当然样式 也可以用注解等方式。
     */
    private WriteCellData<String> writeCellStyle;
}

DemoDataListener类: 读的监听器:DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @Author: shen
 * @CreateTime: 2022-02-04  23:06
 * @Description: 简单的读监听器
 */
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;

    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }

    /**
     * 这个每一条数据解析都会来调用
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        System.out.println("解析到一条数据:" + JSON.toJSONString(data));
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     * @param context 分析上下文
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/127566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智慧城市物联网介绍

智慧城市物联网介绍 智慧城市是一个有机结合的大系统&#xff0c;涵盖了更透切的感知、更全面的互连&#xff0c;更深入的智能。物联网是智慧城市中非常重要的元素&#xff0c;它侧重于底层感知信息的采集与传输&#xff0c;城市范围内泛在网方面的建设。 通过智慧城市物联网支…

探索Feign

目录 1. 简介 2. 原理 2.1. 动态代理 动态代理 动态代理 2.2. 懒加载负载均衡器的问题与解决 2.3. 主要类 3. 使用举例 4. 参数配置 1. 简介 Feign&#xff0c;一种声明式的web service client&#xff0c;可以很容易的创建http apis client。创建一个interface并添加注…

Cubase11/12 Windows 音乐创作工具

前言 Cubase是一款专业级的高级音乐创作软件&#xff0c;凭借其无与伦比的灵活工具&#xff0c;您可以快速和直观地创造任何类型的音&#xff0c;充满了各种各样的虚拟仪器、效果和数千种声音。 下载 官网:Cubase Cubase12 12详细教程 Cubase11教程 管理员身份运行 右击…

python初级教程四 发送邮件

SMTP发送邮件 SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则&#xff0c;由它来控制信件的中转方式。 python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。 …

实力认证!中睿天下荣获“创客北京2022”软件与信息技术产业项目十强

近日&#xff0c;第七届“创客中国”北京市中小企业创新创业大赛暨“创客北京2022”创新创业大赛北京区域赛在决赛阶段按照八个产业对参赛项目进行评选&#xff0c;产生了各产业的十强项目&#xff0c;《中睿天下实战对抗攻击溯源项目》从数百个项目中脱颖而出&#xff0c;荣获…

MXNet的Faster R-CNN(基于区域提议网络的实时目标检测)《2》

上一篇文章 是对这个模型做个测试&#xff0c;效果很不错&#xff0c;然后这节&#xff0c;我们来关注下论文中的一些知识点 原论文&#xff1a;Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks 本文不是按照原论文的顺序一路下来讲解&…

Python基础语法(三)

Python基础语法&#xff08;三&#xff09; 列表和元组 列表是什么, 元组是什么 编程中, 经常需要使用变量, 来保存/表示数据. 如果代码中需要表示的数据个数比较少, 我们直接创建多个变量即可 num1 10 num2 20 num3 30 ......但是有的时候, 代码中需要表示的数据特别多…

小程序:后台交互-个人中心

目录 获取用户昵称头像和昵称 wx.getUserProfile bindgetuserinfo oa-mini 登录过程 登录-小程序 wx.checkSession wx.login wx.request 后台 准备数据表 反向生成工具生成 准备封装前端传过来的数据 小程序服器配置 导入微信小程序SDK application.yml WxPro…

我眼中的Java内存模型

一.JVM内存结构 &#xff08;1&#xff09;方法区只是一种概念上的区域&#xff0c;并说明了其应该具有什么功能&#xff0c;但是没有规定这个区域到底应该处于何处&#xff0c;不同版本的方法区所处位置不同&#xff0c;并不是绝对意义上的物理区域。 &#xff08;2&#xff0…

CSRF攻击方式及预防准则

跨站点请求伪造&#xff08;CSRF&#xff09; 是一种攻击类型&#xff0c;当恶意网站、电子邮件、博客、即时消息或程序导致用户的Web浏览器在用户通过身份验证后对受信任的站点执行不需要的操作时&#xff0c;就会发生这种攻击。CSRF攻击之所以有效&#xff0c;是因为浏览器请…

OpenHarmony#深入浅出学习eTs#(二)拖拽式UI

本项目Gitee仓地址&#xff1a;深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、创建支持Super Visual的工程 在这里选择直尺Super Visual的选项&#xff0c;调整当前路径&#xff0c;进入绘制界面 二、UI设计界面介绍 在左侧是路径&#xff08;即文件管理器&#x…

3.我们一起来学习Linux 安装

Linux 安装 本章节我们将为大家介绍 Linux 的安装&#xff0c;安装步骤比较繁琐&#xff0c;现在其实云服务器挺普遍的&#xff0c;价格也便宜&#xff0c;如果自己不想搭建&#xff0c;也可以直接买一台学习用用。 本章节以 centos6.4 为例。 可以去官网下载最新版本&…

【C语言进阶】通讯录再优化?学会文件操作,没有数据库也能保存和管理本地数据

目录 &#x1f95d;前言&#x1f95d;&#xff1a; 一、&#x1f353;文件概述&#x1f353;&#xff1a; 1.为什么使用文件&#xff1a; 2.什么是文件&#xff1a; ①.程序文件&#xff1a; ②.数据文件&#xff1a; ③.文件名&#xff1a; 二、&#x1f34a;文件顺序读写&…

JAVA集成阿里云OSS对象存储

JAVA集成阿里云OSS对象存储1 : 配置集成1.1、对象存储OSS2 : 代码配置2.1、说明2.2、配置文件2.3、加载配置文件代码2.4、封装统一的DTO2.5、OSS上传Controller2.6、OSS上传Service2.7、OSS上传ServiceImpl3 : 测试3.1、文件上传3.2、文件迁移4 : 总结4.1、参考资料4.2、注意事…

浅谈 C++ 字符串:std::string 与它的替身们

浅谈 C 字符串&#xff1a;std::string 与它的替身们 文章目录浅谈 C 字符串&#xff1a;std::string 与它的替身们零、前言一、前辈&#xff1a;C 风格的字符串1.1 什么是 C 风格的字符串1.2 C 风格的字符串有什么缺陷1.2.1 以 \0 作为结尾&#xff0c;没有直接指明长度1.2.2 …

Android技术分享——APT实现ButterKnife【实战学习】

APT APT &#xff08;Annotation Processing Tool&#xff09; 是一种处理注释的工具&#xff0c;它对源代码文件进行检测并找出其中的 Annotation&#xff0c;根据注解自动生成代码&#xff0c;如果想要自定义的注解处理器能够运行&#xff0c;必须要通过 APT 工具来处理。 …

Python实现FA萤火虫优化算法优化支持向量机分类模型(SVC算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法&#xff08;Fire-fly algorithm&#xff0c;FA&#xff09;由剑桥大学Yang于2009年提出 , 作…

maven第一篇:安装maven以及配置

本篇就是聊如何在电脑上安装maven&#xff0c;以及简单的配置基础环境。 首先需要了解什么适合maven&#xff0c;对于这个理论知识&#xff0c;还是老规矩直接复制一下&#xff1b; Maven 是一款基于 Java 平台的项目管理和整合工具&#xff0c;它将项目的开发和管理过程抽象…

提速300%,PaddleSpeech语音识别高性能部署方案重磅来袭!

在人机交互的过程中&#xff0c;语音是重要的信息载体&#xff0c;而语音交互技术离不开语音识别与语音合成技术。飞桨语音模型库PaddleSpeech为开发者们使用这些技术提供了便捷的环境。本次PaddleSpeech迎来重大更新——1.3版本正式发布。让我们一起看看&#xff0c;这次Paddl…

这样实操一下 JVM 调优,面试超加分

1.写在前面 前段时间一位读者面了阿里&#xff0c;在二面中被问到 GC 日志分析&#xff0c;感觉回答的不是很好&#xff0c;过来找我复盘&#xff0c;大致听了他的回答&#xff0c;虽然回答出了部分&#xff0c;但是没抓到重点。 GC 日志分析算是 JVM 调优中比较难的部分&…