| /******************************************************************************* |
| * Copyright (c) 2012, 2020 Original authors and others. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Original authors and others - initial API and implementation |
| * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 457304 |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.extension.poi; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.text.NumberFormat; |
| import java.text.ParseException; |
| import java.util.Calendar; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.poi.ss.usermodel.Cell; |
| import org.apache.poi.ss.usermodel.CellStyle; |
| import org.apache.poi.ss.usermodel.ClientAnchor; |
| import org.apache.poi.ss.usermodel.CreationHelper; |
| import org.apache.poi.ss.usermodel.Drawing; |
| import org.apache.poi.ss.usermodel.Font; |
| import org.apache.poi.ss.usermodel.Picture; |
| import org.apache.poi.ss.usermodel.Row; |
| import org.apache.poi.ss.usermodel.Sheet; |
| import org.apache.poi.ss.usermodel.Workbook; |
| import org.apache.poi.ss.util.CellRangeAddress; |
| import org.apache.poi.util.IOUtils; |
| import org.eclipse.nebula.widgets.nattable.config.CellConfigAttributes; |
| import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry; |
| import org.eclipse.nebula.widgets.nattable.export.ExportConfigAttributes; |
| import org.eclipse.nebula.widgets.nattable.export.ILayerExporter; |
| import org.eclipse.nebula.widgets.nattable.export.IOutputStreamProvider; |
| import org.eclipse.nebula.widgets.nattable.formula.FormulaParser; |
| import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell; |
| import org.eclipse.nebula.widgets.nattable.painter.cell.AbstractTextPainter; |
| import org.eclipse.nebula.widgets.nattable.painter.cell.CellPainterWrapper; |
| import org.eclipse.nebula.widgets.nattable.painter.cell.ICellPainter; |
| import org.eclipse.nebula.widgets.nattable.painter.cell.VerticalTextPainter; |
| import org.eclipse.nebula.widgets.nattable.painter.cell.decorator.CellPainterDecorator; |
| import org.eclipse.nebula.widgets.nattable.style.CellStyleAttributes; |
| import org.eclipse.nebula.widgets.nattable.style.CellStyleProxy; |
| import org.eclipse.nebula.widgets.nattable.style.DisplayMode; |
| import org.eclipse.nebula.widgets.nattable.style.HorizontalAlignmentEnum; |
| import org.eclipse.nebula.widgets.nattable.style.VerticalAlignmentEnum; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.FontData; |
| import org.eclipse.swt.widgets.Shell; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| public abstract class PoiExcelExporter implements ILayerExporter { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(PoiExcelExporter.class); |
| |
| private final IOutputStreamProvider outputStreamProvider; |
| |
| private Map<ExcelCellStyleAttributes, CellStyle> xlCellStyles; |
| |
| protected Workbook xlWorkbook; |
| protected int sheetNumber; |
| protected Sheet xlSheet; |
| protected Row xlRow; |
| |
| private boolean applyBackgroundColor = true; |
| private boolean applyVerticalTextConfiguration = false; |
| private boolean applyTextWrapping = false; |
| private boolean applyColumnWidths = false; |
| private boolean applyRowHeights = false; |
| private boolean applyCellBorders = false; |
| |
| private String sheetname; |
| |
| protected FormulaParser formulaParser; |
| protected NumberFormat nf = NumberFormat.getInstance(); |
| |
| protected CreationHelper helper; |
| protected Drawing drawing; |
| |
| protected boolean exportOnSameSheet = false; |
| protected int currentRow = 0; |
| |
| private Set<Integer> hiddenColumnPositions = new HashSet<Integer>(); |
| |
| public PoiExcelExporter(IOutputStreamProvider outputStreamProvider) { |
| this.outputStreamProvider = outputStreamProvider; |
| } |
| |
| @Override |
| public OutputStream getOutputStream(Shell shell) { |
| return this.outputStreamProvider.getOutputStream(shell); |
| } |
| |
| @Override |
| public void exportBegin(OutputStream outputStream) throws IOException { |
| this.xlCellStyles = new HashMap<ExcelCellStyleAttributes, CellStyle>(); |
| this.xlWorkbook = createWorkbook(); |
| // the hidden column positions are determined by inspection so |
| // it needs to be cleared at the beginning |
| this.hiddenColumnPositions.clear(); |
| } |
| |
| @Override |
| public void exportEnd(OutputStream outputStream) throws IOException { |
| this.xlWorkbook.write(outputStream); |
| |
| this.xlCellStyles = null; |
| this.xlWorkbook = null; |
| this.sheetNumber = 0; |
| this.xlSheet = null; |
| this.xlRow = null; |
| this.drawing = null; |
| this.currentRow = 0; |
| } |
| |
| @Override |
| public void exportLayerBegin(OutputStream outputStream, String layerName) throws IOException { |
| this.sheetNumber++; |
| if (layerName == null || layerName.length() == 0) { |
| layerName = this.sheetname; |
| |
| if (layerName == null || layerName.length() == 0) { |
| layerName = "Sheet" + this.sheetNumber; //$NON-NLS-1$ |
| } |
| } |
| this.xlSheet = this.xlWorkbook.createSheet(layerName); |
| } |
| |
| @Override |
| public void exportLayerEnd(OutputStream outputStream, String layerName) throws IOException { |
| } |
| |
| @Override |
| public void exportRowBegin(OutputStream outputStream, int rowPosition) throws IOException { |
| int pos = this.exportOnSameSheet ? this.currentRow : rowPosition; |
| |
| // check if row was already created because of spanning |
| this.xlRow = this.xlSheet.getRow(pos); |
| if (this.xlRow == null) { |
| this.xlRow = this.xlSheet.createRow(pos); |
| } |
| |
| this.currentRow++; |
| } |
| |
| @Override |
| public void exportRowEnd(OutputStream outputStream, int rowPosition) throws IOException { |
| } |
| |
| @Override |
| public void exportCell( |
| OutputStream outputStream, |
| Object exportDisplayValue, |
| ILayerCell cell, |
| IConfigRegistry configRegistry) throws IOException { |
| |
| // if the width is 0 we do not export the cell as it is not visible to |
| // the user |
| if (cell.getLayer().getColumnWidthByPosition(cell.getColumnPosition()) == 0) { |
| this.hiddenColumnPositions.add(cell.getColumnPosition()); |
| return; |
| } |
| |
| int columnPosition = cell.getColumnPosition(); |
| if (!this.hiddenColumnPositions.isEmpty()) { |
| for (int hidden : this.hiddenColumnPositions) { |
| if (hidden < cell.getColumnPosition()) { |
| columnPosition--; |
| } |
| } |
| } |
| int rowPosition = cell.getRowPosition(); |
| |
| if (this.applyColumnWidths && cell.getColumnSpan() == 1) { |
| this.xlSheet.setColumnWidth(columnPosition, getPoiColumnWidth(cell.getBounds().width) + getPoiColumnWidth(5)); |
| } |
| if (this.applyRowHeights && cell.getRowSpan() == 1) { |
| this.xlRow.setHeight(getPoiRowHeight(cell.getBounds().height)); |
| } |
| |
| // check if cell was already created because of spanning |
| Cell xlCell = this.xlRow.getCell(columnPosition); |
| if (xlCell == null) { |
| xlCell = this.xlRow.createCell(columnPosition); |
| } else { |
| // if the cell was created before because of spanning, there is no |
| // need to perform further tasks |
| return; |
| } |
| |
| CellStyleProxy cellStyle = new CellStyleProxy( |
| configRegistry, |
| DisplayMode.NORMAL, |
| cell.getConfigLabels()); |
| Color fg = cellStyle.getAttributeValue(CellStyleAttributes.FOREGROUND_COLOR); |
| Color bg = cellStyle.getAttributeValue(CellStyleAttributes.BACKGROUND_COLOR); |
| org.eclipse.swt.graphics.Font font = cellStyle.getAttributeValue(CellStyleAttributes.FONT); |
| FontData fontData = font.getFontData()[0]; |
| String dataFormat = null; |
| if (exportDisplayValue instanceof Calendar |
| || exportDisplayValue instanceof Date) { |
| dataFormat = getDataFormatString(cell, configRegistry); |
| } |
| |
| int hAlign = HorizontalAlignmentEnum.getSWTStyle(cellStyle); |
| int vAlign = VerticalAlignmentEnum.getSWTStyle(cellStyle); |
| |
| ICellPainter cellPainter = configRegistry.getConfigAttribute( |
| CellConfigAttributes.CELL_PAINTER, |
| DisplayMode.NORMAL, |
| cell.getConfigLabels()); |
| boolean vertical = this.applyVerticalTextConfiguration ? isVertical(cellPainter) : false; |
| boolean wrap = this.applyTextWrapping ? wrapText(cellPainter) : false; |
| |
| CellStyle xlCellStyle = getExcelCellStyle(fg, bg, fontData, dataFormat, hAlign, vAlign, vertical, wrap, this.applyCellBorders); |
| xlCell.setCellStyle(xlCellStyle); |
| |
| int columnSpan = cell.getColumnSpan(); |
| if (columnSpan > 1) { |
| // check if a column width in the spanned region is 0 |
| // as we do not export columns with a width of 0 we need to adjust |
| // the spanning |
| for (int col = cell.getOriginColumnPosition(); col < (cell.getOriginColumnPosition() + cell.getColumnSpan()); col++) { |
| if (cell.getLayer().getColumnWidthByPosition(col) == 0) { |
| columnSpan--; |
| } |
| } |
| } |
| int rowSpan = cell.getRowSpan(); |
| if (columnSpan > 1 || rowSpan > 1) { |
| int lastRow = rowPosition + rowSpan - 1; |
| int lastColumn = columnPosition + columnSpan - 1; |
| this.xlSheet.addMergedRegion(new CellRangeAddress(rowPosition, lastRow, columnPosition, lastColumn)); |
| |
| // apply style to all cells that get merged |
| Row tempRow = null; |
| Cell tempCell = null; |
| for (int i = rowPosition; i <= lastRow; i++) { |
| tempRow = this.xlSheet.getRow(i); |
| if (tempRow == null) { |
| tempRow = this.xlSheet.createRow(i); |
| } |
| for (int j = columnPosition; j <= lastColumn; j++) { |
| tempCell = tempRow.getCell(j); |
| if (tempCell == null) { |
| tempCell = tempRow.createCell(j); |
| } |
| tempCell.setCellStyle(xlCellStyle); |
| } |
| } |
| } |
| |
| if (exportDisplayValue == null) |
| exportDisplayValue = ""; //$NON-NLS-1$ |
| |
| if (exportDisplayValue instanceof Boolean) { |
| xlCell.setCellValue((Boolean) exportDisplayValue); |
| } else if (exportDisplayValue instanceof Calendar) { |
| xlCell.setCellValue((Calendar) exportDisplayValue); |
| } else if (exportDisplayValue instanceof Date) { |
| xlCell.setCellValue((Date) exportDisplayValue); |
| } else if (exportDisplayValue instanceof Number) { |
| xlCell.setCellValue(((Number) exportDisplayValue).doubleValue()); |
| } else if (exportDisplayValue instanceof InputStream) { |
| exportImage((InputStream) exportDisplayValue, xlCell); |
| } else if (this.formulaParser != null) { |
| // formula export is enabled, so we perform checks on the cell |
| // values |
| String cellValue = exportDisplayValue.toString(); |
| if (this.formulaParser.isFunction(cellValue)) { |
| String functionString = this.formulaParser.getFunctionOnly(cellValue); |
| // POI expects the formula parameters to be separated by , |
| // instead of ; |
| // also localized decimal separators need to be modified for |
| // export |
| functionString = functionString.replace(',', '.'); |
| functionString = functionString.replace(';', ','); |
| xlCell.setCellFormula(functionString); |
| } else if (this.formulaParser.isNumber(cellValue)) { |
| try { |
| xlCell.setCellValue(this.nf.parse(cellValue).doubleValue()); |
| } catch (ParseException e) { |
| throw new IOException("Error on parsing number value: " + cellValue, e); //$NON-NLS-1$ |
| } |
| } else { |
| xlCell.setCellValue(exportDisplayValue.toString()); |
| } |
| } else { |
| xlCell.setCellValue(exportDisplayValue.toString()); |
| } |
| } |
| |
| private boolean isVertical(ICellPainter cellPainter) { |
| if (cellPainter instanceof VerticalTextPainter) { |
| return true; |
| } else if (cellPainter instanceof CellPainterWrapper) { |
| return isVertical(((CellPainterWrapper) cellPainter).getWrappedPainter()); |
| } else if (cellPainter instanceof CellPainterDecorator) { |
| return (isVertical(((CellPainterDecorator) cellPainter).getBaseCellPainter()) |
| || isVertical(((CellPainterDecorator) cellPainter).getDecoratorCellPainter())); |
| } |
| return false; |
| } |
| |
| private boolean wrapText(ICellPainter cellPainter) { |
| if (cellPainter instanceof AbstractTextPainter) { |
| return ((AbstractTextPainter) cellPainter).isWordWrapping() |
| || ((AbstractTextPainter) cellPainter).isWrapText(); |
| } else if (cellPainter instanceof CellPainterWrapper) { |
| return wrapText(((CellPainterWrapper) cellPainter).getWrappedPainter()); |
| } else if (cellPainter instanceof CellPainterDecorator) { |
| return (wrapText(((CellPainterDecorator) cellPainter).getBaseCellPainter()) |
| || wrapText(((CellPainterDecorator) cellPainter).getDecoratorCellPainter())); |
| } |
| return false; |
| } |
| |
| private CellStyle getExcelCellStyle( |
| Color fg, Color bg, FontData fontData, |
| String dataFormat, int hAlign, int vAlign, |
| boolean vertical, boolean wrap, boolean border) { |
| |
| CellStyle xlCellStyle = this.xlCellStyles.get( |
| new ExcelCellStyleAttributes(fg, bg, fontData, dataFormat, hAlign, vAlign, vertical, wrap, border)); |
| |
| if (xlCellStyle == null) { |
| xlCellStyle = this.xlWorkbook.createCellStyle(); |
| |
| if (this.applyBackgroundColor) { |
| // Note: xl fill foreground = background |
| setFillForegroundColor(xlCellStyle, bg); |
| xlCellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); |
| } |
| |
| Font xlFont = this.xlWorkbook.createFont(); |
| setFontColor(xlFont, fg); |
| xlFont.setFontName(fontData.getName()); |
| xlFont.setFontHeightInPoints((short) fontData.getHeight()); |
| xlCellStyle.setFont(xlFont); |
| |
| if (vertical) |
| xlCellStyle.setRotation((short) 90); |
| |
| if (wrap) |
| xlCellStyle.setWrapText(wrap); |
| |
| if (border) { |
| xlCellStyle.setBorderTop(CellStyle.BORDER_THIN); |
| xlCellStyle.setBorderRight(CellStyle.BORDER_THIN); |
| xlCellStyle.setBorderBottom(CellStyle.BORDER_THIN); |
| xlCellStyle.setBorderLeft(CellStyle.BORDER_THIN); |
| } |
| |
| switch (hAlign) { |
| case SWT.CENTER: |
| xlCellStyle.setAlignment(CellStyle.ALIGN_CENTER); |
| break; |
| case SWT.LEFT: |
| xlCellStyle.setAlignment(CellStyle.ALIGN_LEFT); |
| break; |
| case SWT.RIGHT: |
| xlCellStyle.setAlignment(CellStyle.ALIGN_RIGHT); |
| break; |
| } |
| switch (vAlign) { |
| case SWT.TOP: |
| xlCellStyle.setVerticalAlignment(CellStyle.VERTICAL_TOP); |
| break; |
| case SWT.CENTER: |
| xlCellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER); |
| break; |
| case SWT.BOTTOM: |
| xlCellStyle.setVerticalAlignment(CellStyle.VERTICAL_BOTTOM); |
| break; |
| } |
| |
| if (dataFormat != null) { |
| CreationHelper createHelper = this.xlWorkbook.getCreationHelper(); |
| xlCellStyle.setDataFormat(createHelper.createDataFormat().getFormat(dataFormat)); |
| } |
| |
| this.xlCellStyles.put( |
| new ExcelCellStyleAttributes(fg, bg, fontData, dataFormat, hAlign, vAlign, vertical, wrap, border), xlCellStyle); |
| } |
| return xlCellStyle; |
| } |
| |
| /** |
| * |
| * @param cell |
| * The cell for which the date format needs to be determined. |
| * @param configRegistry |
| * The ConfigRegistry needed to retrieve the configuration. |
| * @return The date format that should be used to format Date or Calendar |
| * values in the export. |
| */ |
| protected String getDataFormatString(ILayerCell cell, IConfigRegistry configRegistry) { |
| String dataFormat = configRegistry.getConfigAttribute( |
| ExportConfigAttributes.DATE_FORMAT, |
| DisplayMode.NORMAL, |
| cell.getConfigLabels()); |
| if (dataFormat == null) { |
| dataFormat = "m/d/yy h:mm"; //$NON-NLS-1$ |
| } |
| return dataFormat; |
| } |
| |
| /** |
| * |
| * @param applyBackgroundColor |
| * <code>true</code> to apply the background color set in the |
| * NatTable to the exported Excel. This also includes white |
| * background and header background color. <code>false</code> if |
| * the background color should not be set on export. |
| */ |
| public void setApplyBackgroundColor(boolean applyBackgroundColor) { |
| this.applyBackgroundColor = applyBackgroundColor; |
| } |
| |
| /** |
| * Configure this exporter whether it should check for vertical text |
| * configuration in NatTable and apply the corresponding rotation style |
| * attribute in the export, or not. |
| * <p> |
| * Note: As showing text vertically in NatTable is not a style information |
| * but a configured via painter implementation, the check whether text is |
| * showed vertically needs to be done via reflection. Therefore setting this |
| * value to <code>true</code> could cause performance issues. As vertical |
| * text is not the default case and the effect on performance might be |
| * negative, the default value for this configuration is <code>false</code>. |
| * If vertical text (e.g. column headers) should also be exported |
| * vertically, you need to set this value to <code>true</code>. |
| * |
| * @param inspectVertical |
| * <code>true</code> to configure this exporter to check for |
| * vertical text configuration and apply the rotation style for |
| * the export, <code>false</code> to always use the regular text |
| * direction, regardless of vertical rendered text in NatTable. |
| */ |
| public void setApplyVerticalTextConfiguration(boolean inspectVertical) { |
| this.applyVerticalTextConfiguration = inspectVertical; |
| } |
| |
| /** |
| * Configure this exporter whether it should check for text wrapping |
| * configuration in NatTable and apply the corresponding style attribute in |
| * the export, or not. |
| * <p> |
| * Note: As showing text wrapping in NatTable is not a style information but |
| * a configured via painter implementation, the check whether text is |
| * wrapped needs to be done via reflection. Therefore setting this value to |
| * <code>true</code> could cause performance issues. As wrapped text is not |
| * the default case and the effect on performance might be negative, the |
| * default value for this configuration is <code>false</code>. If wrapped |
| * text (e.g. column headers) should also be exported wrapped, you need to |
| * set this value to <code>true</code>. |
| * |
| * @param inspectTextWrap |
| * <code>true</code> to configure this exporter to check for text |
| * wrapping configuration, <code>false</code> to never apply text |
| * wrapping to the export. |
| * @since 1.5 |
| */ |
| public void setApplyTextWrapping(boolean inspectTextWrap) { |
| this.applyTextWrapping = inspectTextWrap; |
| } |
| |
| /** |
| * Configure this exporter whether it should apply the cell dimensions to |
| * the same size configuration the NatTable shows. |
| * |
| * @param apply |
| * <code>true</code> to configure this exporter to apply the cell |
| * dimensions based on the NatTable cell dimensions, |
| * <code>false</code> if the Excel default cell dimensions should |
| * be used. |
| * @since 1.5 |
| */ |
| public void setApplyCellDimensions(boolean apply) { |
| this.applyColumnWidths = apply; |
| this.applyRowHeights = apply; |
| } |
| |
| /** |
| * Configure this exporter whether it should apply the column widths to the |
| * same size configuration the NatTable shows. |
| * |
| * @param apply |
| * <code>true</code> to configure this exporter to apply the |
| * column widths based on the NatTable cell dimensions, |
| * <code>false</code> if the Excel default cell dimensions should |
| * be used. |
| * @since 1.5 |
| */ |
| public void setApplyColumnWidths(boolean apply) { |
| this.applyColumnWidths = apply; |
| } |
| |
| /** |
| * Configure this exporter whether it should apply the row heights to the |
| * same size configuration the NatTable shows. |
| * |
| * @param apply |
| * <code>true</code> to configure this exporter to apply the row |
| * heights based on the NatTable cell dimensions, |
| * <code>false</code> if the Excel default cell dimensions should |
| * be used. |
| * @since 1.5 |
| */ |
| public void setApplyRowHeights(boolean apply) { |
| this.applyRowHeights = apply; |
| } |
| |
| /** |
| * Configure this exporter whether it should render cell borders on all |
| * cells. This should typically be enabled if background colors should be |
| * applied to make the cell borders visible. |
| * |
| * @param apply |
| * <code>true</code> to configure this exporter to render cell |
| * borders, <code>false</code> if not. |
| * @since 1.5 |
| */ |
| public void setApplyCellBorders(boolean apply) { |
| this.applyCellBorders = apply; |
| } |
| |
| protected abstract Workbook createWorkbook(); |
| |
| protected abstract void setFillForegroundColor(CellStyle xlCellStyle, Color swtColor); |
| |
| protected abstract void setFontColor(Font xlFont, Color swtColor); |
| |
| @Override |
| public Object getResult() { |
| return this.outputStreamProvider.getResult(); |
| } |
| |
| /** |
| * |
| * @param sheetname |
| * The name that should be set as sheet name in the resulting |
| * Excel file. Setting this value to <code>null</code> will |
| * result in a sheet name following the pattern <i>Sheet + |
| * <sheet number></i> |
| */ |
| public void setSheetname(String sheetname) { |
| this.sheetname = sheetname; |
| } |
| |
| /** |
| * Configure the {@link FormulaParser} that should be used to determine |
| * whether formulas should be exported or not. If <code>null</code> is set, |
| * formulas and cell values of type string will be simply exported as |
| * string. If a valid {@link FormulaParser} is set, cell values will get |
| * inspected so that number values are converted to numbers and formulas |
| * will be exported as formulas. |
| * |
| * @param formulaParser |
| * The {@link FormulaParser} that should be used to determine |
| * whether cell values should be interpreted as formulas or |
| * <code>null</code> to disable formula export handling. |
| * |
| * @since 1.4 |
| */ |
| public void setFormulaParser(FormulaParser formulaParser) { |
| this.formulaParser = formulaParser; |
| } |
| |
| /** |
| * |
| * @param nf |
| * The {@link NumberFormat} that should be used to format numeric |
| * values. |
| */ |
| public void setNumberFormat(NumberFormat nf) { |
| this.nf = nf; |
| } |
| |
| /** |
| * Adds a picture to the workbook at the given cell position. |
| * |
| * @param is |
| * The {@link InputStream} to access the picture. This will be |
| * automatically closed after reading. |
| * @param xlCell |
| * The {@link Cell} to position the image to. |
| * @since 1.5 |
| */ |
| protected void exportImage(InputStream is, Cell xlCell) { |
| try { |
| byte[] bytes = IOUtils.toByteArray(is); |
| int pictureIdx = this.xlWorkbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); |
| |
| if (this.helper == null) { |
| this.helper = this.xlWorkbook.getCreationHelper(); |
| } |
| |
| // Create the drawing patriarch. |
| // This is the top level container for all shapes. |
| if (this.drawing == null) { |
| this.drawing = this.xlSheet.createDrawingPatriarch(); |
| } |
| |
| // add a picture shape |
| ClientAnchor anchor = this.helper.createClientAnchor(); |
| // set top-left corner of the picture, |
| // subsequent call of Picture#resize() will operate relative to it |
| anchor.setCol1(xlCell.getColumnIndex()); |
| anchor.setRow1(xlCell.getRowIndex()); |
| Picture pict = this.drawing.createPicture(anchor, pictureIdx); |
| |
| // auto-size picture relative to its top-left corner |
| pict.resize(); |
| } catch (IOException e) { |
| LOG.error("Error on transforming the image input stream to byte array", e); //$NON-NLS-1$ |
| } finally { |
| try { |
| is.close(); |
| } catch (IOException e) { |
| LOG.error("Error on closing the image input stream", e); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| /** |
| * |
| * @param sameSheet |
| * <code>true</code> if multiple NatTable instances should be |
| * exported on the same sheet, <code>false</code> if every |
| * instance should be exported on separate sheets. Default is |
| * <code>false</code>. |
| * |
| * @since 1.5 |
| */ |
| public void setExportOnSameSheet(boolean sameSheet) { |
| this.exportOnSameSheet = sameSheet; |
| } |
| |
| private int getPoiColumnWidth(int pixel) { |
| return (256 * (pixel / 7)) + 128; |
| } |
| |
| private short getPoiRowHeight(int pixel) { |
| double points = pixel; |
| points *= 72; |
| points /= 96; |
| points *= 21; |
| return (short) (points + 32); |
| } |
| } |