Return-Path: X-Original-To: apmail-poi-commits-archive@minotaur.apache.org Delivered-To: apmail-poi-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id BC7D4931B for ; Fri, 16 Dec 2011 10:01:28 +0000 (UTC) Received: (qmail 49884 invoked by uid 500); 16 Dec 2011 10:01:28 -0000 Delivered-To: apmail-poi-commits-archive@poi.apache.org Received: (qmail 49848 invoked by uid 500); 16 Dec 2011 10:01:28 -0000 Mailing-List: contact commits-help@poi.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@poi.apache.org Delivered-To: mailing list commits@poi.apache.org Received: (qmail 49841 invoked by uid 99); 16 Dec 2011 10:01:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 16 Dec 2011 10:01:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 16 Dec 2011 10:01:24 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 929C923889DA for ; Fri, 16 Dec 2011 10:01:02 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1215079 - in /poi/trunk/src: documentation/content/xdocs/status.xml java/org/apache/poi/ss/util/SheetUtil.java Date: Fri, 16 Dec 2011 10:01:02 -0000 To: commits@poi.apache.org From: yegor@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20111216100102.929C923889DA@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: yegor Date: Fri Dec 16 10:01:02 2011 New Revision: 1215079 URL: http://svn.apache.org/viewvc?rev=1215079&view=rev Log: applied patch from Bugzilla 52314: SheetUtil.getColumnWidth could be more flexible Modified: poi/trunk/src/documentation/content/xdocs/status.xml poi/trunk/src/java/org/apache/poi/ss/util/SheetUtil.java Modified: poi/trunk/src/documentation/content/xdocs/status.xml URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=1215079&r1=1215078&r2=1215079&view=diff ============================================================================== --- poi/trunk/src/documentation/content/xdocs/status.xml (original) +++ poi/trunk/src/documentation/content/xdocs/status.xml Fri Dec 16 10:01:02 2011 @@ -34,6 +34,7 @@ + 52314 - enhanced SheetUtil.getColumnWidth 52204 - Deprecated XSSFWorkbook(String path) constructor because it does not close underlying .zip file Modified: poi/trunk/src/java/org/apache/poi/ss/util/SheetUtil.java URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/util/SheetUtil.java?rev=1215079&r1=1215078&r2=1215079&view=diff ============================================================================== --- poi/trunk/src/java/org/apache/poi/ss/util/SheetUtil.java (original) +++ poi/trunk/src/java/org/apache/poi/ss/util/SheetUtil.java Fri Dec 16 10:01:02 2011 @@ -52,7 +52,7 @@ public class SheetUtil { * {@link org.apache.poi.ss.usermodel.DataFormatter#formatCellValue(org.apache.poi.ss.usermodel.Cell)} * returns formula string for formula cells. Dummy evaluator makes it to format the cached formula result. * - * See Bugzilla #50021 + * See Bugzilla #50021 */ private static final FormulaEvaluator dummyEvaluator = new FormulaEvaluator(){ public void clearAllCachedResultValues(){} @@ -75,6 +75,117 @@ public class SheetUtil { private static final FontRenderContext fontRenderContext = new FontRenderContext(null, true, true); /** + * Compute width of a single cell + * + * @param cell the cell whose width is to be calculated + * @param defaultCharWidth the width of a single character + * @param formatter formatter used to prepare the text to be measured + * @param useMergedCells whether to use merged cells + * @return the width in pixels + */ + public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter formatter, boolean useMergedCells) { + + Sheet sheet = cell.getSheet(); + Workbook wb = sheet.getWorkbook(); + Row row = cell.getRow(); + int column = cell.getColumnIndex(); + + int colspan = 1; + for (int i = 0 ; i < sheet.getNumMergedRegions(); i++) { + CellRangeAddress region = sheet.getMergedRegion(i); + if (containsCell(region, row.getRowNum(), column)) { + if (!useMergedCells) { + // If we're not using merged cells, skip this one and move on to the next. + return -1; + } + cell = row.getCell(region.getFirstColumn()); + colspan = 1 + region.getLastColumn() - region.getFirstColumn(); + } + } + + CellStyle style = cell.getCellStyle(); + int cellType = cell.getCellType(); + + // for formula cells we compute the cell width for the cached formula result + if(cellType == Cell.CELL_TYPE_FORMULA) cellType = cell.getCachedFormulaResultType(); + + Font font = wb.getFontAt(style.getFontIndex()); + + AttributedString str; + TextLayout layout; + + double width = -1; + if (cellType == Cell.CELL_TYPE_STRING) { + RichTextString rt = cell.getRichStringCellValue(); + String[] lines = rt.getString().split("\\n"); + for (int i = 0; i < lines.length; i++) { + String txt = lines[i] + defaultChar; + + str = new AttributedString(txt); + copyAttributes(font, str, 0, txt.length()); + + if (rt.numFormattingRuns() > 0) { + // TODO: support rich text fragments + } + + layout = new TextLayout(str.getIterator(), fontRenderContext); + if(style.getRotation() != 0){ + /* + * Transform the text using a scale so that it's height is increased by a multiple of the leading, + * and then rotate the text before computing the bounds. The scale results in some whitespace around + * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but + * is added by the standard Excel autosize. + */ + AffineTransform trans = new AffineTransform(); + trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); + trans.concatenate( + AffineTransform.getScaleInstance(1, fontHeightMultiple) + ); + width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); + } else { + width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); + } + } + } else { + String sval = null; + if (cellType == Cell.CELL_TYPE_NUMERIC) { + // Try to get it formatted to look the same as excel + try { + sval = formatter.formatCellValue(cell, dummyEvaluator); + } catch (Exception e) { + sval = String.valueOf(cell.getNumericCellValue()); + } + } else if (cellType == Cell.CELL_TYPE_BOOLEAN) { + sval = String.valueOf(cell.getBooleanCellValue()).toUpperCase(); + } + if(sval != null) { + String txt = sval + defaultChar; + str = new AttributedString(txt); + copyAttributes(font, str, 0, txt.length()); + + layout = new TextLayout(str.getIterator(), fontRenderContext); + if(style.getRotation() != 0){ + /* + * Transform the text using a scale so that it's height is increased by a multiple of the leading, + * and then rotate the text before computing the bounds. The scale results in some whitespace around + * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but + * is added by the standard Excel autosize. + */ + AffineTransform trans = new AffineTransform(); + trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); + trans.concatenate( + AffineTransform.getScaleInstance(1, fontHeightMultiple) + ); + width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); + } else { + width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); + } + } + } + return width; + } + + /** * Compute width of a column and return the result * * @param sheet the sheet to calculate @@ -96,7 +207,6 @@ public class SheetUtil { int defaultCharWidth = (int)layout.getAdvance(); double width = -1; - rows: for (Row row : sheet) { Cell cell = row.getCell(column); @@ -104,97 +214,51 @@ public class SheetUtil { continue; } - int colspan = 1; - for (int i = 0 ; i < sheet.getNumMergedRegions(); i++) { - CellRangeAddress region = sheet.getMergedRegion(i); - if (containsCell(region, row.getRowNum(), column)) { - if (!useMergedCells) { - // If we're not using merged cells, skip this one and move on to the next. - continue rows; - } - cell = row.getCell(region.getFirstColumn()); - colspan = 1 + region.getLastColumn() - region.getFirstColumn(); - } - } - - CellStyle style = cell.getCellStyle(); - int cellType = cell.getCellType(); - - // for formula cells we compute the cell width for the cached formula result - if(cellType == Cell.CELL_TYPE_FORMULA) cellType = cell.getCachedFormulaResultType(); - - Font font = wb.getFontAt(style.getFontIndex()); - - if (cellType == Cell.CELL_TYPE_STRING) { - RichTextString rt = cell.getRichStringCellValue(); - String[] lines = rt.getString().split("\\n"); - for (int i = 0; i < lines.length; i++) { - String txt = lines[i] + defaultChar; - - str = new AttributedString(txt); - copyAttributes(font, str, 0, txt.length()); - - if (rt.numFormattingRuns() > 0) { - // TODO: support rich text fragments - } - - layout = new TextLayout(str.getIterator(), fontRenderContext); - if(style.getRotation() != 0){ - /* - * Transform the text using a scale so that it's height is increased by a multiple of the leading, - * and then rotate the text before computing the bounds. The scale results in some whitespace around - * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but - * is added by the standard Excel autosize. - */ - AffineTransform trans = new AffineTransform(); - trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); - trans.concatenate( - AffineTransform.getScaleInstance(1, fontHeightMultiple) - ); - width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } else { - width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } - } - } else { - String sval = null; - if (cellType == Cell.CELL_TYPE_NUMERIC) { - // Try to get it formatted to look the same as excel - try { - sval = formatter.formatCellValue(cell, dummyEvaluator); - } catch (Exception e) { - sval = String.valueOf(cell.getNumericCellValue()); - } - } else if (cellType == Cell.CELL_TYPE_BOOLEAN) { - sval = String.valueOf(cell.getBooleanCellValue()).toUpperCase(); - } - if(sval != null) { - String txt = sval + defaultChar; - str = new AttributedString(txt); - copyAttributes(font, str, 0, txt.length()); - - layout = new TextLayout(str.getIterator(), fontRenderContext); - if(style.getRotation() != 0){ - /* - * Transform the text using a scale so that it's height is increased by a multiple of the leading, - * and then rotate the text before computing the bounds. The scale results in some whitespace around - * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but - * is added by the standard Excel autosize. - */ - AffineTransform trans = new AffineTransform(); - trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); - trans.concatenate( - AffineTransform.getScaleInstance(1, fontHeightMultiple) - ); - width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } else { - width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } + double cellWidth = getCellWidth(cell, defaultCharWidth, formatter, useMergedCells); + width = Math.max(width, cellWidth); + } + return width; + } + + /** + * Compute width of a column based on a subset of the rows and return the result + * + * @param sheet the sheet to calculate + * @param column 0-based index of the column + * @param useMergedCells whether to use merged cells + * @param firstRow 0-based index of the first row to consider (inclusive) + * @param lastRow 0-based index of the last row to consider (inclusive) + * @return the width in pixels + */ + public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCells, int firstRow, int lastRow){ + AttributedString str; + TextLayout layout; + + Workbook wb = sheet.getWorkbook(); + DataFormatter formatter = new DataFormatter(); + Font defaultFont = wb.getFontAt((short) 0); + + str = new AttributedString(String.valueOf(defaultChar)); + copyAttributes(defaultFont, str, 0, 1); + layout = new TextLayout(str.getIterator(), fontRenderContext); + int defaultCharWidth = (int)layout.getAdvance(); + + double width = -1; + for (int rowIdx = firstRow; rowIdx <= lastRow; ++rowIdx) { + Row row = sheet.getRow(rowIdx); + if( row != null ) { + + Cell cell = row.getCell(column); + + if (cell == null) { + continue; } - } + double cellWidth = getCellWidth(cell, defaultCharWidth, formatter, useMergedCells); + width = Math.max(width, cellWidth); + } } - return width; + return width; } /** --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org For additional commands, e-mail: commits-help@poi.apache.org