diff options
Diffstat (limited to 'oox/source/xls/sheetdatacontext.cxx')
-rw-r--r-- | oox/source/xls/sheetdatacontext.cxx | 870 |
1 files changed, 442 insertions, 428 deletions
diff --git a/oox/source/xls/sheetdatacontext.cxx b/oox/source/xls/sheetdatacontext.cxx index c515ec02bfbe..00c4e21d82e7 100644 --- a/oox/source/xls/sheetdatacontext.cxx +++ b/oox/source/xls/sheetdatacontext.cxx @@ -27,8 +27,6 @@ #include "oox/xls/sheetdatacontext.hxx" -#include <com/sun/star/sheet/XArrayFormulaTokens.hpp> -#include <com/sun/star/sheet/XFormulaTokens.hpp> #include <com/sun/star/table/CellContentType.hpp> #include <com/sun/star/table/XCell.hpp> #include <com/sun/star/table/XCellRange.hpp> @@ -39,7 +37,6 @@ #include "oox/xls/biffinputstream.hxx" #include "oox/xls/formulaparser.hxx" #include "oox/xls/richstringcontext.hxx" -#include "oox/xls/sharedformulabuffer.hxx" #include "oox/xls/unitconverter.hxx" namespace oox { @@ -98,64 +95,31 @@ const sal_uInt32 BIFF_ROW_THICKTOP = 0x10000000; const sal_uInt32 BIFF_ROW_THICKBOTTOM = 0x20000000; const sal_uInt32 BIFF_ROW_SHOWPHONETIC = 0x40000000; -const sal_Int32 BIFF2_XF_EXTENDED_IDS = 63; -const sal_uInt8 BIFF2_XF_MASK = 0x3F; +const sal_Int32 BIFF2_CELL_USEIXFE = 63; -// ---------------------------------------------------------------------------- - -/** Formula context for cell formulas. */ -class CellFormulaContext : public SimpleFormulaContext -{ -public: - explicit CellFormulaContext( - const Reference< XFormulaTokens >& rxTokens, - const CellAddress& rCellPos ); -}; - -CellFormulaContext::CellFormulaContext( const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) : - SimpleFormulaContext( rxTokens, false, false ) -{ - setBaseAddress( rCellPos ); -} - -// ---------------------------------------------------------------------------- - -/** Uses the XArrayFormulaTokens interface to set a token sequence. */ -class ArrayFormulaContext : public FormulaContext -{ -public: - explicit ArrayFormulaContext( - const Reference< XArrayFormulaTokens >& rxTokens, - const CellRangeAddress& rArrayRange ); - - virtual void setTokens( const ApiTokenSequence& rTokens ); +} // namespace -private: - Reference< XArrayFormulaTokens > mxTokens; -}; +// ============================================================================ -ArrayFormulaContext::ArrayFormulaContext( - const Reference< XArrayFormulaTokens >& rxTokens, const CellRangeAddress& rArrayRange ) : - FormulaContext( false, false ), - mxTokens( rxTokens ) +SheetDataContextBase::SheetDataContextBase( const WorksheetHelper& rHelper ) : + mrAddressConv( rHelper.getAddressConverter() ), + mrFormulaParser( rHelper.getFormulaParser() ), + mrSheetData( rHelper.getSheetData() ), + mnSheet( rHelper.getSheetIndex() ) { - OSL_ENSURE( mxTokens.is(), "ArrayFormulaContext::ArrayFormulaContext - missing XArrayFormulaTokens interface" ); - setBaseAddress( CellAddress( rArrayRange.Sheet, rArrayRange.StartColumn, rArrayRange.StartRow ) ); } -void ArrayFormulaContext::setTokens( const ApiTokenSequence& rTokens ) +SheetDataContextBase::~SheetDataContextBase() { - mxTokens->setArrayTokens( rTokens ); } -// ---------------------------------------------------------------------------- - -} // namespace - // ============================================================================ SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) : - WorksheetContextBase( rFragment ) + WorksheetContextBase( rFragment ), + SheetDataContextBase( rFragment ), + mbHasFormula( false ), + mbValidRange( false ) { } @@ -168,20 +132,22 @@ ContextHandlerRef SheetDataContext::onCreateContext( sal_Int32 nElement, const A break; case XLS_TOKEN( row ): - if( nElement == XLS_TOKEN( c ) ) { importCell( rAttribs ); return this; } + // do not process cell elements with invalid (out-of-range) address + if( nElement == XLS_TOKEN( c ) && importCell( rAttribs ) ) + return this; break; case XLS_TOKEN( c ): - if( maCurrCell.mxCell.is() ) switch( nElement ) + switch( nElement ) { case XLS_TOKEN( is ): mxInlineStr.reset( new RichString( *this ) ); return new RichStringContext( *this, mxInlineStr ); case XLS_TOKEN( v ): - return this; + return this; // characters contain cell value case XLS_TOKEN( f ): importFormula( rAttribs ); - return this; + return this; // characters contain formula string } break; } @@ -193,94 +159,86 @@ void SheetDataContext::onCharacters( const OUString& rChars ) switch( getCurrentElement() ) { case XLS_TOKEN( v ): - maCurrCell.maValueStr = rChars; - maCurrCell.mbHasValueStr = true; + maCellValue = rChars; break; - case XLS_TOKEN( f ): - if( maCurrCell.mxCell.is() ) try - { - switch( maCurrCell.mnFormulaType ) - { - case XML_normal: - if( rChars.getLength() > 0 ) - { - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW ); - CellFormulaContext aContext( xTokens, maCurrCell.maAddress ); - getFormulaParser().importFormula( aContext, rChars ); - } - break; - - case XML_array: - if( (maCurrCell.maFormulaRef.getLength() > 0) && (rChars.getLength() > 0) ) - { - CellRangeAddress aArrayRange; - Reference< XArrayFormulaTokens > xTokens( getCellRange( maCurrCell.maFormulaRef, &aArrayRange ), UNO_QUERY_THROW ); - ArrayFormulaContext aContext( xTokens, aArrayRange ); - getFormulaParser().importFormula( aContext, rChars ); - } - break; - - case XML_shared: - if( maCurrCell.mnSharedId >= 0 ) - { - if( rChars.getLength() > 0 ) - getSharedFormulas().importSharedFmla( rChars, maCurrCell.maFormulaRef, maCurrCell.mnSharedId, maCurrCell.maAddress ); - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW ); - ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); - getSharedFormulas().setSharedFormulaCell( aContext, maCurrCell.mnSharedId ); - } - break; - - case XML_dataTable: - if( maCurrCell.maFormulaRef.getLength() > 0 ) - { - CellRangeAddress aTableRange; - if( getAddressConverter().convertToCellRange( aTableRange, maCurrCell.maFormulaRef, getSheetIndex(), true, true ) ) - setTableOperation( aTableRange, maTableData ); - } - break; - - default: - OSL_ENSURE( false, "SheetDataContext::onCharacters - unknown formula type" ); - } - } - catch( Exception& ) - { - } + if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID ) + maTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, rChars ); break; } } void SheetDataContext::onEndElement() { - if( isCurrentElement( XLS_TOKEN( c ) ) && maCurrCell.mxCell.is() ) + if( getCurrentElement() == XLS_TOKEN( c ) ) { - if( maCurrCell.mxCell->getType() == CellContentType_EMPTY ) + // try to create a formula cell + if( mbHasFormula ) switch( maFmlaData.mnFormulaType ) + { + case XML_normal: + mrSheetData.setFormulaCell( maCellData, maTokens ); + break; + case XML_shared: + if( maFmlaData.mnSharedId >= 0 ) + { + if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + mrSheetData.createSharedFormula( maFmlaData.mnSharedId, maTokens ); + mrSheetData.setFormulaCell( maCellData, maFmlaData.mnSharedId ); + } + else + // no success, set plain cell value and formatting below + mbHasFormula = false; + break; + case XML_array: + if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, maTokens ); + // set cell formatting, but do not set result as cell value + mrSheetData.setBlankCell( maCellData ); + break; + case XML_dataTable: + if( mbValidRange ) + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData ); + // set cell formatting, but do not set result as cell value + mrSheetData.setBlankCell( maCellData ); + break; + default: + OSL_ENSURE( maFmlaData.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onEndElement - unknown formula type" ); + mbHasFormula = false; + } + + if( !mbHasFormula ) { - if( maCurrCell.mbHasValueStr ) + // no formula created: try to set the cell value + if( maCellValue.getLength() > 0 ) switch( maCellData.mnCellType ) { - // implemented in WorksheetHelper class - setCell( maCurrCell ); + case XML_n: + mrSheetData.setValueCell( maCellData, maCellValue.toDouble() ); + break; + case XML_b: + mrSheetData.setBooleanCell( maCellData, maCellValue.toDouble() != 0.0 ); + break; + case XML_e: + mrSheetData.setErrorCell( maCellData, maCellValue ); + break; + case XML_str: + mrSheetData.setStringCell( maCellData, maCellValue ); + break; + case XML_s: + mrSheetData.setStringCell( maCellData, maCellValue.toInt32() ); + break; } - else if( (maCurrCell.mnCellType == XML_inlineStr) && mxInlineStr.get() ) + else if( (maCellData.mnCellType == XML_inlineStr) && mxInlineStr.get() ) { - // convert font settings mxInlineStr->finalizeImport(); - // write string to cell - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() ) - mxInlineStr->convert( xText, maCurrCell.mnXfId ); + mrSheetData.setStringCell( maCellData, mxInlineStr ); } else { // empty cell, update cell type - maCurrCell.mnCellType = XML_TOKEN_INVALID; + maCellData.mnCellType = XML_TOKEN_INVALID; + mrSheetData.setBlankCell( maCellData ); } } - - // store the cell formatting data - setCellFormat( maCurrCell ); } } @@ -289,10 +247,7 @@ ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, Seq switch( getCurrentElement() ) { case BIFF12_ID_SHEETDATA: - switch( nRecId ) - { - case BIFF12_ID_ROW: importRow( rStrm ); return this; - } + if( nRecId == BIFF12_ID_ROW ) { importRow( rStrm ); return this; } break; case BIFF12_ID_ROW: @@ -332,7 +287,7 @@ ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, Seq void SheetDataContext::importRow( const AttributeList& rAttribs ) { RowModel aModel; - aModel.mnFirstRow = aModel.mnLastRow = rAttribs.getInteger( XML_r, -1 ); + aModel.mnRow = rAttribs.getInteger( XML_r, -1 ); aModel.mfHeight = rAttribs.getDouble( XML_ht, -1.0 ); aModel.mnXfId = rAttribs.getInteger( XML_s, -1 ); aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); @@ -343,41 +298,106 @@ void SheetDataContext::importRow( const AttributeList& rAttribs ) aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); aModel.mbThickTop = rAttribs.getBool( XML_thickTop, false ); aModel.mbThickBottom = rAttribs.getBool( XML_thickBot, false ); + + // decode the column spans (space-separated list of colon-separated integer pairs) + OUString aColSpansText = rAttribs.getString( XML_spans, OUString() ); + sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Column; + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + OUString aColSpanToken = aColSpansText.getToken( 0, ' ', nIndex ); + sal_Int32 nSepPos = aColSpanToken.indexOf( ':' ); + if( (0 < nSepPos) && (nSepPos + 1 < aColSpanToken.getLength()) ) + { + // OOXML uses 1-based integer column indexes, row model expects 0-based colspans + sal_Int32 nLastCol = ::std::min( aColSpanToken.copy( nSepPos + 1 ).toInt32() - 1, nMaxCol ); + aModel.insertColSpan( ValueRange( aColSpanToken.copy( 0, nSepPos ).toInt32() - 1, nLastCol ) ); + } + } + // set row properties in the current sheet setRowModel( aModel ); } -void SheetDataContext::importCell( const AttributeList& rAttribs ) +bool SheetDataContext::importCell( const AttributeList& rAttribs ) { - maCurrCell.reset(); - maCurrCell.mxCell = getCell( rAttribs.getString( XML_r, OUString() ), &maCurrCell.maAddress ); - maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n ); - maCurrCell.mnXfId = rAttribs.getInteger( XML_s, -1 ); - maCurrCell.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); - mxInlineStr.reset(); + bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAttribs.getString( XML_r, OUString() ), mnSheet, true ); + if( bValidAddr ) + { + maCellData.mnCellType = rAttribs.getToken( XML_t, XML_n ); + maCellData.mnXfId = rAttribs.getInteger( XML_s, -1 ); + maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); - // update used area of the sheet - if( maCurrCell.mxCell.is() ) - extendUsedArea( maCurrCell.maAddress ); + // reset cell value, formula settings, and inline string + maCellValue = OUString(); + mxInlineStr.reset(); + mbHasFormula = false; + + // update used area of the sheet + extendUsedArea( maCellData.maCellAddr ); + } + return bValidAddr; } void SheetDataContext::importFormula( const AttributeList& rAttribs ) { - maCurrCell.maFormulaRef = rAttribs.getString( XML_ref, OUString() ); - maCurrCell.mnFormulaType = rAttribs.getToken( XML_t, XML_normal ); - maCurrCell.mnSharedId = rAttribs.getInteger( XML_si, -1 ); - maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() ); - maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() ); - maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false ); - maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false ); - maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false ); - maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false ); + mbHasFormula = true; + mbValidRange = mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, rAttribs.getString( XML_ref, OUString() ), mnSheet, true, true ); + + maFmlaData.mnFormulaType = rAttribs.getToken( XML_t, XML_normal ); + maFmlaData.mnSharedId = rAttribs.getInteger( XML_si, -1 ); + + if( maFmlaData.mnFormulaType == XML_dataTable ) + { + maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() ); + maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() ); + maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false ); + maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false ); + maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false ); + maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false ); + } + + // clear token array, will be regenerated from element text + maTokens = ApiTokenSequence(); } -void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eCellType ) +void SheetDataContext::importRow( SequenceInputStream& rStrm ) { - maCurrCell.reset(); + RowModel aModel; + sal_Int32 nSpanCount; + sal_uInt16 nHeight, nFlags1; + sal_uInt8 nFlags2; + rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2 >> nSpanCount; + maCurrPos.mnCol = 0; + // row index is 0-based in BIFF12, but RowModel expects 1-based + aModel.mnRow = maCurrPos.mnRow + 1; + // row height is in twips in BIFF12, convert to points + aModel.mfHeight = nHeight / 20.0; + aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 ); + aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT ); + aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT ); + aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC ); + aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN ); + aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED ); + aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP ); + aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM ); + + // read the column spans + sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Column; + for( sal_Int32 nSpanIdx = 0; (nSpanIdx < nSpanCount) && !rStrm.isEof(); ++nSpanIdx ) + { + sal_Int32 nFirstCol, nLastCol; + rStrm >> nFirstCol >> nLastCol; + aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) ); + } + + // set row properties in the current sheet + setRowModel( aModel ); +} + +bool SheetDataContext::readCellHeader( SequenceInputStream& rStrm, CellType eCellType ) +{ switch( eCellType ) { case CELLTYPE_VALUE: @@ -388,200 +408,157 @@ void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eC sal_uInt32 nXfId; rStrm >> nXfId; - maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress ); - maCurrCell.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 ); - maCurrCell.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC ); + bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, maCurrPos, mnSheet, true ); + maCellData.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 ); + maCellData.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC ); // update used area of the sheet - if( maCurrCell.mxCell.is() ) - extendUsedArea( maCurrCell.maAddress ); + if( bValidAddr ) + extendUsedArea( maCellData.maCellAddr ); + return bValidAddr; +} + +ApiTokenSequence SheetDataContext::readCellFormula( SequenceInputStream& rStrm ) +{ + rStrm.skip( 2 ); + return mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm ); +} + +bool SheetDataContext::readFormulaRef( SequenceInputStream& rStrm ) +{ + BinRange aRange; + rStrm >> aRange; + return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true ); } void SheetDataContext::importCellBool( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_b; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { + maCellData.mnCellType = XML_b; bool bValue = rStrm.readuInt8() != 0; if( eCellType == CELLTYPE_FORMULA ) - { - importCellFormula( rStrm ); - } + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - { - setBooleanCell( maCurrCell.mxCell, bValue ); - // #108770# set 'Standard' number format for all Boolean cells - maCurrCell.mnNumFmtId = 0; - } + mrSheetData.setBooleanCell( maCellData, bValue ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellBlank( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellBlank - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, eCellType ) ) + mrSheetData.setBlankCell( maCellData ); } void SheetDataContext::importCellDouble( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { + maCellData.mnCellType = XML_n; double fValue = rStrm.readDouble(); if( eCellType == CELLTYPE_FORMULA ) - importCellFormula( rStrm ); + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - maCurrCell.mxCell->setValue( fValue ); + mrSheetData.setValueCell( maCellData, fValue ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellError( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_e; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { + maCellData.mnCellType = XML_e; sal_uInt8 nErrorCode = rStrm.readuInt8(); if( eCellType == CELLTYPE_FORMULA ) - importCellFormula( rStrm ); + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - setErrorCell( maCurrCell.mxCell, nErrorCode ); + mrSheetData.setErrorCell( maCellData, nErrorCode ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellRk( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRk - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) - maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); + } } void SheetDataContext::importCellRString( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRString - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_inlineStr; - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { - RichString aString( *this ); - aString.importString( rStrm, true ); - aString.finalizeImport(); - aString.convert( xText, maCurrCell.mnXfId ); + maCellData.mnCellType = XML_inlineStr; + RichStringRef xString( new RichString( *this ) ); + xString->importString( rStrm, true ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellSi( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellSi - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_s; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) - setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_s; + mrSheetData.setStringCell( maCellData, rStrm.readInt32() ); + } } void SheetDataContext::importCellString( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_inlineStr; - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { - RichString aString( *this ); - aString.importString( rStrm, false ); - aString.finalizeImport(); + maCellData.mnCellType = XML_inlineStr; + // always import the string, stream will point to formula afterwards, if existing + RichStringRef xString( new RichString( *this ) ); + xString->importString( rStrm, false ); + xString->finalizeImport(); if( eCellType == CELLTYPE_FORMULA ) - importCellFormula( rStrm ); + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - aString.convert( xText, maCurrCell.mnXfId ); + mrSheetData.setStringCell( maCellData, xString ); } - setCellFormat( maCurrCell ); -} - -void SheetDataContext::importCellFormula( SequenceInputStream& rStrm ) -{ - rStrm.skip( 2 ); - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY ); - if( xTokens.is() ) - { - ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); - getFormulaParser().importFormula( aContext, rStrm ); - } -} - -void SheetDataContext::importRow( SequenceInputStream& rStrm ) -{ - RowModel aModel; - - sal_uInt16 nHeight, nFlags1; - sal_uInt8 nFlags2; - rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2; - - // row index is 0-based in BIFF12, but RowModel expects 1-based - aModel.mnFirstRow = aModel.mnLastRow = maCurrPos.mnRow + 1; - // row height is in twips in BIFF12, convert to points - aModel.mfHeight = nHeight / 20.0; - aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 ); - aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT ); - aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT ); - aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC ); - aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN ); - aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED ); - aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP ); - aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM ); - // set row properties in the current sheet - setRowModel( aModel ); } void SheetDataContext::importArray( SequenceInputStream& rStrm ) { - BinRange aRange; - rStrm >> aRange; - CellRangeAddress aArrayRange; - Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange ); - Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY ); - if( xRange.is() && xTokens.is() ) + if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) { rStrm.skip( 1 ); - ArrayFormulaContext aContext( xTokens, aArrayRange ); - getFormulaParser().importFormula( aContext, rStrm ); + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm ); + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens ); } } -void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm ) -{ - getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress ); -} - void SheetDataContext::importDataTable( SequenceInputStream& rStrm ) { - BinRange aRange; - rStrm >> aRange; - CellRangeAddress aTableRange; - if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) ) + if( readFormulaRef( rStrm ) ) { - DataTableModel aModel; BinAddress aRef1, aRef2; sal_uInt8 nFlags; rStrm >> aRef1 >> aRef2 >> nFlags; - aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); - aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); - aModel.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW ); - aModel.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D ); - aModel.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL ); - aModel.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL ); - setTableOperation( aTableRange, aModel ); + maTableData.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); + maTableData.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); + maTableData.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW ); + maTableData.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D ); + maTableData.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL ); + maTableData.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL ); + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData ); + } +} + +void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm ) +{ + if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + { + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm ); + mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens ); } } @@ -589,26 +566,27 @@ void SheetDataContext::importDataTable( SequenceInputStream& rStrm ) BiffSheetDataContext::BiffSheetDataContext( const WorksheetHelper& rHelper ) : BiffWorksheetContextBase( rHelper ), + SheetDataContextBase( rHelper ), mnBiff2XfId( 0 ) { - mnArrayIgnoreSize = (getBiff() == BIFF2) ? 1 : ((getBiff() <= BIFF4) ? 2 : 6); switch( getBiff() ) { case BIFF2: - mnFormulaIgnoreSize = 9; // double formula result, 1 byte flags - mnArrayIgnoreSize = 1; // recalc-always flag + mnFormulaSkipSize = 9; // double formula result, 1 byte flags + mnArraySkipSize = 1; // recalc-always flag break; case BIFF3: case BIFF4: - mnFormulaIgnoreSize = 10; // double formula result, 2 byte flags - mnArrayIgnoreSize = 2; // 2 byte flags + mnFormulaSkipSize = 10; // double formula result, 2 byte flags + mnArraySkipSize = 2; // 2 byte flags break; case BIFF5: case BIFF8: - mnFormulaIgnoreSize = 14; // double formula result, 2 byte flags, 4 bytes nothing - mnArrayIgnoreSize = 6; // 2 byte flags, 4 bytes nothing + mnFormulaSkipSize = 14; // double formula result, 2 byte flags, 4 bytes nothing + mnArraySkipSize = 6; // 2 byte flags, 4 bytes nothing + break; + case BIFF_UNKNOWN: break; - case BIFF_UNKNOWN: break; } } @@ -689,258 +667,284 @@ void BiffSheetDataContext::importRecord( BiffInputStream& rStrm ) } break; - case BIFF_UNKNOWN: break; + case BIFF_UNKNOWN: + break; } } } // private -------------------------------------------------------------------- -void BiffSheetDataContext::setCurrCell( const BinAddress& rAddr ) -{ - maCurrCell.reset(); - maCurrCell.mxCell = getCell( rAddr, &maCurrCell.maAddress ); - // update used area of the sheet - if( maCurrCell.mxCell.is() ) - extendUsedArea( maCurrCell.maAddress ); -} - -void BiffSheetDataContext::importXfId( BiffInputStream& rStrm, bool bBiff2 ) +void BiffSheetDataContext::importRow( BiffInputStream& rStrm ) { - if( bBiff2 ) + RowModel aModel; + sal_uInt16 nRow, nFirstUsedCol, nFirstFreeCol, nHeight; + rStrm >> nRow >> nFirstUsedCol >> nFirstFreeCol >> nHeight; + if( getBiff() == BIFF2 ) { - sal_uInt8 nBiff2XfId; - rStrm >> nBiff2XfId; rStrm.skip( 2 ); - maCurrCell.mnXfId = nBiff2XfId & BIFF2_XF_MASK; - if( maCurrCell.mnXfId == BIFF2_XF_EXTENDED_IDS ) - maCurrCell.mnXfId = mnBiff2XfId; + aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT; + if( aModel.mbCustomFormat ) + { + rStrm.skip( 5 ); + aModel.mnXfId = rStrm.readuInt16(); + } } else { - maCurrCell.mnXfId = rStrm.readuInt16(); + rStrm.skip( 4 ); + sal_uInt32 nFlags = rStrm.readuInt32(); + aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 ); + aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 ); + aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT ); + aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT ); + aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC ); + aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN ); + aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED ); + aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP ); + aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM ); + } + + // row index is 0-based in BIFF, but RowModel expects 1-based + aModel.mnRow = static_cast< sal_Int32 >( nRow ) + 1; + // row height is in twips in BIFF, convert to points + aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0; + // set column spans + if( nFirstUsedCol < nFirstFreeCol ) + { + sal_Int32 nLastCol = ::std::min< sal_Int32 >( nFirstFreeCol - 1, mrAddressConv.getMaxApiAddress().Column ); + aModel.insertColSpan( ValueRange( nFirstUsedCol, nLastCol ) ); + } + + // set row properties in the current sheet + setRowModel( aModel ); +} + +bool BiffSheetDataContext::readCellXfId( BiffInputStream& rStrm, const BinAddress& rAddr, bool bBiff2 ) +{ + bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAddr, mnSheet, true ); + if( bValidAddr ) + { + // update used area of the sheet + extendUsedArea( maCellData.maCellAddr ); + + // load the XF identifier according to current BIFF version + if( bBiff2 ) + { + /* #i71453# On first call, check if the file contains XF records + (by trying to access the first XF with index 0). If there are + no XFs, the explicit formatting information contained in each + cell record will be used instead. */ + if( !mobBiff2HasXfs ) + mobBiff2HasXfs = getStyles().getCellXf( 0 ).get() != 0; + // read formatting information (includes the XF identifier) + sal_uInt8 nFlags1, nFlags2, nFlags3; + rStrm >> nFlags1 >> nFlags2 >> nFlags3; + /* If the file contains XFs, extract and set the XF identifier, + otherwise get the explicit formatting. */ + if( mobBiff2HasXfs.get() ) + { + maCellData.mnXfId = extractValue< sal_Int32 >( nFlags1, 0, 6 ); + /* If the identifier is equal to 63, then the real identifier + is contained in the preceding IXFE record (stored in the + class member mnBiff2XfId). */ + if( maCellData.mnXfId == BIFF2_CELL_USEIXFE ) + maCellData.mnXfId = mnBiff2XfId; + } + else + { + /* Let the Xf class do the API conversion. Keeping the member + maCellData.mnXfId untouched will prevent to trigger the + usual XF formatting conversion later on. */ + PropertySet aPropSet( getCell( maCellData.maCellAddr ) ); + Xf::writeBiff2CellFormatToPropertySet( *this, aPropSet, nFlags1, nFlags2, nFlags3 ); + } + } + else + { + // BIFF3-BIFF8: 16-bit XF identifier + maCellData.mnXfId = rStrm.readuInt16(); + } } + return bValidAddr; } -void BiffSheetDataContext::importCellHeader( BiffInputStream& rStrm, bool bBiff2 ) +bool BiffSheetDataContext::readCellHeader( BiffInputStream& rStrm, bool bBiff2 ) { BinAddress aAddr; rStrm >> aAddr; - setCurrCell( aAddr ); - importXfId( rStrm, bBiff2 ); + return readCellXfId( rStrm, aAddr, bBiff2 ); +} + +bool BiffSheetDataContext::readFormulaRef( BiffInputStream& rStrm ) +{ + BinRange aRange; + aRange.read( rStrm, false ); // columns always 8-bit + return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true ); } void BiffSheetDataContext::importBlank( BiffInputStream& rStrm ) { - importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ) ) + mrSheetData.setBlankCell( maCellData ); } void BiffSheetDataContext::importBoolErr( BiffInputStream& rStrm ) { - importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ); - if( maCurrCell.mxCell.is() ) + if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ) ) { sal_uInt8 nValue, nType; rStrm >> nValue >> nType; switch( nType ) { case BIFF_BOOLERR_BOOL: - maCurrCell.mnCellType = XML_b; - setBooleanCell( maCurrCell.mxCell, nValue != 0 ); - // #108770# set 'Standard' number format for all Boolean cells - maCurrCell.mnNumFmtId = 0; + maCellData.mnCellType = XML_b; + mrSheetData.setBooleanCell( maCellData, nValue != 0 ); break; case BIFF_BOOLERR_ERROR: - maCurrCell.mnCellType = XML_e; - setErrorCell( maCurrCell.mxCell, nValue ); + maCellData.mnCellType = XML_e; + mrSheetData.setErrorCell( maCellData, nValue ); break; default: OSL_ENSURE( false, "BiffSheetDataContext::importBoolErr - unknown cell type" ); + maCellData.mnCellType = XML_TOKEN_INVALID; + mrSheetData.setBlankCell( maCellData ); } } - setCellFormat( maCurrCell ); } void BiffSheetDataContext::importFormula( BiffInputStream& rStrm ) { - importCellHeader( rStrm, getBiff() == BIFF2 ); - maCurrCell.mnCellType = XML_n; - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY ); - if( xTokens.is() ) + if( readCellHeader( rStrm, getBiff() == BIFF2 ) ) { - rStrm.skip( mnFormulaIgnoreSize ); - ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); - getFormulaParser().importFormula( aContext, rStrm ); + maCellData.mnCellType = XML_n; + rStrm.skip( mnFormulaSkipSize ); + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm ); + mrSheetData.setFormulaCell( maCellData, aTokens ); } - setCellFormat( maCurrCell ); } void BiffSheetDataContext::importInteger( BiffInputStream& rStrm ) { - importCellHeader( rStrm, true ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( rStrm.readuInt16() ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, true ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, rStrm.readuInt16() ); + } } void BiffSheetDataContext::importLabel( BiffInputStream& rStrm ) { + /* the deep secrets of BIFF type and record identifier... + record id BIFF -> XF type String type + 0x0004 2-7 -> 3 byte 8-bit length, byte string + 0x0004 8 -> 3 byte 16-bit length, unicode string + 0x0204 2-7 -> 2 byte 16-bit length, byte string + 0x0204 8 -> 2 byte 16-bit length, unicode string + */ bool bBiff2Xf = rStrm.getRecId() == BIFF2_ID_LABEL; - importCellHeader( rStrm, bBiff2Xf ); - maCurrCell.mnCellType = XML_inlineStr; - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() ) - { - /* the deep secrets of BIFF type and record identifier... - record id BIFF -> XF type String type - 0x0004 2-7 -> 3 byte 8-bit length, byte string - 0x0004 8 -> 3 byte 16-bit length, unicode string - 0x0204 2-7 -> 2 byte 16-bit length, byte string - 0x0204 8 -> 2 byte 16-bit length, unicode string */ - - RichString aString( *this ); + if( readCellHeader( rStrm, bBiff2Xf ) ) + { + maCellData.mnCellType = XML_inlineStr; if( getBiff() == BIFF8 ) { - aString.importUniString( rStrm ); + // string may contain rich-text formatting + RichStringRef xString( new RichString( *this ) ); + xString->importUniString( rStrm ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); } else { // #i63105# use text encoding from FONT record rtl_TextEncoding eTextEnc = getTextEncoding(); - if( const Font* pFont = getStyles().getFontFromCellXf( maCurrCell.mnXfId ).get() ) + if( const Font* pFont = getStyles().getFontFromCellXf( maCellData.mnXfId ).get() ) eTextEnc = pFont->getFontEncoding(); - BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT; - setFlag( nFlags, BIFF_STR_EXTRAFONTS, rStrm.getRecId() == BIFF_ID_RSTRING ); - aString.importByteString( rStrm, eTextEnc, nFlags ); + // RSTRING record contains rich-text formatting + if( rStrm.getRecId() == BIFF_ID_RSTRING ) + { + BiffStringFlags nFlags = BIFF_STR_EXTRAFONTS; + // BIFF2 record identifier: 8-bit string length (see above) + setFlag( nFlags, BIFF_STR_8BITLENGTH, bBiff2Xf ); + RichStringRef xString( new RichString( *this ) ); + xString->importByteString( rStrm, eTextEnc, nFlags ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); + } + else + { + // BIFF2 record identifier: 8-bit string length (see above) + OUString aText = rStrm.readByteStringUC( !bBiff2Xf, eTextEnc ); + mrSheetData.setStringCell( maCellData, aText ); + } } - aString.finalizeImport(); - aString.convert( xText, maCurrCell.mnXfId ); } - setCellFormat( maCurrCell ); } void BiffSheetDataContext::importLabelSst( BiffInputStream& rStrm ) { - importCellHeader( rStrm, false ); - maCurrCell.mnCellType = XML_s; - if( maCurrCell.mxCell.is() ) - setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, false ) ) + { + maCellData.mnCellType = XML_s; + mrSheetData.setStringCell( maCellData, rStrm.readInt32() ); + } } void BiffSheetDataContext::importMultBlank( BiffInputStream& rStrm ) { BinAddress aAddr; - for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol ) - { - setCurrCell( aAddr ); - importXfId( rStrm, false ); - setCellFormat( maCurrCell ); - } + bool bValidAddr = true; + for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol ) + if( (bValidAddr = readCellXfId( rStrm, aAddr, false )) == true ) + mrSheetData.setBlankCell( maCellData ); } void BiffSheetDataContext::importMultRk( BiffInputStream& rStrm ) { BinAddress aAddr; - for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol ) + bool bValidAddr = true; + for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol ) { - setCurrCell( aAddr ); - maCurrCell.mnCellType = XML_n; - importXfId( rStrm, false ); - sal_Int32 nRkValue = rStrm.readInt32(); - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( nRkValue ) ); - setCellFormat( maCurrCell ); + if( (bValidAddr = readCellXfId( rStrm, aAddr, false )) == true ) + { + maCellData.mnCellType = XML_n; + sal_Int32 nRkValue = rStrm.readInt32(); + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( nRkValue ) ); + } } } void BiffSheetDataContext::importNumber( BiffInputStream& rStrm ) { - importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( rStrm.readDouble() ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, rStrm.readDouble() ); + } } void BiffSheetDataContext::importRk( BiffInputStream& rStrm ) { - importCellHeader( rStrm, false ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); - setCellFormat( maCurrCell ); -} - -void BiffSheetDataContext::importRow( BiffInputStream& rStrm ) -{ - RowModel aModel; - - sal_uInt16 nRow, nHeight; - rStrm >> nRow; - rStrm.skip( 4 ); - rStrm >> nHeight; - if( getBiff() == BIFF2 ) + if( readCellHeader( rStrm, false ) ) { - rStrm.skip( 2 ); - aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT; - if( aModel.mbCustomFormat ) - { - rStrm.skip( 5 ); - aModel.mnXfId = rStrm.readuInt16(); - } + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); } - else - { - rStrm.skip( 4 ); - sal_uInt32 nFlags = rStrm.readuInt32(); - aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 ); - aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 ); - aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT ); - aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT ); - aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC ); - aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN ); - aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED ); - aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP ); - aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM ); - } - - // row index is 0-based in BIFF, but RowModel expects 1-based - aModel.mnFirstRow = aModel.mnLastRow = nRow + 1; - // row height is in twips in BIFF, convert to points - aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0; - // set row properties in the current sheet - setRowModel( aModel ); } void BiffSheetDataContext::importArray( BiffInputStream& rStrm ) { - BinRange aRange; - aRange.read( rStrm, false ); // columns always 8-bit - CellRangeAddress aArrayRange; - Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange ); - Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY ); - if( xRange.is() && xTokens.is() ) + if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) { - rStrm.skip( mnArrayIgnoreSize ); - ArrayFormulaContext aContext( xTokens, aArrayRange ); - getFormulaParser().importFormula( aContext, rStrm ); + rStrm.skip( mnArraySkipSize ); + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm ); + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens ); } } -void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm ) -{ - getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress ); -} - void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm ) { - BinRange aRange; - aRange.read( rStrm, false ); // columns always 8-bit - CellRangeAddress aTableRange; - if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) ) + if( readFormulaRef( rStrm ) ) { DataTableModel aModel; BinAddress aRef1, aRef2; @@ -972,7 +976,17 @@ void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm ) } aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); - setTableOperation( aTableRange, aModel ); + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, aModel ); + } +} + +void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm ) +{ + if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + { + rStrm.skip( 2 ); // flags + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm ); + mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens ); } } |