Projekt

Obecné

Profil

« Předchozí | Další » 

Revize b2108db7

Přidáno uživatelem Lukas Cerny před téměř 6 roky(ů)

Re #7530 Get 'vacation' and 'overtime' from input xlsx file

Zobrazit rozdíly:

server/pom.xml
31 31

  
32 32
        <dependency>
33 33
            <groupId>org.apache.poi</groupId>
34
            <artifactId>poi</artifactId>
34
            <artifactId>poi-ooxml</artifactId>
35 35
            <version>4.1.0</version>
36 36
        </dependency>
37 37

  
......
41 41
            <version>2.0.15</version>
42 42
        </dependency>
43 43

  
44
        <dependency>
45
            <groupId>com.github.dhorions</groupId>
46
            <artifactId>boxable</artifactId>
47
            <version>1.5</version>
48
        </dependency>
49

  
44 50

  
45 51
        <!-- DATABASE -->
46 52
        <dependency>
server/src/main/java/cz/zcu/yamanager/business/FileServiceImpl.java
1
package cz.zcu.yamanager.business;
2

  
3
import cz.zcu.yamanager.business.file.excel.*;
4
import cz.zcu.yamanager.ws.rest.RESTFullException;
5

  
6
import java.io.ByteArrayInputStream;
7
import java.io.IOException;
8
import java.util.*;
9

  
10
import static cz.zcu.yamanager.business.file.excel.ExcelParser.parseXLSX;
11

  
12
public class FileServiceImpl implements FileService {
13

  
14
    private class Content {
15
        double overtime = 0;
16
        List<Date> vacations = new ArrayList<>();
17
    }
18

  
19
    @Override
20
    public FileImportResult parseXLSFile(String fileName, byte[] bytes) throws RESTFullException {
21

  
22
        try {
23
            Map<String, Content> contentMap = getContentInfo(parseXLSX(new ByteArrayInputStream(bytes)));
24

  
25
            return new FileImportResult(fileName, (long) contentMap.size());
26

  
27
        } catch (IOException e) {
28
            throw new RESTFullException("", "");
29
        }
30
    }
31

  
32
    private Map<String, Content> getContentInfo(Map<String, SheetContent[]> sheetForName) {
33

  
34
        Map<String, Content> result = new HashMap<>();
35

  
36
        for (Map.Entry<String, SheetContent[]> item : sheetForName.entrySet()) {
37
            String name = item.getKey();
38
            SheetAttendanceContent content = (SheetAttendanceContent) item.getValue()[SheetType.ATTENDANCE.ordinal()];
39

  
40
            if (!result.containsKey(name)) {
41
                result.put(name, new Content());
42
            }
43

  
44
            for (AttendanceRecord record : content.getRecords()) {
45
                if (record.getType().equals(RecordType.VACATION)) {
46
                    result.get(name).vacations.add(record.getDate());
47
                }
48
            }
49
            result.get(name).overtime = content.getOvertimeHours();
50
        }
51

  
52
        return result;
53
    }
54

  
55

  
56
    @Override
57
    public FileExportResult createPDFFile() throws RESTFullException {
58
        return new FileExportResult("unknown", new byte[0]);
59
    }
60
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/AttendanceRecord.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import java.util.Date;
4

  
5
public class AttendanceRecord {
6

  
7
    private final Date date;
8
    private final double estimateHours;
9
    private final double workHours;
10
    private final LoadType load;
11
    private final RecordType type;
12

  
13
    public AttendanceRecord(Date date, double estimateHours, double workHours, LoadType load, RecordType type) {
14
        this.date = date;
15
        this.estimateHours = estimateHours;
16
        this.workHours = workHours;
17
        this.load = load;
18
        this.type = type;
19
    }
20

  
21
    public Date getDate() {
22
        return date;
23
    }
24

  
25
    public double getEstimateHours() {
26
        return estimateHours;
27
    }
28

  
29
    public double getWorkHours() {
30
        return workHours;
31
    }
32

  
33
    public LoadType getLoad() {
34
        return load;
35
    }
36

  
37
    public RecordType getType() {
38
        return type;
39
    }
40
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/ExcelParser.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import org.apache.poi.ss.usermodel.Sheet;
4
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
5

  
6
import java.io.IOException;
7
import java.io.InputStream;
8
import java.util.HashMap;
9
import java.util.Iterator;
10
import java.util.Map;
11
import java.util.Optional;
12

  
13
public class ExcelParser {
14

  
15
    private static class SheetInfo {
16
        String employee;
17
        SheetParser parser;
18
    }
19

  
20
    public static Map<String, SheetContent[]> parseXLSX(InputStream inputStream) throws IOException {
21

  
22
        Map<String, SheetContent[]> sheets = new HashMap<>();
23

  
24
        XSSFWorkbook wb = new XSSFWorkbook(inputStream);
25

  
26
        Iterator<Sheet> sheetIterator = wb.sheetIterator();
27
        while (sheetIterator.hasNext()) {
28
            Sheet sheet = sheetIterator.next();
29

  
30
            Optional<SheetInfo> sheetTitleOptional = parseSheetTitle(sheet);
31

  
32
            if (!sheetTitleOptional.isPresent()) {
33
                continue;
34
            }
35

  
36
            SheetInfo sheetInfo = sheetTitleOptional.get();
37

  
38
            SheetContent sheetContent = sheetInfo.parser.parseSheet(sheet);
39

  
40
            if (sheetContent == null) continue;
41

  
42
            if (!sheets.containsKey(sheetInfo.employee)) {
43
                sheets.put(sheetInfo.employee, new SheetContent[SheetType.values().length]);
44
            }
45

  
46
            sheets.get(sheetInfo.employee)[sheetInfo.parser.getType().ordinal()] = sheetContent;
47
        }
48

  
49
        return sheets;
50
    }
51

  
52
    private static Optional<SheetInfo> parseSheetTitle(Sheet sheet) {
53

  
54
        String[] sheetName = sheet.getSheetName().split("-");
55

  
56
        if (sheetName.length != 2) {
57
            return Optional.empty();
58
        }
59

  
60
        SheetInfo result = new SheetInfo();
61
        result.employee = sheetName[1].trim();
62
        switch (sheetName[0].trim().toLowerCase()) {
63
            case "dochazka": result.parser = new SheetAttendanceParser(); break;
64
            case "stravenky": result.parser = new SheetMealTicketParser(); break;
65
        }
66
        return Optional.of(result);
67

  
68
    }
69
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/LoadType.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
public enum LoadType {
4
    WEEKEND, WOORKING_WEEK
5
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/RecordType.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
public enum  RecordType {
4
    VACATION, WORK, BLANK
5
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/SheetAttendanceContent.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import java.util.List;
4

  
5
public class SheetAttendanceContent implements SheetContent {
6

  
7
    private List<AttendanceRecord> records;
8

  
9
    private final double sumOfEstimateHours;
10
    private final double sumOfWorkHours;
11
    private final double hoursPerWeek;
12
    private final double overtimeHours;
13

  
14
    public SheetAttendanceContent(
15
            List<AttendanceRecord> records,
16
            double sumOfEstimateHours,
17
            double sumOfWorkHours,
18
            double hoursPerWeek,
19
            double overtimeHours)
20
    {
21
        this.records = records;
22
        this.sumOfEstimateHours = sumOfEstimateHours;
23
        this.sumOfWorkHours = sumOfWorkHours;
24
        this.hoursPerWeek = hoursPerWeek;
25
        this.overtimeHours = overtimeHours;
26
    }
27

  
28
    public double getSumOfEstimateHours() {
29
        return sumOfEstimateHours;
30
    }
31

  
32
    public double getSumOfWorkHours() {
33
        return sumOfWorkHours;
34
    }
35

  
36
    public double getHoursPerWeek() {
37
        return hoursPerWeek;
38
    }
39

  
40
    public double getOvertimeHours() {
41
        return overtimeHours;
42
    }
43

  
44
    public List<AttendanceRecord> getRecords() {
45
        return records;
46
    }
47
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/SheetAttendanceParser.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import org.apache.poi.ss.usermodel.Cell;
4
import org.apache.poi.ss.usermodel.CellType;
5
import org.apache.poi.ss.usermodel.Row;
6
import org.apache.poi.ss.usermodel.Sheet;
7

  
8
import java.util.ArrayList;
9
import java.util.Date;
10
import java.util.Iterator;
11
import java.util.List;
12

  
13
public class SheetAttendanceParser implements SheetParser {
14

  
15

  
16
    @Override
17
    public SheetContent parseSheet(Sheet sheet) {
18

  
19
        List<AttendanceRecord> records = new ArrayList<>();
20

  
21
        double sumOfEstimateHours = 0;
22
        double sumOfWorkHours = 0;
23
        double hoursPerWeek = 0;
24
        double overtimeHours = 0;
25

  
26
        Iterator<Row> rowIterator = sheet.rowIterator();
27
        rowIterator.next(); // skip header
28
        while (rowIterator.hasNext()) {
29
            Row row = rowIterator.next();
30

  
31
           Cell firstCell = row.getCell(0);
32

  
33
           if (firstCell == null) continue;
34

  
35
           switch (firstCell.getCellType()) {
36
               case NUMERIC: {
37
                   AttendanceRecord record = parseRowOfAttendance(row);
38
                   records.add(record);
39

  
40
                   sumOfEstimateHours += record.getEstimateHours();
41
                   sumOfWorkHours += record.getWorkHours();
42

  
43
               } break;
44
               case STRING: {
45
                    Cell loadCell = row.getCell(1);
46
                   String numString = loadCell.getStringCellValue().replaceAll("[^1-9.]", "");
47
                   hoursPerWeek = Double.parseDouble(numString);
48
               }
49
           }
50
        }
51

  
52
        overtimeHours = sumOfEstimateHours - sumOfWorkHours;
53

  
54
        return new SheetAttendanceContent(records, sumOfEstimateHours, sumOfWorkHours, hoursPerWeek, overtimeHours);
55
    }
56

  
57
    private AttendanceRecord parseRowOfAttendance(Row row) {
58

  
59
        Date date = null;
60
        Cell dateCell = row.getCell(0);
61
        if(dateCell.getCellType().equals(CellType.NUMERIC)) {
62
            date = dateCell.getDateCellValue();
63
        }
64

  
65
        LoadType load = null;
66
        Cell loadCell = row.getCell(1);
67
        switch (loadCell.getStringCellValue()) {
68
            case "prac": load = LoadType.WOORKING_WEEK; break;
69
            case "vikend": load = LoadType.WEEKEND; break;
70
        }
71

  
72
        double estimateHours = 0;
73
        RecordType type = RecordType.BLANK;
74
        Cell estimateHoursCell = row.getCell(2);
75
        switch (estimateHoursCell.getCellType()) {
76
            case NUMERIC: {
77
                estimateHours = estimateHoursCell.getNumericCellValue();
78
                type = RecordType.WORK;
79
            } break;
80
            case STRING: {
81
                String cellValue = estimateHoursCell.getStringCellValue();
82
                if (cellValue.equals("dovolena")) {
83
                    estimateHours = 0;
84
                    type = RecordType.VACATION;
85
                }
86
            }
87
        }
88

  
89
        double workHours = 0;
90
        Cell workHoursCell = row.getCell(3);
91
        switch (workHoursCell.getCellType()) {
92
            case NUMERIC: {
93
                workHours = workHoursCell.getNumericCellValue();
94
            } break;
95
            case STRING: {
96
                String cellValue = workHoursCell.getStringCellValue();
97
                if (cellValue.equals("dovolena")) {
98
                    workHours = 0;
99
                }
100
            }
101
        }
102

  
103
        return new AttendanceRecord(date, estimateHours, workHours, load, type);
104
    }
105

  
106

  
107
    @Override
108
    public SheetType getType() {
109
        return SheetType.ATTENDANCE;
110
    }
111
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/SheetContent.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
public interface SheetContent {
4
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/SheetMealTicketParser.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import org.apache.poi.ss.usermodel.Sheet;
4

  
5
public class SheetMealTicketParser implements SheetParser {
6

  
7
    @Override
8
    public SheetContent parseSheet(Sheet sheet) {
9
        return null;
10
    }
11

  
12
    @Override
13
    public SheetType getType() {
14
        return SheetType.MEAL_TICKET;
15
    }
16
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/SheetParser.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import org.apache.poi.ss.usermodel.Sheet;
4

  
5
public interface SheetParser {
6

  
7
    SheetContent parseSheet(Sheet sheet);
8

  
9
    SheetType getType();
10
}
server/src/main/java/cz/zcu/yamanager/business/file/excel/SheetType.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
public enum SheetType {
4
    ATTENDANCE, MEAL_TICKET
5
}
server/src/main/java/cz/zcu/yamanager/business/mock/FileServiceMock.java
1 1
package cz.zcu.yamanager.business.mock;
2 2

  
3
import be.quodlibet.boxable.BaseTable;
4
import be.quodlibet.boxable.Cell;
5
import be.quodlibet.boxable.Row;
6
import be.quodlibet.boxable.datatable.DataTable;
3 7
import cz.zcu.yamanager.business.FileExportResult;
4 8
import cz.zcu.yamanager.business.FileImportResult;
5 9
import cz.zcu.yamanager.business.FileService;
......
9 13
import org.apache.pdfbox.pdmodel.PDPageContentStream;
10 14
import org.apache.pdfbox.pdmodel.common.PDRectangle;
11 15
import org.apache.pdfbox.pdmodel.font.PDType1Font;
12
import org.apache.poi.hssf.usermodel.HSSFCell;
13
import org.apache.poi.hssf.usermodel.HSSFRow;
14
import org.apache.poi.hssf.usermodel.HSSFSheet;
15
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
16
import org.apache.poi.xssf.usermodel.XSSFCell;
17
import org.apache.poi.xssf.usermodel.XSSFRow;
18
import org.apache.poi.xssf.usermodel.XSSFSheet;
19
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
16 20
import org.springframework.stereotype.Component;
17 21

  
18 22
import java.io.ByteArrayInputStream;
19 23
import java.io.ByteArrayOutputStream;
20 24
import java.io.IOException;
21 25
import java.util.ArrayList;
26
import java.util.Arrays;
22 27
import java.util.Iterator;
23 28
import java.util.List;
24 29

  
......
30 35
    @Override
31 36
    public FileImportResult parseXLSFile(String fileName, byte[] bytes) throws RESTFullException {
32 37
        try {
33
            HSSFWorkbook wb = new HSSFWorkbook(new ByteArrayInputStream(bytes));
34 38

  
35
            HSSFSheet sheet=wb.getSheetAt(0);
36
            HSSFRow row;
37
            HSSFCell cell;
39
            XSSFWorkbook wb = new XSSFWorkbook(new ByteArrayInputStream(bytes));
40

  
41
            XSSFSheet sheet=wb.getSheetAt(0);
42
            XSSFRow row;
43
            XSSFCell cell;
38 44

  
39 45
            Iterator rows = sheet.rowIterator();
40 46

  
41 47
            while (rows.hasNext()) {
42
                row=(HSSFRow) rows.next();
48
                row=(XSSFRow) rows.next();
43 49
                Iterator cells = row.cellIterator();
44 50

  
45 51
                while (cells.hasNext()) {
46
                    cell = (HSSFCell) cells.next();
52
                    cell = (XSSFCell) cells.next();
47 53

  
48
                    content.add(cell.getStringCellValue());
54
                    content.add(cell.getRawValue());
49 55
                }
50 56
            }
51 57
            return new FileImportResult(fileName, (long) bytes.length);
......
82 88
            document.save(output);
83 89
            document.close();
84 90

  
85
            return new FileExportResult("export.pdf", output.toByteArray());
91
            return new FileExportResult("export.pdf", pdfTable());
86 92

  
87 93
        } catch (IOException ioex) {
88 94
            throw new RESTFullException("", "");
89 95
        }
90 96
    }
97

  
98
    private byte[] pdfTable() throws IOException {
99
        PDPage myPage = new PDPage(PDRectangle.A4);
100
        PDDocument mainDocument = new PDDocument();
101
        PDPageContentStream contentStream = new PDPageContentStream(mainDocument, myPage);
102

  
103

  
104

  
105
        //Dummy Table
106
        float margin = 50;
107
        // starting y position is whole page height subtracted by top and bottom margin
108
        float yStartNewPage = myPage.getMediaBox().getHeight() - (2 * margin);
109
        // we want table across whole page width (subtracted by left and right margin ofcourse)
110
        float tableWidth = myPage.getMediaBox().getWidth() - (2 * margin);
111

  
112
        boolean drawContent = true;
113
        float yStart = yStartNewPage;
114
        float bottomMargin = 70;
115
        // y position is your coordinate of top left corner of the table
116
        float yPosition = 550;
117

  
118
        List<List> data = new ArrayList();
119
        data.add(new ArrayList<>(
120
                Arrays.asList("Column One", "Column Two", "Column Three", "Column Four", "Column Five")));
121
        for (int i = 1; i <= 100; i++) {
122
            data.add(new ArrayList<>(
123
                    Arrays.asList("Row " + i + " Col One", "Row " + i + " Col Two", "Row " + i + " Col Three", "Row " + i + " Col Four", "Row " + i + " Col Five")));
124
        }
125
        BaseTable dataTable = new BaseTable(yStart, yStartNewPage, bottomMargin, tableWidth, margin, mainDocument, myPage, true, true);
126
        DataTable t = new DataTable(dataTable, myPage);
127
        t.addListToTable(data, DataTable.HASHEADER);
128
        dataTable.draw();
129

  
130
        contentStream.close();
131
        mainDocument.addPage(myPage);
132

  
133
        ByteArrayOutputStream output = new ByteArrayOutputStream();
134
        mainDocument.save(output);
135

  
136
        mainDocument.close();
137
        contentStream.close();
138

  
139
        return output.toByteArray();
140
    }
141

  
142
    private byte[] pdfSimple() throws IOException {
143

  
144
        PDPage myPage = new PDPage(PDRectangle.A4);
145
        PDDocument mainDocument = new PDDocument();
146
        PDPageContentStream contentStream = new PDPageContentStream(mainDocument, myPage);
147

  
148

  
149

  
150
        //Dummy Table
151
        float margin = 50;
152
        // starting y position is whole page height subtracted by top and bottom margin
153
        float yStartNewPage = myPage.getMediaBox().getHeight() - (2 * margin);
154
        // we want table across whole page width (subtracted by left and right margin ofcourse)
155
        float tableWidth = myPage.getMediaBox().getWidth() - (2 * margin);
156

  
157
        boolean drawContent = true;
158
        float yStart = yStartNewPage;
159
        float bottomMargin = 70;
160
        // y position is your coordinate of top left corner of the table
161
        float yPosition = 550;
162

  
163
        BaseTable table = new BaseTable(yPosition, yStartNewPage, bottomMargin, tableWidth, margin, mainDocument, myPage, true, drawContent);
164

  
165

  
166
        Row<PDPage> headerRow = table.createRow(15f);
167
        Cell<PDPage> cell = headerRow.createCell(100, "Header");
168
        table.addHeaderRow(headerRow);
169

  
170

  
171
        Row<PDPage> row = table.createRow(12);
172
        cell = row.createCell(30, "Data 1");
173
        cell = row.createCell(70, "Some value");
174

  
175
        table.draw();
176

  
177

  
178
        contentStream.close();
179
        mainDocument.addPage(myPage);
180

  
181
        ByteArrayOutputStream output = new ByteArrayOutputStream();
182
        mainDocument.save(output);
183

  
184
        mainDocument.close();
185
        contentStream.close();
186

  
187
        return output.toByteArray();
188
    }
189

  
190

  
91 191
}
server/src/test/java/cz/zcu/yamanager/business/file/excel/ExcelParserTest.java
1
package cz.zcu.yamanager.business.file.excel;
2

  
3
import org.junit.jupiter.api.Test;
4

  
5
import java.io.IOException;
6
import java.io.InputStream;
7
import java.util.*;
8

  
9
import static org.junit.jupiter.api.Assertions.*;
10

  
11
class ExcelParserTest {
12

  
13
    @Test
14
    public void parseXLSFile() {
15

  
16
        try {
17

  
18
            InputStream stream = getClass().getClassLoader().getResourceAsStream("dochazka_mezistupen.xlsx");
19

  
20
            Map<String, SheetContent[]> sheets = ExcelParser.parseXLSX(stream);
21

  
22
            Map<String, Double> nameOvertime = new HashMap<>();
23
            Map<String, List<Date>> nameVacation = new HashMap<>();
24

  
25
            for (Map.Entry<String, SheetContent[]> item : sheets.entrySet()) {
26
                String name = item.getKey();
27
                SheetAttendanceContent content = (SheetAttendanceContent) item.getValue()[SheetType.ATTENDANCE.ordinal()];
28
                for (AttendanceRecord record : content.getRecords()) {
29
                    if (record.getType().equals(RecordType.VACATION)) {
30
                        if (!nameVacation.containsKey(name)) {
31
                            nameVacation.put(name, new ArrayList<>());
32
                        }
33
                        nameVacation.get(name).add(record.getDate());
34
                    }
35
                }
36
                nameOvertime.put(name, content.getOvertimeHours());
37
            }
38

  
39
            assertTrue(nameOvertime.containsKey("Onegin"));
40
            assertEquals(0, nameOvertime.get("Onegin").intValue());
41

  
42
            assertTrue(nameOvertime.containsKey("Novak"));
43
            assertEquals(0, nameOvertime.get("Novak").intValue());
44

  
45
            assertTrue(nameOvertime.containsKey("Pavel"));
46
            assertEquals(0, nameOvertime.get("Pavel").intValue());
47

  
48
            assertTrue(nameOvertime.containsKey("Fristensky"));
49
            assertEquals(0, nameOvertime.get("Fristensky").intValue());
50

  
51

  
52
            assertFalse(nameVacation.containsKey("Onegin"));
53
            assertFalse(nameVacation.containsKey("Novak"));
54
            assertFalse(nameVacation.containsKey("Fristensky"));
55

  
56
            assertTrue(nameVacation.containsKey("Pavel"));
57
            assertEquals(5, nameVacation.get("Pavel").size());
58

  
59
        } catch (IOException e) {
60
            assertFalse(false, "");
61
        }
62
    }
63

  
64
}

Také k dispozici: Unified diff