net.sf.jasperreports.engine.export.JRXlsExporter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
/*
* Contributors:
* Wolfgang - [email protected]
* Mario Daepp - [email protected]
*/
package net.sf.jasperreports.engine.export;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.TextAttribute;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HeaderFooter;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import net.sf.jasperreports.engine.DefaultJasperReportsContext;
import net.sf.jasperreports.engine.JRCommonGraphicElement;
import net.sf.jasperreports.engine.JRCommonText;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRFont;
import net.sf.jasperreports.engine.JRGenericElementType;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRLineBox;
import net.sf.jasperreports.engine.JRPen;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintFrame;
import net.sf.jasperreports.engine.JRPrintGraphicElement;
import net.sf.jasperreports.engine.JRPrintHyperlink;
import net.sf.jasperreports.engine.JRPrintImage;
import net.sf.jasperreports.engine.JRPrintLine;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.base.JRBaseFont;
import net.sf.jasperreports.engine.export.JRXlsAbstractExporter.SheetInfo.SheetPrintSettings;
import net.sf.jasperreports.engine.export.data.BooleanTextValue;
import net.sf.jasperreports.engine.export.data.DateTextValue;
import net.sf.jasperreports.engine.export.data.NumberTextValue;
import net.sf.jasperreports.engine.export.data.StringTextValue;
import net.sf.jasperreports.engine.export.data.TextValue;
import net.sf.jasperreports.engine.export.data.TextValueHandler;
import net.sf.jasperreports.engine.export.type.ImageAnchorTypeEnum;
import net.sf.jasperreports.engine.type.HorizontalImageAlignEnum;
import net.sf.jasperreports.engine.type.ImageTypeEnum;
import net.sf.jasperreports.engine.type.LineDirectionEnum;
import net.sf.jasperreports.engine.type.ModeEnum;
import net.sf.jasperreports.engine.type.OrientationEnum;
import net.sf.jasperreports.engine.type.RotationEnum;
import net.sf.jasperreports.engine.type.RunDirectionEnum;
import net.sf.jasperreports.engine.type.VerticalImageAlignEnum;
import net.sf.jasperreports.engine.util.DefaultFormatFactory;
import net.sf.jasperreports.engine.util.ExifOrientationEnum;
import net.sf.jasperreports.engine.util.ImageUtil;
import net.sf.jasperreports.engine.util.JRImageLoader;
import net.sf.jasperreports.engine.util.JRStyledText;
import net.sf.jasperreports.engine.util.JRStyledTextUtil;
import net.sf.jasperreports.export.XlsExporterConfiguration;
import net.sf.jasperreports.export.XlsReportConfiguration;
import net.sf.jasperreports.renderers.DataRenderable;
import net.sf.jasperreports.renderers.DimensionRenderable;
import net.sf.jasperreports.renderers.Graphics2DRenderable;
import net.sf.jasperreports.renderers.Renderable;
import net.sf.jasperreports.renderers.RenderersCache;
import net.sf.jasperreports.renderers.ResourceRenderer;
/**
* Exports a JasperReports document to XLS format. It has binary output type and exports the document to
* a grid-based layout.
*
* @see net.sf.jasperreports.engine.export.JRXlsAbstractExporter
* @see net.sf.jasperreports.export.XlsExporterConfiguration
* @see net.sf.jasperreports.export.XlsReportConfiguration
* @author Teodor Danciu ([email protected])
*/
public class JRXlsExporter extends JRXlsAbstractExporter
{
private static final Log log = LogFactory.getLog(JRXlsExporter.class);
/**
* The exporter key, as used in
* {@link GenericElementHandlerEnviroment#getElementHandler(JRGenericElementType, String)}.
*/
public static final String XLS_EXPORTER_KEY = JRPropertiesUtil.PROPERTY_PREFIX + "xls";
public static short MAX_COLOR_INDEX = 56;
public static short MIN_COLOR_INDEX = 10; /* Indexes from 0 to 9 are reserved */
private static short A2_PAPERSIZE = (short)66; /* A2_PAPERSIZE defined locally since it is not declared in HSSFPrintSetup */
private static Map hssfColorsRgbs;
static
{
Map hssfColors = HSSFColor.getTripletHash();
hssfColorsRgbs = new LinkedHashMap<>();
for (HSSFColor color : hssfColors.values())
{
hssfColorsRgbs.put(color, color.getTriplet());
}
}
protected Map loadedCellStyles = new HashMap<>();
protected Map> anchorLinks = new HashMap<>();
protected Map> pageLinks = new HashMap<>();
protected Map anchorNames = new HashMap<>();
protected Map> autofitColumns = new HashMap<>();
/**
*
*/
protected HSSFWorkbook workbook;
protected HSSFSheet sheet;
protected HSSFRow row;
protected HSSFCell cell;
protected HSSFCellStyle emptyCellStyle;
protected CreationHelper createHelper;
private HSSFPalette palette = null;
private Map hssfColorsCache = new HashMap<>();
/**
*
*/
protected short whiteIndex = HSSFColor.HSSFColorPredefined.WHITE.getIndex();
protected short blackIndex = HSSFColor.HSSFColorPredefined.BLACK.getIndex();
protected short customColorIndex = MIN_COLOR_INDEX;
protected FillPatternType backgroundMode = FillPatternType.SOLID_FOREGROUND;
protected HSSFDataFormat dataFormat;
protected HSSFPatriarch patriarch;
protected Map formulaCellsMap;
protected class ExporterContext extends BaseExporterContext implements JRXlsExporterContext
{
}
/**
* @see #JRXlsExporter(JasperReportsContext)
*/
public JRXlsExporter()
{
this(DefaultJasperReportsContext.getInstance());
}
/**
*
*/
public JRXlsExporter(JasperReportsContext jasperReportsContext)
{
super(jasperReportsContext);
exporterContext = new ExporterContext();
maxColumnIndex = 255;
}
@Override
protected Class getConfigurationInterface()
{
return XlsExporterConfiguration.class;
}
@Override
protected Class getItemConfigurationInterface()
{
return XlsReportConfiguration.class;
}
@Override
protected void initExport()
{
super.initExport();
sheet = null;
}
@Override
protected void initReport()
{
super.initReport();
XlsReportConfiguration configuration = getCurrentItemConfiguration();
if (!configuration.isWhitePageBackground())
{
backgroundMode = FillPatternType.NO_FILL;
}
nature =
new JRXlsExporterNature(
jasperReportsContext,
filter,
configuration.isIgnoreGraphics(),
configuration.isIgnorePageMargins()
);
}
@Override
protected void openWorkbook(OutputStream os)
{
XlsExporterConfiguration configuration = getCurrentConfiguration();
String lcWorkbookTemplate = workbookTemplate == null ? configuration.getWorkbookTemplate() : workbookTemplate;
if (lcWorkbookTemplate == null)
{
workbook = new HSSFWorkbook();
}
else
{
InputStream templateIs = null;
try
{
templateIs = getRepository().getInputStreamFromLocation(lcWorkbookTemplate);
if (templateIs == null)
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_TEMPLATE_NOT_FOUND,
new Object[]{lcWorkbookTemplate}
);
}
else
{
workbook = new HSSFWorkbook(new POIFSFileSystem(templateIs));
boolean keepSheets = keepTemplateSheets == null ? configuration.isKeepWorkbookTemplateSheets() : keepTemplateSheets;
if (keepSheets)
{
sheetIndex += workbook.getNumberOfSheets();
}
else
{
for(int i = 0; i < workbook.getNumberOfSheets(); i++)
{
workbook.removeSheetAt(i);
}
}
}
}
catch (JRException | IOException e)
{
throw new JRRuntimeException(e);
}
finally
{
if (templateIs != null)
{
try
{
templateIs.close();
}
catch (IOException e)
{
}
}
}
}
emptyCellStyle = workbook.createCellStyle();
emptyCellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.WHITE.getIndex());
emptyCellStyle.setFillPattern(backgroundMode);
dataFormat = workbook.createDataFormat();
createHelper = workbook.getCreationHelper();
firstPageNotSet = true;
palette = workbook.getCustomPalette();
customColorIndex = MIN_COLOR_INDEX;
autofitColumns = new HashMap<>();
formulaCellsMap = new HashMap<>();
SummaryInformation summaryInformation = workbook.getSummaryInformation();
if (summaryInformation == null)
{
workbook.createInformationProperties();
summaryInformation = workbook.getSummaryInformation();
}
String application = configuration.getMetadataApplication();
if( application == null )
{
application = "JasperReports Library version " + Package.getPackage("net.sf.jasperreports.engine").getImplementationVersion();
}
summaryInformation.setApplicationName(application);
String title = configuration.getMetadataTitle();
if (title != null)
{
summaryInformation.setTitle(title);
}
String subject = configuration.getMetadataSubject();
if (subject != null)
{
summaryInformation.setSubject(subject);
}
String author = configuration.getMetadataAuthor();
if (author != null)
{
summaryInformation.setAuthor(author);
}
String keywords = configuration.getMetadataKeywords();
if (keywords != null)
{
summaryInformation.setKeywords(keywords);
}
}
@Override
protected void createSheet(CutsInfo xCuts, SheetInfo sheetInfo)
{
sheet = workbook.createSheet(sheetInfo.sheetName);
patriarch = sheet.createDrawingPatriarch();
HSSFPrintSetup printSetup = sheet.getPrintSetup();
printSetup.setLandscape(pageFormat.getOrientation() == OrientationEnum.LANDSCAPE);
short paperSize = getSuitablePaperSize(sheetInfo.printSettings);
if(paperSize != -1)
{
printSetup.setPaperSize(paperSize);
}
XlsReportConfiguration configuration = getCurrentItemConfiguration();
String password = configuration.getPassword();
if(password != null)
{
sheet.protectSheet(password);
}
JRXlsAbstractExporter.SheetInfo.SheetPrintSettings printSettings = sheetInfo.printSettings;
sheet.setMargin(Sheet.LeftMargin, LengthUtil.inch(printSettings.getLeftMargin()));
sheet.setMargin(Sheet.RightMargin, LengthUtil.inch(printSettings.getRightMargin()));
sheet.setMargin(Sheet.TopMargin, LengthUtil.inch(printSettings.getTopMargin()));
sheet.setMargin(Sheet.BottomMargin, LengthUtil.inch(printSettings.getBottomMargin()));
String sheetHeaderLeft = printSettings.getHeaderLeft();
if(sheetHeaderLeft != null)
{
sheet.getHeader().setLeft(sheetHeaderLeft);
}
String sheetHeaderCenter = printSettings.getHeaderCenter();
if(sheetHeaderCenter != null)
{
sheet.getHeader().setCenter(sheetHeaderCenter);
}
String sheetHeaderRight = printSettings.getHeaderRight();
if(sheetHeaderRight != null)
{
sheet.getHeader().setRight(sheetHeaderRight);
}
String sheetFooterLeft = printSettings.getFooterLeft();
if(sheetFooterLeft != null)
{
sheet.getFooter().setLeft(sheetFooterLeft);
}
String sheetFooterCenter = printSettings.getFooterCenter();
if(sheetFooterCenter != null)
{
sheet.getFooter().setCenter(sheetFooterCenter);
}
String sheetFooterRight = printSettings.getFooterRight();
if(sheetFooterRight != null)
{
sheet.getFooter().setRight(sheetFooterRight);
}
printSetup.setHeaderMargin(LengthUtil.inch(printSettings.getHeaderMargin()));
printSetup.setFooterMargin(LengthUtil.inch(printSettings.getFooterMargin()));
RunDirectionEnum sheetDirection = configuration.getSheetDirection();
if(sheetDirection != null)
{
printSetup.setLeftToRight(sheetDirection == RunDirectionEnum.LTR);
sheet.setRightToLeft(sheetDirection == RunDirectionEnum.RTL);
}
if(sheetInfo.sheetFirstPageNumber != null && sheetInfo.sheetFirstPageNumber > 0)
{
printSetup.setPageStart((short)sheetInfo.sheetFirstPageNumber.intValue());
printSetup.setUsePage(true);
firstPageNotSet = false;
}
else
{
Integer documentFirstPageNumber = configuration.getFirstPageNumber();
if(documentFirstPageNumber != null && documentFirstPageNumber > 0 && firstPageNotSet)
{
printSetup.setPageStart((short)documentFirstPageNumber.intValue());
printSetup.setUsePage(true);
firstPageNotSet = false;
}
}
if(!firstPageNotSet && (sheet.getFooter().getCenter() == null || sheet.getFooter().getCenter().length() == 0))
{
sheet.getFooter().setCenter("Page " + HeaderFooter.page());
}
boolean showGridlines = true;
if (sheetInfo.sheetShowGridlines == null)
{
Boolean documentShowGridlines = configuration.isShowGridLines();
if (documentShowGridlines != null)
{
showGridlines = documentShowGridlines;
}
}
else
{
showGridlines = sheetInfo.sheetShowGridlines;
}
sheet.setDisplayGridlines(showGridlines);
backgroundMode = Boolean.TRUE.equals(sheetInfo.whitePageBackground)
? FillPatternType.SOLID_FOREGROUND
: FillPatternType.NO_FILL;
// maxRowFreezeIndex = 0;
// maxColumnFreezeIndex = 0;
//
onePagePerSheetMap.put(sheetIndex, onePagePerSheet);
sheetsBeforeCurrentReportMap.put(sheetIndex, sheetsBeforeCurrentReport);
}
@Override
protected void closeSheet()
{
if (sheet == null)
{
return;
}
HSSFPrintSetup printSetup = sheet.getPrintSetup();
if (isValidScale(sheetInfo.sheetPageScale))
{
printSetup.setScale((short)sheetInfo.sheetPageScale.intValue());
}
else
{
XlsReportConfiguration configuration = getCurrentItemConfiguration();
Integer fitWidth = configuration.getFitWidth();
if (fitWidth != null)
{
printSetup.setFitWidth(fitWidth.shortValue());
sheet.setAutobreaks(true);
}
Integer fitHeight = configuration.getFitHeight();
fitHeight =
fitHeight == null
? (Boolean.TRUE == configuration.isAutoFitPageHeight()
? (pageIndex - sheetInfo.sheetFirstPageIndex)
: null)
: fitHeight;
if (fitHeight != null)
{
printSetup.setFitHeight(fitHeight.shortValue());
sheet.setAutobreaks(true);
}
}
}
@Override
protected void closeWorkbook(OutputStream os) throws JRException
{
try
{
for (Entry entry : anchorNames.entrySet()) // the anchorNames map contains no entries for reports with ignore anchors == true;
{
String anchorName = entry.getKey();
HSSFName anchor = entry.getValue();
List linkList = anchorLinks.get(anchorName);
anchor.setRefersToFormula("'" + workbook.getSheetName(anchor.getSheetIndex()) + "'!"+ anchor.getRefersToFormula());
if(linkList != null && !linkList.isEmpty())
{
for(Hyperlink link : linkList)
{
link.setAddress(anchor.getRefersToFormula());
}
}
}
if(!definedNamesMap.isEmpty())
{
for(Map.Entry entry : definedNamesMap.entrySet())
{
HSSFName name = workbook.createName();
NameScope nameScope = entry.getKey();
name.setNameName(nameScope.getName());
name.setRefersToFormula(entry.getValue());
int scopeIndex = workbook.getSheetIndex(nameScope.getScope());
// name and name scope are ignoring case in Excel
if(nameScope.getScope() != null
&& !DEFAULT_DEFINED_NAME_SCOPE.equalsIgnoreCase(nameScope.getScope())
&& scopeIndex >= 0)
{
name.setSheetIndex(scopeIndex);
}
}
}
// applying formulas
if(formulaCellsMap != null && !formulaCellsMap.isEmpty())
{
for(Map.Entry formulaCell: formulaCellsMap.entrySet())
{
try
{
formulaCell.getKey().setCellFormula(formulaCell.getValue());
}
catch(Exception e)
{
// usually an org.apache.poi.ss.formula.FormulaParseException
// or a java.lang.IllegalArgumentException
// or a java.lang.IllegalStateException
if(log.isWarnEnabled())
{
log.warn(e.getMessage());
}
throw new JRException(e);
}
}
}
int index = 0;
for (Entry> entry : pageLinks.entrySet()) { // the pageLinks map contains no entries for reports with ignore hyperlinks == true
Integer linkPage = entry.getKey();
List linkList = entry.getValue();
if(linkList != null && !linkList.isEmpty()) {
for(Hyperlink link : linkList) {
index = onePagePerSheetMap.get(linkPage-1)!= null
? (onePagePerSheetMap.get(linkPage-1)
? Math.max(0, linkPage - 1)
: Math.max(0, sheetsBeforeCurrentReportMap.get(linkPage)))
: 0;
link.setAddress("'" + workbook.getSheetName(index)+ "'!$A$1");
}
}
}
for(int i=0; i < workbook.getNumberOfSheets(); i++)
{
HSSFSheet currentSheet = workbook.getSheetAt(i);
currentSheet.setForceFormulaRecalculation(true);
List autofitList= autofitColumns.get(currentSheet);
if(autofitList != null)
{
for(Integer j : autofitList)
{
currentSheet.autoSizeColumn(j, false);
}
}
}
String encryptionPassword = getCurrentConfiguration().getEncryptionPassword();
if (encryptionPassword == null || encryptionPassword.trim().length() == 0)
{
Biff8EncryptionKey.setCurrentUserPassword(null);
}
else
{
Biff8EncryptionKey.setCurrentUserPassword(encryptionPassword);
}
workbook.write(os);
Biff8EncryptionKey.setCurrentUserPassword(null);
}
catch (IOException e)
{
throw
new JRException(
EXCEPTION_MESSAGE_KEY_REPORT_GENERATION_ERROR,
new Object[]{jasperPrint.getName()},
e);
}
}
@Override
protected void setColumnWidth(int col, int width, boolean autoFit)
{
if (autoFit)
{
//the autofit will be applied before closing workbook, after the sheet completion
List autofitList= autofitColumns.get(sheet) != null ? autofitColumns.get(sheet) : new ArrayList<>();
autofitList.add(col);
autofitColumns.put(sheet, autofitList);
}
else
{
sheet.setColumnWidth(col, Math.min(43 * width, 256*255));
}
}
@Override
protected void setRowHeight(int rowIndex, int lastRowHeight, Cut yCut, XlsRowLevelInfo levelInfo)
{
row = sheet.getRow(rowIndex);
if (row == null)
{
row = sheet.createRow(rowIndex);
}
boolean isAutoFit = yCut.hasProperty(PROPERTY_AUTO_FIT_ROW)
&& (Boolean)yCut.getProperty(PROPERTY_AUTO_FIT_ROW);
if (!isAutoFit)
{
row.setHeightInPoints(lastRowHeight);
}
}
@Override
protected void addRowBreak(int rowIndex)
{
if(rowIndex >= 0 && rowIndex <= SpreadsheetVersion.EXCEL97.getLastRowIndex())
{
sheet.setRowBreak(rowIndex);
}
}
// protected void setCell(JRExporterGridCell gridCell, int colIndex, int rowIndex)
// {
// HSSFCell emptyCell = row.getCell(colIndex);
// if (emptyCell == null)
// {
// emptyCell = row.createCell(colIndex);
// emptyCell.setCellStyle(emptyCellStyle);
// }
// }
@Override
protected void addBlankCell(JRExporterGridCell gridCell, int colIndex, int rowIndex)
{
cell = row.createCell(colIndex);
FillPatternType mode = backgroundMode;
short backcolor = whiteIndex;
if (!Boolean.TRUE.equals(sheetInfo.ignoreCellBackground) && gridCell.getCellBackcolor() != null)
{
mode = FillPatternType.SOLID_FOREGROUND;
backcolor = getWorkbookColor(gridCell.getCellBackcolor()).getIndex();
}
short forecolor = blackIndex;
if (gridCell.getForecolor() != null)
{
forecolor = getWorkbookColor(gridCell.getForecolor()).getIndex();
}
HSSFCellStyle cellStyle =
getLoadedCellStyle(
mode,
backcolor,
HorizontalAlignment.LEFT,
VerticalAlignment.TOP,
(short)0,
getLoadedFont(getDefaultFont(), forecolor, null, getLocale()),
gridCell,
true,
true,
false,
false
);
cell.setCellStyle(cellStyle);
}
@Override
protected void addOccupiedCell(OccupiedGridCell occupiedGridCell, int colIndex, int rowIndex)
{
}
@Override
protected void exportLine(JRPrintLine line, JRExporterGridCell gridCell, int colIndex, int rowIndex)
{
short forecolor = getWorkbookColor(line.getLinePen().getLineColor()).getIndex();
int side = BoxStyle.TOP;
float ratio = line.getWidth() / line.getHeight();
if (ratio > 1)
{
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN)
{
side = BoxStyle.TOP;
}
else
{
side = BoxStyle.BOTTOM;
}
}
else
{
if (line.getDirectionValue() == LineDirectionEnum.TOP_DOWN)
{
side = BoxStyle.LEFT;
}
else
{
side = BoxStyle.RIGHT;
}
}
BoxStyle boxStyle = new BoxStyle(side, line.getLinePen());
FillPatternType mode = backgroundMode;
short backcolor = whiteIndex;
if (!Boolean.TRUE.equals(sheetInfo.ignoreCellBackground) && gridCell.getCellBackcolor() != null)
{
mode = FillPatternType.SOLID_FOREGROUND;
backcolor = getWorkbookColor(gridCell.getCellBackcolor()).getIndex();
}
HSSFCellStyle cellStyle =
getLoadedCellStyle(
mode,
backcolor,
HorizontalAlignment.LEFT,
VerticalAlignment.TOP,
(short)0,
getLoadedFont(getDefaultFont(), forecolor, null, getLocale()),
boxStyle,
false,
isCellLocked(line),
isCellHidden(line),
isShrinkToFit(line)
);
createMergeRegion(gridCell, colIndex, rowIndex, cellStyle);
cell = row.createCell(colIndex);
cell.setCellStyle(cellStyle);
}
@Override
protected void exportRectangle(JRPrintGraphicElement element, JRExporterGridCell gridCell, int colIndex, int rowIndex)
{
short forecolor = getWorkbookColor(element.getLinePen().getLineColor()).getIndex();
FillPatternType mode = backgroundMode;
short backcolor = whiteIndex;
if (!Boolean.TRUE.equals(sheetInfo.ignoreCellBackground) && gridCell.getCellBackcolor() != null)
{
mode = FillPatternType.SOLID_FOREGROUND;
backcolor = getWorkbookColor(gridCell.getCellBackcolor()).getIndex();
}
HSSFCellStyle cellStyle =
getLoadedCellStyle(
mode,
backcolor,
HorizontalAlignment.LEFT,
VerticalAlignment.TOP,
(short)0,
getLoadedFont(getDefaultFont(), forecolor, null, getLocale()),
gridCell,
isWrapText(element),
isCellLocked(element),
isCellHidden(element),
isShrinkToFit(element)
);
createMergeRegion(gridCell, colIndex, rowIndex, cellStyle);
cell = row.createCell(colIndex);
cell.setCellStyle(cellStyle);
}
@Override
public void exportText(JRPrintText textElement, JRExporterGridCell gridCell, int colIndex, int rowIndex) throws JRException
{
JRStyledText styledText = getStyledText(textElement);
if (styledText == null)
{
return;
}
short forecolor = getWorkbookColor(textElement.getForecolor()).getIndex();
TextAlignHolder textAlignHolder = getTextAlignHolder(textElement);
HorizontalAlignment horizontalAlignment = getHorizontalAlignment(textAlignHolder);
VerticalAlignment verticalAlignment = getVerticalAlignment(textAlignHolder);
short rotation = getRotation(textAlignHolder);
FillPatternType mode = backgroundMode;
short backcolor = whiteIndex;
if (!Boolean.TRUE.equals(sheetInfo.ignoreCellBackground) && gridCell.getCellBackcolor() != null)
{
mode = FillPatternType.SOLID_FOREGROUND;
backcolor = getWorkbookColor(gridCell.getCellBackcolor()).getIndex();
}
StyleInfo baseStyle =
isIgnoreTextFormatting(textElement)
? new StyleInfo(
mode,
whiteIndex,
horizontalAlignment,
verticalAlignment,
(short)0,
null,
(JRExporterGridCell)null,
isWrapText(textElement) || Boolean.TRUE.equals(((JRXlsExporterNature)nature).getColumnAutoFit(textElement)),
isCellLocked(textElement),
isCellHidden(textElement),
isShrinkToFit(textElement)
)
: new StyleInfo(
mode,
backcolor,
horizontalAlignment,
verticalAlignment,
rotation,
getLoadedFont(textElement, forecolor, null, getTextLocale(textElement)),
gridCell,
isWrapText(textElement) || Boolean.TRUE.equals(((JRXlsExporterNature)nature).getColumnAutoFit(textElement)),
isCellLocked(textElement),
isCellHidden(textElement),
isShrinkToFit(textElement)
);
createTextCell(textElement, gridCell, colIndex, rowIndex, styledText, baseStyle, forecolor);
}
protected void createTextCell(final JRPrintText textElement, final JRExporterGridCell gridCell, final int colIndex, final int rowIndex, final JRStyledText styledText, final StyleInfo baseStyle, final short forecolor) throws JRException
{
String formula = getFormula(textElement);
String textStr = styledText.getText();
TextValue value = null;
String pattern = null;
if (
formula != null
|| detectCellType
)
{
value = getTextValue(textElement, textStr);
if (value instanceof NumberTextValue)
{
pattern = ((NumberTextValue)value).getPattern();
}
else if (value instanceof DateTextValue)
{
pattern = ((DateTextValue)value).getPattern();
}
}
String convertedPattern = getConvertedPattern(textElement, pattern);
if (convertedPattern != null)
{
//FIXME: use localized Excel pattern
baseStyle.setDataFormat(
dataFormat.getFormat(convertedPattern)
);
}
if (formula != null)
{
try
{
HSSFCellStyle cellStyle = initCreateCell(gridCell, colIndex, rowIndex, baseStyle);
// the formula text will be stored in formulaCellsMap in order to be applied only after
// all defined names are created and available in the workbook (see #closeWorkbook())
formulaCellsMap.put(cell, formula);
endCreateCell(cellStyle);
return;
}
catch(Exception e)//FIXMENOW what exceptions could we get here?
{
if(log.isWarnEnabled())
{
log.warn(e.getMessage());
}
}
}
if (detectCellType)
{
value.handle(new TextValueHandler()
{
@Override
public void handle(StringTextValue textValue)
{
HSSFCellStyle cellStyle = initCreateCell(gridCell, colIndex, rowIndex, baseStyle);
if (textValue.getText() == null || textValue.getText().length() == 0)
{
cell.setCellType(CellType.BLANK);
}
else
{
if (JRCommonText.MARKUP_NONE.equals(textElement.getMarkup()) || isIgnoreTextFormatting(textElement))
{
setStringCellValue(textValue.getText());
}
else
{
setRichTextStringCellValue(styledText, forecolor, textElement, getTextLocale(textElement));
}
}
endCreateCell(cellStyle);
}
@Override
public void handle(NumberTextValue textValue)
{
HSSFCellStyle cellStyle = initCreateCell(gridCell, colIndex, rowIndex, baseStyle);
if (textValue.getValue() == null)
{
cell.setCellType(CellType.BLANK);
}
else
{
double doubleValue = textValue.getValue().doubleValue();
if (DefaultFormatFactory.STANDARD_NUMBER_FORMAT_DURATION.equals(convertedPattern))
{
doubleValue = doubleValue / 86400;
}
cell.setCellValue(doubleValue);
}
endCreateCell(cellStyle);
}
@Override
public void handle(DateTextValue textValue)
{
HSSFCellStyle cellStyle = initCreateCell(gridCell, colIndex, rowIndex, baseStyle);
Date date = textValue.getValue();
if (date == null)
{
cell.setCellType(CellType.BLANK);
}
else
{
date = translateDateValue(textElement, date);
cell.setCellValue(date);
}
endCreateCell(cellStyle);
}
@Override
public void handle(BooleanTextValue textValue)
{
HSSFCellStyle cellStyle = initCreateCell(gridCell, colIndex, rowIndex, baseStyle);
if (textValue.getValue() == null)
{
cell.setCellType(CellType.BLANK);
}
else
{
cell.setCellValue(textValue.getValue());
}
endCreateCell(cellStyle);
}
});
}
else
{
HSSFCellStyle cellStyle = initCreateCell(gridCell, colIndex, rowIndex, baseStyle);
if (JRCommonText.MARKUP_NONE.equals(textElement.getMarkup()) || isIgnoreTextFormatting(textElement))
{
setStringCellValue(textStr);
}
else
{
setRichTextStringCellValue(styledText, forecolor, textElement, getTextLocale(textElement));
}
endCreateCell(cellStyle);
}
if(!ignoreAnchors)
{
String anchorName = textElement.getAnchorName();
if(anchorName != null)
{
HSSFName aName = workbook.createName();
aName.setNameName(toExcelName(anchorName));
aName.setSheetIndex(workbook.getSheetIndex(sheet));
CellReference cRef = new CellReference(rowIndex, colIndex, true, true);
aName.setRefersToFormula(cRef.formatAsString());
anchorNames.put(anchorName, aName);
}
}
setHyperlinkCell(textElement);
}
protected HSSFCellStyle initCreateCell(JRExporterGridCell gridCell, int colIndex, int rowIndex, StyleInfo baseStyle)
{
HSSFCellStyle cellStyle = getLoadedCellStyle(baseStyle);
createMergeRegion(gridCell, colIndex, rowIndex, cellStyle);
cell = row.createCell(colIndex);
return cellStyle;
}
protected void endCreateCell(HSSFCellStyle cellStyle)
{
cell.setCellStyle(cellStyle);
}
protected final void setStringCellValue(String textStr)
{
//cell.setCellValue(JRStringUtil.replaceDosEOL(textStr));
//cell.setCellValue(textStr);
cell.setCellValue(new HSSFRichTextString(textStr));
}
protected final void setRichTextStringCellValue(JRStyledText styledText, short forecolor, JRFont defaultFont, Locale locale)
{
if(styledText != null)
{
cell.setCellValue(getRichTextString(styledText, forecolor, defaultFont, locale));
}
}
protected HSSFRichTextString getRichTextString(JRStyledText styledText, short forecolor, JRFont defaultFont, Locale locale)
{
styledText = JRStyledTextUtil.getBulletedStyledText(styledText);
String text = styledText.getText();
HSSFRichTextString richTextStr = new HSSFRichTextString(text);
int runLimit = 0;
AttributedCharacterIterator iterator = styledText.getAttributedString().getIterator();
while (runLimit < styledText.length() && (runLimit = iterator.getRunLimit()) <= styledText.length())
{
Map attributes = iterator.getAttributes();
JRFont runFont = attributes.isEmpty()? defaultFont : new JRBaseFont(attributes);
short runForecolor =
attributes.get(TextAttribute.FOREGROUND) != null
? getWorkbookColor((Color)attributes.get(TextAttribute.FOREGROUND)).getIndex()
: forecolor;
HSSFFont font = getLoadedFont(runFont, runForecolor, attributes, locale);
richTextStr.applyFont(iterator.getIndex(), runLimit, font);
iterator.setIndex(runLimit);
}
return richTextStr;
}
protected void createMergeRegion(JRExporterGridCell gridCell, int colIndex, int rowIndex, HSSFCellStyle cellStyle)
{
int rowSpan = collapseRowSpan ? 1 : gridCell.getRowSpan();
if (gridCell.getColSpan() > 1 || rowSpan > 1)
{
sheet.addMergedRegion(new CellRangeAddress(rowIndex, (rowIndex + rowSpan - 1),
colIndex, (colIndex + gridCell.getColSpan() - 1)));
for(int i = 0; i < rowSpan; i++)
{
HSSFRow spanRow = sheet.getRow(rowIndex + i);
if (spanRow == null)
{
spanRow = sheet.createRow(rowIndex + i);
}
for(int j = 0; j < gridCell.getColSpan(); j++)
{
HSSFCell spanCell = spanRow.getCell((colIndex + j));
if (spanCell == null)
{
spanCell = spanRow.createCell((colIndex + j));
}
spanCell.setCellStyle(cellStyle);
}
}
}
}
private HorizontalAlignment getHorizontalAlignment(TextAlignHolder alignment)
{
switch (alignment.horizontalAlignment)
{
case RIGHT:
return HorizontalAlignment.RIGHT;
case CENTER:
return HorizontalAlignment.CENTER;
case JUSTIFIED:
return HorizontalAlignment.JUSTIFY;
case LEFT:
default:
return HorizontalAlignment.LEFT;
}
}
private VerticalAlignment getVerticalAlignment(TextAlignHolder alignment)
{
switch (alignment.verticalAlignment)
{
case BOTTOM:
return VerticalAlignment.BOTTOM;
case MIDDLE:
return VerticalAlignment.CENTER;
case JUSTIFIED:
return VerticalAlignment.JUSTIFY;
case TOP:
default:
return VerticalAlignment.TOP;
}
}
private short getRotation(TextAlignHolder alignment)
{
switch (alignment.rotation)
{
case LEFT:
return 90;
case RIGHT:
return -90;
case UPSIDE_DOWN:
case NONE:
default:
return 0;
}
}
/**
*
*/
protected HSSFColor getWorkbookColor(Color awtColor)
{
byte red = (byte)awtColor.getRed();
byte green = (byte)awtColor.getGreen();
byte blue = (byte)awtColor.getBlue();
HSSFColor color = null;
if (getCurrentConfiguration().isCreateCustomPalette())
{
try
{
color = palette.findColor(red,green, blue) != null
? palette.findColor(red,green, blue)
: palette.addColor(red,green, blue);
}
catch(Exception e)
{
if(customColorIndex < MAX_COLOR_INDEX)
{
palette.setColorAtIndex(customColorIndex, red, green, blue);
color = palette.getColor(customColorIndex++);
}
else
{
color = palette.findSimilarColor(red, green, blue);
}
}
}
return color == null ? getNearestColor(awtColor) : color;
}
/**
*
*/
protected HSSFColor getNearestColor(Color awtColor)
{
HSSFColor color = hssfColorsCache.get(awtColor);
if (color == null)
{
int minDiff = Integer.MAX_VALUE;
for (Map.Entry hssfColorEntry : hssfColorsRgbs.entrySet())
{
HSSFColor crtColor = hssfColorEntry.getKey();
short[] rgb = hssfColorEntry.getValue();
int diff = Math.abs(rgb[0] - awtColor.getRed()) + Math.abs(rgb[1] - awtColor.getGreen()) + Math.abs(rgb[2] - awtColor.getBlue());
if (diff < minDiff)
{
minDiff = diff;
color = crtColor;
}
}
hssfColorsCache.put(awtColor, color);
}
return color;
}
/**
*
*/
protected HSSFFont getLoadedFont(JRFont font, short forecolor, Map attributes, Locale locale)
{
HSSFFont cellFont = null;
String fontName = fontUtil.getExportFontFamily(font.getFontName(), locale, getExporterKey());
short superscriptType = HSSFFont.SS_NONE;
if( attributes != null && attributes.get(TextAttribute.SUPERSCRIPT) != null)
{
Object value = attributes.get(TextAttribute.SUPERSCRIPT);
if(TextAttribute.SUPERSCRIPT_SUPER.equals(value))
{
superscriptType = HSSFFont.SS_SUPER;
}
else if(TextAttribute.SUPERSCRIPT_SUB.equals(value))
{
superscriptType = HSSFFont.SS_SUB;
}
}
boolean isFontSizeFixEnabled = getCurrentItemConfiguration().isFontSizeFixEnabled();
for (int i = 0; i < loadedFonts.size(); i++)
{
HSSFFont cf = (HSSFFont)loadedFonts.get(i);
short fontSize = (short)font.getFontsize();
if (isFontSizeFixEnabled)
{
fontSize -= 1;
}
if (
cf.getFontName().equals(fontName) &&
(cf.getColor() == forecolor) &&
(cf.getFontHeightInPoints() == fontSize) &&
((cf.getUnderline() == HSSFFont.U_SINGLE)?(font.isUnderline()):(!font.isUnderline())) &&
(cf.getStrikeout() == font.isStrikeThrough()) &&
(cf.getBold() == font.isBold()) &&
(cf.getItalic() == font.isItalic()) &&
(cf.getTypeOffset() == superscriptType)
)
{
cellFont = cf;
break;
}
}
if (cellFont == null)
{
cellFont = workbook.createFont();
cellFont.setFontName(fontName);
cellFont.setColor(forecolor);
short fontSize = (short)font.getFontsize();
if (isFontSizeFixEnabled)
{
fontSize -= 1;
}
cellFont.setFontHeightInPoints(fontSize);
if (font.isUnderline())
{
cellFont.setUnderline(HSSFFont.U_SINGLE);
}
if (font.isStrikeThrough())
{
cellFont.setStrikeout(true);
}
if (font.isBold())
{
cellFont.setBold(true);
}
if (font.isItalic())
{
cellFont.setItalic(true);
}
cellFont.setTypeOffset(superscriptType);
loadedFonts.add(cellFont);
}
return cellFont;
}
protected HSSFCellStyle getLoadedCellStyle(StyleInfo style)
{
HSSFCellStyle cellStyle = loadedCellStyles.get(style);
if (cellStyle == null)
{
cellStyle = workbook.createCellStyle();
cellStyle.setFillForegroundColor(style.backcolor);
cellStyle.setFillPattern(style.mode);
cellStyle.setAlignment(style.horizontalAlignment);
cellStyle.setVerticalAlignment(style.verticalAlignment);
cellStyle.setRotation(style.rotation);
if(style.font != null)
{
cellStyle.setFont(style.font);
}
cellStyle.setWrapText(style.lcWrapText);
cellStyle.setLocked(style.lcCellLocked);
cellStyle.setHidden(style.lcCellHidden);
cellStyle.setShrinkToFit(style.lcShrinkToFit);
if (style.hasDataFormat())
{
cellStyle.setDataFormat(style.getDataFormat());
}
boolean isIgnoreCellBorder = Boolean.TRUE.equals(sheetInfo.ignoreCellBorder) || style.box ==null;
if (!isIgnoreCellBorder)
{
BoxStyle box = style.box;
if (box.borderStyle[BoxStyle.TOP] != null)
cellStyle.setBorderTop(box.borderStyle[BoxStyle.TOP]);
cellStyle.setTopBorderColor(box.borderColour[BoxStyle.TOP]);
if (box.borderStyle[BoxStyle.LEFT] != null)
cellStyle.setBorderLeft(box.borderStyle[BoxStyle.LEFT]);
cellStyle.setLeftBorderColor(box.borderColour[BoxStyle.LEFT]);
if (box.borderStyle[BoxStyle.BOTTOM] != null)
cellStyle.setBorderBottom(box.borderStyle[BoxStyle.BOTTOM]);
cellStyle.setBottomBorderColor(box.borderColour[BoxStyle.BOTTOM]);
if (box.borderStyle[BoxStyle.RIGHT] != null)
cellStyle.setBorderRight(box.borderStyle[BoxStyle.RIGHT]);
cellStyle.setRightBorderColor(box.borderColour[BoxStyle.RIGHT]);
}
loadedCellStyles.put(style, cellStyle);
}
return cellStyle;
}
protected HSSFCellStyle getLoadedCellStyle(
FillPatternType mode,
short backcolor,
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment,
short rotation,
HSSFFont font,
JRExporterGridCell gridCell,
boolean isWrapText,
boolean isCellLocked,
boolean isCellHidden,
boolean isShrinkToFit
)
{
return getLoadedCellStyle(
new StyleInfo(
mode,
backcolor,
horizontalAlignment,
verticalAlignment,
rotation,
font,
gridCell,
isWrapText,
isCellLocked,
isCellHidden,
isShrinkToFit));
}
protected HSSFCellStyle getLoadedCellStyle(
FillPatternType mode,
short backcolor,
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment,
short rotation,
HSSFFont font,
BoxStyle box,
boolean isWrapText,
boolean isCellLocked,
boolean isCellHidden,
boolean isShrinkToFit
)
{
StyleInfo style = new StyleInfo(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, font, box, isWrapText, isCellLocked, isCellHidden, isShrinkToFit);
return getLoadedCellStyle(style);
}
/**
*
*/
protected static BorderStyle getBorderStyle(JRPen pen)
{
float lineWidth = pen.getLineWidth();
if (lineWidth > 0f)
{
switch (pen.getLineStyleValue())
{
case DOUBLE :
{
return BorderStyle.DOUBLE;
}
case DOTTED :
{
return BorderStyle.DOTTED;
}
case DASHED :
{
if (lineWidth >= 1f)
{
return BorderStyle.MEDIUM_DASHED;
}
return BorderStyle.DASHED;
}
case SOLID :
default :
{
if (lineWidth >= 2f)
{
return BorderStyle.THICK;
}
else if (lineWidth >= 1f)
{
return BorderStyle.MEDIUM;
}
else if (lineWidth >= 0.5f)
{
return BorderStyle.THIN;
}
return BorderStyle.HAIR;
}
}
}
return BorderStyle.NONE;
}
@Override
public void exportImage(
JRPrintImage element,
JRExporterGridCell gridCell,
int colIndex,
int rowIndex,
int emptyCols,
int yCutsRow,
JRGridLayout layout
) throws JRException
{
int topPadding =
Math.max(element.getLineBox().getTopPadding(), getImageBorderCorrection(element.getLineBox().getTopPen()));
int leftPadding =
Math.max(element.getLineBox().getLeftPadding(), getImageBorderCorrection(element.getLineBox().getLeftPen()));
int bottomPadding =
Math.max(element.getLineBox().getBottomPadding(), getImageBorderCorrection(element.getLineBox().getBottomPen()));
int rightPadding =
Math.max(element.getLineBox().getRightPadding(), getImageBorderCorrection(element.getLineBox().getRightPen()));
int tmpAvailableImageWidth = element.getWidth() - leftPadding - rightPadding;
int availableImageWidth = tmpAvailableImageWidth < 0 ? 0 : tmpAvailableImageWidth;
int tmpAvailableImageHeight = element.getHeight() - topPadding - bottomPadding;
int availableImageHeight = tmpAvailableImageHeight < 0 ? 0 : tmpAvailableImageHeight;
InternalImageProcessor imageProcessor =
new InternalImageProcessor(
element,
availableImageWidth,
availableImageHeight
);
try
{
Renderable renderer = element.getRenderer();
if (
renderer != null
&& availableImageWidth > 0
&& availableImageHeight > 0
)
{
InternalImageProcessorResult imageProcessorResult = null;
try
{
imageProcessorResult = imageProcessor.process(renderer);
}
catch (Exception e)
{
Renderable onErrorRenderer = getRendererUtil().handleImageError(e, element.getOnErrorTypeValue());
if (onErrorRenderer != null)
{
imageProcessorResult = imageProcessor.process(onErrorRenderer);
}
}
if (imageProcessorResult != null)//FIXMEXLS background for null images like the other exporters
{
FillPatternType mode = backgroundMode;
short backcolor = whiteIndex;
if (!Boolean.TRUE.equals(sheetInfo.ignoreCellBackground) && gridCell.getCellBackcolor() != null)
{
mode = FillPatternType.SOLID_FOREGROUND;
backcolor = getWorkbookColor(gridCell.getCellBackcolor()).getIndex();
}
short forecolor = getWorkbookColor(element.getLineBox().getPen().getLineColor()).getIndex();
if(element.getModeValue() == ModeEnum.OPAQUE )
{
backcolor = getWorkbookColor(element.getBackcolor()).getIndex();
}
HSSFCellStyle cellStyle =
getLoadedCellStyle(
mode,
backcolor,
HorizontalAlignment.LEFT,
VerticalAlignment.TOP,
(short)0,
getLoadedFont(getDefaultFont(), forecolor, null, getLocale()),
gridCell,
isWrapText(element),
isCellLocked(element),
isCellHidden(element),
isShrinkToFit(element)
);
createMergeRegion(gridCell, colIndex, rowIndex, cellStyle);
cell = row.createCell(colIndex);
cell.setCellStyle(cellStyle);
double topPos = getRowRelativePosition(layout, yCutsRow, topPadding + imageProcessorResult.topOffset);
double leftPos = getColumnRelativePosition(layout, colIndex, leftPadding + imageProcessorResult.leftOffset);
double bottomPos = getRowRelativePosition(layout, yCutsRow, element.getHeight() - bottomPadding - imageProcessorResult.bottomOffset);
double rightPos = getColumnRelativePosition(layout, colIndex, element.getWidth() - rightPadding - imageProcessorResult.rightOffset);
HSSFClientAnchor anchor =
new HSSFClientAnchor(
(int)((leftPos - (int)leftPos) * 1023), //numbers taken from POI source code
(int)((topPos - (int)topPos) * 255),
(int)((rightPos - (int)rightPos) * 1023),
(int)((bottomPos - (int)bottomPos) * 255),
(short)(colIndex + (int)leftPos),
(rowIndex + (int)topPos),
//(short) (colIndex + gridCell.getColSpan()),
(short)(colIndex + (int)rightPos),
//rowIndex + (isCollapseRowSpan ? 1 : gridCell.getRowSpan())
(rowIndex + (int)bottomPos)
);
ImageAnchorTypeEnum imageAnchorType =
ImageAnchorTypeEnum.getByName(
JRPropertiesUtil.getOwnProperty(element, XlsReportConfiguration.PROPERTY_IMAGE_ANCHOR_TYPE)
);
if (imageAnchorType == null)
{
imageAnchorType = defaultImageAnchorType;
if (imageAnchorType == null)
{
imageAnchorType = ImageAnchorTypeEnum.MOVE_NO_SIZE;
}
}
anchor.setAnchorType(getAnchorType(imageAnchorType));
//pngEncoder.setImage(bi);
//int imgIndex = workbook.addPicture(pngEncoder.pngEncode(), HSSFWorkbook.PICTURE_TYPE_PNG);
int imgIndex = workbook.addPicture(imageProcessorResult.imageData, HSSFWorkbook.PICTURE_TYPE_PNG);
patriarch.createPicture(anchor, imgIndex).setRotationDegree(imageProcessorResult.angle);
// setHyperlinkCell(element);
}
}
}
catch (Exception ex)
{
throw
new JRException(
EXCEPTION_MESSAGE_KEY_CANNOT_ADD_CELL,
null,
ex);
}
catch (Error err)
{
throw
new JRException(
EXCEPTION_MESSAGE_KEY_CANNOT_ADD_CELL,
null,
err);
}
}
private class InternalImageProcessor
{
private final JRPrintImage imageElement;
private final RenderersCache imageRenderersCache;
private final int availableImageWidth;
private final int availableImageHeight;
protected InternalImageProcessor(
JRPrintImage imageElement,
int availableImageWidth,
int availableImageHeight
)
{
this.imageElement = imageElement;
this.imageRenderersCache = imageElement.isUsingCache() ? renderersCache : new RenderersCache(getJasperReportsContext());
this.availableImageWidth = availableImageWidth;
this.availableImageHeight = availableImageHeight;
}
private InternalImageProcessorResult process(Renderable renderer) throws JRException
{
InternalImageProcessorResult imageProcessorResult = null;
if (renderer instanceof ResourceRenderer)
{
renderer = imageRenderersCache.getLoadedRenderer((ResourceRenderer)renderer);
}
switch (imageElement.getScaleImageValue())
{
case CLIP:
{
imageProcessorResult =
processImageClip(
imageRenderersCache.getGraphics2DRenderable(renderer)
);
break;
}
case FILL_FRAME:
{
Dimension dimension = null;
if (
imageElement.getRotation() == RotationEnum.LEFT
|| imageElement.getRotation() == RotationEnum.RIGHT
)
{
dimension = new Dimension(availableImageHeight, availableImageWidth);
}
else
{
dimension = new Dimension(availableImageWidth, availableImageHeight);
}
imageProcessorResult =
processImageFillFrame(
getRendererUtil().getImageDataRenderable(
imageRenderersCache,
renderer,
dimension,
ModeEnum.OPAQUE == imageElement.getModeValue() ? imageElement.getBackcolor() : null
)
);
break;
}
case RETAIN_SHAPE:
default:
{
Dimension dimension = null;
if (
imageElement.getRotation() == RotationEnum.LEFT
|| imageElement.getRotation() == RotationEnum.RIGHT
)
{
dimension = new Dimension(availableImageHeight, availableImageWidth);
}
else
{
dimension = new Dimension(availableImageWidth, availableImageHeight);
}
imageProcessorResult =
processImageRetainShape(
getRendererUtil().getImageDataRenderable(
imageRenderersCache,
renderer,
dimension,
ModeEnum.OPAQUE == imageElement.getModeValue() ? imageElement.getBackcolor() : null
)
);
break;
}
}
return imageProcessorResult;
}
private InternalImageProcessorResult processImageClip(Graphics2DRenderable renderer) throws JRException
{
int normalWidth = availableImageWidth;
int normalHeight = availableImageHeight;
DimensionRenderable dimensionRenderer = imageRenderersCache.getDimensionRenderable((Renderable)renderer);
Dimension2D dimension = dimensionRenderer == null ? null : dimensionRenderer.getDimension(jasperReportsContext);
if (dimension != null)
{
normalWidth = (int) dimension.getWidth();
normalHeight = (int) dimension.getHeight();
}
int minWidth = 0;
int minHeight = 0;
int topOffset = 0;
int leftOffset = 0;
int bottomOffset = 0;
int rightOffset = 0;
int translateX = 0;
int translateY = 0;
short angle = 0;
// exif orientation is taken care inside the wrapping renderer
switch (imageElement.getRotation())
{
case LEFT :
if (dimension == null)
{
normalWidth = availableImageHeight;
normalHeight = availableImageWidth;
}
minWidth = Math.min(normalWidth, availableImageHeight);
minHeight = Math.min(normalHeight, availableImageWidth);
topOffset = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageHeight - normalWidth));
leftOffset = (int)(ImageUtil.getYAlignFactor(imageElement) * (availableImageWidth - normalHeight));
bottomOffset = (int)(ImageUtil.getXAlignFactor(imageElement) * (availableImageHeight - normalWidth));
rightOffset = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageWidth - normalHeight));
translateX = bottomOffset;
translateY = leftOffset;
angle = -90;
break;
case RIGHT :
if (dimension == null)
{
normalWidth = availableImageHeight;
normalHeight = availableImageWidth;
}
minWidth = Math.min(normalWidth, availableImageHeight);
minHeight = Math.min(normalHeight, availableImageWidth);
topOffset = (int)(ImageUtil.getXAlignFactor(imageElement) * (availableImageHeight - normalWidth));
leftOffset = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageWidth - normalHeight));
bottomOffset = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageHeight - normalWidth));
rightOffset = (int)(ImageUtil.getYAlignFactor(imageElement) * (availableImageWidth - normalHeight));
translateX = topOffset;
translateY = rightOffset;
angle = 90;
break;
case UPSIDE_DOWN :
minWidth = Math.min(normalWidth, availableImageWidth);
minHeight = Math.min(normalHeight, availableImageHeight);
topOffset = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageHeight - normalHeight));
leftOffset = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageWidth - normalWidth));
bottomOffset = (int)(ImageUtil.getYAlignFactor(imageElement) * (availableImageHeight - normalHeight));
rightOffset = (int)(ImageUtil.getXAlignFactor(imageElement) * (availableImageWidth - normalWidth));
translateX = rightOffset;
translateY = bottomOffset;
angle = 180;
break;
case NONE :
default :
minWidth = Math.min(normalWidth, availableImageWidth);
minHeight = Math.min(normalHeight, availableImageHeight);
topOffset = (int)(ImageUtil.getYAlignFactor(imageElement) * (availableImageHeight - normalHeight));
leftOffset = (int)(ImageUtil.getXAlignFactor(imageElement) * (availableImageWidth - normalWidth));
bottomOffset = (int)((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageHeight - normalHeight));
rightOffset = (int)((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageWidth - normalWidth));
translateX = leftOffset;
translateY = topOffset;
angle = 0;
break;
}
int dpi = getPropertiesUtil().getIntegerProperty(Renderable.PROPERTY_IMAGE_DPI, 72);
double scale = dpi/72d;
BufferedImage bi =
new BufferedImage(
(int)(scale * minWidth),
(int)(scale * minHeight),
BufferedImage.TYPE_INT_ARGB
);
Graphics2D grx = bi.createGraphics();
try
{
grx.scale(scale, scale);
grx.clip(
new Rectangle(
0,
0,
minWidth,
minHeight
)
);
renderer.render(
jasperReportsContext,
grx,
new Rectangle(
translateX > 0 ? 0 : translateX,
translateY > 0 ? 0 : translateY,
normalWidth,
normalHeight
)
);
}
finally
{
grx.dispose();
}
return
new InternalImageProcessorResult(
JRImageLoader.getInstance(jasperReportsContext).loadBytesFromAwtImage(bi, ImageTypeEnum.PNG),
topOffset < 0 ? 0 : topOffset,
leftOffset < 0 ? 0 : leftOffset,
bottomOffset < 0 ? 0 : bottomOffset,
rightOffset < 0 ? 0 : rightOffset,
angle
);
}
private InternalImageProcessorResult processImageFillFrame(DataRenderable renderer) throws JRException
{
byte[] imageData = renderer.getData(jasperReportsContext);
ExifOrientationEnum exifOrientation = ImageUtil.getExifOrientation(imageData);
short angle = 0;
switch (ImageUtil.getRotation(imageElement.getRotation(), exifOrientation))
{
case LEFT:
angle = -90;
break;
case RIGHT:
angle = 90;
break;
case UPSIDE_DOWN:
angle = 180;
break;
case NONE:
default:
angle = 0;
break;
}
return
new InternalImageProcessorResult(
imageData,
0,
0,
0,
0,
angle
);
}
private InternalImageProcessorResult processImageRetainShape(DataRenderable renderer) throws JRException
{
float normalWidth = availableImageWidth;
float normalHeight = availableImageHeight;
DimensionRenderable dimensionRenderer = imageRenderersCache.getDimensionRenderable((Renderable)renderer);
Dimension2D dimension = dimensionRenderer == null ? null : dimensionRenderer.getDimension(jasperReportsContext);
if (dimension != null)
{
normalWidth = (int) dimension.getWidth();
normalHeight = (int) dimension.getHeight();
}
float ratioX = 1f;
float ratioY = 1f;
int imageWidth = 0;
int imageHeight = 0;
int topOffset = 0;
int leftOffset = 0;
int bottomOffset = 0;
int rightOffset = 0;
short angle = 0;
byte[] imageData = renderer.getData(jasperReportsContext);
ExifOrientationEnum exifOrientation = ImageUtil.getExifOrientation(imageData);
switch (ImageUtil.getRotation(imageElement.getRotation(), exifOrientation))
{
case LEFT:
ratioX = availableImageWidth / normalHeight;
ratioY = availableImageHeight / normalWidth;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
imageWidth = (int)(normalHeight * ratioX);
imageHeight = (int)(normalWidth * ratioY);
topOffset = (int) ((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageHeight - imageHeight));
leftOffset = (int) (ImageUtil.getYAlignFactor(imageElement) * (availableImageWidth - imageWidth));
bottomOffset = (int) (ImageUtil.getXAlignFactor(imageElement) * (availableImageHeight - imageHeight));
rightOffset = (int) ((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageWidth - imageWidth));
angle = -90;
break;
case RIGHT:
ratioX = availableImageWidth / normalHeight;
ratioY = availableImageHeight / normalWidth;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
imageWidth = (int)(normalHeight * ratioX);
imageHeight = (int)(normalWidth * ratioY);
topOffset = (int) (ImageUtil.getXAlignFactor(imageElement) * (availableImageHeight - imageHeight));
leftOffset = (int) ((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageWidth - imageWidth));
bottomOffset = (int) ((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageHeight - imageHeight));
rightOffset = (int) (ImageUtil.getYAlignFactor(imageElement) * (availableImageWidth - imageWidth));
angle = 90;
break;
case UPSIDE_DOWN:
ratioX = availableImageWidth / normalWidth;
ratioY = availableImageHeight / normalHeight;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
imageWidth = (int)(normalWidth * ratioX);
imageHeight = (int)(normalHeight * ratioY);
topOffset = (int) ((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageHeight - imageHeight));
leftOffset = (int) ((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageWidth - imageWidth));
bottomOffset = (int) (ImageUtil.getYAlignFactor(imageElement) * (availableImageHeight - imageHeight));
rightOffset = (int) (ImageUtil.getXAlignFactor(imageElement) * (availableImageWidth - imageWidth));
angle = 180;
break;
case NONE:
default:
ratioX = availableImageWidth / normalWidth;
ratioY = availableImageHeight / normalHeight;
ratioX = ratioX < ratioY ? ratioX : ratioY;
ratioY = ratioX;
imageWidth = (int)(normalWidth * ratioX);
imageHeight = (int)(normalHeight * ratioY);
topOffset = (int) (ImageUtil.getYAlignFactor(imageElement) * (availableImageHeight - imageHeight));
leftOffset = (int) (ImageUtil.getXAlignFactor(imageElement) * (availableImageWidth - imageWidth));
bottomOffset = (int) ((1f - ImageUtil.getYAlignFactor(imageElement)) * (availableImageHeight - imageHeight));
rightOffset = (int) ((1f - ImageUtil.getXAlignFactor(imageElement)) * (availableImageWidth - imageWidth));
angle = 0;
break;
}
/*
* The code below the result of tests alone and not the result of prior design or understanding of how image cropping works in the Microsoft document formats.
* Trial and error during tests were the only way to achieve desired output and this code is the result of this trial and error technique alone,
* without actually understanding how image cropping works in these document formats.
*/
switch (imageElement.getRotation())
{
case LEFT :
switch (exifOrientation)
{
case UPSIDE_DOWN :
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
break;
}
case RIGHT :
{
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
}
case LEFT :
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
case NORMAL :
default :
break;
}
break;
case RIGHT :
switch (exifOrientation)
{
case UPSIDE_DOWN :
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
break;
}
case RIGHT :
{
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
}
case LEFT :
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
case NORMAL :
default :
break;
}
break;
case UPSIDE_DOWN :
switch (exifOrientation)
{
case UPSIDE_DOWN :
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
break;
}
case RIGHT :
{
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
}
case LEFT :
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
case NORMAL :
default :
break;
}
break;
case NONE :
default :
switch (exifOrientation)
{
case UPSIDE_DOWN :
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
break;
}
case RIGHT :
{
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
break;
}
case LEFT :
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
)
{
int t = topOffset;
topOffset = bottomOffset;
bottomOffset = t;
}
if (
(imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.LEFT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.BOTTOM)
|| (imageElement.getHorizontalImageAlign() == HorizontalImageAlignEnum.RIGHT && imageElement.getVerticalImageAlign() == VerticalImageAlignEnum.TOP)
)
{
int t = leftOffset;
leftOffset = rightOffset;
rightOffset = t;
}
break;
case NORMAL :
default :
break;
}
break;
}
return
new InternalImageProcessorResult(
imageData,
topOffset,
leftOffset,
bottomOffset,
rightOffset,
angle
);
}
}
private class InternalImageProcessorResult
{
private final byte[] imageData;
private final int topOffset;
private final int leftOffset;
private final int bottomOffset;
private final int rightOffset;
private final short angle;
protected InternalImageProcessorResult(
byte[] imageData,
int topOffset,
int leftOffset,
int bottomOffset,
int rightOffset,
short angle
)
{
this.imageData = imageData;
this.topOffset = topOffset;
this.leftOffset = leftOffset;
this.bottomOffset = bottomOffset;
this.rightOffset = rightOffset;
this.angle = angle;
}
}
/**
*
*/
protected double getColumnRelativePosition(JRGridLayout layout, int col, int offset)
{
double colRelPos = 0;
int cumulativeColWidth = 0;
int colIndex = 0;
while(cumulativeColWidth < offset)
{
int colWidth = layout.getColumnWidth(col + colIndex);
if (cumulativeColWidth + colWidth < offset)
{
colIndex++;
}
else
{
colRelPos += colIndex + ((offset - cumulativeColWidth) / (double) colWidth);
}
cumulativeColWidth += colWidth;
}
return colRelPos;
}
/**
*
*/
protected double getRowRelativePosition(JRGridLayout layout, int row, int offset)
{
double rowRelPos = 0;
//isCollapseRowSpan
int cumulativeRowHeight = 0;
int rowIndex = 0;
while(cumulativeRowHeight < offset)
{
int rowHeight = collapseRowSpan ? layout.getMaxRowHeight(row + rowIndex) : layout.getRowHeight(row + rowIndex);
if (cumulativeRowHeight + rowHeight < offset)
{
rowIndex++;
}
else
{
rowRelPos += rowIndex + ((offset - cumulativeRowHeight) / (double) rowHeight);
}
cumulativeRowHeight += rowHeight;
}
return rowRelPos;
}
@Override
protected void exportFrame(JRPrintFrame frame, JRExporterGridCell gridCell, int x, int y)
{
FillPatternType mode = backgroundMode;
short backcolor = whiteIndex;
if (frame.getModeValue() == ModeEnum.OPAQUE)
{
mode = FillPatternType.SOLID_FOREGROUND;
backcolor = getWorkbookColor(frame.getBackcolor()).getIndex();
}
short forecolor = getWorkbookColor(frame.getForecolor()).getIndex();
HSSFCellStyle cellStyle =
getLoadedCellStyle(
mode,
backcolor,
HorizontalAlignment.LEFT,
VerticalAlignment.TOP,
(short)0,
getLoadedFont(getDefaultFont(), forecolor, null, getLocale()),
gridCell,
isWrapText(frame),
isCellLocked(frame),
isCellHidden(frame),
isShrinkToFit(frame)
);
createMergeRegion(gridCell, x, y, cellStyle);
cell = row.createCell(x);
cell.setCellStyle(cellStyle);
}
@Override
protected void exportGenericElement(JRGenericPrintElement element, JRExporterGridCell gridCell, int colIndex, int rowIndex, int emptyCols, int yCutsRow, JRGridLayout layout) throws JRException
{
GenericElementXlsHandler handler = (GenericElementXlsHandler)
GenericElementHandlerEnviroment.getInstance(getJasperReportsContext()).getElementHandler(
element.getGenericType(), XLS_EXPORTER_KEY);
if (handler != null)
{
handler.exportElement(exporterContext, element, gridCell, colIndex, rowIndex, emptyCols, yCutsRow, layout);
}
else
{
if (log.isDebugEnabled())
{
log.debug("No XLS generic element handler for "
+ element.getGenericType());
}
}
}
private final short getSuitablePaperSize(SheetPrintSettings printSettings)
{
if (printSettings == null)
{
return -1;
}
long width = 0;
long height = 0;
short ps = -1;
if ((printSettings.getPageWidth() != 0) && (printSettings.getPageHeight() != 0))
{
double dWidth = (printSettings.getPageWidth() / 72.0);
double dHeight = (printSettings.getPageHeight() / 72.0);
height = Math.round(dHeight * 25.4);
width = Math.round(dWidth * 25.4);
// Compare to ISO 216 A-Series (A3-A5). All other ISO 216 formats
// not supported by POI Api yet.
for (int i = 2; i < 6; i++)
{
int w = calculateWidthForDinAN(i);
int h = calculateHeightForDinAN(i);
if (((w == width) && (h == height)) || ((h == width) && (w == height)))
{
if (i == 2)
{
// local A2_PAPERSIZE constant
ps = A2_PAPERSIZE;
}
if (i == 3)
{
ps = HSSFPrintSetup.A3_PAPERSIZE;
}
else if (i == 4)
{
ps = HSSFPrintSetup.A4_PAPERSIZE;
}
else if (i == 5)
{
ps = HSSFPrintSetup.A5_PAPERSIZE;
}
break;
}
}
//envelope sizes
if (ps == -1)
{
// ISO 269 sizes - "Envelope DL" (110 x 220 mm)
if (((width == 110) && (height == 220)) || ((width == 220) && (height == 110)))
{
ps = HSSFPrintSetup.ENVELOPE_DL_PAPERSIZE;
}
}
// Compare to common North American Paper Sizes (ANSI X3.151-1987).
if (ps == -1)
{
// ANSI X3.151-1987 - "Letter" (216 x 279 mm)
if (((width == 216) && (height == 279)) || ((width == 279) && (height == 216)))
{
ps = HSSFPrintSetup.LETTER_PAPERSIZE;
}
// ANSI X3.151-1987 - "Legal" (216 x 356 mm)
if (((width == 216) && (height == 356)) || ((width == 356) && (height == 216)))
{
ps = HSSFPrintSetup.LEGAL_PAPERSIZE;
}
// ANSI X3.151-1987 - "Executive" (190 x 254 mm)
else if (((width == 190) && (height == 254)) || ((width == 254) && (height == 190)))
{
ps = HSSFPrintSetup.EXECUTIVE_PAPERSIZE;
}
// ANSI X3.151-1987 - "Ledger/Tabloid" (279 x 432 mm)
// Not supported by POI Api yet.
}
}
return ps;
}
protected void setHyperlinkCell(JRPrintHyperlink hyperlink)
{
Hyperlink link = null;
Boolean ignoreHyperlink = HyperlinkUtil.getIgnoreHyperlink(XlsReportConfiguration.PROPERTY_IGNORE_HYPERLINK, hyperlink);
if (ignoreHyperlink == null)
{
ignoreHyperlink = defaultIgnoreHyperlink;
}
//test for ignore hyperlinks done here
if (!ignoreHyperlink)
{
JRHyperlinkProducer customHandler = getHyperlinkProducer(hyperlink);
if (customHandler == null)
{
switch (hyperlink.getHyperlinkTypeValue())
{
case REFERENCE:
{
String href = hyperlink.getHyperlinkReference();
if (href != null)
{
link = createHelper.createHyperlink(HyperlinkType.URL);
link.setAddress(href);
}
break;
}
case LOCAL_ANCHOR :
{
//test for ignore anchors done here
if(!ignoreAnchors)
{
String href = hyperlink.getHyperlinkAnchor();
if (href != null)
{
link = createHelper.createHyperlink(HyperlinkType.DOCUMENT);
if(anchorLinks.containsKey(href))
{
(anchorLinks.get(href)).add(link);
}
else
{
List hrefList = new ArrayList<>();
hrefList.add(link);
anchorLinks.put(href, hrefList);
}
}
}
break;
}
case LOCAL_PAGE :
{
Integer hrefPage = (onePagePerSheet ? hyperlink.getHyperlinkPage() : 0);
if (hrefPage != null)
{
link = createHelper.createHyperlink(HyperlinkType.DOCUMENT);
if(pageLinks.containsKey(sheetsBeforeCurrentReport+hrefPage))
{
pageLinks.get(sheetsBeforeCurrentReport + hrefPage).add(link);
}
else
{
List hrefList = new ArrayList<>();
hrefList.add(link);
pageLinks.put(sheetsBeforeCurrentReport + hrefPage, hrefList);
}
}
break;
}
case REMOTE_ANCHOR :
{
String href = hyperlink.getHyperlinkReference();
if (href != null && hyperlink.getHyperlinkAnchor() != null)
{
href = href + "#" + hyperlink.getHyperlinkAnchor();
link = createHelper.createHyperlink(HyperlinkType.FILE);
link.setAddress(href);
}
break;
}
case REMOTE_PAGE :
{
String href = hyperlink.getHyperlinkReference();
if (href != null && hyperlink.getHyperlinkPage() != null)
{
href = href + "#JR_PAGE_ANCHOR_0_" + hyperlink.getHyperlinkPage().toString();
link = createHelper.createHyperlink(HyperlinkType.FILE);
link.setAddress(href);
}
break;
}
case NONE:
default:
{
}
}
}
else
{
String href = customHandler.getHyperlink(hyperlink);
if (href != null)
{
link = createHelper.createHyperlink(HyperlinkType.URL);
link.setAddress(href);
}
}
if(link != null)
{
//TODO: make tooltips functional
// if(hyperlink.getHyperlinkTooltip() != null)
// {
// link.setLabel(hyperlink.getHyperlinkTooltip());
// }
cell.setHyperlink(link);
}
}
}
@Override
protected Integer getMaxRowsPerSheet()
{
Integer maxRowsPerSheet = super.getMaxRowsPerSheet();
return maxRowsPerSheet == null || maxRowsPerSheet == 0 || maxRowsPerSheet > 65536 ? 65536 : maxRowsPerSheet;
}
@Override
public String getExporterKey()
{
return XLS_EXPORTER_KEY;
}
@Override
public String getExporterPropertiesPrefix()
{
return XLS_EXPORTER_PROPERTIES_PREFIX;
}
/**
* Creates a freeze pane for the current sheet. Freeze pane row and column indexes defined at element level override indexes defined at report level.
* If multiple row freeze indexes are found in the same sheet, their maximum
* value is considered.
*
* @param rowIndex the freeze 0-based row index
* @param colIndex the freeze 0-based column index
*/
@Override
protected void setFreezePane(int rowIndex, int colIndex)
{
if(rowIndex > 0 || colIndex > 0)
{
sheet.createFreezePane(Math.max(0, colIndex), Math.max(0, rowIndex));
}
}
@Override
protected void setSheetName(String sheetName)
{
workbook.setSheetName(workbook.getSheetIndex(sheet) , sheetName);
}
@Override
protected void setAutoFilter(String autoFilterRange)
{
sheet.setAutoFilter(CellRangeAddress.valueOf(autoFilterRange));
}
@Override
protected void setRowLevels(XlsRowLevelInfo levelInfo, String level)
{
Map levelMap = levelInfo.getLevelMap();
if(levelMap != null && levelMap.size() > 0)
{
for (Entry entry : levelMap.entrySet())
{
String l = entry.getKey();
if (level == null || l.compareTo(level) >= 0)
{
Integer startIndex = entry.getValue();
if(levelInfo.getEndIndex() >= startIndex)
{
sheet.groupRow(startIndex, levelInfo.getEndIndex());
}
}
}
sheet.setRowSumsBelow(false);
}
}
public static ClientAnchor.AnchorType getAnchorType(ImageAnchorTypeEnum anchorType)
{
switch (anchorType)
{
case MOVE_SIZE:
return ClientAnchor.AnchorType.MOVE_AND_RESIZE;
case NO_MOVE_NO_SIZE:
return ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE;
case MOVE_NO_SIZE:
default:
return ClientAnchor.AnchorType.MOVE_DONT_RESIZE;
}
}
/**
*
*/
class BoxStyle
{
protected static final int TOP = 0;
protected static final int LEFT = 1;
protected static final int BOTTOM = 2;
protected static final int RIGHT = 3;
protected BorderStyle[] borderStyle = new BorderStyle[] {BorderStyle.NONE, BorderStyle.NONE, BorderStyle.NONE, BorderStyle.NONE};
protected short[] borderColour = new short[4];
private int hash;
public BoxStyle(int side, JRPen pen)
{
borderStyle[side] = JRXlsExporter.getBorderStyle(pen);
borderColour[side] = JRXlsExporter.this.getWorkbookColor(pen.getLineColor()).getIndex();
hash = computeHash();
}
public BoxStyle(JRExporterGridCell gridCell)
{
if(gridCell != null)
{
JRLineBox lineBox = gridCell.getBox();
if (lineBox != null)
{
setBox(lineBox);
}
JRPrintElement element = gridCell.getElement();
if (element instanceof JRCommonGraphicElement)
{
setPen(((JRCommonGraphicElement)element).getLinePen());
}
hash = computeHash();
}
}
public void setBox(JRLineBox box)
{
borderStyle[TOP] = JRXlsExporter.getBorderStyle(box.getTopPen());
borderColour[TOP] = JRXlsExporter.this.getWorkbookColor(box.getTopPen().getLineColor()).getIndex();
borderStyle[BOTTOM] = JRXlsExporter.getBorderStyle(box.getBottomPen());
borderColour[BOTTOM] = JRXlsExporter.this.getWorkbookColor(box.getBottomPen().getLineColor()).getIndex();
borderStyle[LEFT] = JRXlsExporter.getBorderStyle(box.getLeftPen());
borderColour[LEFT] = JRXlsExporter.this.getWorkbookColor(box.getLeftPen().getLineColor()).getIndex();
borderStyle[RIGHT] = JRXlsExporter.getBorderStyle(box.getRightPen());
borderColour[RIGHT] = JRXlsExporter.this.getWorkbookColor(box.getRightPen().getLineColor()).getIndex();
hash = computeHash();
}
public void setPen(JRPen pen)
{
if (
borderStyle[TOP] == BorderStyle.NONE
&& borderStyle[LEFT] == BorderStyle.NONE
&& borderStyle[BOTTOM] == BorderStyle.NONE
&& borderStyle[RIGHT] == BorderStyle.NONE
)
{
BorderStyle style = JRXlsExporter.getBorderStyle(pen);
short colour = JRXlsExporter.this.getWorkbookColor(pen.getLineColor()).getIndex();
borderStyle[TOP] = style;
borderStyle[BOTTOM] = style;
borderStyle[LEFT] = style;
borderStyle[RIGHT] = style;
borderColour[TOP] = colour;
borderColour[BOTTOM] = colour;
borderColour[LEFT] = colour;
borderColour[RIGHT] = colour;
}
hash = computeHash();
}
private int computeHash()
{
int hashCode = (borderStyle[TOP] == null ? 0 : borderStyle[TOP].hashCode());
hashCode = 31*hashCode + borderColour[TOP];
hashCode = 31*hashCode + (borderStyle[BOTTOM] == null ? 0 : borderStyle[BOTTOM].hashCode());
hashCode = 31*hashCode + borderColour[BOTTOM];
hashCode = 31*hashCode + (borderStyle[LEFT] == null ? 0 : borderStyle[LEFT].hashCode());
hashCode = 31*hashCode + borderColour[LEFT];
hashCode = 31*hashCode + (borderStyle[RIGHT] == null ? 0 : borderStyle[RIGHT].hashCode());
hashCode = 31*hashCode + borderColour[RIGHT];
return hashCode;
}
@Override
public int hashCode()
{
return hash;
}
@Override
public boolean equals(Object o)
{
BoxStyle b = (BoxStyle) o;
return
b.borderStyle[TOP] == borderStyle[TOP] &&
b.borderColour[TOP] == borderColour[TOP] &&
b.borderStyle[BOTTOM] == borderStyle[BOTTOM] &&
b.borderColour[BOTTOM] == borderColour[BOTTOM] &&
b.borderStyle[LEFT] == borderStyle[LEFT] &&
b.borderColour[LEFT] == borderColour[LEFT] &&
b.borderStyle[RIGHT] == borderStyle[RIGHT] &&
b.borderColour[RIGHT] == borderColour[RIGHT];
}
@Override
public String toString()
{
return "(" +
borderStyle[TOP] + "/" + borderColour[TOP] + "," +
borderStyle[BOTTOM] + "/" + borderColour[BOTTOM] + "," +
borderStyle[LEFT] + "/" + borderColour[LEFT] + "," +
borderStyle[RIGHT] + "/" + borderColour[RIGHT] + ")";
}
}
/**
*
*/
protected class StyleInfo
{
protected final FillPatternType mode;
protected final short backcolor;
protected final HorizontalAlignment horizontalAlignment;
protected final VerticalAlignment verticalAlignment;
protected final short rotation;
protected final HSSFFont font;
protected final BoxStyle box;
protected final boolean lcWrapText;
protected final boolean lcCellLocked;
protected final boolean lcCellHidden;
protected final boolean lcShrinkToFit;
private short lcDataFormat = -1;
private int hashCode;
public StyleInfo(
FillPatternType mode,
short backcolor,
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment,
short rotation,
HSSFFont font,
JRExporterGridCell gridCell,
boolean wrapText,
boolean cellLocked,
boolean cellHidden,
boolean shrinkToFit
)
{
this(mode,
backcolor,
horizontalAlignment,
verticalAlignment,
rotation,
font,
(gridCell == null ? null : new BoxStyle(gridCell)),
wrapText,
cellLocked,
cellHidden,
shrinkToFit);
}
public StyleInfo(
FillPatternType mode,
short backcolor,
HorizontalAlignment horizontalAlignment,
VerticalAlignment verticalAlignment,
short rotation,
HSSFFont font,
BoxStyle box,
boolean wrapText,
boolean cellLocked,
boolean cellHidden,
boolean shrinkToFit
)
{
this.mode = mode;
this.backcolor = backcolor;
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
this.rotation = rotation;
this.font = font;
this.box = box;
this.lcWrapText = shrinkToFit ? false : wrapText;
this.lcCellLocked = cellLocked;
this.lcCellHidden = cellHidden;
this.lcShrinkToFit = shrinkToFit;
hashCode = computeHash();
}
@SuppressWarnings("deprecation")
protected int computeHash()
{
int hash = mode.hashCode();
hash = 31*hash + backcolor;
hash = 31*hash + horizontalAlignment.hashCode();
hash = 31*hash + verticalAlignment.hashCode();
hash = 31*hash + rotation;
hash = 31*hash + (font == null ? 0 : font.getIndexAsInt());
hash = 31*hash + (box == null ? 0 : box.hashCode());
hash = 31*hash + lcDataFormat;
hash = 31*hash + (lcWrapText ? 0 : 1);
hash = 31*hash + (lcCellLocked ? 0 : 1);
hash = 31*hash + (lcCellHidden ? 0 : 1);
hash = 31*hash + (lcShrinkToFit ? 0 : 1);
return hash;
}
public void setDataFormat(short dataFormat)
{
this.lcDataFormat = dataFormat;
hashCode = computeHash();
}
public boolean hasDataFormat()
{
return lcDataFormat != -1;
}
public short getDataFormat()
{
return lcDataFormat;
}
@Override
public int hashCode()
{
return hashCode;
}
@SuppressWarnings("deprecation")
@Override
public boolean equals(Object o)
{
StyleInfo s = (StyleInfo) o;
return s.mode == mode
&& s.backcolor == backcolor
&& s.horizontalAlignment == horizontalAlignment
&& s.verticalAlignment == verticalAlignment
&& s.rotation == rotation
&& (s.font == null ? font == null : (font != null && s.font.getIndexAsInt() == font.getIndexAsInt()))
&& (s.box == null ? box == null : (box != null && s.box.equals(box)))
&& s.rotation == rotation && s.lcWrapText == lcWrapText
&& s.lcCellLocked == lcCellLocked && s.lcCellHidden == lcCellHidden
&& s.lcShrinkToFit == lcShrinkToFit; //FIXME should dataformat be part of equals? it is part of toString()...
}
@Override
public String toString()
{
return "(" +
mode + "," + backcolor + "," +
horizontalAlignment + "," + verticalAlignment + "," +
rotation + "," + font + "," +
box + "," + lcDataFormat + "," + lcWrapText + "," + lcCellLocked + "," + lcCellHidden + "," + lcShrinkToFit + ")";
}
}
}