From d76154e27918068d77032a1ac8a13a0435f18e74 Mon Sep 17 00:00:00 2001 From: jomu Date: Fri, 15 Feb 2019 17:54:53 +0100 Subject: [PATCH] added more POI helper methods --- .../muehlencord/shared/poi/PoiException.java | 51 ++++ .../de/muehlencord/shared/poi/PoiUtil.java | 226 +++++++++++++++++- .../muehlencord/shared/poi/WorkbookApp.java | 2 +- 3 files changed, 268 insertions(+), 11 deletions(-) create mode 100644 poi-util/src/main/java/de/muehlencord/shared/poi/PoiException.java diff --git a/poi-util/src/main/java/de/muehlencord/shared/poi/PoiException.java b/poi-util/src/main/java/de/muehlencord/shared/poi/PoiException.java new file mode 100644 index 0000000..d81e532 --- /dev/null +++ b/poi-util/src/main/java/de/muehlencord/shared/poi/PoiException.java @@ -0,0 +1,51 @@ +/* + * Copyright 2019 joern.muehlencord. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package de.muehlencord.shared.poi; + +/** + * + * @author joern.muehlencord + */ +public class PoiException extends Exception { + + /** + * Creates a new instance of PoiException without detail + * message. + */ + public PoiException() { + } + + /** + * Constructs an instance of PoiException with the specified + * detail message. + * + * @param msg the detail message. + */ + public PoiException(String msg) { + super(msg); + } + + /** + * Constructs an instance of PoiException with the specified + * detail message. + * + * @param msg the detail message. + * @param th the root cause of this exception + */ + public PoiException(String msg, Throwable th) { + super(msg, th); + } +} diff --git a/poi-util/src/main/java/de/muehlencord/shared/poi/PoiUtil.java b/poi-util/src/main/java/de/muehlencord/shared/poi/PoiUtil.java index 1898de4..08c92ad 100644 --- a/poi-util/src/main/java/de/muehlencord/shared/poi/PoiUtil.java +++ b/poi-util/src/main/java/de/muehlencord/shared/poi/PoiUtil.java @@ -15,8 +15,23 @@ */ package de.muehlencord.shared.poi; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -24,21 +39,212 @@ import org.apache.poi.ss.usermodel.CellType; */ public abstract class PoiUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(PoiUtil.class); + private PoiUtil() { // hide constructor of abstract classes } - + public static boolean cellEmpty(Cell cell) { - if (cell == null) + if (cell == null) { return true; - if (cell.getCellType() == CellType.BLANK) - return true; - if (cell.getCellType() == CellType.STRING) { - return cell.getStringCellValue().equals (""); } - return false; + if (cell.getCellType() == CellType.BLANK) { + return true; + } + if (cell.getCellType() == CellType.STRING) { + return cell.getStringCellValue().equals(""); + } + return false; } - - - + + public static Cell createOrGetCell(Row row, int cellNumber, CellStyle cellStyle) { + Cell currentCell = row.getCell(cellNumber); + if (currentCell == null) { + currentCell = row.createCell(cellNumber); + } + if (cellStyle != null) { + currentCell.setCellStyle(cellStyle); + } + return currentCell; + } + + public static Cell setStringValue(Row row, int cellNumber, String stringValue, CellStyle cellStyle) { + Cell currentCell = createOrGetCell(row, cellNumber, cellStyle); + if (stringValue != null) { + currentCell.setCellValue(stringValue); + } + return currentCell; + } + + public static void addCellComment(XSSFWorkbook wb, Row row, int cellNumber, String cellComment) { + addCellComment(wb, row, cellNumber, cellComment, 3, 1); + } + + public static void addCellComment(XSSFWorkbook wb, Row row, int cellNumber, String cellComment, int rowCount, int columnCount) { + Drawing drawing = row.getSheet().createDrawingPatriarch(); + CreationHelper factory = wb.getCreationHelper(); + + Cell cell = createOrGetCell(row, cellNumber, null); + + // When the comment box is visible, have it show in a 1x3 space + ClientAnchor anchor = factory.createClientAnchor(); + anchor.setCol1(cell.getColumnIndex()); + anchor.setCol2(cell.getColumnIndex() + columnCount); + anchor.setRow1(row.getRowNum()); + anchor.setRow2(row.getRowNum() + rowCount); + + // Create the comment and set the text+author + Comment comment = drawing.createCellComment(anchor); + RichTextString str = factory.createRichTextString(cellComment); + comment.setString(str); + comment.setAuthor("PCD"); + + // Assign the comment to the cell + cell.setCellComment(comment); + } + + public static void setDateValue(Row row, int cellNumber, Date date, CellStyle cellStyle) { + Cell currentCell = createOrGetCell(row, cellNumber, cellStyle); + if (date != null) { + currentCell.setCellValue(date); + } + } + + public static void setDoubleValue(Row row, int cellNumber, Double value, CellStyle cellStyle) { + Cell currentCell = createOrGetCell(row, cellNumber, cellStyle); + if (value != null) { + currentCell.setCellValue(value); + } + } + + public static void setBooleanValue(Row row, int cellNumber, boolean value, CellStyle cellStyle) { + Cell currentCell = createOrGetCell(row, cellNumber, cellStyle); + currentCell.setCellValue(value); + } + + public static void setDateValue(Row row, int cellNumber, String dateString, String dateFormat, CellStyle cellStyle) { + Cell currentCell = createOrGetCell(row, cellNumber, cellStyle); + SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); + Date date; + try { + date = sdf.parse(dateString); + } catch (ParseException ex) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace(ex.toString(), ex); + } + date = null; + } + currentCell.setCellValue(date); + } + + public static String getStringValue(Row row, int cellNumber) throws PoiException { + return getStringValue(row, cellNumber, false, null); + } + + public static String getStringValue(Row row, int cellNumber, boolean returnDefaultValue, String defaultValue) throws PoiException { + if (row == null) { + throw new PoiException("Current row must not be null"); + } + Cell cell = row.getCell(cellNumber); + if ((PoiUtil.cellEmpty(cell)) && !returnDefaultValue) { + throw new PoiException("Cannot read cell " + cellNumber + " from row " + row.getRowNum()); + } else { + if (PoiUtil.cellEmpty(cell)) { + return defaultValue; + } else { + if (cell.getCellType() == CellType.NUMERIC) { + Double doubleValue = cell.getNumericCellValue(); + return Integer.toString(doubleValue.intValue()); + } else { + String returnValue = cell.getStringCellValue(); + if (returnValue != null) { + returnValue = returnValue.trim(); + returnValue = replaceProblematicCharacters(returnValue); + } + return returnValue; + } + } + } + } + + public static LocalDate getDateValue(Row row, int cellNumber) throws PoiException { + return getDateValue(row, cellNumber, false, null); + } + + public static LocalDate getDateValue(Row row, int cellNumber, boolean returnDefaultValue, LocalDate defaultValue) throws PoiException { + if (row == null) { + throw new PoiException("Current row must not be null"); + } + Cell cell = row.getCell(cellNumber); + if ((PoiUtil.cellEmpty(cell)) && !returnDefaultValue) { + throw new PoiException("Cannot read cell " + cellNumber + " from row " + row.getRowNum()); + } else { + if (PoiUtil.cellEmpty(cell)) { + return defaultValue; + } else { + Date date = cell.getDateCellValue(); + if (date == null) { + if (returnDefaultValue) { + return defaultValue; + } else { + throw new PoiException("Cell contains null value but not default value shall be returned"); + } + } + return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + } + } + } + + public static boolean getBooleanValue(Row currentRow, int cellNumber, boolean returnDefaultValue, boolean defaultValue) throws PoiException { + if (currentRow == null) { + throw new PoiException("Current row must not be null"); + } + Cell cell = currentRow.getCell(cellNumber); + if ((PoiUtil.cellEmpty(cell)) && !returnDefaultValue) { + throw new PoiException("Cannot read cell " + cellNumber + " from row " + currentRow.getRowNum()); + } else { + if (PoiUtil.cellEmpty(cell)) { + return defaultValue; + } else { + return cell.getBooleanCellValue(); + } + } + } + + public static double getDoubleValue(Row currentRow, int cellNumber) throws PoiException { + return getDoubleValue(currentRow, cellNumber, false, 0D); + } + + public static Double getDoubleValue(Row currentRow, int cellNumber, boolean returnDefaultValue, Double defaultValue) throws PoiException { + if (currentRow == null) { + throw new PoiException("Current row must not be null"); + } + Cell cell = currentRow.getCell(cellNumber); + if ((PoiUtil.cellEmpty(cell)) && !returnDefaultValue) { + throw new PoiException("Cannot read cell " + cellNumber + " from row " + currentRow.getRowNum()); + } else { + if (PoiUtil.cellEmpty(cell)) { + return defaultValue; + } else { + return cell.getNumericCellValue(); + } + } + } + + /** + * remove charecters which often cause troubles in other applications - e.g. em dash (long dash) is created by Excel automatically + * @param sourceValue the input string to execute the replacement + * @return sourceValue with replaced characters + */ + protected static String replaceProblematicCharacters(final String sourceValue) { + String returnValue = sourceValue; + returnValue = returnValue.replace("\u2011", "-"); + returnValue = returnValue.replace("\u2012", "-"); + returnValue = returnValue.replace("\u2013", "-"); + returnValue = returnValue.replace("\u2014", "-"); + + return returnValue; + } + } diff --git a/poi-util/src/main/java/de/muehlencord/shared/poi/WorkbookApp.java b/poi-util/src/main/java/de/muehlencord/shared/poi/WorkbookApp.java index 974f2c4..4f9f5a1 100644 --- a/poi-util/src/main/java/de/muehlencord/shared/poi/WorkbookApp.java +++ b/poi-util/src/main/java/de/muehlencord/shared/poi/WorkbookApp.java @@ -315,5 +315,5 @@ public class WorkbookApp { sheet.autoSizeColumn(currentColumn); } } - + }