From 106e3e0dfe40cf3cb9a3c009361d747fb36b982e Mon Sep 17 00:00:00 2001 From: Sergey Vladimirov Date: Fri, 22 Jul 2011 12:49:29 +0000 Subject: [PATCH] Fix table processing. Spanned columns / different width / spanned rows are correcly rendered in HTML and FO now git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1149593 13f79535-47bb-0310-9956-ffa450edef68 --- .../hwpf/converter/AbstractWordConverter.java | 69 +++++++++++- .../poi/hwpf/converter/WordToFoConverter.java | 101 ++++++++---------- .../hwpf/converter/WordToHtmlConverter.java | 72 +++++-------- 3 files changed, 139 insertions(+), 103 deletions(-) diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java index 78198ce596..38968f082f 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/AbstractWordConverter.java @@ -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 ); } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java index ca5b4a89e5..4991fbc566 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java @@ -54,6 +54,28 @@ import org.w3c.dom.Text; public class WordToFoConverter extends AbstractWordConverter { + /** + * Holds properties values, applied to current fo:block element. + * Those properties shall not be doubled in children fo:inline + * 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 fo:block element. - * Those properties shall not be doubled in children fo:inline - * 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; - } - } - } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java index 72410abc7f..75701ba3ba 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java @@ -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 p element. Those + * properties shall not be doubled in children span 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 p element. Those - * properties shall not be doubled in children span elements. - */ - private static class BlockProperies - { - final String pFontName; - final int pFontSize; - - public BlockProperies( String pFontName, int pFontSize ) - { - this.pFontName = pFontName; - this.pFontSize = pFontSize; - } - } - } -- 2.39.5