View Javadoc
1   package de.aikiit.bilanzanalyser.reader;
2   
3   import de.aikiit.bilanzanalyser.entity.BilanzRow;
4   import lombok.AllArgsConstructor;
5   import lombok.Data;
6   import lombok.extern.log4j.Log4j2;
7   import org.odftoolkit.odfdom.doc.OdfSpreadsheetDocument;
8   import org.odftoolkit.odfdom.doc.table.OdfTable;
9   import org.odftoolkit.odfdom.doc.table.OdfTableCell;
10  import org.odftoolkit.odfdom.doc.table.OdfTableRow;
11  
12  import java.io.File;
13  import java.io.IOException;
14  import java.nio.file.Path;
15  import java.util.ArrayList;
16  import java.util.List;
17  import java.util.Optional;
18  import java.util.concurrent.atomic.AtomicInteger;
19  
20  import static de.aikiit.bilanzanalyser.reader.BilanzRowParser.fromOdfTableRow;
21  
22  @Data
23  @AllArgsConstructor
24  @Log4j2
25  public final class BilanzOdsReader {
26  
27      private String tableName;
28      private Path source;
29  
30      public static void main(final String[] args) {
31          try (OdfSpreadsheetDocument document = OdfSpreadsheetDocument.loadDocument(new File("/tmp/example.ods"))) {
32              OdfTable table = document.getTableByName("Ausgaben");
33              log.info("{} lines to read", table.getRowCount());
34  
35              for (int row = 0; row < 10 /*table.getRowCount() */; row++) {
36                  for (int col = 0; col < table.getColumnCount(); col++) {
37                      OdfTableCell cell = table.getCellByPosition(col, row);
38                      System.out.print(cell.getStringValue() + "\t");
39                  }
40                  System.out.println();
41              }
42  
43          } catch (Exception e) {
44              log.error(e);
45          }
46      }
47  
48      /**
49       * Parses the given tableName in the configured ODS file.
50       *
51       * @return result object.
52       * @throws IOException in case of general I/O errors as parsing errors are transformed into skipped rows.
53       */
54      public BilanzRowParserResult extractData() throws IOException {
55          try {
56              BilanzRowParserResult result = BilanzRowParserResult.empty();
57  
58              OdfTable table = readTable();
59              if (table == null) {
60                  return result;
61              }
62  
63              // ODS default is 1048576 albeit it's only empty rows
64              log.info("Given table '{}' has {} rows", this.tableName, table.getRowCount());
65  
66              List<BilanzRow> rows = new ArrayList<>();
67              AtomicInteger counter = new AtomicInteger(0);
68              AtomicInteger readRows = new AtomicInteger(0);
69              AtomicInteger rowsWithParsingErrors = new AtomicInteger(0);
70  
71              for (int rowCount = 0; rowCount < table.getRowCount(); rowCount++) {
72                  OdfTableRow row = table.getRowByIndex(rowCount);
73  
74                  // only allow 5 empty rows in a row
75                  if (counter.get() == 5) {
76                      log.info("STOPPING due to too many empty lines after having read {} non-empty rows.", readRows.get());
77                      break;
78                  }
79  
80                  OdfTableCell cell = row.getCellByIndex(0);
81                  if (cell.getStringValue().isEmpty()) {
82                      counter.incrementAndGet();
83                      // skip empty rows
84                  } else {
85                      counter.set(0);
86                      readRows.incrementAndGet();
87                      result = result.withRow();
88  
89                      Optional<BilanzRow> br = fromOdfTableRow(row);
90                      if (br.isPresent()) {
91                          rows.add(br.get());
92                      } else {
93                          rowsWithParsingErrors.incrementAndGet();
94                          result = result.withError();
95                      }
96                  }
97              }
98  
99              log.info("Extracted {} rows successfully, while skipping {} not well formatted rows.", rows.size(), rowsWithParsingErrors.get());
100             return result.withRows(rows);
101         } catch (Exception e) {
102             throw new IOException(e);
103         }
104     }
105 
106     private OdfTable readTable() throws Exception {
107         try (OdfSpreadsheetDocument document = OdfSpreadsheetDocument.loadDocument(source.toFile())) {
108             return document.getTableByName(this.tableName);
109         }
110     }
111 }