Package org.pentaho.reporting.engine.classic.core.modules.output.fast.xls

Source Code of org.pentaho.reporting.engine.classic.core.modules.output.fast.xls.FastExcelPrinter

/*
* This program is free software; you can redistribute it and/or modify it under the
*  terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
*  Foundation.
*
*  You should have received a copy of the GNU Lesser General Public License along with this
*  program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
*  or from the Free Software Foundation, Inc.,
*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*  This program 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.
*
*  Copyright (c) 2006 - 2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.modules.output.fast.xls;

import java.awt.Image;
import java.awt.Shape;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.Band;
import org.pentaho.reporting.engine.classic.core.DefaultImageReference;
import org.pentaho.reporting.engine.classic.core.ImageContainer;
import org.pentaho.reporting.engine.classic.core.PageDefinition;
import org.pentaho.reporting.engine.classic.core.ReportDefinition;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.layout.model.PhysicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.output.ContentProcessingException;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorMetaData;
import org.pentaho.reporting.engine.classic.core.layout.output.RenderUtility;
import org.pentaho.reporting.engine.classic.core.modules.output.fast.template.CellLayoutInfo;
import org.pentaho.reporting.engine.classic.core.modules.output.fast.template.FastSheetLayout;
import org.pentaho.reporting.engine.classic.core.modules.output.fast.template.SheetPropertyCollector;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.CellBackground;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.SheetLayout;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.TableRectangle;
import org.pentaho.reporting.engine.classic.core.modules.output.table.xls.helper.CellStyleProducer;
import org.pentaho.reporting.engine.classic.core.modules.output.table.xls.helper.ExcelPrinterBase;
import org.pentaho.reporting.engine.classic.core.style.BandStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictBounds;
import org.pentaho.reporting.engine.classic.core.util.geom.StrictGeomUtility;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
import org.pentaho.reporting.libraries.resourceloader.factory.drawable.DrawableWrapper;

@SuppressWarnings("HardCodedStringLiteral")
public class FastExcelPrinter extends ExcelPrinterBase
{
  private static final Log logger = LogFactory.getLog(FastExcelPrinter.class);

  private Workbook workbook;
  private Sheet sheet;
  private PageDefinition pageDefinition;
  private int rowOffset;
  private long rowHeightOffset;
  private FastExcelTextExtractor textExtractor;
  private FastSheetLayout sheetLayout;
  private long[] cellHeights;

  public FastExcelPrinter(final SheetLayout sheetLayout)
  {
    this.sheetLayout = new FastSheetLayout(sheetLayout);
  }

  public void init(final OutputProcessorMetaData metaData,
                   final ResourceManager resourceManager,
                   final ReportDefinition report)
  {
    this.pageDefinition = report.getPageDefinition();
    super.init(metaData, resourceManager);
    workbook = createWorkbook();
    initializeStyleProducers(workbook);
    textExtractor = new FastExcelTextExtractor
        (getColorProducer(), getCellStyleProducer().getFontFactory(), workbook.getCreationHelper());
  }

  protected Sheet getSheet()
  {
    return sheet;
  }

  public Workbook getWorkbook()
  {
    return workbook;
  }

  public void startSection(final Band band,
                           final long[] cellHeights)
  {
    this.cellHeights = cellHeights;
    this.sheetLayout.reinit(rowHeightOffset, cellHeights);

    if (band.getComputedStyle().getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_BEFORE))
    {
      closeSheet();
    }

    if (sheet == null)
    {
      SheetPropertyCollector collector = new SheetPropertyCollector();
      String sheetName = collector.compute(band);
      sheet = openSheet(sheetName);
      configureSheetColumnWidths(sheet, sheetLayout, sheetLayout.getColumnCount());
      configureSheetPaperSize(sheet, new PhysicalPageBox(pageDefinition.getPageFormat(0), 0, 0));
      configureSheetProperties(sheet, collector);
    }

    for (int r = 0; r < cellHeights.length; r += 1)
    {
      getRowAt(r + rowOffset).setHeightInPoints((float) StrictGeomUtility.toExternalValue(cellHeights[r]));
    }
  }

  public void endSection(final Band band, final ArrayList<CellLayoutInfo> backgroundCells)
  {
    for (final CellLayoutInfo layoutInfo : backgroundCells)
    {
      int col = layoutInfo.getX1();
      int row = layoutInfo.getY1();
      final Cell cell = getCellAt(col, row);
      final CellStyle style = getCellStyleProducer().createCellStyle(null, null, layoutInfo.getBackground());
      if (style != null)
      {
        cell.setCellStyle(style);
      }

    }

    if (band.getComputedStyle().getBooleanStyleProperty(BandStyleKeys.PAGEBREAK_AFTER))
    {
      closeSheet();
    }

    this.rowOffset += cellHeights.length;
    for (int i = 0; i < cellHeights.length; i++)
    {
      this.rowHeightOffset += cellHeights[i];
    }
  }

  protected CellStyleProducer createCellStyleProducer(final Workbook workbook)
  {
    return new FastExcelCellStyleProducer(super.createCellStyleProducer(workbook));
  }

  public void closeSheet()
  {
    sheet = null;
  }

  public void print(final CellLayoutInfo tableRectangle,
                    final ReportElement element,
                    final ExpressionRuntime runtime) throws ContentProcessingException
  {
    TableRectangle rect = new TableRectangle();
    rect.setRect(tableRectangle.getX1(), tableRectangle.getY1() + rowOffset,
        tableRectangle.getX2(), tableRectangle.getY2() + rowOffset);

    Cell cellAt = getCellAt(rect.getX1(), rect.getY1());
    CellBackground bg = tableRectangle.getBackground();
    CellStyle cellStyle = getCellStyleProducer().createCellStyle(element.getObjectID(), element.getComputedStyle(), bg);
    if (cellStyle != null)
    {
      cellAt.setCellStyle(cellStyle);
    }
    if (applyCellValue(element, cellAt, rect, runtime))
    {
      mergeCellRegion(rect, cellStyle);
    }
  }


  private void mergeCellRegion(final TableRectangle rectangle,
                               final CellStyle spannedStyle)
  {
    final int rowSpan = rectangle.getRowSpan();
    final int columnSpan = rectangle.getColumnSpan();
    if (rowSpan <= 1 && columnSpan <= 1)
    {
      return;
    }

    int row = rectangle.getY1();
    int col = rectangle.getX1();

    sheet.addMergedRegion(new CellRangeAddress(row, (row + rowSpan - 1), col, (col + columnSpan - 1)));

    for (int spannedRow = 0; spannedRow < rowSpan; spannedRow += 1)
    {
      for (int spannedCol = 0; spannedCol < columnSpan; spannedCol += 1)
      {
        final Cell regionCell = getCellAt((col + spannedCol), row + spannedRow);
        if (spannedStyle != null)
        {
          regionCell.setCellStyle(spannedStyle);
        }
      }
    }
  }


  /**
   * Applies the cell value and determines whether the cell should be merged. Merging will only take place if the cell
   * has a row or colspan greater than one. Images will never be merged, as image content is rendered into an anchored
   * frame on top of the cells.
   *
   * @return true, if the cell may to be put into a merged region, false otherwise.
   */
  private boolean applyCellValue(final ReportElement content,
                                 final Cell cell,
                                 final TableRectangle rectangle,
                                 final ExpressionRuntime runtime) throws ContentProcessingException
  {
    final Object value = textExtractor.compute(content, runtime);

    if (handleImageValues(content, rectangle, value))
    {
      return false;
    }

    final String linkTarget = (String) content.getComputedStyle().getStyleProperty(ElementStyleKeys.HREF_TARGET);
    if (linkTarget != null)
    {
      // this may be wrong if we have quotes inside. We should escape them ..
      final String formula = "HYPERLINK(" + splitAndQuoteExcelFormula(linkTarget) +
          "," + splitAndQuoteExcelFormula(textExtractor.getText()) + ")";
      if (formula.length() < 1024)
      {
        cell.setCellFormula(formula);
        return true;
      }

      logger.warn(
          "Excel-Cells cannot contain formulas longer than 1023 characters. Converting hyperlink into plain text");
    }

    final Object attr1 = content.getAttributes().getAttribute(AttributeNames.Excel.NAMESPACE,
        AttributeNames.Excel.FIELD_FORMULA);
    if (attr1 != null)
    {
      final String formula = String.valueOf(attr1);
      if (formula.length() < 1024)
      {
        cell.setCellFormula(formula);
        return true;
      }

      logger.warn(
          "Excel-Cells cannot contain formulas longer than 1023 characters. Converting excel formula into plain text");
    }

    if (value instanceof RichTextString)
    {
      cell.setCellValue((RichTextString) value);
    }
    else if (value instanceof Date)
    {
      cell.setCellValue((Date) value);
    }
    else if (value instanceof Number)
    {
      final Number number = (Number) value;
      cell.setCellValue(number.doubleValue());
    }
    else if (value instanceof Boolean)
    {
      cell.setCellValue(Boolean.TRUE.equals(value));
    }
    else // Something we can't handle.
    {
      if (value == null)
      {
        cell.setCellType(Cell.CELL_TYPE_BLANK);
      }
      else
      {
        cell.setCellValue(String.valueOf(value));
      }
    }
    return true;
  }

  private boolean handleImageValues(final ReportElement content,
                                    final TableRectangle rectangle,
                                    final Object value)
  {
    final StyleSheet rawSource = content.getComputedStyle();

    if (value instanceof Image)
    {
      try
      {
        final StrictBounds contentBounds = sheetLayout.getBounds(rectangle);
        final ImageContainer imageContainer = new DefaultImageReference((Image) value);
        createImageCell(rawSource, imageContainer, sheetLayout, rectangle, contentBounds);
      }
      catch (final IOException ioe)
      {
        // Should not happen.
        logger.warn("Failed to process AWT-Image in Excel-Export", ioe);
      }
      return true;
    }
    else if (value instanceof ImageContainer)
    {
      final ImageContainer imageContainer = (ImageContainer) value;
      final StrictBounds contentBounds = sheetLayout.getBounds(rectangle);
      createImageCell(rawSource, imageContainer, sheetLayout, rectangle, contentBounds);
      return true;
    }
    else if (value instanceof DrawableWrapper)
    {
      final DrawableWrapper drawable = (DrawableWrapper) value;
      final StrictBounds contentBounds = sheetLayout.getBounds(rectangle);
      final ImageContainer imageFromDrawable =
          RenderUtility.createImageFromDrawable(drawable, contentBounds, content.getComputedStyle(), getMetaData());
      createImageCell(rawSource, imageFromDrawable, sheetLayout, rectangle, contentBounds);
      return true;
    }
    else if (value instanceof Shape)
    {
      // We *could* do this as well ... but for now we dont.
      return true;
    }
    return false;
  }

  public void closeWorkbook(final OutputStream outputStream) throws IOException
  {
    workbook.write(outputStream);
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.modules.output.fast.xls.FastExcelPrinter

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.