/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 ro.nextreports.engine.exporter.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* http://www.coderanch.com/t/420958/open-source/Copying-sheet-excel-file-another
*/
public final class XlsUtil {
private XlsUtil() {
}
/**
* Copy a sheet to another sheet at a specific (row, column) position
*
* @param parentSheet the sheet to copy into
* @param parentSheetRow the row inside parentSheet where we start to copy
* @param parentSheetColumn the column inside parentSheet where we start to copy
* @param sheet the sheet that is copied
* @return column number
*/
public static int copyToSheet(HSSFSheet parentSheet, int parentSheetRow, int parentSheetColumn, HSSFSheet sheet) {
return copyToSheet(parentSheet, parentSheetRow, parentSheetColumn, sheet, true);
}
/**
* Copy a sheet to another sheet at a specific (row, column) position
*
* @param parentSheet the sheet to copy into
* @param parentSheetRow the row inside parentSheet where we start to copy
* @param parentSheetColumn the column inside parentSheet where we start to copy
* @param sheet the sheet that is copied
* @param copyStyle true to copy the style
* @return column number
*/
public static int copyToSheet(HSSFSheet parentSheet, int parentSheetRow, int parentSheetColumn, HSSFSheet sheet, boolean copyStyle) {
int maxColumnNum = 0;
Map<Integer, HSSFCellStyle> styleMap = (copyStyle) ? new HashMap<Integer, HSSFCellStyle>() : null;
for (int i = sheet.getFirstRowNum(); i <= sheet.getLastRowNum(); i++) {
HSSFRow srcRow = sheet.getRow(i);
HSSFRow destRow;
// subreport is not the first cell in a row
if ((parentSheetColumn > 0) && (i == sheet.getFirstRowNum())) {
destRow = parentSheet.getRow(parentSheetRow);
} else {
destRow = parentSheet.getRow(parentSheetRow+i);
if (destRow == null) {
destRow = parentSheet.createRow(parentSheetRow + i);
}
}
if (srcRow != null) {
XlsUtil.copyRow(sheet, parentSheet, parentSheetRow, parentSheetColumn, srcRow, destRow, styleMap);
if (srcRow.getLastCellNum() > maxColumnNum) {
maxColumnNum = srcRow.getLastCellNum();
}
}
}
for (int i = 0; i <= maxColumnNum; i++) {
parentSheet.setColumnWidth(i, sheet.getColumnWidth(i));
}
return maxColumnNum;
}
/**
* Copy a row from a sheet to another sheet
*
*
* @param srcSheet the sheet to copy
* @param destSheet the sheet to copy into
* @param parentSheetRow the row inside destSheet where we start to copy
* @param parentSheetColumn the column inside destSheet where we start to copy
* @param srcRow the row to copy
* @param destRow the row to create
* @param styleMap style map
*
*/
public static void copyRow(HSSFSheet srcSheet, HSSFSheet destSheet, int parentSheetRow, int parentSheetColumn, HSSFRow srcRow, HSSFRow destRow,
Map<Integer, HSSFCellStyle> styleMap) {
// manage a list of merged zone in order to not insert two times a
// merged zone
Set<CellRangeAddressWrapper> mergedRegions = new TreeSet<CellRangeAddressWrapper>();
destRow.setHeight(srcRow.getHeight());
// pour chaque row
for (int j = srcRow.getFirstCellNum(); j <= srcRow.getLastCellNum(); j++) {
HSSFCell oldCell = srcRow.getCell(j); // ancienne cell
if (oldCell != null) {
HSSFCell newCell = destRow.createCell(parentSheetColumn + j);
copyCell(oldCell, newCell, styleMap);
CellRangeAddress mergedRegion = getMergedRegion(srcSheet, srcRow.getRowNum(), (short) oldCell.getColumnIndex());
if (mergedRegion != null) {
CellRangeAddress newMergedRegion = new CellRangeAddress(parentSheetRow + mergedRegion.getFirstRow(),
parentSheetRow + mergedRegion.getLastRow(),
parentSheetColumn + mergedRegion.getFirstColumn(),
parentSheetColumn + mergedRegion.getLastColumn());
CellRangeAddressWrapper wrapper = new CellRangeAddressWrapper(newMergedRegion);
if (isNewMergedRegion(wrapper, mergedRegions)) {
mergedRegions.add(wrapper);
destSheet.addMergedRegion(wrapper.range);
}
}
}
}
}
/**
* Copy a cell to another cell
*
* @param oldCell cell to be copied
* @param newCell cell to be created
* @param styleMap style map
*/
public static void copyCell(HSSFCell oldCell, HSSFCell newCell, Map<Integer, HSSFCellStyle> styleMap) {
if (styleMap != null) {
if (oldCell.getSheet().getWorkbook() == newCell.getSheet().getWorkbook()) {
newCell.setCellStyle(oldCell.getCellStyle());
} else {
int stHashCode = oldCell.getCellStyle().hashCode();
HSSFCellStyle 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 HSSFCell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case HSSFCell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case HSSFCell.CELL_TYPE_BLANK:
newCell.setCellType(HSSFCell.CELL_TYPE_BLANK);
break;
case HSSFCell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case HSSFCell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case HSSFCell.CELL_TYPE_FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
default:
break;
}
}
public static CellRangeAddress getMergedRegion(HSSFSheet sheet, int rowNum, short cellNum) {
for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
CellRangeAddress merged = sheet.getMergedRegion(i);
if (merged.isInRange(rowNum, cellNum)) {
return merged;
}
}
return null;
}
/**
* Check that the merged region has been created in the destination sheet.
*
* @param newMergedRegion the merged region to copy or not in the destination sheet.
* @param mergedRegions the list containing all the merged region.
* @return true if the merged region is already in the list or not.
*/
private static boolean isNewMergedRegion(CellRangeAddressWrapper newMergedRegion, Set<CellRangeAddressWrapper> mergedRegions) {
return !mergedRegions.contains(newMergedRegion);
}
}