]> source.dussan.org Git - poi.git/commitdiff
Fix table processing. Spanned columns / different width / spanned rows are correcly...
authorSergey Vladimirov <sergey@apache.org>
Fri, 22 Jul 2011 12:49:29 +0000 (12:49 +0000)
committerSergey Vladimirov <sergey@apache.org>
Fri, 22 Jul 2011 12:49:29 +0000 (12:49 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1149593 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java

index 78198ce5966313c773a6823490ad651d30cbfb26..38968f082f0f48837c2f19a24b23ab83b778cdc5 100644 (file)
@@ -41,6 +41,8 @@ import org.apache.poi.hwpf.usermodel.Picture;
 import org.apache.poi.hwpf.usermodel.Range;
 import org.apache.poi.hwpf.usermodel.Section;
 import org.apache.poi.hwpf.usermodel.Table;
+import org.apache.poi.hwpf.usermodel.TableCell;
+import org.apache.poi.hwpf.usermodel.TableRow;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
 import org.w3c.dom.Document;
@@ -86,6 +88,68 @@ public abstract class AbstractWordConverter
         return fontReplacer;
     }
 
+    protected int getNumberColumnsSpanned( int[] tableCellEdges,
+            int currentEdgeIndex, TableCell tableCell )
+    {
+        int nextEdgeIndex = currentEdgeIndex;
+        int colSpan = 0;
+        int cellRightEdge = tableCell.getLeftEdge() + tableCell.getWidth();
+        while ( tableCellEdges[nextEdgeIndex] < cellRightEdge )
+        {
+            colSpan++;
+            nextEdgeIndex++;
+        }
+        return colSpan;
+    }
+
+    protected int getNumberRowsSpanned( Table table, int currentRowIndex,
+            int currentColumnIndex, TableCell tableCell )
+    {
+        if ( !tableCell.isFirstVerticallyMerged() )
+            return 1;
+
+        final int numRows = table.numRows();
+
+        int count = 1;
+        for ( int r1 = currentRowIndex + 1; r1 < numRows; r1++ )
+        {
+            TableRow nextRow = table.getRow( r1 );
+            if ( nextRow.numCells() < currentColumnIndex )
+                break;
+            TableCell nextCell = nextRow.getCell( currentColumnIndex );
+            if ( !nextCell.isVerticallyMerged()
+                    || nextCell.isFirstVerticallyMerged() )
+                break;
+            count++;
+        }
+        return count;
+    }
+
+    protected int getTableCellEdgesIndexSkipCount( Table table, int r,
+            int[] tableCellEdges, int currentEdgeIndex, int c,
+            TableCell tableCell )
+    {
+        TableCell upperCell = null;
+        for ( int r1 = r - 1; r1 >= 0; r1-- )
+        {
+            final TableCell prevCell = table.getRow( r1 ).getCell( c );
+            if ( prevCell != null && prevCell.isFirstVerticallyMerged() )
+            {
+                upperCell = prevCell;
+                break;
+            }
+        }
+        if ( upperCell == null )
+        {
+            logger.log( POILogger.WARN, "First vertically merged cell for ",
+                    tableCell, " not found" );
+            return 0;
+        }
+
+        return getNumberColumnsSpanned( tableCellEdges, currentEdgeIndex,
+                tableCell );
+    }
+
     protected abstract void outputCharacters( Element block,
             CharacterRun characterRun, String text );
 
@@ -211,7 +275,7 @@ public abstract class AbstractWordConverter
             }
 
             if ( text.endsWith( "\r" )
-                    || ( text.charAt( text.length() - 1 ) == BEL_MARK && currentTableLevel != 0 ) )
+                    || ( text.charAt( text.length() - 1 ) == BEL_MARK && currentTableLevel != Integer.MIN_VALUE ) )
                 text = text.substring( 0, text.length() - 1 );
 
             {
@@ -239,7 +303,8 @@ public abstract class AbstractWordConverter
                         // Non-required hyphens to zero-width space
                         stringBuilder.append( UNICODECHAR_ZERO_WIDTH_SPACE );
                     }
-                    else
+                    else if ( charChar > 0x20 || charChar == 0x09
+                            || charChar == 0x0A || charChar == 0x0D )
                     {
                         stringBuilder.append( charChar );
                     }
index ca5b4a89e549a49a7bc00ba2adac64c80e45c148..4991fbc566117f13fbcc01f35f5deb263300de11 100644 (file)
@@ -54,6 +54,28 @@ import org.w3c.dom.Text;
 public class WordToFoConverter extends AbstractWordConverter
 {
 
+    /**
+     * Holds properties values, applied to current <tt>fo:block</tt> element.
+     * Those properties shall not be doubled in children <tt>fo:inline</tt>
+     * elements.
+     */
+    private static class BlockProperies
+    {
+        final boolean pBold;
+        final String pFontName;
+        final int pFontSize;
+        final boolean pItalic;
+
+        public BlockProperies( String pFontName, int pFontSize, boolean pBold,
+                boolean pItalic )
+        {
+            this.pFontName = pFontName;
+            this.pFontSize = pFontSize;
+            this.pBold = pBold;
+            this.pItalic = pItalic;
+        }
+    }
+
     private static final POILogger logger = POILogFactory
             .getLogger( WordToFoConverter.class );
 
@@ -513,26 +535,22 @@ public class WordToFoConverter extends AbstractWordConverter
             {
                 TableCell tableCell = tableRow.getCell( c );
 
-                if ( tableCell.isMerged() && !tableCell.isFirstMerged() )
-                    continue;
-
                 if ( tableCell.isVerticallyMerged()
                         && !tableCell.isFirstVerticallyMerged() )
+                {
+                    currentEdgeIndex += getTableCellEdgesIndexSkipCount( table,
+                            r, tableCellEdges, currentEdgeIndex, c, tableCell );
                     continue;
+                }
 
                 Element tableCellElement = foDocumentFacade.createTableCell();
                 WordToFoUtils.setTableCellProperties( tableRow, tableCell,
                         tableCellElement, r == 0, r == tableRows - 1, c == 0,
                         c == rowCells - 1 );
 
-                int colSpan = 0;
-                int cellRightEdge = tableCell.getLeftEdge()
-                        + tableCell.getWidth();
-                while ( tableCellEdges[currentEdgeIndex] < cellRightEdge )
-                {
-                    colSpan++;
-                    currentEdgeIndex++;
-                }
+                int colSpan = getNumberColumnsSpanned( tableCellEdges,
+                        currentEdgeIndex, tableCell );
+                currentEdgeIndex += colSpan;
 
                 if ( colSpan == 0 )
                     continue;
@@ -541,24 +559,11 @@ public class WordToFoConverter extends AbstractWordConverter
                     tableCellElement.setAttribute( "number-columns-spanned",
                             String.valueOf( colSpan ) );
 
-                if ( tableCell.isFirstVerticallyMerged() )
-                {
-                    int count = 0;
-                    for ( int r1 = r; r1 < tableRows; r1++ )
-                    {
-                        TableRow nextRow = table.getRow( r1 );
-                        if ( nextRow.numCells() < c )
-                            break;
-                        TableCell nextCell = nextRow.getCell( c );
-                        if ( nextCell.isVerticallyMerged() )
-                            count++;
-                        if ( !nextCell.isVerticallyMerged() )
-                            break;
-                    }
-                    if ( count > 1 )
-                        tableCellElement.setAttribute( "number-rows-spanned",
-                                String.valueOf( count ) );
-                }
+                final int rowSpan = getNumberRowsSpanned( table, r, c,
+                        tableCell );
+                if ( rowSpan > 1 )
+                    tableCellElement.setAttribute( "number-rows-spanned",
+                            String.valueOf( rowSpan ) );
 
                 processParagraphes( wordDocument, tableCellElement, tableCell,
                         table.getTableLevel() );
@@ -572,17 +577,21 @@ public class WordToFoConverter extends AbstractWordConverter
                 tableRowElement.appendChild( tableCellElement );
             }
 
-            if ( tableRow.isTableHeader() )
+            if ( tableRowElement.hasChildNodes() )
             {
-                tableHeader.appendChild( tableRowElement );
-            }
-            else
-            {
-                tableBody.appendChild( tableRowElement );
+                if ( tableRow.isTableHeader() )
+                {
+                    tableHeader.appendChild( tableRowElement );
+                }
+                else
+                {
+                    tableBody.appendChild( tableRowElement );
+                }
             }
         }
 
         final Element tableElement = foDocumentFacade.createTable();
+        tableElement.setAttribute( "table-layout", "fixed" );
         if ( tableHeader.hasChildNodes() )
         {
             tableElement.appendChild( tableHeader );
@@ -602,26 +611,4 @@ public class WordToFoConverter extends AbstractWordConverter
         }
     }
 
-    /**
-     * Holds properties values, applied to current <tt>fo:block</tt> element.
-     * Those properties shall not be doubled in children <tt>fo:inline</tt>
-     * elements.
-     */
-    private static class BlockProperies
-    {
-        final boolean pBold;
-        final String pFontName;
-        final int pFontSize;
-        final boolean pItalic;
-
-        public BlockProperies( String pFontName, int pFontSize, boolean pBold,
-                boolean pItalic )
-        {
-            this.pFontName = pFontName;
-            this.pFontSize = pFontSize;
-            this.pBold = pBold;
-            this.pItalic = pItalic;
-        }
-    }
-
 }
index 72410abc7f10ee9a30feecd90bd002acaee1b031..75701ba3baab6e9ff8147377c5b876db6c092dbd 100644 (file)
@@ -61,6 +61,22 @@ import static org.apache.poi.hwpf.converter.AbstractWordUtils.TWIPS_PER_INCH;
 public class WordToHtmlConverter extends AbstractWordConverter
 {
 
+    /**
+     * Holds properties values, applied to current <tt>p</tt> element. Those
+     * properties shall not be doubled in children <tt>span</tt> elements.
+     */
+    private static class BlockProperies
+    {
+        final String pFontName;
+        final int pFontSize;
+
+        public BlockProperies( String pFontName, int pFontSize )
+        {
+            this.pFontName = pFontName;
+            this.pFontSize = pFontSize;
+        }
+    }
+
     private static final POILogger logger = POILogFactory
             .getLogger( WordToHtmlConverter.class );
 
@@ -584,7 +600,11 @@ public class WordToHtmlConverter extends AbstractWordConverter
 
                 if ( tableCell.isVerticallyMerged()
                         && !tableCell.isFirstVerticallyMerged() )
+                {
+                    currentEdgeIndex += getTableCellEdgesIndexSkipCount( table,
+                            r, tableCellEdges, currentEdgeIndex, c, tableCell );
                     continue;
+                }
 
                 Element tableCellElement;
                 if ( tableRow.isTableHeader() )
@@ -601,42 +621,22 @@ public class WordToHtmlConverter extends AbstractWordConverter
                         r == 0, r == tableRows - 1, c == 0, c == rowCells - 1,
                         tableCellStyle );
 
-                int colSpan = 0;
-                int cellRightEdge = tableCell.getLeftEdge()
-                        + tableCell.getWidth();
-                while ( tableCellEdges[currentEdgeIndex] < cellRightEdge )
-                {
-                    colSpan++;
-                    currentEdgeIndex++;
-                }
+                int colSpan = getNumberColumnsSpanned( tableCellEdges,
+                        currentEdgeIndex, tableCell );
+                currentEdgeIndex += colSpan;
 
                 if ( colSpan == 0 )
                     continue;
 
                 if ( colSpan != 1 )
-                {
                     tableCellElement.setAttribute( "colspan",
                             String.valueOf( colSpan ) );
-                }
 
-                if ( tableCell.isFirstVerticallyMerged() )
-                {
-                    int count = 1;
-                    for ( int r1 = r + 1; r1 < tableRows; r1++ )
-                    {
-                        TableRow nextRow = table.getRow( r1 );
-                        if ( nextRow.numCells() < c )
-                            break;
-                        TableCell nextCell = nextRow.getCell( c );
-                        if ( !nextCell.isVerticallyMerged()
-                                || nextCell.isFirstVerticallyMerged() )
-                            break;
-                        count++;
-                    }
-                    if ( count > 1 )
-                        tableCellElement.setAttribute( "rowspan",
-                                String.valueOf( count ) );
-                }
+                final int rowSpan = getNumberRowsSpanned( table, r, c,
+                        tableCell );
+                if ( rowSpan > 1 )
+                    tableCellElement.setAttribute( "rowspan",
+                            String.valueOf( rowSpan ) );
 
                 processParagraphes( hwpfDocument, tableCellElement, tableCell,
                         table.getTableLevel() );
@@ -695,20 +695,4 @@ public class WordToHtmlConverter extends AbstractWordConverter
         }
     }
 
-    /**
-     * Holds properties values, applied to current <tt>p</tt> element. Those
-     * properties shall not be doubled in children <tt>span</tt> elements.
-     */
-    private static class BlockProperies
-    {
-        final String pFontName;
-        final int pFontSize;
-
-        public BlockProperies( String pFontName, int pFontSize )
-        {
-            this.pFontName = pFontName;
-            this.pFontSize = pFontSize;
-        }
-    }
-
 }