Use of poi, selection of easypoi and easyexcel

Posted by lordofgore on Mon, 20 Sep 2021 12:13:03 +0200

The project needs to read excel, get in touch with poi, and use it. Summarize yourself

Here, a small demo is written, which is a SpringBoot project. Its main function is to read a total curriculum and then generate the curriculum of the specified class we need

Let's take a look at our master schedule first

easyexcel

When the amount of excel data is large, the speed has obvious advantages
Key codes:
Guide Package:

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--xls-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

Data entity class (add @ ExcelProperty annotation to the attributes that need to participate in import and export, where the value of the value attribute represents the column name at the time of export, and the value of the index is the subscript of the column, starting from 0. There is an interval between morning and afternoon, so it must be set here in order to read accurately):

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
//@Accessors(chain = true)
public class DemoData {
    //Set excel header name
    @ExcelProperty(value = "date",index = 0)
    private String DateTime;
    @ExcelProperty(value = "week",index = 1)
    private String week;

    @ExcelProperty(value = "place",index = 2)
    private String AMClassroom;
    @ExcelProperty(value = "1,2 class hour",index = 3)
    private String hourOneAndTwo;
    @ExcelProperty(value = "3,4 class hour",index = 4)
    private String hourThreeAndFour;
    @ExcelProperty(value = "teacher",index = 5)
    private String AMTeacher;
    @ExcelProperty(value = "class",index = 6)
    private String AMGrade;

    @ExcelProperty(value = "place",index = 8)
    private String PMClassroom;
    @ExcelProperty(value = "5,6 class hour",index = 9)
    private String hourFiveAndSix;
    @ExcelProperty(value = "7,8 class hour",index = 10)
    private String hourSevenAndEight;
    @ExcelProperty(value = "teacher",index = 11)
    private String PMTeacher;
    @ExcelProperty(value = "class",index = 12)
    private String PMGrade;

    @ExcelProperty(value = "Evening (18:30)-20:10)",index = 13)
    private String night;
}

To create an excel event analyzer:

import javax.swing.filechooser.FileSystemView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelListener extends AnalysisEventListener<DemoData> {

    //A collection of class timetables to print
    private List<DemoData> list = new ArrayList<>();
    //The ID that must be saved in the first row is the column header
    private boolean flag = true;
    //Class name in the schedule to generate the schedule
    public static String grade;
    //Header
    private String head;
    //Week temporary storage
    private String week;
    //The class is temporarily stored in the evening self-study classroom
    private Map<String,String> night=new HashMap<>();

    //Read header content
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        //Header, there is only one header of the timetable here
        System.out.println("Header:" + headMap);
        head = headMap.get(0).substring(0, headMap.get(0).length() - 3);
    }

    //Read excel content line by line
    @Override
    public void invoke(DemoData data, AnalysisContext analysisContext) {
        System.out.println("****" + data);
        //Read of column header
        if ((!StringUtils.isEmpty(data.getWeek())) && flag) {
            list.add(data);
            flag = false;
            return;
        }
        //Temporary storage of week and assignment of week in data
        if (StringUtils.isEmpty(data.getWeek())) {
            data.setWeek(week);
        } else {
            week = data.getWeek();
        }
        //Read the evening self-study classroom of this class on this day of the week
        if (!StringUtils.isEmpty(data.getNight())) {
            if (data.getNight().contains(grade) || grade.contains(data.getNight())) {
                night.put(data.getWeek(), data.getAMClassroom());
            }
        }
        data.setNight(null);//After reading, there is no need to exist. Fill in the method after reading as a whole
        //Just look for the class schedule we need
        if (grade.equals(data.getAMGrade()) || grade.equals(data.getPMGrade())) {
            //The distinction between half day and half day. If there is this class on this day, but a half day is not this class, the half day will be emptied directly
            if (!grade.equals(data.getAMGrade())) {
                data.setAMClassroom(null);
                data.setHourOneAndTwo(null);
                data.setHourThreeAndFour(null);
                data.setAMTeacher(null);
                data.setAMGrade(null);
            }
            if (!grade.equals(data.getPMGrade())) {
                data.setPMClassroom(null);
                data.setHourFiveAndSix(null);
                data.setHourSevenAndEight(null);
                data.setPMTeacher(null);
                data.setPMGrade(null);
            }
            //If the date is the same as the previous data, merge with the previous data
            if (list.get(list.size()-1).getWeek().equals(data.getWeek())) {
                DemoData oldData = list.get(list.size() - 1);//Merged target data
                //Merge into the morning
                if (StringUtils.isEmpty(oldData.getAMGrade())) {
                    oldData.setAMClassroom(data.getAMClassroom());
                    oldData.setHourOneAndTwo(data.getHourOneAndTwo());
                    oldData.setHourThreeAndFour(data.getHourThreeAndFour());
                    oldData.setAMTeacher(data.getAMTeacher());
                    oldData.setAMGrade(data.getAMGrade());
                }else {//Merge into the afternoon
                    oldData.setPMClassroom(data.getPMClassroom());
                    oldData.setHourFiveAndSix(data.getHourFiveAndSix());
                    oldData.setHourSevenAndEight(data.getHourSevenAndEight());
                    oldData.setPMTeacher(data.getPMTeacher());
                    oldData.setPMGrade(data.getPMGrade());
                }
                list.set(list.size() - 1, oldData);
                return;
            }
            list.add(data);
        }
    }

    //After reading
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        //Write after reading
        // Get desktop path
        FileSystemView fsv = FileSystemView.getFileSystemView();
        String desktop = fsv.getHomeDirectory().getPath();
        String filePath = desktop + "\\" + grade + " " + head + ".xls";//C:\Users\fuck\Desktop\T119 on 9.13-9.18.xls
        //Fill in the evening self-study
        for (String wk : night.keySet()) {
            for (DemoData data : list) {
                if (data.getWeek().equals(wk)) {
                    data.setNight(night.get(wk));
                }
            }
        }
        System.out.println(filePath);
        list.forEach(list -> System.out.println(list));

        //write in
        EasyExcel.write(filePath, DemoData.class).sheet("Student list").doWrite(list);
    }
}

Summary: the reading of excel file header, the reading of conventional lines and the writing of excel files are all implemented in the rewriting method in this class. The characteristics of reading data: reading line by line

easyexcel document address.

excelpoi

Implementation mode
The dependency of the import has changed, and the annotation used has also changed

It is as like as two peas in the general schedule.
Moreover, I don't know why I can't read the data of some columns. If I use the template to generate, if there is a one to many relationship, which involves the consolidation of cells, the exported table will report an error even when it is opened, and finally give up. I'm sorry to omit it here

poi

The most primitive method has a high degree of freedom. It should be the most appropriate choice for this complex table
Import dependency:

		<!-- poi -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>

Read (idea: get the worksheet, get the sheet, and traverse the row and cell of the sheet):

	/**
     * Read the master timetable
     *
     * @param schedule
     * @param list
     * @throws Exception
     */
    public String timeTableRead(Schedule schedule, List<ScheduleVo> list) throws Exception {
        //read
        if (!ObjectUtils.isEmpty(schedule.getMultipartFile())) {
            //One day's course
            ScheduleVo scheduleVo = new ScheduleVo();
            //file name
            String fileName = "";

            //MultipartFile to inputStream
            InputStream inputStream = schedule.getMultipartFile().getInputStream();
            Workbook sheets = new XSSFWorkbook(inputStream);//Create worksheet
            //Get a worksheet (sheet page) with subscripts starting from 0
            Sheet sheet = sheets.getSheetAt(0);
            //When traversing the row, the subscripts of sheet, row and cell start from 0. The number of rows is 313. sheet.getLastRowNum() also gets 313, so i can be equal to rowNum
            for (int i = 0, rowNum = sheet.getLastRowNum(); i <= rowNum; i++) {
                // Get row content
                Row row = sheet.getRow(i);
                if (ObjectUtils.isEmpty(row)) {
                    //If the knowledge has only one behavior null, continue to read the next line
                    continue;
                }
                //Prevent row missing column! = null, but read the specified column with a null pointer and a row missing cell
                if (row.getPhysicalNumberOfCells() < 13) {
                    continue;
                }
                //Read column
                //Read header
                if (i == 0) {
                    String title = row.getCell(0).getStringCellValue();
                    fileName = schedule.getName() + " " + title.substring(0, title.length() - 3) + "Timetable";
                } else if (i > 1) {
                    //There is nothing to read at the head of the second row and column. Read directly from the third row
                    //If you have time, it means that this is the beginning of a new day. Rewrite and instantiate the timetable object
                    String dateTime = row.getCell(0).getStringCellValue();
                    if (!StringUtils.isEmpty(dateTime)) {
                        if (!StringUtils.isEmpty(scheduleVo.getDateTime())) {//The new day starts to add the data read from the old day to the collection
                            list.add(scheduleVo);
                        }
                        scheduleVo = new ScheduleVo();
                        scheduleVo.setDateTime(dateTime.substring(5));//Set time
                        scheduleVo.setWeek(row.getCell(1).getStringCellValue());//Set week
                    }
                    //If column 7 is the class to be searched, add the data of the specified column in this row to the object
                    String clazz = row.getCell(6).getStringCellValue();
                    if (clazz.equals(schedule.getName())) {
                        Cell cell = row.getCell(2);
                        cell.setCellType(CellType.STRING);
                        scheduleVo.setAmClassroom(cell.getStringCellValue());//Read morning locations
                        scheduleVo.setAmCourse(row.getCell(3).getStringCellValue());//Read the morning course
                        scheduleVo.setAmTeacher(row.getCell(5).getStringCellValue());//Read the morning teacher
                    }
                    //If column 13 is the class to be searched, add the data of the specified column in this row to the object
                    clazz = row.getCell(12).getStringCellValue();
                    if (clazz.equals(schedule.getName())) {
                        Cell cell = row.getCell(8);
                        cell.setCellType(CellType.STRING);
                        scheduleVo.setPmClassroom(cell.getStringCellValue());//Read afternoon locations
                        scheduleVo.setPmCourse(row.getCell(9).getStringCellValue());//Read the afternoon course
                        scheduleVo.setPmTeacher(row.getCell(11).getStringCellValue());//Read the afternoon teacher
                    }
                    //If column 14 is the class to be searched, add the data of the specified column in this row to the object
                    clazz = row.getCell(13).getStringCellValue();
                    if ((!StringUtils.isEmpty(clazz)) && schedule.getName().contains(clazz)) {//There is a night self-study on this day
                        Cell cell = row.getCell(2);
                        cell.setCellType(CellType.STRING);
                        scheduleVo.setNight(cell.getStringCellValue());//Save the evening study location to the evening study field
                    }
                    //If it is the last row, it will be directly added to the collection after reading
                    if (i == rowNum) {
                        list.add(scheduleVo);
                    }
                }
            }
            //Closed flow
            sheets.close();
            inputStream.close();
            return fileName;
        } else {
            throw new Exception("The table is empty,Please select a table!");
        }
    }
Note: for reading complex tables like this, it should be noted that the read row object may lack columns. The normal situation is as follows:


The table shows that the classroom was originally arranged to be separated from Monday and Tuesday for beauty:

However, the table I encountered did not know what the table did, which led to the lack of cell

This is a pit encountered. I don't know the cause. Those who know are welcome to give advice.
The temporary solution is to judge the number of cell s in row. If the weight is less than two, read the next line:

	//Prevent row missing column! = null, but read the specified column with a null pointer and a row missing cell
    if (row.getPhysicalNumberOfCells() < 13) {
          continue;
    }

Write (idea: create worksheet, create sheet, create row of sheet, create cell of row):

    /**
     * Generate lesson schedule on desktop
     *
     * @param schedule
     * @param list
     */
    public void timeTableWrite(Schedule schedule, List<ScheduleVo> list) throws IOException {
        //Creating a workbook is similar to creating an Excel file
        HSSFWorkbook workbook = new HSSFWorkbook();
        //Create a sheetname page name, and directly use the time of the timetable set to make a splice to make the page name
        HSSFSheet sheet = workbook.createSheet(list.get(0).getDateTime() + "-" + list.get(list.size() - 1).getDateTime());

        //Create a header row with subscripts starting from 0
        HSSFRow row = sheet.createRow(0);
        //Cell merging - merging columns (merging does not require the creation of rows or columns as a prerequisite)
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, 9);
        sheet.addMergedRegion(region);
        //Create a column in this row and assign a direct value to it. The header row has only one column
        row.createCell(0).setCellValue(schedule.getName() + " Timetable");
        //However, setting the cell style requires the creation of a cell as a prerequisite, otherwise an error will be reported
        for (int i = 1; i <= 9; i++) {
            row.createCell(i);
        }
        //Create a style for the schedule Title row
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//horizontally
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//Vertical center
        cellStyle.setBorderBottom(BorderStyle.THIN);//Set borders up, down, left and right one by one, with thin lines
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);//The border color of the cell defaults to black
        //Set background color
//        cellStyle.setFillForegroundColor(IndexedColors.BLUE1.getIndex());
//        Cellstyle. Setfillpattern (fillpatterntype. Solid_foreround); / / if the filling mode is not set, the background color will not go up
        //To add a style to a column, not only the first cell needs a border, but all cells participating in the merge need a border
        for (Cell cell : row) {
            cell.setCellStyle(cellStyle);
        }

        //Create column header row
        row = sheet.createRow(1);
        row.createCell(0).setCellValue("date");
        row.createCell(1).setCellValue("week");
        row.createCell(2).setCellValue("place");
        row.createCell(3).setCellValue("morning");
        row.createCell(4).setCellValue("teacher");
        row.createCell(5).setCellValue("");
        row.createCell(6).setCellValue("place");
        row.createCell(7).setCellValue("afternoon");
        row.createCell(8).setCellValue("teacher");
        row.createCell(9).setCellValue("Evening self study classroom");
        //Set column header style
        cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//horizontally
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//Vertical center
        cellStyle.setBorderBottom(BorderStyle.THIN);//Set borders up, down, left and right one by one, with thin lines
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);//The border color of the cell defaults to black
        //To add a style to a column, not only the first cell needs a border, but all cells participating in the merge need a border
        for (Cell cell : row) {
            cell.setCellStyle(cellStyle);
        }

        //Start traversing the timetable information set to create columns
        for (int i = 0; i < list.size(); i++) {
            row = sheet.createRow(i + 2);//The header behavior is 0 and the column header is 1, so i+2
            row.createCell(0).setCellValue(list.get(i).getDateTime());
            row.createCell(1).setCellValue(list.get(i).getWeek());
            row.createCell(2).setCellValue(list.get(i).getAmClassroom());
            row.createCell(3).setCellValue(list.get(i).getAmCourse());
            row.createCell(4).setCellValue(list.get(i).getAmTeacher());
            //If you are traversing the course collection for the first time, you need to merge rows, that is, the lunch break column in the timetable
            if (i == 0) {
                region = new CellRangeAddress(2, list.size() + 1, 5, 5);
                sheet.addMergedRegion(region);
                row.createCell(5).setCellValue("noon break");
            }
            row.createCell(6).setCellValue(list.get(i).getPmClassroom());
            row.createCell(7).setCellValue(list.get(i).getPmCourse());
            row.createCell(8).setCellValue(list.get(i).getPmTeacher());
            row.createCell(9).setCellValue(list.get(i).getNight());
            //Add special styles to traverse columns. Different styles need to be set for different columns
            //Style, common to all columns
            cellStyle = workbook.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);//horizontally
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//Vertical center
            cellStyle.setBorderBottom(BorderStyle.THIN);//Set borders up, down, left and right one by one, with thin lines
            cellStyle.setBorderLeft(BorderStyle.THIN);
            cellStyle.setBorderTop(BorderStyle.THIN);
            cellStyle.setBorderRight(BorderStyle.THIN);//The border color of the cell defaults to black
            for (Cell cell : row) {
                cell.setCellStyle(cellStyle);
            }
        }

        //Set path
        // Get desktop path
        FileSystemView fsv = FileSystemView.getFileSystemView();
        String desktop = fsv.getHomeDirectory().getPath();
        String filePath = desktop + "/" + fileName + ".xls";
        FileOutputStream stream = new FileOutputStream(new File(filePath));
        // Write worksheet
        workbook.write(stream);
        //Closed flow
        stream.close();
    }
}

Final effect:

Topics: Java Excel poi