]> source.dussan.org Git - poi.git/commitdiff
add tricky mode (disabled by default) to output cell's text in next cells, if they...
authorSergey Vladimirov <sergey@apache.org>
Mon, 18 Jul 2011 15:37:48 +0000 (15:37 +0000)
committerSergey Vladimirov <sergey@apache.org>
Mon, 18 Jul 2011 15:37:48 +0000 (15:37 +0000)
add option (enabled by default) to change leading spaces into &nbsp; entities

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1147933 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToHtmlConverter.java

index 751cb30aa5e720df98bebcb8e5c5e350f80c0991..8b0780aab7ca09a408c78f3c68c3e49370066db6 100644 (file)
@@ -59,6 +59,12 @@ public class ExcelToHtmlConverter
     private static final POILogger logger = POILogFactory
             .getLogger( ExcelToHtmlConverter.class );
 
+    protected static int getColumnWidth( HSSFSheet sheet, int columnIndex )
+    {
+        return ExcelToHtmlUtils.getColumnWidthInPx( sheet
+                .getColumnWidth( columnIndex ) );
+    }
+
     /**
      * Java main() interface to interact with {@link ExcelToHtmlConverter}
      * 
@@ -133,10 +139,14 @@ public class ExcelToHtmlConverter
 
     private boolean outputHiddenRows = false;
 
+    private boolean outputLeadingSpacesAsNonBreaking = true;
+
     private boolean outputRowNumbers = true;
 
     private final Element stylesElement;
 
+    private boolean useDivsToSpan = false;
+
     public ExcelToHtmlConverter( Document doc )
     {
         htmlDocumentFacade = new HtmlDocumentFacade( doc );
@@ -328,13 +338,84 @@ public class ExcelToHtmlConverter
         return outputHiddenRows;
     }
 
+    public boolean isOutputLeadingSpacesAsNonBreaking()
+    {
+        return outputLeadingSpacesAsNonBreaking;
+    }
+
     public boolean isOutputRowNumbers()
     {
         return outputRowNumbers;
     }
 
+    protected boolean isTextEmpty( HSSFCell cell )
+    {
+        final String value;
+        switch ( cell.getCellType() )
+        {
+        case HSSFCell.CELL_TYPE_STRING:
+            // XXX: enrich
+            value = cell.getRichStringCellValue().getString();
+            break;
+        case HSSFCell.CELL_TYPE_FORMULA:
+            switch ( cell.getCachedFormulaResultType() )
+            {
+            case HSSFCell.CELL_TYPE_STRING:
+                HSSFRichTextString str = cell.getRichStringCellValue();
+                if ( str == null || str.length() <= 0 )
+                    return false;
+
+                value = str.toString();
+                break;
+            case HSSFCell.CELL_TYPE_NUMERIC:
+                HSSFCellStyle style = cell.getCellStyle();
+                if ( style == null )
+                {
+                    return false;
+                }
+
+                value = ( _formatter.formatRawCellContents(
+                        cell.getNumericCellValue(), style.getDataFormat(),
+                        style.getDataFormatString() ) );
+                break;
+            case HSSFCell.CELL_TYPE_BOOLEAN:
+                value = String.valueOf( cell.getBooleanCellValue() );
+                break;
+            case HSSFCell.CELL_TYPE_ERROR:
+                value = ErrorEval.getText( cell.getErrorCellValue() );
+                break;
+            default:
+                value = ExcelToHtmlUtils.EMPTY;
+                break;
+            }
+            break;
+        case HSSFCell.CELL_TYPE_BLANK:
+            value = ExcelToHtmlUtils.EMPTY;
+            break;
+        case HSSFCell.CELL_TYPE_NUMERIC:
+            value = _formatter.formatCellValue( cell );
+            break;
+        case HSSFCell.CELL_TYPE_BOOLEAN:
+            value = String.valueOf( cell.getBooleanCellValue() );
+            break;
+        case HSSFCell.CELL_TYPE_ERROR:
+            value = ErrorEval.getText( cell.getErrorCellValue() );
+            break;
+        default:
+            return true;
+        }
+
+        return ExcelToHtmlUtils.isEmpty( value );
+    }
+
+    public boolean isUseDivsToSpan()
+    {
+        return useDivsToSpan;
+    }
+
     protected boolean processCell( HSSFWorkbook workbook, HSSFCell cell,
-            Element tableCellElement )
+            Element tableCellElement, int normalWidthPx, int maxSpannedWidthPx,
+            float normalHeightPt )
     {
         final HSSFCellStyle cellStyle = cell.getCellStyle();
 
@@ -421,8 +502,50 @@ public class ExcelToHtmlConverter
             }
         }
 
+        if ( isOutputLeadingSpacesAsNonBreaking() && value.startsWith( " " ) )
+        {
+            StringBuilder builder = new StringBuilder();
+            for ( int c = 0; c < value.length(); c++ )
+            {
+                if ( value.charAt( c ) != ' ' )
+                    break;
+                builder.append( '\u00a0' );
+            }
+
+            if ( value.length() != builder.length() )
+                builder.append( value.substring( builder.length() ) );
+
+            value = builder.toString();
+        }
+
         Text text = htmlDocumentFacade.createText( value );
-        tableCellElement.appendChild( text );
+
+        if ( isUseDivsToSpan() )
+        {
+            tableCellElement.setAttribute( "style",
+                    "padding:0;margin:0;align:left;vertical-align:top;" );
+            Element outerDiv = htmlDocumentFacade.getDocument().createElement(
+                    "div" );
+            outerDiv.setAttribute( "style", "position:relative;" );
+
+            Element innerDiv = htmlDocumentFacade.getDocument().createElement(
+                    "div" );
+            innerDiv.setAttribute( "style", "position:absolute;min-width:"
+                    + normalWidthPx
+                    + "px;"
+                    + ( maxSpannedWidthPx != Integer.MAX_VALUE ? "max-width:"
+                            + maxSpannedWidthPx + "px;" : "" )
+                    + "overflow:hidden;max-height:" + normalHeightPt
+                    + "pt;white-space:nowrap;" );
+
+            innerDiv.appendChild( text );
+            outerDiv.appendChild( innerDiv );
+            tableCellElement.appendChild( outerDiv );
+        }
+        else
+        {
+            tableCellElement.appendChild( text );
+        }
 
         return ExcelToHtmlUtils.isEmpty( value ) && cellStyleIndex == 0;
     }
@@ -473,8 +596,8 @@ public class ExcelToHtmlConverter
                 continue;
 
             Element col = htmlDocumentFacade.createTableColumn();
-            col.setAttribute( "width", String.valueOf( ExcelToHtmlUtils
-                    .getColumnWidthInPx( sheet.getColumnWidth( c ) ) ) );
+            col.setAttribute( "width",
+                    String.valueOf( getColumnWidth( sheet, c ) ) );
             columnGroup.appendChild( col );
         }
         table.appendChild( columnGroup );
@@ -525,12 +648,40 @@ public class ExcelToHtmlConverter
             if ( !isOutputHiddenColumns() && sheet.isColumnHidden( colIx ) )
                 continue;
 
+            int divWidthPx = 0;
+            if ( isUseDivsToSpan() )
+            {
+                divWidthPx = getColumnWidth( sheet, colIx );
+
+                boolean hasBreaks = false;
+                for ( int nextColumnIndex = colIx + 1; nextColumnIndex < maxColIx; nextColumnIndex++ )
+                {
+                    if ( !isOutputHiddenColumns()
+                            && sheet.isColumnHidden( nextColumnIndex ) )
+                        continue;
+
+                    if ( row.getCell( nextColumnIndex ) != null
+                            && !isTextEmpty( row.getCell( nextColumnIndex ) ) )
+                    {
+                        hasBreaks = true;
+                        break;
+                    }
+
+                    divWidthPx += getColumnWidth( sheet, nextColumnIndex );
+                }
+
+                if ( !hasBreaks )
+                    divWidthPx = Integer.MAX_VALUE;
+            }
+
             Element tableCellElement = htmlDocumentFacade.createTableCell();
 
             boolean emptyCell;
             if ( cell != null )
             {
-                emptyCell = processCell( workbook, cell, tableCellElement );
+                emptyCell = processCell( workbook, cell, tableCellElement,
+                        getColumnWidth( sheet, colIx ), divWidthPx,
+                        row.getHeight() / 20f );
             }
             else
             {
@@ -592,6 +743,8 @@ public class ExcelToHtmlConverter
                 continue;
 
             Element tableRowElement = htmlDocumentFacade.createTableRow();
+            tableRowElement.setAttribute( "style",
+                    "height:" + ( row.getHeight() / 20f ) + "pt;" );
 
             int maxRowColumnNumber = processRow( workbook, sheet, row,
                     tableRowElement );
@@ -678,8 +831,27 @@ public class ExcelToHtmlConverter
         this.outputHiddenRows = outputZeroHeightRows;
     }
 
+    public void setOutputLeadingSpacesAsNonBreaking(
+            boolean outputPrePostSpacesAsNonBreaking )
+    {
+        this.outputLeadingSpacesAsNonBreaking = outputPrePostSpacesAsNonBreaking;
+    }
+
     public void setOutputRowNumbers( boolean outputRowNumbers )
     {
         this.outputRowNumbers = outputRowNumbers;
     }
+
+    /**
+     * Allows converter to wrap content into two additional DIVs with tricky
+     * styles, so it will wrap across empty cells (like in Excel).
+     * <p>
+     * <b>Warning:</b> after enabling this mode do not serialize result HTML
+     * with INDENT=YES option, because line breaks will make additional
+     * (unwanted) changes
+     */
+    public void setUseDivsToSpan( boolean useDivsToSpan )
+    {
+        this.useDivsToSpan = useDivsToSpan;
+    }
 }