fix styles output;

add columns and rows headers (optional, on by default);
output sheet headers as h2, not as h1;
output columns widths.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1146142 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sergey Vladimirov 2011-07-13 17:10:13 +00:00
parent ae3d9daaaa
commit ee7016f12e
3 changed files with 179 additions and 22 deletions

View File

@ -123,6 +123,10 @@ public class ExcelToHtmlConverter
private final HtmlDocumentFacade htmlDocumentFacade; private final HtmlDocumentFacade htmlDocumentFacade;
private boolean outputColumnHeaders = true;
private boolean outputRowNumbers = true;
private final Element styles; private final Element styles;
private final Set<Short> usedStyles = new LinkedHashSet<Short>(); private final Set<Short> usedStyles = new LinkedHashSet<Short>();
@ -249,11 +253,42 @@ public class ExcelToHtmlConverter
} }
} }
/**
* Generates name for output as column header in case
* <tt>{@link #isOutputColumnHeaders()} == true</tt>
*
* @param columnIndex
* 0-based column index
*/
protected String getColumnName( int columnIndex )
{
return String.valueOf( columnIndex + 1 );
}
public Document getDocument() public Document getDocument()
{ {
return htmlDocumentFacade.getDocument(); return htmlDocumentFacade.getDocument();
} }
/**
* Generates name for output as row number in case
* <tt>{@link #isOutputRowNumbers()} == true</tt>
*/
private String getRowName( HSSFRow row )
{
return String.valueOf( row.getRowNum() + 1 );
}
public boolean isOutputColumnHeaders()
{
return outputColumnHeaders;
}
public boolean isOutputRowNumbers()
{
return outputRowNumbers;
}
protected boolean processCell( HSSFCell cell, Element tableCellElement ) protected boolean processCell( HSSFCell cell, Element tableCellElement )
{ {
final HSSFCellStyle cellStyle = cell.getCellStyle(); final HSSFCellStyle cellStyle = cell.getCellStyle();
@ -348,6 +383,52 @@ public class ExcelToHtmlConverter
return ExcelToHtmlUtils.isEmpty( value ) && cellStyleIndex == 0; return ExcelToHtmlUtils.isEmpty( value ) && cellStyleIndex == 0;
} }
protected void processColumnHeaders( int maxSheetColumns, Element table )
{
Element tableHeader = htmlDocumentFacade.createTableHeader();
table.appendChild( tableHeader );
Element tr = htmlDocumentFacade.createTableRow();
if ( isOutputRowNumbers() )
{
// empty row at left-top corner
tr.appendChild( htmlDocumentFacade.createTableHeaderCell() );
}
for ( int c = 0; c < maxSheetColumns; c++ )
{
Element th = htmlDocumentFacade.createTableHeaderCell();
String text = getColumnName( c );
th.appendChild( htmlDocumentFacade.createText( text ) );
tr.appendChild( th );
}
tableHeader.appendChild( tr );
}
/**
* Creates COLGROUP element with width specified for all columns. (Except
* first if <tt>{@link #isOutputRowNumbers()}==true</tt>)
*/
protected void processColumnWidths( HSSFSheet sheet, int maxSheetColumns,
Element table )
{
// draw COLS after we know max column number
Element columnGroup = htmlDocumentFacade.createTableColumnGroup();
if ( isOutputRowNumbers() )
{
columnGroup.appendChild( htmlDocumentFacade.createTableColumn() );
}
for ( int c = 0; c < maxSheetColumns; c++ )
{
Element col = htmlDocumentFacade.createTableColumn();
col.setAttribute( "width", String.valueOf( ExcelToHtmlUtils
.getColumnWidthInPx( sheet.getColumnWidth( c ) ) ) );
columnGroup.appendChild( col );
}
table.appendChild( columnGroup );
}
protected void processDocumentInformation( protected void processDocumentInformation(
SummaryInformation summaryInformation ) SummaryInformation summaryInformation )
{ {
@ -365,16 +446,26 @@ public class ExcelToHtmlConverter
.addDescription( summaryInformation.getComments() ); .addDescription( summaryInformation.getComments() );
} }
protected boolean processRow( HSSFRow row, Element tableRowElement ) /**
* @return maximum 1-base index of column that were rendered, zero if none
*/
protected int processRow( HSSFRow row, Element tableRowElement )
{ {
boolean emptyRow = true;
final short maxColIx = row.getLastCellNum(); final short maxColIx = row.getLastCellNum();
if ( maxColIx <= 0 ) if ( maxColIx <= 0 )
return true; return 0;
final List<Element> emptyCells = new ArrayList<Element>( maxColIx ); final List<Element> emptyCells = new ArrayList<Element>( maxColIx );
if ( isOutputRowNumbers() )
{
Element tableRowNumberCellElement = htmlDocumentFacade
.createTableHeaderCell();
processRowNumber( row, tableRowNumberCellElement );
emptyCells.add( tableRowNumberCellElement );
}
int maxRenderedColumn = 0;
for ( int colIx = 0; colIx < maxColIx; colIx++ ) for ( int colIx = 0; colIx < maxColIx; colIx++ )
{ {
HSSFCell cell = row.getCell( colIx ); HSSFCell cell = row.getCell( colIx );
@ -404,18 +495,24 @@ public class ExcelToHtmlConverter
emptyCells.clear(); emptyCells.clear();
tableRowElement.appendChild( tableCellElement ); tableRowElement.appendChild( tableCellElement );
emptyRow = false; maxRenderedColumn = colIx;
} }
} }
return emptyRow; return maxRenderedColumn + 1;
}
protected void processRowNumber( HSSFRow row,
Element tableRowNumberCellElement )
{
tableRowNumberCellElement.setAttribute( "class", "rownumber" );
Text text = htmlDocumentFacade.createText( getRowName( row ) );
tableRowNumberCellElement.appendChild( text );
} }
protected void processSheet( HSSFSheet sheet ) protected void processSheet( HSSFSheet sheet )
{ {
Element h1 = htmlDocumentFacade.createHeader1(); processSheetHeader( htmlDocumentFacade.getBody(), sheet );
h1.appendChild( htmlDocumentFacade.createText( sheet.getSheetName() ) );
htmlDocumentFacade.getBody().appendChild( h1 );
final int physicalNumberOfRows = sheet.getPhysicalNumberOfRows(); final int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
if ( physicalNumberOfRows <= 0 ) if ( physicalNumberOfRows <= 0 )
@ -426,24 +523,24 @@ public class ExcelToHtmlConverter
final List<Element> emptyRowElements = new ArrayList<Element>( final List<Element> emptyRowElements = new ArrayList<Element>(
physicalNumberOfRows ); physicalNumberOfRows );
int maxSheetColumns = 1;
for ( int r = 0; r < physicalNumberOfRows; r++ ) for ( int r = 0; r < physicalNumberOfRows; r++ )
{ {
HSSFRow row = sheet.getRow( r ); HSSFRow row = sheet.getRow( r );
Element tableRowElement = htmlDocumentFacade.createTableRow(); Element tableRowElement = htmlDocumentFacade.createTableRow();
boolean emptyRow; int maxRowColumnNumber;
if ( row != null ) if ( row != null )
{ {
emptyRow = processRow( row, tableRowElement ); maxRowColumnNumber = processRow( row, tableRowElement );
} }
else else
{ {
emptyRow = true; maxRowColumnNumber = 0;
} }
if ( emptyRow ) if ( maxRowColumnNumber == 0 )
{ {
emptyRowElements.add( tableRowElement ); emptyRowElements.add( tableRowElement );
} }
@ -451,22 +548,37 @@ public class ExcelToHtmlConverter
{ {
if ( !emptyRowElements.isEmpty() ) if ( !emptyRowElements.isEmpty() )
{ {
for ( Element emptyCellElement : emptyRowElements ) for ( Element emptyRowElement : emptyRowElements )
{ {
tableBody.appendChild( emptyCellElement ); tableBody.appendChild( emptyRowElement );
} }
emptyRowElements.clear(); emptyRowElements.clear();
} }
tableBody.appendChild( tableRowElement ); tableBody.appendChild( tableRowElement );
emptyRow = false;
} }
maxSheetColumns = Math.max( maxSheetColumns, maxRowColumnNumber );
}
processColumnWidths( sheet, maxSheetColumns, table );
if ( isOutputColumnHeaders() )
{
processColumnHeaders( maxSheetColumns, table );
} }
table.appendChild( tableBody ); table.appendChild( tableBody );
htmlDocumentFacade.getBody().appendChild( table ); htmlDocumentFacade.getBody().appendChild( table );
} }
protected void processSheetHeader( Element htmlBody, HSSFSheet sheet )
{
Element h2 = htmlDocumentFacade.createHeader2();
h2.appendChild( htmlDocumentFacade.createText( sheet.getSheetName() ) );
htmlBody.appendChild( h2 );
}
public void processWorkbook( HSSFWorkbook workbook ) public void processWorkbook( HSSFWorkbook workbook )
{ {
final SummaryInformation summaryInformation = workbook final SummaryInformation summaryInformation = workbook
@ -476,6 +588,12 @@ public class ExcelToHtmlConverter
processDocumentInformation( summaryInformation ); processDocumentInformation( summaryInformation );
} }
for ( int s = 0; s < workbook.getNumberOfSheets(); s++ )
{
HSSFSheet sheet = workbook.getSheetAt( s );
processSheet( sheet );
}
for ( short i = 0; i < workbook.getNumCellStyles(); i++ ) for ( short i = 0; i < workbook.getNumCellStyles(); i++ )
{ {
HSSFCellStyle cellStyle = workbook.getCellStyleAt( i ); HSSFCellStyle cellStyle = workbook.getCellStyleAt( i );
@ -488,11 +606,15 @@ public class ExcelToHtmlConverter
.createText( "td.cellstyle_" + i + "{" .createText( "td.cellstyle_" + i + "{"
+ buildStyle( workbook, cellStyle ) + "}\n" ) ); + buildStyle( workbook, cellStyle ) + "}\n" ) );
} }
}
for ( int s = 0; s < workbook.getNumberOfSheets(); s++ ) public void setOutputColumnHeaders( boolean outputColumnHeaders )
{ {
HSSFSheet sheet = workbook.getSheetAt( s ); this.outputColumnHeaders = outputColumnHeaders;
processSheet( sheet ); }
}
public void setOutputRowNumbers( boolean outputRowNumbers )
{
this.outputRowNumbers = outputRowNumbers;
} }
} }

View File

@ -29,6 +29,9 @@ public class ExcelToHtmlUtils
{ {
static final String EMPTY = ""; static final String EMPTY = "";
private static final short EXCEL_COLUMN_WIDTH_FACTOR = 256;
private static final int UNIT_OFFSET_LENGTH = 7;
public static String getBorderStyle( short xlsBorder ) public static String getBorderStyle( short xlsBorder )
{ {
final String borderStyle; final String borderStyle;
@ -93,6 +96,23 @@ public class ExcelToHtmlUtils
return stringBuilder.toString(); return stringBuilder.toString();
} }
/**
* See <a href=
* "http://apache-poi.1045710.n5.nabble.com/Excel-Column-Width-Unit-Converter-pixels-excel-column-width-units-td2301481.html"
* >here</a> for Xio explanation and details
*/
public static int getColumnWidthInPx( int widthUnits )
{
int pixels = ( widthUnits / EXCEL_COLUMN_WIDTH_FACTOR )
* UNIT_OFFSET_LENGTH;
int offsetWidthUnits = widthUnits % EXCEL_COLUMN_WIDTH_FACTOR;
pixels += Math.round( offsetWidthUnits
/ ( (float) EXCEL_COLUMN_WIDTH_FACTOR / UNIT_OFFSET_LENGTH ) );
return pixels;
}
static boolean isEmpty( String str ) static boolean isEmpty( String str )
{ {
return str == null || str.length() == 0; return str == null || str.length() == 0;

View File

@ -75,6 +75,11 @@ public class HtmlDocumentFacade
return document.createElement( "h1" ); return document.createElement( "h1" );
} }
public Element createHeader2()
{
return document.createElement( "h2" );
}
public Element createHyperlink( String internalDestination ) public Element createHyperlink( String internalDestination )
{ {
final Element basicLink = document.createElement( "a" ); final Element basicLink = document.createElement( "a" );
@ -112,6 +117,16 @@ public class HtmlDocumentFacade
return document.createElement( "td" ); return document.createElement( "td" );
} }
public Element createTableColumn()
{
return document.createElement( "col" );
}
public Element createTableColumnGroup()
{
return document.createElement( "colgroup" );
}
public Element createTableHeader() public Element createTableHeader()
{ {
return document.createElement( "thead" ); return document.createElement( "thead" );