Package net.sf.jasperreports.engine.export

Source Code of net.sf.jasperreports.engine.export.JExcelApiExporter

/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2009 Jaspersoft Corporation. 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.Shape;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import jxl.CellView;
import jxl.JXLException;
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.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.JRCommonGraphicElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRFont;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRImageRenderer;
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.JRPrintImage;
import net.sf.jasperreports.engine.JRPrintLine;
import net.sf.jasperreports.engine.JRPrintText;
import net.sf.jasperreports.engine.JRRenderable;
import net.sf.jasperreports.engine.JRWrappingSvgRenderer;
import net.sf.jasperreports.engine.JasperPrint;
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.fonts.FontFamily;
import net.sf.jasperreports.engine.fonts.FontInfo;
import net.sf.jasperreports.engine.type.HorizontalAlignEnum;
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.VerticalAlignEnum;
import net.sf.jasperreports.engine.util.JRFontUtil;
import net.sf.jasperreports.engine.util.JRImageLoader;
import net.sf.jasperreports.engine.util.JRProperties;
import net.sf.jasperreports.engine.util.JRStyledText;

import org.apache.commons.collections.ReferenceMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
* @author Manuel Paul (mpaul@ratundtat.com)
* @version $Id: JExcelApiExporter.java 4261 2011-03-24 13:35:37Z teodord $
*/
public class JExcelApiExporter extends JRXlsAbstractExporter
{

  private static final Log log = LogFactory.getLog(JExcelApiExporter.class);

  /**
   * Boolean property enabling the JExcelApiExporter to use temporary files when creating large documents.
   * <p/>
   * This property is by default not set (<code>false</code>).
   *
   * @see JRProperties
   */
  public static final String PROPERTY_USE_TEMP_FILE = JRProperties.PROPERTY_PREFIX + "export.jxl.use.temp.file";

  /**
   * Boolean property specifying whether the cell format pattern is user-defined.
   * When set to true, the exporter will assume that the specified pattern is well defined.
   * If the pattern is invalid, it won't be taken into account by the Excel file viewer.
   *
   * @see JRProperties
   */
  public static final String PROPERTY_COMPLEX_FORMAT = JRProperties.PROPERTY_PREFIX + "export.jxl.cell.complex.format";

  /**
   * The exporter key, as used in
   * {@link GenericElementHandlerEnviroment#getHandler(net.sf.jasperreports.engine.JRGenericElementType, String)}.
   */
  public static final String JXL_EXPORTER_KEY = JRProperties.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 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 loadedCellStyles = new HashMap();

  private WritableWorkbook workbook;

  private WritableSheet sheet;

  private Pattern backgroundMode = Pattern.SOLID;

  private Map numberFormats;
  private Map dateFormats;

  protected Map workbookColours = new HashMap();
  protected Map usedColours = new HashMap();
  protected String password;
 
  protected ExporterNature nature;
  protected boolean useTempFile;
  protected boolean complexFormat;
 
  protected class ExporterContext extends BaseExporterContext implements JExcelApiExporterContext
  {
    public String getExportPropertiesPrefix()
    {
      return XLS_EXPORTER_PROPERTIES_PREFIX;
    }
  }
 
  protected JExcelApiExporterContext exporterContext = new ExporterContext();
 

  public JExcelApiExporter()
  {
    numberFormats = new HashMap();
    dateFormats = new HashMap();
  }

  protected void setParameters()
  {
    super.setParameters();

    if (createCustomPalette)
    {
      initCustomPalette();
    }

    password =
      getStringParameter(
        JExcelApiExporterParameter.PASSWORD,
        JExcelApiExporterParameter.PROPERTY_PASSWORD
        );
   
    nature = new JExcelApiExporterNature(filter, isIgnoreGraphics, isIgnorePageMargins);
   
    useTempFile =
      JRProperties.getBooleanProperty(
        jasperPrint,
        PROPERTY_USE_TEMP_FILE,
        false
        );
   
    complexFormat =
      JRProperties.getBooleanProperty(
        jasperPrint,
        PROPERTY_COMPLEX_FORMAT,
        false
        );
  }

  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 setBackground()
  {
    if (isWhitePageBackground)
    {
      this.backgroundMode = Pattern.SOLID;
    }
    else
    {
      this.backgroundMode = Pattern.NONE;
    }
  }

  protected void openWorkbook(OutputStream os) throws JRException
  {
    try
    {
      WorkbookSettings settings = new WorkbookSettings();
      settings.setUseTemporaryFileDuringWrite(useTempFile);
      workbook = Workbook.createWorkbook(os, settings);
    }
    catch (IOException e)
    {
      throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e);
    }
  }

  protected void createSheet(String name)
  {
    sheet = workbook.createSheet(name, Integer.MAX_VALUE);
    setSheetSettings(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)
  {
    CellView cv = new CellView();
    cv.setSize(43 * width);
    sheet.setColumnView(col, cv);
  }

  protected void setRowHeight(int y, int lastRowHeight) throws JRException
  {
    try
    {
      sheet.setRowView(y, LengthUtil.twip(lastRowHeight));
    }
    catch (RowsExceededException e)
    {
      throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e);
    }
  }

  protected void setCell(JRExporterGridCell gridCell, int x, int y)
  {
  }

  protected void removeColumn(int col)
  {
    sheet.removeColumn(col);
  }

  protected void addBlankCell(JRExporterGridCell gridCell, int colIndex, int rowIndex) throws JRException
  {
    Colour forecolor = BLACK;
    if (gridCell.getForecolor() != null)
    {
      forecolor = getWorkbookColour(gridCell.getForecolor());
    }

    Pattern mode = backgroundMode;
    Colour backcolor = WHITE;
   
    if (!isIgnoreCellBackground && gridCell.getCellBackcolor() != null)
    {
      mode = Pattern.SOLID;
      backcolor = getWorkbookColour(gridCell.getCellBackcolor(), true);
    }

    WritableFont cellFont = getLoadedFont(getDefaultFont(), forecolor.getValue(), getLocale());
    WritableCellFormat cellStyle =
      getLoadedCellStyle(
        mode,
        backcolor,
        cellFont,
        gridCell
        );

    try
    {
      sheet.addCell(new Blank(colIndex, rowIndex, cellStyle));
    }
    catch (RowsExceededException e)
    {
      throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e);//FIXMENOW raise same exception everywhere
    }
    catch (WriteException e)
    {
      throw new JRException("Error generating XLS report : " + jasperPrint.getName(), e);
    }
  }
 
  protected void addOccupiedCell(OccupiedGridCell occupiedGridCell, int colIndex, int rowIndex) throws JRException
  {
  }

  protected void exportLine(JRPrintLine line, JRExporterGridCell gridCell, int col, int row) throws JRException
  {
    addMergeRegion(gridCell, col, row);

    Colour forecolor2 = getWorkbookColour(line.getLinePen().getLineColor());
    WritableFont cellFont2 = getLoadedFont(getDefaultFont(), forecolor2.getValue(), getLocale());
   
    Colour backcolor = WHITE;
    Pattern mode = this.backgroundMode;

    if (!isIgnoreCellBackground && gridCell.getCellBackcolor() != null)
    {
      mode = Pattern.SOLID;
      backcolor = getWorkbookColour(gridCell.getCellBackcolor(), 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)
        );
    Blank cell2 = new Blank(col, row, cellStyle2);

    try
    {
      sheet.addCell(cell2);
    }
    catch (Exception e)
    {
      throw new JRException("Can't add cell.", e);
    }
  }

  protected void exportRectangle(JRPrintGraphicElement element, JRExporterGridCell gridCell, int col, int row) throws JRException
  {
    addMergeRegion(gridCell, col, row);

    Colour backcolor = WHITE;
    Pattern mode = this.backgroundMode;

    if (!isIgnoreCellBackground && gridCell.getCellBackcolor() != null)
    {
      mode = Pattern.SOLID;
      backcolor = getWorkbookColour(gridCell.getCellBackcolor(), true);
    }

    Colour forecolor = getWorkbookColour(element.getLinePen().getLineColor());
    WritableFont cellFont2 = getLoadedFont(getDefaultFont(), forecolor.getValue(), getLocale());
    WritableCellFormat cellStyle2 =
      getLoadedCellStyle(
        mode,
        backcolor,
        cellFont2,
        gridCell,
        isCellLocked(element)
        );
   
    Blank cell2 = new Blank(col, row, cellStyle2);

    try
    {
      sheet.addCell(cell2);
    }
    catch (Exception e)
    {
      throw new JRException("Can't add cell.", e);
    }
  }

  public void exportText(JRPrintText text, JRExporterGridCell gridCell, int col, int row) throws JRException
  {
    addMergeRegion(gridCell, col, row);

    JRStyledText styledText = getStyledText(text);

    if (styledText != null)
    {
      Colour forecolor = getWorkbookColour(text.getForecolor());
      WritableFont cellFont = this.getLoadedFont(text, forecolor.getValue(), getTextLocale(text));

      TextAlignHolder alignment = getTextAlignHolder(text);
      int horizontalAlignment = getHorizontalAlignment(alignment);
      int verticalAlignment = getVerticalAlignment(alignment);
      int rotation = getRotation(alignment);

      Pattern mode = this.backgroundMode;
      Colour backcolor = WHITE;

      if (!isIgnoreCellBackground && gridCell.getCellBackcolor() != null)
      {
        mode = Pattern.SOLID;
        backcolor = getWorkbookColour(gridCell.getCellBackcolor(), true);
      }

      StyleInfo baseStyle =
        new StyleInfo(
          mode,
          backcolor,
          horizontalAlignment,
          verticalAlignment,
          rotation,
          cellFont,
          gridCell,
          isWrapText(text),
          isCellLocked(text)
          );

      String textStr = styledText.getText();

      String href = null;
      JRHyperlinkProducer customHandler = getCustomHandler(text);
      if (customHandler == null)
      {
        switch (text.getHyperlinkTypeValue())
        {
          case REFERENCE:
          {
            href = text.getHyperlinkReference();
            break;
          }
          case LOCAL_ANCHOR :
          case LOCAL_PAGE :
          case REMOTE_ANCHOR :
          case REMOTE_PAGE :
          case NONE:
          default:
          {
          }
        }
      }
      else
      {
        href = customHandler.getHyperlink(text);
      }

      try
      {
        if (href != null)
        {
          try
          {
            URL url = new URL(href);
            WritableHyperlink hyperlink = new WritableHyperlink(col, row, col, row, url);
            sheet.addHyperlink(hyperlink);
          }
          catch (MalformedURLException e)
          {
            if (log.isWarnEnabled())
            {
              log.warn("Reference \"" + href + "\" could not be parsed as URL.", e);
            }
          }
        }
       
        addCell(col, row, text, textStr, baseStyle);
      }
      catch (Exception e)
      {
        throw new JRException("Can't add cell.", e);
      }
    }
  }

  protected void addCell(int x, int y, JRPrintText text, String textStr, StyleInfo baseStyle) throws WriteException, RowsExceededException, JRException
  {
    CellValue cellValue = null;

    TextValue textValue = null;

    String textFormula = getFormula(text);
    if( textFormula != null)
    {
      // if the cell has formula, we try create a formula cell
      textValue = getTextValue(text, textStr);
      cellValue = getFormulaCellValue(x, y, textValue, textFormula, baseStyle, isComplexFormat(text));
    }
   
    if (cellValue == null)
    {
      // there was no formula, or the formula cell creation failed
      if (isDetectCellType)
      {
        if (textFormula == null)
        {
          // there was no formula, so textValue was not created
          textValue = getTextValue(text, textStr);
        }
        cellValue = getDetectedCellValue(x, y, textValue, baseStyle, isComplexFormat(text));
      }
      else if (isAutoDetectCellType)
      {
        cellValue = getAutoDetectedCellValue(x, y, textStr, baseStyle);
      }
      else
      {
        cellValue = getLabelCell(x, y, textStr, baseStyle);
      }
    }

    sheet.addCell(cellValue);
  }


  protected CellValue getFormulaCellValue(int x, int y, TextValue textValue, String formula, StyleInfo baseStyle, boolean complexFormat) throws JRException
  {
    FormulaTextValueHandler handler = new FormulaTextValueHandler(x, y, formula, baseStyle, complexFormat);
    textValue.handle(handler);
    return handler.getResult();
  }


  protected CellValue getDetectedCellValue(int x, int y, TextValue textValue, StyleInfo baseStyle, boolean complexFormat) throws JRException
  {
    CellTextValueHandler handler = new CellTextValueHandler(x, y, baseStyle, complexFormat);
    textValue.handle(handler);
    return handler.getResult();
  }


  protected class FormulaTextValueHandler implements TextValueHandler
  {
    private final int x;
    private final int y;
    private final String formula;
    private final StyleInfo baseStyle;
    private final boolean cellComplexFormat;
   
    private CellValue result;

//    public FormulaTextValueHandler(int x, int y, String formula, StyleInfo baseStyle)
//    {
//      this(x, y, formula, baseStyle, false);
//    }

    public FormulaTextValueHandler(int x, int y, String formula, StyleInfo baseStyle, boolean cellComplexFormat)
    {
      this.x = x;
      this.y = y;
      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
    {
      if (textValue.getPattern() != null)
      {
        baseStyle.setDisplayFormat(getNumberFormat(textValue.getPattern(), cellComplexFormat));
      }

      result = formula();
    }

    public void handle(DateTextValue textValue) throws JRException
    {
      baseStyle.setDisplayFormat(getDateFormat(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 StyleInfo baseStyle;
    private final boolean cellComplexFormat;

    private CellValue result;

//    public CellTextValueHandler(int x, int y, StyleInfo baseStyle)
//    {
//      this(x, y, baseStyle, false);
//    }

    public CellTextValueHandler(int x, int y, StyleInfo baseStyle, boolean cellComplexFormat)
    {
      this.x = x;
      this.y = y;
      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
    {
      if (textValue.getPattern() != null)
      {
        baseStyle.setDisplayFormat(getNumberFormat(textValue.getPattern(), 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(textValue.getPattern()));
      WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle);
      if (textValue.getValue() == null)
      {
        result = blank(cellStyle);
      }
      else
      {
        result = new DateTime(x, y, textValue.getValue(), 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 pattern, boolean isComplexFormat)
  {
    String convertedPattern = getConvertedPattern(pattern);
    NumberFormat cellFormat = (NumberFormat) 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 pattern)
  {
    String convertedPattern = getConvertedPattern(pattern);
    DateFormat cellFormat = (DateFormat) dateFormats.get(convertedPattern);
    if (cellFormat == null)
    {
      cellFormat = new DateFormat(convertedPattern);
      dateFormats.put(convertedPattern, cellFormat);
    }
    return cellFormat;
  }

  protected CellValue getAutoDetectedCellValue(int x, int y, String textStr, StyleInfo baseStyle) throws JRException
  {
    CellValue cellValue;
    try
    {
      double d = Double.parseDouble(textStr);
      WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle);
      cellValue = new Number(x, y, d, cellStyle);
    }
    catch (NumberFormatException nfe)
    {
      cellValue = getLabelCell(x, y, textStr, baseStyle);
    }
    return cellValue;
  }

  protected CellValue getLabelCell(int x, int y, String textStr, StyleInfo baseStyle) throws JRException
  {
    WritableCellFormat cellStyle = getLoadedCellStyle(baseStyle);
    return new Label(x, y, textStr, cellStyle);
  }

  protected void addMergeRegion(JRExporterGridCell gridCell, int x, int y) throws JRException
  {
    if (gridCell.getColSpan() > 1 ||
        (gridCell.getRowSpan() > 1 && !isCollapseRowSpan))
    {
      try
      {
        if (isCollapseRowSpan)
        {
          sheet.mergeCells(x, y, (x + gridCell.getColSpan() - 1), y);
        }
        else
        {
          sheet.mergeCells(x, y, (x + gridCell.getColSpan() - 1), (y + gridCell.getRowSpan() - 1));
        }
      }
      catch (JXLException e)
      {
        throw new JRException("Can't merge cells.", e);
      }
    }
  }

  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();
    }
  }

  protected void exportImage(
    JRPrintImage element,
    JRExporterGridCell gridCell,
    int col,
    int row,
    int emptyCols,
    int yCutsRow,
    JRGridLayout layout
    ) throws JRException
  {
    addMergeRegion(gridCell, col, row);

    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;

    JRRenderable renderer = element.getRenderer();

    if (
      renderer != null &&
      availableImageWidth > 0 &&
      availableImageHeight > 0
      )
    {
      if (renderer.getType() == JRRenderable.TYPE_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 = JRImageRenderer.getOnErrorRendererForImageData(renderer, element.getOnErrorTypeValue());
        if (renderer != null)
        {
          renderer = JRImageRenderer.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();
      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;
      int topOffset = 0;
      int leftOffset = 0;
      int bottomOffset = 0;
      int rightOffset = 0;
     
      switch (element.getScaleImageValue())
      {
        case CLIP:
        {
          BufferedImage bi = new BufferedImage(availableImageWidth, availableImageHeight, BufferedImage.TYPE_INT_ARGB);
          Graphics2D grx = bi.createGraphics();
         
          int xoffset = (int) (xalignFactor * (availableImageWidth - normalWidth));
          int yoffset = (int) (yalignFactor * (availableImageHeight - normalHeight));

          Shape oldClipShape = grx.getClip();

          grx.clip(
            new Rectangle(
              0,
              0,
              availableImageWidth,
              availableImageHeight
              )
            );
         
          try
          {
            renderer.render(
              grx,
              new Rectangle(
                xoffset,
                yoffset,
                normalWidth,
                normalHeight
                )
              );
          }
          finally
          {
            grx.setClip(oldClipShape);
          }

          topOffset = topPadding;
          leftOffset = leftPadding;
          bottomOffset = bottomPadding;
          rightOffset = rightPadding;

          imageData = JRImageLoader.loadImageDataFromAWTImage(bi, JRRenderable.IMAGE_TYPE_PNG);

          break;
        }
        case FILL_FRAME:
        {
          topOffset = topPadding;
          leftOffset = leftPadding;
          bottomOffset = bottomPadding;
          rightOffset = rightPadding;

          imageData = renderer.getImageData();

          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;
            }

            topOffset = topPadding + (int) (yalignFactor * (availableImageHeight - normalHeight));
            leftOffset = leftPadding + (int) (xalignFactor * (availableImageWidth - normalWidth));
            bottomOffset = bottomPadding + (int) ((1f - yalignFactor) * (availableImageHeight - normalHeight));
            rightOffset = rightPadding + (int) ((1f - xalignFactor) * (availableImageWidth - normalWidth));

            imageData = renderer.getImageData();
          }

          break;
        }
      }

      Pattern mode = this.backgroundMode;
      Colour background = WHITE;

      if (!isIgnoreCellBackground && gridCell.getCellBackcolor() != null)
      {
        mode = Pattern.SOLID;
        background = getWorkbookColour(gridCell.getCellBackcolor(), 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,
          gridCell,
          isCellLocked(element)
          );

      try
      {
        sheet.addCell(new Blank(col, row, cellStyle2));
        double leftPos = getColumnRelativePosition(layout, col, leftOffset);
        double topPos = getRowRelativePosition(layout, yCutsRow, topOffset);
        WritableImage image =
          new WritableImage(
            col - emptyCols + leftPos,
            row + topPos,
            getColumnRelativePosition(layout, col, element.getWidth() - rightOffset) - leftPos,
            getRowRelativePosition(layout, yCutsRow, element.getHeight() - bottomOffset) - topPos,
            imageData
            );
        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 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 = isCollapseRowSpan ? layout.getMaxRowHeight(row + rowIndex) : layout.getRowHeight(row + rowIndex);
      if (cumulativeRowHeight + rowHeight < offset)
      {
        rowIndex++;
      }
      else
      {
        rowRelPos += rowIndex + ((offset - cumulativeRowHeight) / (double) rowHeight);
      }
      cumulativeRowHeight += rowHeight;
    }
   
    return rowRelPos;
 

  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)
  {
    Colour colour;
    if (createCustomPalette)
    {
      colour = (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 = (RGB) 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 = (Colour) 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 static Colour getNearestColour(Color awtColor) {
    Colour retVal = null;
    Colour[] colors = Colour.getAllColours();

    int diff = 50;

    if (colors != null && colors.length > 0 ){
      Colour crtColor = null;
      for (int i = 0; i < colors.length; i++) {
        crtColor = colors[i];

        int red = crtColor.getDefaultRGB().getRed();
        if (Math.abs(awtColor.getRed() - red) < diff) {
          int green = crtColor.getDefaultRGB().getGreen();
          if (Math.abs(awtColor.getGreen() - green) < diff) {
            int blue = crtColor.getDefaultRGB().getBlue();
            if (Math.abs(awtColor.getBlue() - blue) < diff) {
              retVal = crtColor;
            }
          }
        }
      }
    }

    return retVal;
  }*/

  private WritableFont getLoadedFont(JRFont font, int forecolor, Locale locale) throws JRException
  {
    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 = font.getFontSize();
        if (isFontSizeFixEnabled)
        {
          fontSize -= 1;
        }
        String fontName = font.getFontName();
        if (fontMap != null && fontMap.containsKey(fontName))
        {
          fontName = (String) fontMap.get(fontName);
        }
        else
        {
          FontInfo fontInfo = JRFontUtil.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 = font.getFontSize();
        if (isFontSizeFixEnabled)
        {
          fontSize -= 1;
        }
        String fontName = font.getFontName();
        if (fontMap != null && fontMap.containsKey(fontName))
        {
          fontName = (String) fontMap.get(fontName);
        }

        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(JRExporterGridCell gridCell)
    {
      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] = 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,
        JRExporterGridCell gridCell
        )
      {
        this(
          mode,
          backcolor,
          horizontalAlignment,
          verticalAlignment,
          rotation,
          font,
          new BoxStyle(gridCell),
          true
          );
      }
     
    protected StyleInfo(
        Pattern mode,
        Colour backcolor,
        int horizontalAlignment,
        int verticalAlignment,
        int rotation,
        WritableFont font,
        JRExporterGridCell gridCell,
        boolean wrapText
        )
      {
        this(
          mode,
          backcolor,
          horizontalAlignment,
          verticalAlignment,
          rotation,
          font,
          new BoxStyle(gridCell),
          wrapText
          );
      }
     
    protected StyleInfo(
        Pattern mode,
        Colour backcolor,
        int horizontalAlignment,
        int verticalAlignment,
        int rotation,
        WritableFont font,
        JRExporterGridCell gridCell,
        boolean wrapText,
        boolean cellLocked
        )
      {
        this(
          mode,
          backcolor,
          horizontalAlignment,
          verticalAlignment,
          rotation,
          font,
          new BoxStyle(gridCell),
          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 == wrapText && k.isCellLocked == cellLocked);
    }

    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 + "," + wrapText + "," + cellLocked + ")";
    }
  }

  private WritableCellFormat getLoadedCellStyle(
      Pattern mode,
      Colour backcolor,
      WritableFont font,
      JRExporterGridCell gridCell
      ) throws JRException
    {
      StyleInfo styleKey =
        new StyleInfo(
          mode,
          backcolor,
          Alignment.LEFT.getValue(),
          VerticalAlignment.TOP.getValue(),
          Orientation.HORIZONTAL.getValue(),
          font,
          gridCell
          );
      return getLoadedCellStyle(styleKey);
    }

    private WritableCellFormat getLoadedCellStyle(
        Pattern mode,
        Colour backcolor,
        WritableFont font,
        JRExporterGridCell gridCell,
        boolean cellLocked
        ) throws JRException
      {
        StyleInfo styleKey =
          new StyleInfo(
            mode,
            backcolor,
            Alignment.LEFT.getValue(),
            VerticalAlignment.TOP.getValue(),
            Orientation.HORIZONTAL.getValue(),
            font,
            gridCell,
            true,
            cellLocked
            );
        return getLoadedCellStyle(styleKey);
      }

      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 = (WritableCellFormat) 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);

        if (!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(WritableSheet sheet)
  {
    PageOrientation po;
    PaperSize ps;

    if (jasperPrint.getOrientationValue() == OrientationEnum.PORTRAIT)
    {
      po = PageOrientation.PORTRAIT;
    }
    else
    {
      po = PageOrientation.LANDSCAPE;
    }
    if ((ps = getSuitablePaperSize(jasperPrint)) != null)
    {
      sheet.setPageSetup(po, ps, 0, 0);
    }
    else
    {
      sheet.setPageSetup(po);
    }
    SheetSettings sheets = sheet.getSettings();
   
    if (jasperPrint.getTopMargin() != null)
    {
      sheets.setTopMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : jasperPrint.getTopMargin()));
    }

    if (jasperPrint.getLeftMargin() != null)
    {
      sheets.setLeftMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : jasperPrint.getLeftMargin()));
    }
   
    if (jasperPrint.getRightMargin() != null)
    {
      sheets.setRightMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : jasperPrint.getRightMargin()));
    }

    if (jasperPrint.getBottomMargin() != null)
    {
      sheets.setBottomMargin(LengthUtil.inchNoRound(isIgnorePageMargins ? 0 : jasperPrint.getBottomMargin()));
    }

    sheets.setHeaderMargin(0.0);
    sheets.setFooterMargin(0.0);

    String fitWidth = JRProperties.getProperty(jasperPrint, PROPERTY_FIT_WIDTH);
    if(fitWidth != null && fitWidth.length() > 0)
    {
      sheets.setFitWidth(Integer.valueOf(fitWidth));
      sheets.setFitToPages(true);
    }
   
    String fitHeight = JRProperties.getProperty(jasperPrint, PROPERTY_FIT_HEIGHT);
    if(fitHeight != null && fitHeight.length() > 0)
    {
      sheets.setFitHeight(Integer.valueOf(fitHeight));
      sheets.setFitToPages(true);
    }

    if(password != null)
    {
      sheets.setPassword(password);
      sheets.setProtected(true);
    }
   
    if(sheetHeaderLeft != null)
    {
      sheets.getHeader().getLeft().append(sheetHeaderLeft);
    }
   
    if(sheetHeaderCenter != null)
    {
      sheets.getHeader().getCentre().append(sheetHeaderCenter);
    }
   
    if(sheetHeaderRight != null)
    {
      sheets.getHeader().getRight().append(sheetHeaderRight);
    }
   
    if(sheetFooterLeft != null)
    {
      sheets.getFooter().getLeft().append(sheetFooterLeft);
    }
   
    if(sheetFooterCenter != null)
    {
      sheets.getFooter().getCentre().append(sheetFooterCenter);
    }
   
    if(sheetFooterRight != null)
    {
      sheets.getFooter().getRight().append(sheetFooterRight);
    }
   
  }

  private final PaperSize getSuitablePaperSize(JasperPrint jasP)
  {

    if (jasP == null)
    {
      return null;
    }
    long width = 0;
    long height = 0;
    PaperSize ps = null;

    if ((jasP.getPageWidth() != 0) && (jasP.getPageHeight() != 0))
    {

      double dWidth = (jasP.getPageWidth() / 72.0);
      double dHeight = (jasP.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, JRExporterGridCell gridCell, int col, int row) throws JRException
  {
    addMergeRegion(gridCell, col, row);

    Colour forecolor = getWorkbookColour(frame.getForecolor());
    Colour backcolor = WHITE;
    Pattern mode = backgroundMode;

    if (frame.getModeValue() == ModeEnum.OPAQUE)
    {
      mode = Pattern.SOLID;
      backcolor = getWorkbookColour(frame.getBackcolor(), true);
    }

    WritableFont cellFont = getLoadedFont(getDefaultFont(), forecolor.getValue(), getLocale());
    WritableCellFormat cellStyle =
      getLoadedCellStyle(
        mode,
        backcolor,
        cellFont,
        gridCell,
        isCellLocked(frame)
        );

    Blank cell = new Blank(col, row, cellStyle);
    try
    {
      sheet.addCell(cell);
    }
    catch (JXLException e)
    {
      throw new JRException("Can't add cell.", e);
    }
  }


  protected void exportGenericElement(JRGenericPrintElement element, JRExporterGridCell gridCell, int colIndex, int rowIndex, int emptyCols, int yCutsRow, JRGridLayout layout) throws JRException
  {
    GenericElementJExcelApiHandler handler = (GenericElementJExcelApiHandler)
    GenericElementHandlerEnviroment.getHandler(
        element.getGenericType(), JXL_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());
      }
    }
  }


  protected ExporterNature getNature()
  {
    return nature;
  }


  protected String getExporterKey()
  {
    return JXL_EXPORTER_KEY;
  }

  /**
   *
   */
  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 JRProperties.getBooleanProperty(element, PROPERTY_COMPLEX_FORMAT, complexFormat);
      }
    return complexFormat;
  }

}
TOP

Related Classes of net.sf.jasperreports.engine.export.JExcelApiExporter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.