diff --git a/poi-util/pom.xml b/poi-util/pom.xml index 7b3e851..2abf5b0 100644 --- a/poi-util/pom.xml +++ b/poi-util/pom.xml @@ -36,7 +36,4 @@ provided - - apache20 - \ No newline at end of file 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 4f9f5a1..dc3fd93 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 @@ -1,319 +1,323 @@ -/* - * Copyright 2019 Joern Muehlencord (joern (at) muehlencord.de) - * - * 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; - -import de.muehlencord.shared.util.file.FileUtil; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.formula.FormulaParser; -import org.apache.poi.ss.formula.FormulaRenderer; -import org.apache.poi.ss.formula.FormulaType; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.ss.formula.ptg.RefPtgBase; -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.DataValidation; -import org.apache.poi.ss.usermodel.DataValidationHelper; -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.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.xssf.usermodel.XSSFDataValidation; -import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook; -import org.apache.poi.xssf.usermodel.XSSFSheet; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Joern Muehlencord (joern (at) muehlencord.de) - */ -public class WorkbookApp { - - private final static Logger LOGGER = LoggerFactory.getLogger(WorkbookApp.class); - - /** - * the workbook to work on - */ - protected Workbook wb; - - /** - * opens the given workbook - * - * @param filename path and filename of the workbook to open. - * @return the workbook loaded - * @throws FileNotFoundException if the workbook cannot be found - * @throws IOException if the workbook cannot be loaded - */ - public Workbook loadWorkbook(String filename) throws IOException { - if (filename.toLowerCase().endsWith(".xlsx")) { - FileInputStream fis = new FileInputStream(new File(filename)); - return new XSSFWorkbook(fis); - } else { - POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filename)); - return new HSSFWorkbook(fs, true); - } - } - - /** - * stores the (changed) workbook under the given filename - * - * @param filename the path and name of the file to store the workbook - * under. - * @throws FileNotFoundException if the path is not found - * @throws IOException if the file cannot be genrated. - */ - public void storeWorkbook(String filename) throws IOException { - FileOutputStream fos = new FileOutputStream(new File(filename)); - wb.write(fos); - } - - /** - * stores the (changed) workbook under the given filename - * - * @param fileName the path and name of the file to store the workbook - * under. - * @param tempName a temporary name the file is stored under before it is - * renamed to fileName. This is required as POI cannot open and store a - * Workbook under the same name. - * @throws FileNotFoundException if the path is not found - * @throws IOException if the file cannot be generated. - */ - public void storeWorkbook(String fileName, String tempName) throws IOException { - FileOutputStream fos = new FileOutputStream(new File(tempName)); - wb.write(fos); - - File source = Paths.get(tempName).toFile(); - File destination = Paths.get(fileName).toFile(); - FileUtil.moveFileTo(source, destination); - } - - protected void copyColumn(Sheet oldSheet, int oldColumn, Sheet newSheet, int newColumn) { - int maxRowNum = oldSheet.getLastRowNum(); - for (int i = 0; i <= maxRowNum; i++) { - Row currentRow = oldSheet.getRow(i); - if (currentRow != null) { - Cell sourceCell = currentRow.getCell(oldColumn); - Cell destCell = currentRow.createCell(newColumn); - copyCell(sourceCell, destCell, null); // copy to same sheet, cellStyle map not needed - - CellRangeAddress oldRegion = getMergedRegion(oldSheet, i, oldColumn); - CellRangeAddress newRegion = getMergedRegion(newSheet, i, newColumn); - if (oldRegion != null && newRegion == null) { - - if (oldSheet != newSheet | oldRegion.getFirstColumn() == oldColumn) { - // region starts in this column; create new one - int firstRow = oldRegion.getFirstRow(); - int lastRow = oldRegion.getLastRow(); - int firstColumn = oldRegion.getFirstColumn() + newColumn - oldColumn; - int lastColumn = oldRegion.getLastColumn() + newColumn - oldColumn; - - newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn); - newSheet.addMergedRegion(newRegion); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Created new merged region {}", newRegion.toString()); - } - } else { - // region contains source column, extend column to including new column - Integer mergedRegionIndex = getMergedRegionIndex(oldSheet, oldRegion); - if (mergedRegionIndex != null) { - oldSheet.removeMergedRegion(mergedRegionIndex); - } - - int firstRow = oldRegion.getFirstRow(); - int lastRow = oldRegion.getLastRow(); - int firstColumn = oldRegion.getFirstColumn(); - int lastColumn = newColumn; - - newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn); - newSheet.addMergedRegion(newRegion); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Updated merged region from {} to ", oldRegion.toString(), newRegion.toString()); - } - } - } - } - } - newSheet.setColumnWidth(newColumn, oldSheet.getColumnWidth(oldColumn)); - } - - protected void copyCell(Cell oldCell, Cell newCell, Map styleMap) { - if (oldCell.getSheet().getWorkbook() == newCell.getSheet().getWorkbook()) { - newCell.setCellStyle(oldCell.getCellStyle()); - } else if (styleMap != null) { - int stHashCode = oldCell.getCellStyle().hashCode(); - CellStyle newCellStyle = styleMap.get(stHashCode); - if (newCellStyle == null) { - newCellStyle = newCell.getSheet().getWorkbook().createCellStyle(); - newCellStyle.cloneStyleFrom(oldCell.getCellStyle()); - styleMap.put(stHashCode, newCellStyle); - } - newCell.setCellStyle(newCellStyle); - } - - switch (oldCell.getCellType()) { - case STRING: - newCell.setCellValue(oldCell.getStringCellValue()); - break; - case NUMERIC: - newCell.setCellValue(oldCell.getNumericCellValue()); - break; - case BLANK: - newCell.setCellType(CellType.BLANK); - break; - case BOOLEAN: - newCell.setCellValue(oldCell.getBooleanCellValue()); - break; - case ERROR: - newCell.setCellErrorValue(oldCell.getErrorCellValue()); - break; - case FORMULA: - String formula = oldCell.getCellFormula(); - XSSFEvaluationWorkbook workbookWrapper = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb); - /* parse formula */ - Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL, 0 /*sheet index*/); - /* re-calculate cell references */ - for (Ptg ptg : ptgs) { - //base class for cell reference "things" - if (ptg instanceof RefPtgBase) { - RefPtgBase ref = (RefPtgBase) ptg; - if (ref.isColRelative()) { - ref.setColumn(ref.getColumn() + newCell.getColumnIndex() - oldCell.getColumnIndex()); - } - if (ref.isRowRelative()) { - ref.setRow(ref.getRow() + +newCell.getRowIndex() - oldCell.getRowIndex()); - } - } - } - formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs); - newCell.setCellFormula(formula); - break; - default: - break; - } - - XSSFSheet sheet = (XSSFSheet) oldCell.getSheet(); - - // TODO copy conditional formating - // FIXME - does not work, it does not take care about formulas at the moment - /* - - XSSFSheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting(); - int countConditionalFormatting = conditionalFormatting.getNumConditionalFormattings(); - for (int i = 0; i < countConditionalFormatting; i++) { - XSSFConditionalFormatting currentFormatting = conditionalFormatting.getConditionalFormattingAt(i); - CellRangeAddress[] cellRangeAddresses = currentFormatting.getFormattingRanges(); - boolean oldCellHasConditionalFormatting = false; - for (CellRangeAddress currentCellRange : cellRangeAddresses) { - oldCellHasConditionalFormatting = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex()); - } - if (oldCellHasConditionalFormatting) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Found conditional formatting for cell {} ", oldCell.getAddress().toString()); - } - - - - // add the new cell to the cell rang addresses - CellRangeAddress[] newCellRangeAddresses = new CellRangeAddress[cellRangeAddresses.length+1]; - for (int j = 0; j < cellRangeAddresses.length; j++) { - newCellRangeAddresses[j] = cellRangeAddresses[j]; - } - newCellRangeAddresses[cellRangeAddresses.length] = new CellRangeAddress (newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex()); - currentFormatting.setFormattingRanges(newCellRangeAddresses); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Copied conditional formatting to cell {}", newCell.getAddress().toString()); - } - - } - } - */ - // SheetConditionalFormatting cf = oldCell.getSheet().getSheetConditionalFormatting(); - // copy data constraints - List dataValidations = sheet.getDataValidations(); - DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper(); - - Iterator it = dataValidations.iterator(); - - while (it.hasNext()) { - XSSFDataValidation dataValidation = it.next(); - boolean oldCellHasDataValidation = false; - CellRangeAddress[] cellRangeAddresses = dataValidation.getRegions().getCellRangeAddresses(); - for (CellRangeAddress currentCellRange : cellRangeAddresses) { - oldCellHasDataValidation = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex()); - } - if (oldCellHasDataValidation) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Found data validation for cell {} ", oldCell.getAddress().toString()); - } - - CellRangeAddressList newCellRangeList = new CellRangeAddressList(newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex()); - DataValidation newValidation = dataValidationHelper.createValidation(dataValidation.getValidationConstraint(), newCellRangeList); - sheet.addValidationData(newValidation); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Copied data validation to cell {}", newCell.getAddress().toString()); - } - } - } - } - - protected CellRangeAddress getMergedRegion(Sheet sheet, int rowNum, int cellNum) { - for (int i = 0; i < sheet.getNumMergedRegions(); i++) { - CellRangeAddress merged = sheet.getMergedRegion(i); - if (merged.isInRange(rowNum, cellNum)) { - return merged; - } - } - return null; - } - - protected Integer getMergedRegionIndex(Sheet sheet, CellRangeAddress mergedRegion) { - for (int i = 0; i < sheet.getNumMergedRegions(); i++) { - CellRangeAddress merged = sheet.getMergedRegion(i); - if ((merged.getFirstColumn() == mergedRegion.getFirstColumn()) - && (merged.getLastColumn() == mergedRegion.getLastColumn()) - && (merged.getFirstRow() == mergedRegion.getFirstRow()) - && (merged.getLastRow() == mergedRegion.getLastRow())) { - return i; - } - } - return null; - } - - protected void autoResizeColumns(Sheet sheet) { - int maxColumn = sheet.getRow(0).getPhysicalNumberOfCells(); - for (int currentColumn = 0; currentColumn < maxColumn; currentColumn++) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Auto resize column {}/{}", currentColumn, maxColumn); - } - - sheet.autoSizeColumn(currentColumn); - } - } - -} +/* + * Copyright 2019 Joern Muehlencord (joern (at) muehlencord.de) + * + * 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; + +import de.muehlencord.shared.util.file.FileUtil; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.formula.FormulaParser; +import org.apache.poi.ss.formula.FormulaRenderer; +import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.ss.formula.ptg.RefPtgBase; +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.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationHelper; +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.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Joern Muehlencord (joern (at) muehlencord.de) + */ +public class WorkbookApp { + + private final static Logger LOGGER = LoggerFactory.getLogger(WorkbookApp.class); + + /** + * the workbook to work on + */ + protected Workbook wb; + + /** + * opens the given workbook + * + * @param filename path and filename of the workbook to open. + * @return the workbook loaded + * @throws FileNotFoundException if the workbook cannot be found + * @throws IOException if the workbook cannot be loaded + */ + public Workbook loadWorkbook(String filename) throws IOException { + if (filename.toLowerCase().endsWith(".xlsx")) { + FileInputStream fis = new FileInputStream(new File(filename)); + return new XSSFWorkbook(fis); + } else { + POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filename)); + return new HSSFWorkbook(fs, true); + } + } + + /** + * stores the (changed) workbook under the given filename + * + * @param filename the path and name of the file to store the workbook + * under. + * @throws FileNotFoundException if the path is not found + * @throws IOException if the file cannot be genrated. + */ + public void storeWorkbook(String filename) throws IOException { + FileOutputStream fos = new FileOutputStream(new File(filename)); + wb.write(fos); + } + + /** + * stores the (changed) workbook under the given filename + * + * @param fileName the path and name of the file to store the workbook + * under. + * @param tempName a temporary name the file is stored under before it is + * renamed to fileName. This is required as POI cannot open and store a + * Workbook under the same name. + * @throws FileNotFoundException if the path is not found + * @throws IOException if the file cannot be generated. + */ + public void storeWorkbook(String fileName, String tempName) throws IOException { + FileOutputStream fos = new FileOutputStream(new File(tempName)); + wb.write(fos); + + File source = Paths.get(tempName).toFile(); + File destination = Paths.get(fileName).toFile(); + FileUtil.moveFileTo(source, destination); + } + + protected void copyColumn(Sheet oldSheet, int oldColumn, Sheet newSheet, int newColumn) { + int maxRowNum = oldSheet.getLastRowNum(); + for (int i = 0; i <= maxRowNum; i++) { + Row currentRow = oldSheet.getRow(i); + if (currentRow != null) { + Cell sourceCell = currentRow.getCell(oldColumn); + Cell destCell = currentRow.createCell(newColumn); + copyCell(sourceCell, destCell, null); // copy to same sheet, cellStyle map not needed + + CellRangeAddress oldRegion = getMergedRegion(oldSheet, i, oldColumn); + CellRangeAddress newRegion = getMergedRegion(newSheet, i, newColumn); + if (oldRegion != null && newRegion == null) { + + if (oldSheet != newSheet | oldRegion.getFirstColumn() == oldColumn) { + // region starts in this column; create new one + int firstRow = oldRegion.getFirstRow(); + int lastRow = oldRegion.getLastRow(); + int firstColumn = oldRegion.getFirstColumn() + newColumn - oldColumn; + int lastColumn = oldRegion.getLastColumn() + newColumn - oldColumn; + + newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn); + newSheet.addMergedRegion(newRegion); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Created new merged region {}", newRegion.toString()); + } + } else { + // region contains source column, extend column to including new column + Integer mergedRegionIndex = getMergedRegionIndex(oldSheet, oldRegion); + if (mergedRegionIndex != null) { + oldSheet.removeMergedRegion(mergedRegionIndex); + } + + int firstRow = oldRegion.getFirstRow(); + int lastRow = oldRegion.getLastRow(); + int firstColumn = oldRegion.getFirstColumn(); + int lastColumn = newColumn; + + newRegion = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn); + newSheet.addMergedRegion(newRegion); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Updated merged region from {} to ", oldRegion.toString(), newRegion.toString()); + } + } + } + } + } + newSheet.setColumnWidth(newColumn, oldSheet.getColumnWidth(oldColumn)); + } + + protected void copyCell(Cell oldCell, Cell newCell, Map styleMap) { + if (oldCell.getSheet().getWorkbook() == newCell.getSheet().getWorkbook()) { + newCell.setCellStyle(oldCell.getCellStyle()); + } else if (styleMap != null) { + int stHashCode = oldCell.getCellStyle().hashCode(); + CellStyle newCellStyle = styleMap.get(stHashCode); + if (newCellStyle == null) { + newCellStyle = newCell.getSheet().getWorkbook().createCellStyle(); + newCellStyle.cloneStyleFrom(oldCell.getCellStyle()); + styleMap.put(stHashCode, newCellStyle); + } + newCell.setCellStyle(newCellStyle); + } + + switch (oldCell.getCellType()) { + case STRING: + newCell.setCellValue(oldCell.getStringCellValue()); + break; + case NUMERIC: + newCell.setCellValue(oldCell.getNumericCellValue()); + break; + case BLANK: + newCell.setBlank(); + break; + case BOOLEAN: + newCell.setCellValue(oldCell.getBooleanCellValue()); + break; + case ERROR: + newCell.setCellErrorValue(oldCell.getErrorCellValue()); + break; + case FORMULA: + String formula = oldCell.getCellFormula(); + XSSFEvaluationWorkbook workbookWrapper = XSSFEvaluationWorkbook.create((XSSFWorkbook) wb); + /* parse formula */ + Ptg[] ptgs = FormulaParser.parse(formula, workbookWrapper, FormulaType.CELL, 0 /*sheet index*/); + /* re-calculate cell references */ + for (Ptg ptg : ptgs) { + //base class for cell reference "things" + if (ptg instanceof RefPtgBase) { + RefPtgBase ref = (RefPtgBase) ptg; + if (ref.isColRelative()) { + ref.setColumn(ref.getColumn() + newCell.getColumnIndex() - oldCell.getColumnIndex()); + } + if (ref.isRowRelative()) { + ref.setRow(ref.getRow() + +newCell.getRowIndex() - oldCell.getRowIndex()); + } + } + } + formula = FormulaRenderer.toFormulaString(workbookWrapper, ptgs); + newCell.setCellFormula(formula); + break; + default: + break; + } + + XSSFSheet sheet = (XSSFSheet) oldCell.getSheet(); + + // TODO copy conditional formating + // FIXME - does not work, it does not take care about formulas at the moment + /* + + XSSFSheetConditionalFormatting conditionalFormatting = sheet.getSheetConditionalFormatting(); + int countConditionalFormatting = conditionalFormatting.getNumConditionalFormattings(); + for (int i = 0; i < countConditionalFormatting; i++) { + XSSFConditionalFormatting currentFormatting = conditionalFormatting.getConditionalFormattingAt(i); + CellRangeAddress[] cellRangeAddresses = currentFormatting.getFormattingRanges(); + boolean oldCellHasConditionalFormatting = false; + for (CellRangeAddress currentCellRange : cellRangeAddresses) { + oldCellHasConditionalFormatting = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex()); + } + if (oldCellHasConditionalFormatting) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Found conditional formatting for cell {} ", oldCell.getAddress().toString()); + } + + + + // add the new cell to the cell rang addresses + CellRangeAddress[] newCellRangeAddresses = new CellRangeAddress[cellRangeAddresses.length+1]; + for (int j = 0; j < cellRangeAddresses.length; j++) { + newCellRangeAddresses[j] = cellRangeAddresses[j]; + } + newCellRangeAddresses[cellRangeAddresses.length] = new CellRangeAddress (newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex()); + currentFormatting.setFormattingRanges(newCellRangeAddresses); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Copied conditional formatting to cell {}", newCell.getAddress().toString()); + } + + } + } + */ + // SheetConditionalFormatting cf = oldCell.getSheet().getSheetConditionalFormatting(); + // copy data constraints + List dataValidations = sheet.getDataValidations(); + DataValidationHelper dataValidationHelper = sheet.getDataValidationHelper(); + + Iterator it = dataValidations.iterator(); + + while (it.hasNext()) { + XSSFDataValidation dataValidation = it.next(); + boolean oldCellHasDataValidation = false; + CellRangeAddress[] cellRangeAddresses = dataValidation.getRegions().getCellRangeAddresses(); + for (CellRangeAddress currentCellRange : cellRangeAddresses) { + oldCellHasDataValidation = currentCellRange.containsRow(oldCell.getRowIndex()) && currentCellRange.containsColumn(oldCell.getColumnIndex()); + } + if (oldCellHasDataValidation) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Found data validation for cell {} ", oldCell.getAddress().toString()); + } + + CellRangeAddressList newCellRangeList = new CellRangeAddressList(newCell.getRowIndex(), newCell.getRowIndex(), newCell.getColumnIndex(), newCell.getColumnIndex()); + DataValidation newValidation = dataValidationHelper.createValidation(dataValidation.getValidationConstraint(), newCellRangeList); + sheet.addValidationData(newValidation); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Copied data validation to cell {}", newCell.getAddress().toString()); + } + } + } + } + + protected CellRangeAddress getMergedRegion(Sheet sheet, int rowNum, int cellNum) { + for (int i = 0; i < sheet.getNumMergedRegions(); i++) { + CellRangeAddress merged = sheet.getMergedRegion(i); + if (merged.isInRange(rowNum, cellNum)) { + return merged; + } + } + return null; + } + + protected Integer getMergedRegionIndex(Sheet sheet, CellRangeAddress mergedRegion) { + for (int i = 0; i < sheet.getNumMergedRegions(); i++) { + CellRangeAddress merged = sheet.getMergedRegion(i); + if ((merged.getFirstColumn() == mergedRegion.getFirstColumn()) + && (merged.getLastColumn() == mergedRegion.getLastColumn()) + && (merged.getFirstRow() == mergedRegion.getFirstRow()) + && (merged.getLastRow() == mergedRegion.getLastRow())) { + return i; + } + } + return null; + } + + protected void autoResizeColumns(Sheet sheet) { + autoResizeColumns(sheet,0); + } + + protected void autoResizeColumns(Sheet sheet, int referenceRow) { + int maxColumn = sheet.getRow(referenceRow).getPhysicalNumberOfCells(); + for (int currentColumn = 0; currentColumn < maxColumn; currentColumn++) { + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Auto resize column {}/{}", currentColumn, maxColumn); + } + + sheet.autoSizeColumn(currentColumn); + } + } + +}