Java tutorial
/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2014 TIBCO Software 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 <http://www.gnu.org/licenses/>. */ /* * Contributor: Manuel Paul <mpaul@ratundtat.com>, * Rat & Tat Beratungsgesellschaft mbH, * Muehlenkamp 6c, * 22303 Hamburg, * Germany. */ 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.geom.Dimension2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; import jxl.CellView; import jxl.SheetSettings; import jxl.Workbook; import jxl.WorkbookSettings; import jxl.biff.DisplayFormat; import jxl.format.Alignment; import jxl.format.BoldStyle; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.Colour; import jxl.format.Orientation; import jxl.format.PageOrientation; import jxl.format.PaperSize; import jxl.format.Pattern; import jxl.format.RGB; import jxl.format.UnderlineStyle; import jxl.format.VerticalAlignment; import jxl.read.biff.BiffException; import jxl.write.Blank; import jxl.write.DateFormat; import jxl.write.DateTime; import jxl.write.Formula; import jxl.write.Label; import jxl.write.Number; import jxl.write.NumberFormat; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableHyperlink; import jxl.write.WritableImage; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; import jxl.write.biff.CellValue; import jxl.write.biff.RowsExceededException; import net.sf.jasperreports.engine.DefaultJasperReportsContext; import net.sf.jasperreports.engine.JRBoxContainer; import net.sf.jasperreports.engine.JRCommonGraphicElement; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRFont; 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.JRPrintEllipse; import net.sf.jasperreports.engine.JRPrintFrame; import net.sf.jasperreports.engine.JRPrintGraphicElement; import net.sf.jasperreports.engine.JRPrintImage; import net.sf.jasperreports.engine.JRPrintLine; import net.sf.jasperreports.engine.JRPrintRectangle; import net.sf.jasperreports.engine.JRPrintText; import net.sf.jasperreports.engine.JRPropertiesUtil; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JRWrappingSvgRenderer; import net.sf.jasperreports.engine.JasperReportsContext; import net.sf.jasperreports.engine.Renderable; import net.sf.jasperreports.engine.RenderableUtil; 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.fonts.FontFamily; import net.sf.jasperreports.engine.fonts.FontInfo; import net.sf.jasperreports.engine.fonts.FontUtil; import net.sf.jasperreports.engine.type.HorizontalAlignEnum; 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.RenderableTypeEnum; import net.sf.jasperreports.engine.type.RotationEnum; import net.sf.jasperreports.engine.type.VerticalAlignEnum; import net.sf.jasperreports.engine.util.JRClassLoader; import net.sf.jasperreports.engine.util.JRDataUtils; import net.sf.jasperreports.engine.util.JRImageLoader; import net.sf.jasperreports.engine.util.JRStyledText; import net.sf.jasperreports.export.JxlExporterConfiguration; import net.sf.jasperreports.export.JxlMetadataExporterConfiguration; import net.sf.jasperreports.export.JxlMetadataReportConfiguration; import net.sf.jasperreports.export.JxlReportConfiguration; import net.sf.jasperreports.export.XlsReportConfiguration; import net.sf.jasperreports.repo.RepositoryUtil; import org.apache.commons.collections.map.ReferenceMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * @deprecated Replaced by {@link JRXlsMetadataExporter}. * @author sanda zaharia (shertage@users.sourceforge.net) * @version $Id: JExcelApiMetadataExporter.java 7366 2014-11-07 01:25:15Z teodord $ */ public class JExcelApiMetadataExporter extends JRXlsAbstractMetadataExporter<JxlMetadataReportConfiguration, JxlMetadataExporterConfiguration, JExcelApiExporterContext> { private static final Log log = LogFactory.getLog(JExcelApiMetadataExporter.class); /** * @deprecated Replaced by {@link JxlExporterConfiguration#PROPERTY_USE_TEMP_FILE}. */ public static final String PROPERTY_USE_TEMP_FILE = JxlExporterConfiguration.PROPERTY_USE_TEMP_FILE; /** * @deprecated Replaced by {@link JxlReportConfiguration#PROPERTY_COMPLEX_FORMAT}. */ public static final String PROPERTY_COMPLEX_FORMAT = JxlReportConfiguration.PROPERTY_COMPLEX_FORMAT; /** * The exporter key, as used in * {@link GenericElementHandlerEnviroment#getHandler(net.sf.jasperreports.engine.JRGenericElementType, String)}. */ public static final String JXL_EXPORTER_KEY = JRPropertiesUtil.PROPERTY_PREFIX + "jxl"; protected static final Colour WHITE = Colour.WHITE; protected static final Colour BLACK = Colour.BLACK; protected static final String EMPTY_SHEET_NAME = "Sheet1"; private static Map<Color, Colour> colorsCache = new ReferenceMap(); private static final Colour[] FIXED_COLOURS = new Colour[] { WHITE, BLACK, Colour.PALETTE_BLACK, Colour.DEFAULT_BACKGROUND, Colour.DEFAULT_BACKGROUND1, Colour.AUTOMATIC, Colour.UNKNOWN }; private Map<StyleInfo, WritableCellFormat> loadedCellStyles = new HashMap<StyleInfo, WritableCellFormat>(); private WritableWorkbook workbook; private WritableSheet sheet; private Pattern backgroundMode = Pattern.SOLID; private Map<String, NumberFormat> numberFormats = new HashMap<String, NumberFormat>(); private Map<String, DateFormat> dateFormats = new HashMap<String, DateFormat>(); protected Map<Color, Colour> workbookColours = new HashMap<Color, Colour>(); protected Map<Colour, RGB> usedColours = new HashMap<Colour, RGB>(); protected ExporterNature nature; protected final java.text.DateFormat isoDateFormat = JRDataUtils.getIsoDateFormat(); protected class ExporterContext extends BaseExporterContext implements JExcelApiExporterContext { } /** * @see #JExcelApiMetadataExporter(JasperReportsContext) */ public JExcelApiMetadataExporter() { this(DefaultJasperReportsContext.getInstance()); } /** * */ public JExcelApiMetadataExporter(JasperReportsContext jasperReportsContext) { super(jasperReportsContext); exporterContext = new ExporterContext(); } /** * */ protected Class<JxlMetadataExporterConfiguration> getConfigurationInterface() { return JxlMetadataExporterConfiguration.class; } /** * */ protected Class<JxlMetadataReportConfiguration> getItemConfigurationInterface() { return JxlMetadataReportConfiguration.class; } @Override protected void initExport() { super.initExport(); JxlMetadataExporterConfiguration configuration = getCurrentConfiguration(); if (configuration.isCreateCustomPalette()) { initCustomPalette(); } } @Override protected void initReport() { super.initReport(); JxlMetadataReportConfiguration configuration = getCurrentItemConfiguration(); if (configuration.isWhitePageBackground()) { this.backgroundMode = Pattern.SOLID; } else { this.backgroundMode = Pattern.NONE; } nature = new JExcelApiExporterNature(jasperReportsContext, filter, configuration.isIgnoreGraphics(), configuration.isIgnorePageMargins()); } protected void initCustomPalette() { //mark "fixed" colours as always used for (int i = 0; i < FIXED_COLOURS.length; i++) { Colour colour = FIXED_COLOURS[i]; setColourUsed(colour); } } protected void setColourUsed(Colour colour) { usedColours.put(colour, colour.getDefaultRGB()); } protected void setColourUsed(Colour colour, Color reportColour) { if (log.isDebugEnabled()) { log.debug("Modifying palette colour " + colour.getValue() + " to " + reportColour); } int red = reportColour.getRed(); int green = reportColour.getGreen(); int blue = reportColour.getBlue(); workbook.setColourRGB(colour, red, green, blue); RGB customRGB = new RGB(red, green, blue); usedColours.put(colour, customRGB); } protected void openWorkbook(OutputStream os) throws JRException { JxlMetadataExporterConfiguration configuration = getCurrentConfiguration(); WorkbookSettings settings = new WorkbookSettings(); settings.setUseTemporaryFileDuringWrite(configuration.isUseTempFile()); InputStream templateIs = null; try { String lcWorkbookTemplate = workbookTemplate == null ? configuration.getWorkbookTemplate() : workbookTemplate; if (lcWorkbookTemplate == null) { workbook = Workbook.createWorkbook(os, settings); } else { templateIs = RepositoryUtil.getInstance(jasperReportsContext) .getInputStreamFromLocation(lcWorkbookTemplate); if (templateIs == null) { throw new JRRuntimeException("Workbook template not found at : " + lcWorkbookTemplate); } else { Workbook template = Workbook.getWorkbook(templateIs); workbook = Workbook.createWorkbook(os, template, settings); boolean keepSheets = keepTemplateSheets == null ? configuration.isKeepWorkbookTemplateSheets() : keepTemplateSheets; if (!keepSheets) { for (int i = 0; i < workbook.getNumberOfSheets(); i++) { workbook.removeSheet(i); } } else { sheetIndex += workbook.getNumberOfSheets(); } } } firstPageNotSet = true; } catch (IOException e) { throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e); } catch (BiffException e) { throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e); } finally { if (templateIs != null) { try { templateIs.close(); } catch (IOException e) { } } } } protected void createSheet(SheetInfo sheetInfo) { sheet = workbook.createSheet(sheetInfo.sheetName, Integer.MAX_VALUE); setSheetSettings(sheetInfo, sheet); } protected void closeWorkbook(OutputStream os) throws JRException { if (sheet == null)//empty document { //creating an empty sheet so that write() doesn't fail workbook.createSheet(EMPTY_SHEET_NAME, Integer.MAX_VALUE); } try { workbook.write(); workbook.close(); } catch (IOException e) { throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e); } catch (WriteException e) { throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e); } } protected void setColumnWidth(int col, int width, boolean autoFit) { // if (autoFit) // { // CellView cv = new CellView(); // cv.setAutosize(true); // sheet.setColumnView(col, cv); // } // else // { // CellView cv = sheet.getColumnView(col); // if(cv == null || cv.getSize() < 43 * width) // { // cv = new CellView(); // cv.setSize(43 * width); // sheet.setColumnView(col, cv); // } // } CellView cv = new CellView(); if (autoFit) { cv.setAutosize(true); } else { cv.setSize(43 * width); } sheet.setColumnView(col, cv); } protected void setRowHeight(int rowIndex, int lastRowHeight, Cut yCut, XlsRowLevelInfo levelInfo) throws JRException { boolean isAutoFit = yCut != null && yCut.hasProperty(JRXlsAbstractExporter.PROPERTY_AUTO_FIT_ROW) && (Boolean) yCut.getProperty(JRXlsAbstractExporter.PROPERTY_AUTO_FIT_ROW); if (isAutoFit) { try { CellView cv = sheet.getRowView(rowIndex) == null ? new CellView() : sheet.getRowView(rowIndex); cv.setAutosize(true); sheet.setRowView(rowIndex, cv); } catch (RowsExceededException e) { throw new JRException("Too many rows in sheet " + sheet.getName() + ": " + rowIndex, e); } } else { try { CellView cv = sheet.getRowView(rowIndex); if (cv == null || cv.getSize() < LengthUtil.twip(lastRowHeight)) { sheet.setRowView(rowIndex, LengthUtil.twip(lastRowHeight)); } } catch (RowsExceededException e) { throw new JRException("Too many rows in sheet " + sheet.getName() + ": " + rowIndex, e); } } } protected void addBlankCell(WritableCellFormat baseStyleFormat, Map<String, Object> cellValueMap, String currentColumnName) throws JRException { if (baseStyleFormat != null) { int colIndex = columnNamesMap.get(currentColumnName); cellValueMap.put(currentColumnName, new Blank(colIndex, rowIndex, baseStyleFormat)); } } protected void writeCurrentRow(Map<String, Object> currentRow, Map<String, Object> repeatedValues) throws JRException { for (int i = 0; i < columnNames.size(); i++) { CellValue cellValue = (CellValue) currentRow.get(columnNames.get(i)) == null ? (repeatedValues.get(columnNames.get(i)) != null ? (CellValue) (((CellValue) repeatedValues.get(columnNames.get(i))).copyTo(i, rowIndex)) : null) : (CellValue) currentRow.get(columnNames.get(i)); if (cellValue != null) { try { sheet.addCell(cellValue); } catch (RowsExceededException e) { throw new JRException("There are too many rows in the current sheet", e); } catch (WriteException e) { throw new JRException(e); } } } ++rowIndex; } protected void exportLine(JRPrintLine line) throws JRException { String currentColumnName = line.getPropertiesMap() .getProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_COLUMN_NAME); if (currentColumnName != null && currentColumnName.length() > 0) { boolean repeatValue = getPropertiesUtil().getBooleanProperty(line, JRXlsAbstractMetadataExporterParameter.PROPERTY_REPEAT_VALUE, false); setColumnName(currentColumnName); setColumnWidth(columnNamesMap.get(currentColumnName), line.getWidth()); setRowHeight(rowIndex, line.getHeight()); Colour forecolor2 = getWorkbookColour(line.getLinePen().getLineColor()); WritableFont cellFont2 = getLoadedFont(getDefaultFont(), forecolor2.getValue(), getLocale()); Colour backcolor = WHITE; Pattern mode = this.backgroundMode; JxlReportConfiguration configuration = getCurrentItemConfiguration(); if (!configuration.isIgnoreCellBackground() && line.getBackcolor() != null) { mode = Pattern.SOLID; backcolor = getWorkbookColour(line.getBackcolor(), true); } 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()); WritableCellFormat cellStyle2 = getLoadedCellStyle(mode, backcolor, cellFont2, boxStyle, isCellLocked(line)); addBlankElement(cellStyle2, repeatValue, currentColumnName); } } protected void exportRectangle(JRPrintGraphicElement element) throws JRException { String currentColumnName = element.getPropertiesMap() .getProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_COLUMN_NAME); if (currentColumnName != null && currentColumnName.length() > 0) { boolean repeatValue = getPropertiesUtil().getBooleanProperty(element, JRXlsAbstractMetadataExporterParameter.PROPERTY_REPEAT_VALUE, false); setColumnName(currentColumnName); setColumnWidth(columnNamesMap.get(currentColumnName), element.getWidth()); setRowHeight(rowIndex, element.getHeight()); Colour backcolor = WHITE; Pattern mode = this.backgroundMode; JxlReportConfiguration configuration = getCurrentItemConfiguration(); if (!configuration.isIgnoreCellBackground() && element.getBackcolor() != null) { mode = Pattern.SOLID; backcolor = getWorkbookColour(element.getBackcolor(), true); } Colour forecolor = getWorkbookColour(element.getLinePen().getLineColor()); WritableFont cellFont2 = getLoadedFont(getDefaultFont(), forecolor.getValue(), getLocale()); BoxStyle boxStyle = new BoxStyle(element.getStyle()); WritableCellFormat cellStyle2 = getLoadedCellStyle(mode, backcolor, cellFont2, boxStyle, isCellLocked(element)); addBlankElement(cellStyle2, repeatValue, currentColumnName); } } protected void exportText(JRPrintText textElement) throws JRException { String currentColumnName = textElement.getPropertiesMap() .getProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_COLUMN_NAME); if (currentColumnName != null && currentColumnName.length() > 0) { boolean hasCurrentColumnData = textElement.getPropertiesMap() .containsProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_DATA); String currentColumnData = textElement.getPropertiesMap() .getProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_DATA); boolean repeatValue = getPropertiesUtil().getBooleanProperty(textElement, JRXlsAbstractMetadataExporterParameter.PROPERTY_REPEAT_VALUE, false); setColumnName(currentColumnName); setColumnWidth(columnNamesMap.get(currentColumnName), textElement.getWidth()); setRowHeight(rowIndex, textElement.getHeight()); Color textForecolor = textElement.getForecolor() == null ? Color.BLACK : textElement.getForecolor(); Colour forecolor = getWorkbookColour(textForecolor); WritableFont cellFont = this.getLoadedFont(textElement, forecolor.getValue(), getTextLocale(textElement)); TextAlignHolder alignment = getTextAlignHolder(textElement); int horizontalAlignment = getHorizontalAlignment(alignment); int verticalAlignment = getVerticalAlignment(alignment); int rotation = getRotation(alignment); Pattern mode = this.backgroundMode; Colour backcolor = WHITE; JxlReportConfiguration configuration = getCurrentItemConfiguration(); if (!configuration.isIgnoreCellBackground() && textElement.getBackcolor() != null) { mode = Pattern.SOLID; backcolor = getWorkbookColour(textElement.getBackcolor(), true); } StyleInfo baseStyle = new StyleInfo(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, cellFont, textElement, isWrapText(textElement) || Boolean.TRUE .equals(((JExcelApiExporterNature) nature).getColumnAutoFit(textElement)), isCellLocked(textElement)); String href = null; JRHyperlinkProducer customHandler = getHyperlinkProducer(textElement); if (customHandler == null) { switch (textElement.getHyperlinkTypeValue()) { case REFERENCE: { href = textElement.getHyperlinkReference(); break; } case LOCAL_ANCHOR: case LOCAL_PAGE: case REMOTE_ANCHOR: case REMOTE_PAGE: case NONE: default: { } } } else { href = customHandler.getHyperlink(textElement); } Integer colIndex = columnNamesMap.get(currentColumnName); if (href != null) { try { URL url = new URL(href); WritableHyperlink hyperlink = new WritableHyperlink(colIndex, rowIndex, colIndex, rowIndex, url); sheet.addHyperlink(hyperlink); } catch (MalformedURLException e) { if (log.isWarnEnabled()) { log.warn("Reference \"" + href + "\" could not be parsed as URL.", e); } } catch (RowsExceededException e) { throw new JRException("There are too many rows in the current sheet", e); } catch (WriteException e) { throw new JRException(e); } } JRStyledText styledText = null; String textStr = null; if (hasCurrentColumnData) { styledText = new JRStyledText(); if (currentColumnData != null) { styledText.append(currentColumnData); } textStr = currentColumnData; } else { styledText = getStyledText(textElement); if (styledText != null) { textStr = styledText.getText(); } } addTextElement(textElement, textStr, baseStyle, repeatValue, currentColumnName, hasCurrentColumnData); } } protected void addTextElement(JRPrintText textElement, String textStr, StyleInfo baseStyle, boolean repeatValue, String currentColumnName, boolean hasCurrentColumnData) throws JRException { if (columnNames.size() > 0) { if (columnNames.contains(currentColumnName) && !currentRow.containsKey(currentColumnName) && isColumnReadOnTime(currentRow, currentColumnName)) // the column is for export but was not read yet and comes in the expected order { addCell(textElement, textStr, baseStyle, currentRow, currentColumnName, hasCurrentColumnData); } else if ((columnNames.contains(currentColumnName) && !currentRow.containsKey(currentColumnName) && !isColumnReadOnTime(currentRow, currentColumnName)) // the column is for export, was not read yet, but it is read after it should be || (columnNames.contains(currentColumnName) && currentRow.containsKey(currentColumnName))) // the column is for export and was already read { if (rowIndex == 1 && getCurrentItemConfiguration().isWriteHeader()) { writeReportHeader(); } writeCurrentRow(currentRow, repeatedValues); currentRow = new HashMap<String, Object>(); addCell(textElement, textStr, baseStyle, currentRow, currentColumnName, hasCurrentColumnData); } // set auto fill columns if (repeatValue) { if (currentColumnName != null && currentColumnName.length() > 0 && textStr.length() > 0) { addCell(textElement, textStr, baseStyle, repeatedValues, currentColumnName, hasCurrentColumnData); } } else { repeatedValues.remove(currentColumnName); } } } protected void addBlankElement(WritableCellFormat baseCellFormat, boolean repeatValue, String currentColumnName) throws JRException { if (columnNames.size() > 0) { if (columnNames.contains(currentColumnName) && !currentRow.containsKey(currentColumnName) && isColumnReadOnTime(currentRow, currentColumnName)) // the column is for export but was not read yet and comes in the expected order { addBlankCell(baseCellFormat, currentRow, currentColumnName); } else if ((columnNames.contains(currentColumnName) && !currentRow.containsKey(currentColumnName) && !isColumnReadOnTime(currentRow, currentColumnName)) // the column is for export, was not read yet, but it is read after it should be || (columnNames.contains(currentColumnName) && currentRow.containsKey(currentColumnName))) // the column is for export and was already read { if (rowIndex == 1 && getCurrentItemConfiguration().isWriteHeader()) { writeReportHeader(); } writeCurrentRow(currentRow, repeatedValues); currentRow = new HashMap<String, Object>(); addBlankCell(baseCellFormat, currentRow, currentColumnName); } // set auto fill columns if (repeatValue) { if (repeatValue && currentColumnName != null && currentColumnName.length() > 0 && baseCellFormat != null) { addBlankCell(baseCellFormat, repeatedValues, currentColumnName); } } else { repeatedValues.remove(currentColumnName); } } } protected void addCell(JRPrintText text, String textStr, StyleInfo baseStyle, Map<String, Object> cellValueMap, String currentColumnName, boolean hasCurrentColumnData) throws JRException { CellValue cellValue = null; TextValue textValue = null; int colIndex = columnNamesMap.get(currentColumnName); String textFormula = hasCurrentColumnData ? null : getFormula(text); if (text != null && textFormula != null) { // if the cell has formula, we try create a formula cell textValue = getTextValue(text, textStr); cellValue = getFormulaCellValue(colIndex, rowIndex, text, textValue, textFormula, baseStyle, isComplexFormat(text)); } if (cellValue == null) { JxlReportConfiguration configuration = getCurrentItemConfiguration(); // there was no formula, or the formula cell creation failed if (configuration.isDetectCellType()) { if (textFormula == null) { // there was no formula, so textValue was not created textValue = getTextValue(text, textStr, hasCurrentColumnData); } cellValue = getDetectedCellValue(colIndex, rowIndex, text, textValue, baseStyle, isComplexFormat(text)); } else { cellValue = getLabelCell(colIndex, rowIndex, textStr, baseStyle); } } cellValueMap.put(currentColumnName, cellValue); } protected CellValue getFormulaCellValue(int x, int y, JRPrintText textElement, TextValue textValue, String formula, StyleInfo baseStyle, boolean complexFormat) throws JRException { FormulaTextValueHandler handler = new FormulaTextValueHandler(x, y, textElement, formula, baseStyle, complexFormat); textValue.handle(handler); return handler.getResult(); } protected CellValue getDetectedCellValue(int x, int y, JRPrintText textElement, TextValue textValue, StyleInfo baseStyle, boolean complexFormat) throws JRException { CellTextValueHandler handler = new CellTextValueHandler(x, y, textElement, baseStyle, complexFormat); textValue.handle(handler); return handler.getResult(); } protected class FormulaTextValueHandler implements TextValueHandler { private final int x; private final int y; private final JRPrintText textElement; private final String formula; private final StyleInfo baseStyle; private final boolean cellComplexFormat; private CellValue result; public FormulaTextValueHandler(int x, int y, JRPrintText textElement, String formula, StyleInfo baseStyle, boolean cellComplexFormat) { this.x = x; this.y = y; this.textElement = textElement; this.formula = formula; this.baseStyle = baseStyle; this.cellComplexFormat = cellComplexFormat; } public void handle(StringTextValue textValue) throws JRException { result = formula(); } public void handle(NumberTextValue textValue) throws JRException { String convertedPattern = getConvertedPattern(textElement, textValue.getPattern()); if (convertedPattern != null) { baseStyle.setDisplayFormat(getNumberFormat(convertedPattern, cellComplexFormat)); } result = formula(); } public void handle(DateTextValue textValue) throws JRException { baseStyle.setDisplayFormat(getDateFormat(getConvertedPattern(textElement, textValue.getPattern()))); result = formula(); } public void handle(BooleanTextValue textValue) throws JRException { result = formula(); } protected Formula formula() throws JRException { try { return new Formula(x, y, formula, getLoadedCellStyle(baseStyle)); } catch (Exception e)//FIXMENOW what exceptions could we get here? { if (log.isWarnEnabled()) { log.warn(e.getMessage(), e); } } return null; } public CellValue getResult() { return result; } } protected class CellTextValueHandler implements TextValueHandler { private final int x; private final int y; private final JRPrintText textElement; private final StyleInfo baseStyle; private final boolean cellComplexFormat; private CellValue result; public CellTextValueHandler(int x, int y, JRPrintText textElement, StyleInfo baseStyle, boolean cellComplexFormat) { this.x = x; this.y = y; this.textElement = textElement; this.baseStyle = baseStyle; this.cellComplexFormat = cellComplexFormat; } public void handle(StringTextValue textValue) throws JRException { WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle); result = new Label(x, y, textValue.getText(), cellStyle); } public void handle(NumberTextValue textValue) throws JRException { String convertedPattern = getConvertedPattern(textElement, textValue.getPattern()); if (convertedPattern != null) { baseStyle.setDisplayFormat(getNumberFormat(convertedPattern, cellComplexFormat)); } WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle); if (textValue.getValue() == null) { result = blank(cellStyle); } else { result = new Number(x, y, textValue.getValue().doubleValue(), cellStyle); } } public void handle(DateTextValue textValue) throws JRException { baseStyle.setDisplayFormat(getDateFormat(getConvertedPattern(textElement, textValue.getPattern()))); WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle); Date date = textValue.getValue(); if (date == null) { result = blank(cellStyle); } else { date = translateDateValue(textElement, date); result = new DateTime(x, y, date, cellStyle); } } public void handle(BooleanTextValue textValue) throws JRException { WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle); if (textValue.getValue() == null) { result = blank(cellStyle); } else { result = new jxl.write.Boolean(x, y, textValue.getValue().booleanValue(), cellStyle); } } protected Blank blank(WritableCellFormat cellStyle) { return new Blank(x, y, cellStyle); } public CellValue getResult() { return result; } public boolean isCellComplexFormat() { return cellComplexFormat; } } protected NumberFormat getNumberFormat(String convertedPattern, boolean isComplexFormat) { NumberFormat cellFormat = numberFormats.get(convertedPattern); if (cellFormat == null) { if (isComplexFormat) { cellFormat = new NumberFormat(convertedPattern, NumberFormat.COMPLEX_FORMAT); } else { cellFormat = new NumberFormat(convertedPattern); } numberFormats.put(convertedPattern, cellFormat); } return cellFormat; } protected DateFormat getDateFormat(String convertedPattern) { DateFormat cellFormat = dateFormats.get(convertedPattern); if (cellFormat == null) { cellFormat = new DateFormat(convertedPattern); dateFormats.put(convertedPattern, cellFormat); } return cellFormat; } protected CellValue getLabelCell(int x, int y, String textStr, StyleInfo baseStyle) throws JRException { WritableCellFormat cellStyle = null; if (baseStyle != null) { cellStyle = getLoadedCellStyle(baseStyle); } else { cellStyle = new WritableCellFormat(); } return new Label(x, y, textStr, cellStyle); } private int getHorizontalAlignment(TextAlignHolder alignment) { switch (alignment.horizontalAlignment) { case RIGHT: return Alignment.RIGHT.getValue(); case CENTER: return Alignment.CENTRE.getValue(); case JUSTIFIED: return Alignment.JUSTIFY.getValue(); case LEFT: default: return Alignment.LEFT.getValue(); } } private int getVerticalAlignment(TextAlignHolder alignment) { switch (alignment.verticalAlignment) { case BOTTOM: return VerticalAlignment.BOTTOM.getValue(); case MIDDLE: return VerticalAlignment.CENTRE.getValue(); case JUSTIFIED: return VerticalAlignment.JUSTIFY.getValue(); case TOP: default: return VerticalAlignment.TOP.getValue(); } } private int getRotation(TextAlignHolder alignment) { switch (alignment.rotation) { case LEFT: return Orientation.PLUS_90.getValue(); case RIGHT: return Orientation.MINUS_90.getValue(); case UPSIDE_DOWN: case NONE: default: return Orientation.HORIZONTAL.getValue(); } } public void exportImage(JRPrintImage element) throws JRException { String currentColumnName = element.getPropertiesMap() .getProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_COLUMN_NAME); if (currentColumnName != null && currentColumnName.length() > 0) { boolean repeatValue = getPropertiesUtil().getBooleanProperty(element, JRXlsAbstractMetadataExporterParameter.PROPERTY_REPEAT_VALUE, false); setColumnName(currentColumnName); setColumnWidth(columnNamesMap.get(currentColumnName), element.getWidth()); setRowHeight(rowIndex, element.getHeight()); int topPadding = Math.max(element.getLineBox().getTopPadding().intValue(), getImageBorderCorrection(element.getLineBox().getTopPen())); int leftPadding = Math.max(element.getLineBox().getLeftPadding().intValue(), getImageBorderCorrection(element.getLineBox().getLeftPen())); int bottomPadding = Math.max(element.getLineBox().getBottomPadding().intValue(), getImageBorderCorrection(element.getLineBox().getBottomPen())); int rightPadding = Math.max(element.getLineBox().getRightPadding().intValue(), getImageBorderCorrection(element.getLineBox().getRightPen())); int availableImageWidth = element.getWidth() - leftPadding - rightPadding; availableImageWidth = availableImageWidth < 0 ? 0 : availableImageWidth; int availableImageHeight = element.getHeight() - topPadding - bottomPadding; availableImageHeight = availableImageHeight < 0 ? 0 : availableImageHeight; Renderable renderer = element.getRenderable(); if (renderer != null && availableImageWidth > 0 && availableImageHeight > 0) { if (renderer.getTypeValue() == RenderableTypeEnum.IMAGE) { // Image renderers are all asked for their image data and dimension at some point. // Better to test and replace the renderer now, in case of lazy load error. renderer = RenderableUtil.getInstance(jasperReportsContext) .getOnErrorRendererForImageData(renderer, element.getOnErrorTypeValue()); if (renderer != null) { renderer = RenderableUtil.getInstance(jasperReportsContext) .getOnErrorRendererForDimension(renderer, element.getOnErrorTypeValue()); } } else { renderer = new JRWrappingSvgRenderer(renderer, new Dimension(element.getWidth(), element.getHeight()), ModeEnum.OPAQUE == element.getModeValue() ? element.getBackcolor() : null); } } else { renderer = null; } if (renderer != null) { int normalWidth = availableImageWidth; int normalHeight = availableImageHeight; Dimension2D dimension = renderer.getDimension(jasperReportsContext); if (dimension != null) { normalWidth = (int) dimension.getWidth(); normalHeight = (int) dimension.getHeight(); } float xalignFactor = 0f; switch (element.getHorizontalAlignmentValue()) { case RIGHT: { xalignFactor = 1f; break; } case CENTER: { xalignFactor = 0.5f; break; } case LEFT: default: { xalignFactor = 0f; break; } } float yalignFactor = 0f; switch (element.getVerticalAlignmentValue()) { case BOTTOM: { yalignFactor = 1f; break; } case MIDDLE: { yalignFactor = 0.5f; break; } case TOP: default: { yalignFactor = 0f; break; } } byte[] imageData = null; switch (element.getScaleImageValue()) { case CLIP: { int dpi = getPropertiesUtil().getIntegerProperty(Renderable.PROPERTY_IMAGE_DPI, 72); double scale = dpi / 72d; BufferedImage bi = new BufferedImage((int) (scale * availableImageWidth), (int) (scale * availableImageHeight), BufferedImage.TYPE_INT_ARGB); Graphics2D grx = bi.createGraphics(); grx.scale(scale, scale); grx.clip(new Rectangle(0, 0, availableImageWidth, availableImageHeight)); renderer.render(jasperReportsContext, grx, new Rectangle((int) (xalignFactor * (availableImageWidth - normalWidth)), (int) (yalignFactor * (availableImageHeight - normalHeight)), normalWidth, normalHeight)); imageData = JRImageLoader.getInstance(jasperReportsContext).loadBytesFromAwtImage(bi, ImageTypeEnum.PNG); break; } case FILL_FRAME: { imageData = renderer.getImageData(jasperReportsContext); break; } case RETAIN_SHAPE: default: { if (element.getHeight() > 0) { double ratio = (double) normalWidth / (double) normalHeight; if (ratio > (double) availableImageWidth / (double) availableImageHeight) { normalWidth = availableImageWidth; normalHeight = (int) (availableImageWidth / ratio); } else { normalWidth = (int) (availableImageHeight * ratio); normalHeight = availableImageHeight; } imageData = renderer.getImageData(jasperReportsContext); } break; } } Pattern mode = this.backgroundMode; Colour background = WHITE; JxlReportConfiguration configuration = getCurrentItemConfiguration(); if (!configuration.isIgnoreCellBackground() && element.getBackcolor() != null) { mode = Pattern.SOLID; background = getWorkbookColour(element.getBackcolor(), true); } if (element.getModeValue() == ModeEnum.OPAQUE) { background = getWorkbookColour(element.getBackcolor(), true); } Colour forecolor = getWorkbookColour(element.getLineBox().getPen().getLineColor()); WritableFont cellFont2 = this.getLoadedFont(getDefaultFont(), forecolor.getValue(), getLocale()); WritableCellFormat cellStyle2 = getLoadedCellStyle(mode, background, cellFont2, new BoxStyle(element), isCellLocked(element)); addBlankElement(cellStyle2, repeatValue, currentColumnName); try { int colIndex = columnNamesMap.get(currentColumnName); WritableImage image = new WritableImage(colIndex, rowIndex, 1, 1, imageData); ImageAnchorTypeEnum imageAnchorType = ImageAnchorTypeEnum.getByName(JRPropertiesUtil .getOwnProperty(element, XlsReportConfiguration.PROPERTY_IMAGE_ANCHOR_TYPE)); if (imageAnchorType == null) { imageAnchorType = configuration.getImageAnchorType(); if (imageAnchorType == null) { imageAnchorType = ImageAnchorTypeEnum.MOVE_NO_SIZE; } } setAnchorType(image, imageAnchorType); sheet.addImage(image); } catch (Exception ex) { throw new JRException("The cell cannot be added", ex); } catch (Error err) { throw new JRException("The cell cannot be added", err); } } } } protected Colour getWorkbookColour(Color awtColor, boolean isBackcolor) { if (isBackcolor && awtColor.getRGB() == Color.black.getRGB()) { return Colour.PALETTE_BLACK; } return getWorkbookColour(awtColor); } protected Colour getWorkbookColour(Color awtColor) { JxlExporterConfiguration configuration = getCurrentConfiguration(); Colour colour; if (configuration.isCreateCustomPalette()) { colour = workbookColours.get(awtColor); if (colour == null) { colour = determineWorkbookColour(awtColor); workbookColours.put(awtColor, colour); } } else { colour = getNearestColour(awtColor); } return colour; } protected Colour determineWorkbookColour(Color awtColor) { //nearest match int minDist = 999; Colour minColour = null; //nearest match among the available (not used) colours int minDistAvailable = 999; Colour minColourAvailable = null; Colour[] colors = Colour.getAllColours(); for (int i = 0; i < colors.length; i++) { Colour colour = colors[i]; RGB customRGB = usedColours.get(colour); RGB rgb = customRGB == null ? colour.getDefaultRGB() : customRGB; int dist = rgbDistance(awtColor, rgb); if (dist < minDist) { minDist = dist; minColour = colour; } if (dist == 0)//exact match { break; } if (customRGB == null)//the colour is not used { if (dist < minDistAvailable) { minDistAvailable = dist; minColourAvailable = colour; } } } Colour workbookColour; if (minDist == 0)//exact match found { if (!usedColours.containsKey(minColour)) { //if the colour is not marked as used, mark it setColourUsed(minColour); } workbookColour = minColour; } else if (minColourAvailable == null)//all the colours are used { if (log.isWarnEnabled()) { log.warn("No more available colours in the palette. Using the nearest match for " + awtColor); } workbookColour = minColour; } else { //modifying the nearest available colour to the report colour setColourUsed(minColourAvailable, awtColor); workbookColour = minColourAvailable; } return workbookColour; } protected static Colour getNearestColour(Color awtColor) { Colour color = colorsCache.get(awtColor); if (color == null) { Colour[] colors = Colour.getAllColours(); if ((colors != null) && (colors.length > 0)) { int minDiff = 999; for (int i = 0; i < colors.length; i++) { Colour crtColor = colors[i]; int diff = rgbDistance(awtColor, crtColor.getDefaultRGB()); if (diff < minDiff) { minDiff = diff; color = crtColor; } } } colorsCache.put(awtColor, color); } return color; } protected static int rgbDistance(Color awtColor, RGB rgb) { return Math.abs(rgb.getRed() - awtColor.getRed()) + Math.abs(rgb.getGreen() - awtColor.getGreen()) + Math.abs(rgb.getBlue() - awtColor.getBlue()); } private WritableFont getLoadedFont(JRFont font, int forecolor, Locale locale) throws JRException { boolean isFontSizeFixEnabled = getCurrentItemConfiguration().isFontSizeFixEnabled(); WritableFont cellFont = null; if (this.loadedFonts != null && this.loadedFonts.size() > 0) { for (int i = 0; i < this.loadedFonts.size(); i++) { WritableFont cf = (WritableFont) this.loadedFonts.get(i); int fontSize = (int) font.getFontsize(); if (isFontSizeFixEnabled) { fontSize -= 1; } String fontName = font.getFontName(); FontInfo fontInfo = FontUtil.getInstance(jasperReportsContext).getFontInfo(fontName, locale); if (fontInfo != null) { //fontName found in font extensions FontFamily family = fontInfo.getFontFamily(); String exportFont = family.getExportFont(getExporterKey()); if (exportFont != null) { fontName = exportFont; } } if ((cf.getName().equals(fontName)) && (cf.getColour().getValue() == forecolor) && (cf.getPointSize() == fontSize) && (cf.getUnderlineStyle() == UnderlineStyle.SINGLE ? (font.isUnderline()) : (!font.isUnderline())) && (cf.isStruckout() == font.isStrikeThrough()) && (cf.getBoldWeight() == BoldStyle.BOLD.getValue() ? (font.isBold()) : (!font.isBold())) && (cf.isItalic() == font.isItalic())) { cellFont = cf; break; } } } try { if (cellFont == null) { int fontSize = (int) font.getFontsize(); if (isFontSizeFixEnabled) { fontSize -= 1; } String fontName = font.getFontName(); cellFont = new WritableFont(WritableFont.createFont(fontName), fontSize, font.isBold() ? WritableFont.BOLD : WritableFont.NO_BOLD, font.isItalic(), font.isUnderline() ? UnderlineStyle.SINGLE : UnderlineStyle.NO_UNDERLINE, Colour.getInternalColour(forecolor)); cellFont.setStruckout(font.isStrikeThrough()); this.loadedFonts.add(cellFont); } } catch (Exception e) { throw new JRException("Can't get loaded fonts.", e); } return cellFont; } protected 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 BorderLineStyle[] borderStyle = new BorderLineStyle[] { BorderLineStyle.NONE, BorderLineStyle.NONE, BorderLineStyle.NONE, BorderLineStyle.NONE }; protected Colour[] borderColour = new Colour[] { BLACK, BLACK, BLACK, BLACK }; private int hash; public BoxStyle(int side, JRPen pen) { borderStyle[side] = getBorderLineStyle(pen); borderColour[side] = getWorkbookColour(pen.getLineColor()); hash = computeHash(); } public BoxStyle(JRBoxContainer element) { JRLineBox lineBox = element.getLineBox(); if (lineBox != null) { setBox(lineBox); } if (element instanceof JRCommonGraphicElement) { setPen(((JRCommonGraphicElement) element).getLinePen()); } hash = computeHash(); } public void setBox(JRLineBox box) { borderStyle[TOP] = getBorderLineStyle(box.getTopPen()); borderColour[TOP] = getWorkbookColour(box.getTopPen().getLineColor()); borderStyle[BOTTOM] = getBorderLineStyle(box.getBottomPen()); borderColour[BOTTOM] = getWorkbookColour(box.getBottomPen().getLineColor()); borderStyle[LEFT] = getBorderLineStyle(box.getLeftPen()); borderColour[LEFT] = getWorkbookColour(box.getLeftPen().getLineColor()); borderStyle[RIGHT] = getBorderLineStyle(box.getRightPen()); borderColour[RIGHT] = getWorkbookColour(box.getRightPen().getLineColor()); hash = computeHash(); } public void setPen(JRPen pen) { if (borderStyle[TOP] == BorderLineStyle.NONE && borderStyle[LEFT] == BorderLineStyle.NONE && borderStyle[BOTTOM] == BorderLineStyle.NONE && borderStyle[RIGHT] == BorderLineStyle.NONE) { BorderLineStyle style = getBorderLineStyle(pen); Colour colour = getWorkbookColour(pen.getLineColor()); borderStyle[TOP] = style; borderStyle[LEFT] = style; borderStyle[BOTTOM] = style; borderStyle[RIGHT] = style; borderColour[TOP] = colour; borderColour[LEFT] = colour; borderColour[BOTTOM] = colour; borderColour[RIGHT] = colour; } hash = computeHash(); } private int computeHash() { int hashCode = borderStyle[TOP].hashCode(); hashCode = 31 * hashCode + borderColour[TOP].hashCode(); hashCode = 31 * hashCode + borderStyle[BOTTOM].hashCode(); hashCode = 31 * hashCode + borderColour[BOTTOM].hashCode(); hashCode = 31 * hashCode + borderStyle[LEFT].hashCode(); hashCode = 31 * hashCode + borderColour[LEFT].hashCode(); hashCode = 31 * hashCode + borderStyle[RIGHT].hashCode(); hashCode = 31 * hashCode + borderColour[RIGHT].hashCode(); return hashCode; } public int hashCode() { return hash; } public boolean equals(Object o) { BoxStyle b = (BoxStyle) o; return b.borderStyle[TOP].equals(borderStyle[TOP]) && b.borderColour[TOP].equals(borderColour[TOP]) && b.borderStyle[LEFT].equals(borderStyle[LEFT]) && b.borderColour[LEFT].equals(borderColour[LEFT]) && b.borderStyle[BOTTOM].equals(borderStyle[BOTTOM]) && b.borderColour[BOTTOM].equals(borderColour[BOTTOM]) && b.borderStyle[RIGHT].equals(borderStyle[RIGHT]) && b.borderColour[RIGHT].equals(borderColour[RIGHT]); } public String toString() { return "(" + borderStyle[TOP].getValue() + "/" + borderColour[TOP].getValue() + "," + borderStyle[BOTTOM].getValue() + "/" + borderColour[BOTTOM].getValue() + "," + borderStyle[LEFT].getValue() + "/" + borderColour[LEFT].getValue() + "," + borderStyle[RIGHT].getValue() + "/" + borderColour[RIGHT].getValue() + ")"; } } protected class StyleInfo { protected final Pattern mode; protected final Colour backcolor; protected final int horizontalAlignment; protected final int verticalAlignment; protected final int rotation; protected final WritableFont font; protected final BoxStyle box; protected final boolean isWrapText; protected final boolean isCellLocked; private DisplayFormat displayFormat; private int hashCode; protected StyleInfo(Pattern mode, Colour backcolor, int horizontalAlignment, int verticalAlignment, int rotation, WritableFont font, JRBoxContainer element) { this(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, font, new BoxStyle(element), true); } protected StyleInfo(Pattern mode, Colour backcolor, int horizontalAlignment, int verticalAlignment, int rotation, WritableFont font, JRBoxContainer element, boolean wrapText) { this(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, font, new BoxStyle(element), wrapText); } protected StyleInfo(Pattern mode, Colour backcolor, int horizontalAlignment, int verticalAlignment, int rotation, WritableFont font, JRBoxContainer element, boolean wrapText, boolean cellLocked) { this(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, font, new BoxStyle(element), wrapText, cellLocked); } protected StyleInfo(Pattern mode, Colour backcolor, int horizontalAlignment, int verticalAlignment, int rotation, WritableFont font, BoxStyle box) { this(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, font, box, true); } protected StyleInfo(Pattern mode, Colour backcolor, int horizontalAlignment, int verticalAlignment, int rotation, WritableFont font, BoxStyle box, boolean wrapText) { this(mode, backcolor, horizontalAlignment, verticalAlignment, rotation, font, box, wrapText, true); } protected StyleInfo(Pattern mode, Colour backcolor, int horizontalAlignment, int verticalAlignment, int rotation, WritableFont font, BoxStyle box, boolean wrapText, boolean cellLocked) { this.mode = mode; this.backcolor = backcolor; this.horizontalAlignment = horizontalAlignment; this.verticalAlignment = verticalAlignment; this.rotation = rotation; this.font = font; this.box = box; this.isWrapText = wrapText; this.isCellLocked = cellLocked; computeHash(); } protected void computeHash() { int hash = this.mode.hashCode(); hash = 31 * hash + this.backcolor.hashCode(); hash = 31 * hash + this.horizontalAlignment; hash = 31 * hash + this.verticalAlignment; hash = 31 * hash + this.rotation; hash = 31 * hash + this.font.hashCode(); hash = 31 * hash + (this.box == null ? 0 : this.box.hashCode()); hash = 31 * hash + (this.displayFormat == null ? 0 : this.displayFormat.hashCode()); hash = 31 * hash + (this.isWrapText ? 0 : 1); hash = 31 * hash + (this.isCellLocked ? 0 : 1); hashCode = hash; } public int hashCode() { return hashCode; } public boolean equals(Object o) { StyleInfo k = (StyleInfo) o; return k.mode.equals(mode) && k.backcolor.equals(backcolor) && k.horizontalAlignment == horizontalAlignment && k.verticalAlignment == verticalAlignment && k.rotation == rotation && k.font.equals(font) && (k.box == null ? box == null : (box != null && k.box.equals(box))) && (k.displayFormat == null ? displayFormat == null : (displayFormat != null && k.displayFormat.equals(displayFormat)) && k.isWrapText == isWrapText && k.isCellLocked == isCellLocked); } public DisplayFormat getDisplayFormat() { return displayFormat; } public void setDisplayFormat(DisplayFormat displayFormat) { this.displayFormat = displayFormat; computeHash(); } public String toString() { return "(" + mode + "," + backcolor + "," + horizontalAlignment + "," + verticalAlignment + "," + rotation + "," + font + "," + box + "," + displayFormat + "," + isWrapText + "," + isCellLocked + ")"; } } private WritableCellFormat getLoadedCellStyle(Pattern mode, Colour backcolor, WritableFont font, BoxStyle box, boolean cellLocked) throws JRException { StyleInfo styleKey = new StyleInfo(mode, backcolor, Alignment.LEFT.getValue(), VerticalAlignment.TOP.getValue(), Orientation.HORIZONTAL.getValue(), font, box, true, cellLocked); return getLoadedCellStyle(styleKey); } protected WritableCellFormat getLoadedCellStyle(StyleInfo styleKey) throws JRException { WritableCellFormat cellStyle = loadedCellStyles.get(styleKey); if (cellStyle == null) { try { if (styleKey.getDisplayFormat() == null) { cellStyle = new WritableCellFormat(styleKey.font); } else { cellStyle = new WritableCellFormat(styleKey.font, styleKey.getDisplayFormat()); } cellStyle.setBackground(styleKey.backcolor, styleKey.mode); cellStyle.setAlignment(Alignment.getAlignment(styleKey.horizontalAlignment)); cellStyle.setVerticalAlignment(VerticalAlignment.getAlignment(styleKey.verticalAlignment)); cellStyle.setOrientation(Orientation.getOrientation(styleKey.rotation)); cellStyle.setWrap(styleKey.isWrapText); cellStyle.setLocked(styleKey.isCellLocked); JxlReportConfiguration configuration = getCurrentItemConfiguration(); if (!configuration.isIgnoreCellBorder()) { BoxStyle box = styleKey.box; cellStyle.setBorder(Border.TOP, box.borderStyle[BoxStyle.TOP], box.borderColour[BoxStyle.TOP]); cellStyle.setBorder(Border.BOTTOM, box.borderStyle[BoxStyle.BOTTOM], box.borderColour[BoxStyle.BOTTOM]); cellStyle.setBorder(Border.LEFT, box.borderStyle[BoxStyle.LEFT], box.borderColour[BoxStyle.LEFT]); cellStyle.setBorder(Border.RIGHT, box.borderStyle[BoxStyle.RIGHT], box.borderColour[BoxStyle.RIGHT]); } } catch (Exception e) { throw new JRException("Error setting cellFormat-template.", e); } loadedCellStyles.put(styleKey, cellStyle); } return cellStyle; } /** * */ protected static BorderLineStyle getBorderLineStyle(JRPen pen) { float lineWidth = pen.getLineWidth().floatValue(); if (lineWidth > 0f) { switch (pen.getLineStyleValue()) { case DOUBLE: { return BorderLineStyle.DOUBLE; } case DOTTED: { return BorderLineStyle.DOTTED; } case DASHED: { if (lineWidth >= 1f) { return BorderLineStyle.MEDIUM_DASHED; } return BorderLineStyle.DASHED; } case SOLID: default: { if (lineWidth >= 2f) { return BorderLineStyle.THICK; } else if (lineWidth >= 1f) { return BorderLineStyle.MEDIUM; } else if (lineWidth >= 0.5f) { return BorderLineStyle.THIN; } return BorderLineStyle.HAIR; } } } return BorderLineStyle.NONE; } private final void setSheetSettings(SheetInfo sheetInfo, WritableSheet sheet) { rowIndex = 0; PageOrientation po; PaperSize ps; if (pageFormat.getOrientation() == OrientationEnum.PORTRAIT) { po = PageOrientation.PORTRAIT; } else { po = PageOrientation.LANDSCAPE; } if ((ps = getSuitablePaperSize()) != null) { sheet.setPageSetup(po, ps, 0, 0); } else { sheet.setPageSetup(po); } SheetSettings sheets = sheet.getSettings(); JxlReportConfiguration configuration = getCurrentItemConfiguration(); boolean isIgnorePageMargins = configuration.isIgnorePageMargins(); if (pageFormat.getTopMargin() != null) { sheets.setTopMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : pageFormat.getTopMargin())); } if (pageFormat.getLeftMargin() != null) { sheets.setLeftMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : pageFormat.getLeftMargin())); } if (pageFormat.getRightMargin() != null) { sheets.setRightMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : pageFormat.getRightMargin())); } if (pageFormat.getBottomMargin() != null) { sheets.setBottomMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : pageFormat.getBottomMargin())); } sheets.setHeaderMargin(0.0); sheets.setFooterMargin(0.0); Integer fitWidth = configuration.getFitWidth(); Integer fitHeight = configuration.getFitHeight(); if (fitWidth != null || fitWidth != null) { sheets.setFitWidth(fitWidth == null ? 1 : fitWidth); sheets.setFitHeight(fitHeight == null ? 1 : fitHeight); sheets.setFitToPages(true); } String password = configuration.getPassword(); if (password != null) { sheets.setPassword(password); sheets.setProtected(true); } String sheetHeaderLeft = configuration.getSheetHeaderLeft(); if (sheetHeaderLeft != null) { sheets.getHeader().getLeft().append(sheetHeaderLeft); } String sheetHeaderCenter = configuration.getSheetHeaderCenter(); if (sheetHeaderCenter != null) { sheets.getHeader().getCentre().append(sheetHeaderCenter); } String sheetHeaderRight = configuration.getSheetHeaderRight(); if (sheetHeaderRight != null) { sheets.getHeader().getRight().append(sheetHeaderRight); } String sheetFooterLeft = configuration.getSheetFooterLeft(); if (sheetFooterLeft != null) { sheets.getFooter().getLeft().append(sheetFooterLeft); } String sheetFooterCenter = configuration.getSheetFooterCenter(); if (sheetFooterCenter != null) { sheets.getFooter().getCentre().append(sheetFooterCenter); } String sheetFooterRight = configuration.getSheetFooterRight(); if (sheetFooterRight != null) { sheets.getFooter().getRight().append(sheetFooterRight); } if (sheetInfo.sheetFirstPageNumber != null && sheetInfo.sheetFirstPageNumber > 0) { sheets.setPageStart(sheetInfo.sheetFirstPageNumber); firstPageNotSet = false; } else { Integer documentFirstPageNumber = configuration.getFirstPageNumber(); if (documentFirstPageNumber != null && documentFirstPageNumber > 0 && firstPageNotSet) { sheets.setPageStart(documentFirstPageNumber); firstPageNotSet = false; } } if (!firstPageNotSet && sheets.getFooter().getCentre().empty()) { sheets.getFooter().getCentre().append("Page "); sheets.getFooter().getCentre().appendPageNumber(); } boolean showGridlines = true; if (sheetInfo.sheetShowGridlines == null) { Boolean documentShowGridlines = configuration.isShowGridLines(); if (documentShowGridlines != null) { showGridlines = documentShowGridlines; } } else { showGridlines = sheetInfo.sheetShowGridlines; } sheets.setShowGridLines(showGridlines); maxRowFreezeIndex = 0; maxColumnFreezeIndex = 0; } private final PaperSize getSuitablePaperSize() { if (pageFormat == null) { return null; } long width = 0; long height = 0; PaperSize ps = null; if ((pageFormat.getPageWidth() != 0) && (pageFormat.getPageHeight() != 0)) { double dWidth = (pageFormat.getPageWidth() / 72.0); double dHeight = (pageFormat.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 JExcelApi yet. for (int i = 3; i < 6; i++) { int w = calculateWidthForDinAN(i); int h = calculateHeightForDinAN(i); if (((w == width) && (h == height)) || ((h == width) && (w == height))) { if (i == 3) { ps = PaperSize.A3; } else if (i == 4) { ps = PaperSize.A4; } else if (i == 5) { ps = PaperSize.A5; } break; } } // Compare to common North American Paper Sizes (ANSI X3.151-1987). if (ps == null) { // ANSI X3.151-1987 - "Letter" (216 279 mm) if (((width == 216) && (height == 279)) || ((width == 279) && (height == 216))) { ps = PaperSize.LETTER; } // ANSI X3.151-1987 - "Legal" (216 356 mm) if (((width == 216) && (height == 356)) || ((width == 356) && (height == 216))) { ps = PaperSize.LEGAL; } // ANSI X3.151-1987 - "Executive" (190 254 mm) // Not supperted by JExcelApi yet. // ANSI X3.151-1987 - "Ledger/Tabloid" (279 432 mm) // Not supperted by JExcelApi yet. } } return ps; } public static TextAlignHolder getTextAlignHolder(JRPrintText textElement) { HorizontalAlignEnum horizontalAlignment; VerticalAlignEnum verticalAlignment; RotationEnum rotation = textElement.getRotationValue(); switch (textElement.getRotationValue()) { case LEFT: { switch (textElement.getHorizontalAlignmentValue()) { case LEFT: { verticalAlignment = VerticalAlignEnum.BOTTOM; break; } case CENTER: { verticalAlignment = VerticalAlignEnum.MIDDLE; break; } case RIGHT: { verticalAlignment = VerticalAlignEnum.TOP; break; } case JUSTIFIED: { verticalAlignment = VerticalAlignEnum.JUSTIFIED; break; } default: { verticalAlignment = VerticalAlignEnum.BOTTOM; } } switch (textElement.getVerticalAlignmentValue()) { case TOP: { horizontalAlignment = HorizontalAlignEnum.LEFT; break; } case MIDDLE: { horizontalAlignment = HorizontalAlignEnum.CENTER; break; } case BOTTOM: { horizontalAlignment = HorizontalAlignEnum.RIGHT; break; } default: { horizontalAlignment = HorizontalAlignEnum.LEFT; } } break; } case RIGHT: { switch (textElement.getHorizontalAlignmentValue()) { case LEFT: { verticalAlignment = VerticalAlignEnum.TOP; break; } case CENTER: { verticalAlignment = VerticalAlignEnum.MIDDLE; break; } case RIGHT: { verticalAlignment = VerticalAlignEnum.BOTTOM; break; } case JUSTIFIED: { verticalAlignment = VerticalAlignEnum.JUSTIFIED; break; } default: { verticalAlignment = VerticalAlignEnum.TOP; } } switch (textElement.getVerticalAlignmentValue()) { case TOP: { horizontalAlignment = HorizontalAlignEnum.RIGHT; break; } case MIDDLE: { horizontalAlignment = HorizontalAlignEnum.CENTER; break; } case BOTTOM: { horizontalAlignment = HorizontalAlignEnum.LEFT; break; } default: { horizontalAlignment = HorizontalAlignEnum.RIGHT; } } break; } case UPSIDE_DOWN: case NONE: default: { horizontalAlignment = textElement.getHorizontalAlignmentValue(); verticalAlignment = textElement.getVerticalAlignmentValue(); } } return new TextAlignHolder(horizontalAlignment, verticalAlignment, rotation); } protected void exportFrame(JRPrintFrame frame) throws JRException { for (Object element : frame.getElements()) { if (element instanceof JRPrintLine) { exportLine((JRPrintLine) element); } else if (element instanceof JRPrintRectangle) { exportRectangle((JRPrintRectangle) element); } else if (element instanceof JRPrintEllipse) { exportRectangle((JRPrintEllipse) element); } else if (element instanceof JRPrintImage) { exportImage((JRPrintImage) element); } else if (element instanceof JRPrintText) { exportText((JRPrintText) element); } else if (element instanceof JRPrintFrame) { exportFrame((JRPrintFrame) element); } else if (element instanceof JRGenericPrintElement) { exportGenericElement((JRGenericPrintElement) element); } } } protected void exportGenericElement(JRGenericPrintElement element) throws JRException { String currentColumnName = element.getPropertiesMap() .getProperty(JRXlsAbstractMetadataExporterParameter.PROPERTY_COLUMN_NAME); if (currentColumnName != null && currentColumnName.length() > 0) { boolean repeatValue = getPropertiesUtil().getBooleanProperty(element, JRXlsAbstractMetadataExporterParameter.PROPERTY_REPEAT_VALUE, false); int colIndex = columnNamesMap.get(currentColumnName); setColumnName(currentColumnName); setColumnWidth(columnNamesMap.get(currentColumnName), element.getWidth()); setRowHeight(rowIndex, element.getHeight()); GenericElementJExcelApiMetadataHandler handler = (GenericElementJExcelApiMetadataHandler) GenericElementHandlerEnviroment .getInstance(getJasperReportsContext()) .getElementHandler(element.getGenericType(), JXL_EXPORTER_KEY); if (handler != null) { rowIndex = handler.exportElement(exporterContext, element, currentRow, repeatedValues, columnNames, columnNamesMap, currentColumnName, colIndex, rowIndex, repeatValue); } else { if (log.isDebugEnabled()) { log.debug("No XLS generic element handler for " + element.getGenericType()); } } } } protected ExporterNature getNature() { return nature; } public String getExporterKey() { return JXL_EXPORTER_KEY; } public String getExporterPropertiesPrefix() { return XLS_EXPORTER_PROPERTIES_PREFIX; } /** * */ protected boolean isComplexFormat(JRPrintElement element) { if (element.hasProperties() && element.getPropertiesMap().containsProperty(PROPERTY_COMPLEX_FORMAT)) { // we make this test to avoid reaching the global default value of the property directly // and thus skipping the report level one, if present return getPropertiesUtil().getBooleanProperty(element, PROPERTY_COMPLEX_FORMAT, getCurrentItemConfiguration().isComplexFormat()); } return getCurrentItemConfiguration().isComplexFormat(); } protected void setColumnName(String currentColumnName) { // when no columns are provided, build the column names list as they are retrieved from the report element property if (!hasDefinedColumns) { if (currentColumnName != null && currentColumnName.length() > 0 && !columnNames.contains(currentColumnName)) { columnNamesMap.put(currentColumnName, columnNames.size()); columnNames.add(currentColumnName); } } } /** * Writes the header column names */ protected void writeReportHeader() throws JRException { try { for (int i = 0; i < columnNames.size(); ++i) { CellValue cellValue = getLabelCell(i, 0, columnNames.get(i), null); sheet.addCell(cellValue); } } catch (RowsExceededException e) { throw new JRException("There are too many rows in the current sheet", e); } catch (WriteException e) { throw new JRException(e); } } /** * 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 * @param isRowEdge specifies if the freeze row index is set at element level * @param isColumnEdge specifies if the freeze column index is set at element level */ protected void setFreezePane(int rowIndex, int colIndex, boolean isRowEdge, boolean isColumnEdge) { int maxRowIndex = isFreezeRowEdge ? Math.max(rowIndex, maxRowFreezeIndex) : (isRowEdge ? rowIndex : Math.max(rowIndex, maxRowFreezeIndex)); int maxColIndex = isFreezeColumnEdge ? Math.max(colIndex, maxColumnFreezeIndex) : (isColumnEdge ? colIndex : Math.max(colIndex, maxColumnFreezeIndex)); SheetSettings settings = sheet.getSettings(); settings.setVerticalFreeze(maxRowIndex); settings.setHorizontalFreeze(maxColIndex); maxRowFreezeIndex = maxRowIndex; maxColumnFreezeIndex = maxColIndex; isFreezeRowEdge = isRowEdge; isFreezeColumnEdge = isColumnEdge; } protected void setSheetName(String sheetName) { sheet.setName(sheetName); } protected void setAutoFilter(String autoFilterRange) { // TODO support auto filter feature } @Override protected void setRowLevels(XlsRowLevelInfo levelInfo, String level) { // TODO set row levels } protected void setScale(Integer scale) { if (scale != null && scale > 9 && scale < 401) { SheetSettings sheetSettings = sheet.getSettings(); sheetSettings.setScaleFactor(scale); /* the scale factor takes precedence over fitWidth and fitHeight properties */ sheetSettings.setFitWidth(0); sheetSettings.setFitHeight(0); sheetSettings.setFitToPages(false); } } protected void setAnchorType(WritableImage image, ImageAnchorTypeEnum anchorType) { switch (anchorType) { case MOVE_SIZE: image.setImageAnchor(WritableImage.MOVE_AND_SIZE_WITH_CELLS); break; case NO_MOVE_NO_SIZE: image.setImageAnchor(WritableImage.NO_MOVE_OR_SIZE_WITH_CELLS); break; case MOVE_NO_SIZE: default: image.setImageAnchor(WritableImage.MOVE_WITH_CELLS); break; } } protected TextValue getTextValue(JRPrintText text, String textStr, boolean hasCurrentColumnData) { if (!hasCurrentColumnData) { return getTextValue(text, textStr); } TextValue textValue; String valueClassName = text.getValueClassName(); if (valueClassName == null) { textValue = getTextValueString(text, textStr); } else { try { Class<?> valueClass = textValueClasses.get(valueClassName); if (valueClass == null) { valueClass = JRClassLoader.loadClassForRealName(valueClassName); textValueClasses.put(valueClassName, valueClass); } if (java.lang.Number.class.isAssignableFrom(valueClass)) { textValue = new NumberTextValue(textStr, Double.parseDouble(textStr), text.getPattern()); } else if (Date.class.isAssignableFrom(valueClass)) { textValue = new DateTextValue(textStr, isoDateFormat.parse(textStr), text.getPattern()); } else if (Boolean.class.equals(valueClass)) { textValue = new BooleanTextValue(textStr, Boolean.valueOf(textStr)); } else { textValue = getTextValueString(text, textStr); } } catch (ParseException e) { //log.warn("Error parsing text value", e); textValue = getTextValueString(text, textStr); } catch (ClassNotFoundException e) { //log.warn("Error loading text value class", e); textValue = getTextValueString(text, textStr); } } return textValue; } }