You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ye...@apache.org on 2011/12/16 11:01:02 UTC

svn commit: r1215079 - in /poi/trunk/src: documentation/content/xdocs/status.xml java/org/apache/poi/ss/util/SheetUtil.java

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 @@
 
     <changes>
         <release version="3.8-beta6" date="2012-??-??">
+           <action dev="poi-developers" type="fix">52314 - enhanced SheetUtil.getColumnWidth</action>
         </release>
         <release version="3.8-beta5" date="2011-12-17">
            <action dev="poi-developers" type="fix">52204 - Deprecated XSSFWorkbook(String path) constructor because it does not close underlying .zip file</action>

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