summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorRüdiger Timm <rt@openoffice.org>2004-11-09 14:04:02 +0000
committerRüdiger Timm <rt@openoffice.org>2004-11-09 14:04:02 +0000
commit800285d2d7ccb943d17871e0ca3c80b1bb74556c (patch)
treed8b53698fefa4f487aa0efdd025e0fa3df3d8a37 /sc
parent907e434f7eeb3d930ca0c78869936820e11620c5 (diff)
INTEGRATION: CWS dr27 (1.2.18); FILE MERGED
2004/10/21 14:30:00 dr 1.2.18.5: RESYNC: (1.2-1.3); FILE MERGED 2004/10/14 10:13:23 dr 1.2.18.4: #110618# #i3724# #i25653# new formula export, step 8: volatile functions, spaces, optimized SUM 2004/10/12 15:47:38 dr 1.2.18.3: #110618# #i3724# #i25653# new formula export, step 7: unary/ref operator precedence, builtin function list, list validation 2004/10/05 11:40:17 dr 1.2.18.2: #110618# #i3724# #i25653# new formula export, step 2: basic functionality: const operands, unary/binary operators, parentheses 2004/10/01 11:07:27 dr 1.2.18.1: #110618# #i3724# #i25653# new formula export, step 1: new infrastructure
Diffstat (limited to 'sc')
-rw-r--r--sc/source/filter/excel/xetable.cxx313
1 files changed, 166 insertions, 147 deletions
diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx
index 5fe380fba70e..29643f6a68b8 100644
--- a/sc/source/filter/excel/xetable.cxx
+++ b/sc/source/filter/excel/xetable.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: xetable.cxx,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: obo $ $Date: 2004-10-18 15:15:19 $
+ * last change: $Author: rt $ $Date: 2004-11-09 15:04:02 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -95,12 +95,12 @@
#include "attrib.hxx"
#endif
-#ifndef SC_XLFORMULA_HXX
-#include "xlformula.hxx"
-#endif
#ifndef SC_XEHELPER_HXX
#include "xehelper.hxx"
#endif
+#ifndef SC_XEFORMULA_HXX
+#include "xeformula.hxx"
+#endif
#ifndef SC_XECONTENT_HXX
#include "xecontent.hxx"
#endif
@@ -108,8 +108,6 @@
#include "xeescher.hxx"
#endif
-#include "excupn.hxx"
-
// ============================================================================
// Helper records for cell records
// ============================================================================
@@ -131,44 +129,36 @@ void XclExpStringRec::WriteBody( XclExpStream& rStrm )
// Additional records for special formula ranges ==============================
XclExpRangeFmlaBase::XclExpRangeFmlaBase(
- sal_uInt16 nRecId, sal_uInt32 nRecSize, sal_uInt16 nXclCol, sal_uInt16 nXclRow ) :
- XclExpRecord( nRecId, nRecSize ),
- mnUsedCount( 1 ),
- mnFirstXclCol( nXclCol ),
- mnFirstXclRow( nXclRow ),
- mnLastXclCol( nXclCol ),
- mnLastXclRow( nXclRow ),
- mnBaseXclCol( nXclCol ),
- mnBaseXclRow( nXclRow )
+ sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScAddress& rScPos ) :
+ XclExpRecord( nRecId, nRecSize )
+{
+ mnFirstXclCol = mnLastXclCol = mnBaseXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
+ mnFirstXclRow = mnLastXclRow = mnBaseXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
+}
+
+XclExpRangeFmlaBase::XclExpRangeFmlaBase(
+ sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScRange& rScRange ) :
+ XclExpRecord( nRecId, nRecSize )
{
+ mnFirstXclCol = mnBaseXclCol = static_cast< sal_uInt16 >( rScRange.aStart.Col() );
+ mnFirstXclRow = mnBaseXclRow = static_cast< sal_uInt16 >( rScRange.aStart.Row() );
+ mnLastXclCol = static_cast< sal_uInt16 >( rScRange.aEnd.Col() );
+ mnLastXclRow = static_cast< sal_uInt16 >( rScRange.aEnd.Row() );
}
-XclExpRangeFmlaBase::XclExpRangeFmlaBase( sal_uInt16 nRecId, sal_uInt32 nRecSize,
- sal_uInt16 nFirstXclCol, sal_uInt16 nFirstXclRow, sal_uInt16 nLastXclCol, sal_uInt16 nLastXclRow ) :
- XclExpRecord( nRecId, nRecSize ),
- mnUsedCount( 1 ),
- mnFirstXclCol( nFirstXclCol ),
- mnFirstXclRow( nFirstXclRow ),
- mnLastXclCol( nLastXclCol ),
- mnLastXclRow( nLastXclRow ),
- mnBaseXclCol( nFirstXclCol ),
- mnBaseXclRow( nFirstXclRow )
+bool XclExpRangeFmlaBase::IsBasePos( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
{
+ return (mnBaseXclCol == nXclCol) && (mnBaseXclRow == nXclRow);
}
-void XclExpRangeFmlaBase::Extend( sal_uInt16 nXclCol, sal_uInt16 nXclRow )
+void XclExpRangeFmlaBase::Extend( const ScAddress& rScPos )
{
+ sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
+ sal_uInt16 nXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
mnFirstXclCol = ::std::min( mnFirstXclCol, nXclCol );
mnFirstXclRow = ::std::min( mnFirstXclRow, nXclRow );
mnLastXclCol = ::std::max( mnLastXclCol, nXclCol );
mnLastXclRow = ::std::max( mnLastXclRow, nXclRow );
- ++mnUsedCount;
-}
-
-bool XclExpRangeFmlaBase::Contains( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
-{
- return (mnFirstXclCol <= nXclCol) && (nXclCol <= mnLastXclCol) &&
- (mnFirstXclRow <= nXclRow) && (nXclRow <= mnLastXclRow);
}
void XclExpRangeFmlaBase::WriteRangeAddress( XclExpStream& rStrm ) const
@@ -180,56 +170,96 @@ void XclExpRangeFmlaBase::WriteRangeAddress( XclExpStream& rStrm ) const
// Array formulas =============================================================
-XclExpArray::XclExpArray( const ExcUPN& rXclTokArr,
- sal_uInt16 nFirstXclCol, sal_uInt16 nFirstXclRow, sal_uInt16 nLastXclCol, sal_uInt16 nLastXclRow ) :
- XclExpRangeFmlaBase( EXC_ID_ARRAY, 0, nFirstXclCol, nFirstXclRow, nLastXclCol, nLastXclRow )
+XclExpArray::XclExpArray( XclExpTokenArrayRef xTokArr, const ScRange& rScRange ) :
+ XclExpRangeFmlaBase( EXC_ID_ARRAY, 14 + xTokArr->GetSize(), rScRange ),
+ mxTokArr( xTokArr )
{
- rXclTokArr.GetFmlaData( maFmlaData );
- SetRecSize( static_cast< sal_uInt32 >( 14 + maFmlaData.size() ) );
}
-void XclExpArray::WriteCellTokenArray( XclExpStream& rStrm, sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
+XclExpTokenArrayRef XclExpArray::CreateCellTokenArray( const XclExpRoot& rRoot ) const
{
- DBG_ASSERT( Contains( nXclCol, nXclRow ), "XclExpArray::WriteCellTokenArray - invalid cell address" );
- rStrm << sal_uInt16( 5 ) << EXC_TOKID_EXP << mnBaseXclRow << mnBaseXclCol;
+ return rRoot.GetFormulaCompiler().CreateSpecialRefFormula( EXC_TOKID_EXP, mnBaseXclCol, mnBaseXclRow );
+}
+
+bool XclExpArray::IsVolatile() const
+{
+ return mxTokArr->IsVolatile();
}
void XclExpArray::WriteBody( XclExpStream& rStrm )
{
- sal_uInt16 nFmlaSize = static_cast< sal_uInt16 >( maFmlaData.size() );
WriteRangeAddress( rStrm );
- rStrm << EXC_ARRAY_DEFAULTFLAGS << sal_uInt32( 0 ) << nFmlaSize;
- if( nFmlaSize )
- rStrm.Write( &maFmlaData.front(), nFmlaSize );
+ sal_uInt16 nFlags = EXC_ARRAY_DEFAULTFLAGS;
+ ::set_flag( nFlags, EXC_ARRAY_RECALC_ALWAYS, IsVolatile() );
+ rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
+}
+
+// ----------------------------------------------------------------------------
+
+XclExpArrayBuffer::XclExpArrayBuffer( const XclExpRoot& rRoot ) :
+ XclExpRoot( rRoot )
+{
+}
+
+XclExpArrayRef XclExpArrayBuffer::CreateArray( const ScTokenArray& rScTokArr, const ScRange& rScRange )
+{
+ const ScAddress& rScPos = rScRange.aStart;
+ XclExpTokenArrayRef xTokArr = GetFormulaCompiler().CreateMatrixFormula( rScTokArr, rScPos );
+
+ DBG_ASSERT( maRecMap.find( rScPos ) == maRecMap.end(), "XclExpArrayBuffer::CreateArray - array exists already" );
+ XclExpArrayRef& rxRec = maRecMap[ rScPos ];
+ rxRec.reset( new XclExpArray( xTokArr, rScRange ) );
+ return rxRec;
+}
+
+XclExpArrayRef XclExpArrayBuffer::FindArray( const ScTokenArray& rScTokArr ) const
+{
+ XclExpArrayRef xRec;
+ // try to extract a matrix reference token
+ if( rScTokArr.GetLen() == 1 )
+ {
+ const ScToken* pToken = rScTokArr.GetArray()[ 0 ];
+ if( pToken && (pToken->GetOpCode() == ocMatRef) )
+ {
+ const SingleRefData& rRef = pToken->GetSingleRef();
+ ScAddress aBasePos( rRef.nCol, rRef.nRow, GetCurrScTab() );
+ XclExpArrayMap::const_iterator aIt = maRecMap.find( aBasePos );
+ if( aIt != maRecMap.end() )
+ xRec = aIt->second;
+ }
+ }
+ return xRec;
}
// Shared formulas ============================================================
-XclExpShrfmla::XclExpShrfmla( const ExcUPN& rXclTokArr, sal_uInt16 nXclCol, sal_uInt16 nXclRow ) :
- XclExpRangeFmlaBase( EXC_ID_SHRFMLA, 0, nXclCol, nXclRow )
+XclExpShrfmla::XclExpShrfmla( XclExpTokenArrayRef xTokArr, const ScAddress& rScPos ) :
+ XclExpRangeFmlaBase( EXC_ID_SHRFMLA, 10 + xTokArr->GetSize(), rScPos ),
+ mxTokArr( xTokArr ),
+ mnUsedCount( 1 )
{
- rXclTokArr.GetFmlaData( maFmlaData );
- SetRecSize( static_cast< sal_uInt32 >( 10 + maFmlaData.size() ) );
}
-void XclExpShrfmla::ExtendRange( sal_uInt16 nXclCol, sal_uInt16 nXclRow )
+void XclExpShrfmla::ExtendRange( const ScAddress& rScPos )
+{
+ Extend( rScPos );
+ ++mnUsedCount;
+}
+
+XclExpTokenArrayRef XclExpShrfmla::CreateCellTokenArray( const XclExpRoot& rRoot ) const
{
- Extend( nXclCol, nXclRow );
+ return rRoot.GetFormulaCompiler().CreateSpecialRefFormula( EXC_TOKID_EXP, mnBaseXclCol, mnBaseXclRow );
}
-void XclExpShrfmla::WriteCellTokenArray( XclExpStream& rStrm, sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
+bool XclExpShrfmla::IsVolatile() const
{
- DBG_ASSERT( Contains( nXclCol, nXclRow ), "XclExpShrfmla::WriteCellTokenArray - invalid cell address" );
- rStrm << sal_uInt16( 5 ) << EXC_TOKID_EXP << mnBaseXclRow << mnBaseXclCol;
+ return mxTokArr->IsVolatile();
}
void XclExpShrfmla::WriteBody( XclExpStream& rStrm )
{
- sal_uInt16 nFmlaSize = static_cast< sal_uInt16 >( maFmlaData.size() );
WriteRangeAddress( rStrm );
- rStrm << static_cast< sal_uInt16 >( GetUsedCount() ) << nFmlaSize;
- if( nFmlaSize )
- rStrm.Write( &maFmlaData.front(), nFmlaSize );
+ rStrm << sal_uInt8( 0 ) << mnUsedCount << *mxTokArr;
}
// ----------------------------------------------------------------------------
@@ -240,25 +270,25 @@ XclExpShrfmlaBuffer::XclExpShrfmlaBuffer( const XclExpRoot& rRoot ) :
}
XclExpShrfmlaRef XclExpShrfmlaBuffer::CreateOrExtendShrfmla(
- const ScTokenArray& rScTokArr, const ExcUPN& rXclTokArr,
- sal_uInt16 nXclCol, sal_uInt16 nXclRow )
+ const ScTokenArray& rScTokArr, const ScAddress& rScPos )
{
XclExpShrfmlaRef xRec;
- if( const ScRangeData* pRangeData = XclTokenArrayHelper::GetSharedFormula( GetRoot(), rScTokArr ) )
+ if( const ScTokenArray* pShrdScTokArr = XclTokenArrayHelper::GetSharedFormula( GetRoot(), rScTokArr ) )
{
- XclExpShrfmlaMap::iterator aIt = maRecMap.find( pRangeData );
+ XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr );
if( aIt == maRecMap.end() )
{
// create a new record
- xRec.reset( new XclExpShrfmla( rXclTokArr, nXclCol, nXclRow ) );
- maRecMap[ pRangeData ] = xRec;
+ XclExpTokenArrayRef xTokArr = GetFormulaCompiler().CreateSharedFormula( *pShrdScTokArr, rScPos );
+ xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) );
+ maRecMap[ pShrdScTokArr ] = xRec;
}
else
{
// extend existing record
DBG_ASSERT( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" );
xRec = aIt->second;
- xRec->ExtendRange( nXclCol, nXclRow );
+ xRec->ExtendRange( rScPos );
}
}
return xRec;
@@ -268,7 +298,7 @@ XclExpShrfmlaRef XclExpShrfmlaBuffer::CreateOrExtendShrfmla(
XclExpTableop::XclExpTableop( const ScAddress& rScPos,
const XclMultipleOpRefs& rRefs, sal_uInt8 nScMode ) :
- XclExpRangeFmlaBase( EXC_ID_TABLEOP, 16, static_cast< sal_uInt16 >( rScPos.Col() ), static_cast< sal_uInt16 >( rScPos.Row() ) ),
+ XclExpRangeFmlaBase( EXC_ID_TABLEOP, 16, rScPos ),
mnLastAppXclCol( static_cast< sal_uInt16 >( rScPos.Col() ) ),
mnColInpXclCol( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Col() ) ),
mnColInpXclRow( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Row() ) ),
@@ -337,7 +367,7 @@ bool XclExpTableop::TryExtend( const ScAddress& rScPos, const XclMultipleOpRefs&
{
// extend the cell range
DBG_ASSERT( IsAppendable( nXclCol, nXclRow ), "XclExpTableop::TryExtend - wrong cell address" );
- Extend( nXclCol, nXclRow );
+ Extend( rScPos );
mnLastAppXclCol = nXclCol;
}
}
@@ -376,12 +406,17 @@ void XclExpTableop::Finalize()
}
}
-void XclExpTableop::WriteCellTokenArray( XclExpStream& rStrm, sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
+XclExpTokenArrayRef XclExpTableop::CreateCellTokenArray( const XclExpRoot& rRoot ) const
{
- if( mbValid && Contains( nXclCol, nXclRow ) )
- rStrm << sal_uInt16( 5 ) << EXC_TOKID_TBL << mnBaseXclRow << mnBaseXclCol;
- else
- rStrm << sal_uInt16( 2 ) << EXC_TOKID_ERR << EXC_ERR_NA;
+ XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
+ return mbValid ?
+ rFmlaComp.CreateSpecialRefFormula( EXC_TOKID_TBL, mnBaseXclCol, mnBaseXclRow ) :
+ rFmlaComp.CreateErrorFormula( EXC_ERR_NA );
+}
+
+bool XclExpTableop::IsVolatile() const
+{
+ return true;
}
void XclExpTableop::Save( XclExpStream& rStrm )
@@ -400,6 +435,7 @@ bool XclExpTableop::IsAppendable( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
void XclExpTableop::WriteBody( XclExpStream& rStrm )
{
sal_uInt16 nFlags = EXC_TABLEOP_DEFAULTFLAGS;
+ ::set_flag( nFlags, EXC_TABLEOP_RECALC_ALWAYS, IsVolatile() );
switch( mnScMode )
{
case 1: ::set_flag( nFlags, EXC_TABLEOP_ROW ); break;
@@ -421,7 +457,8 @@ XclExpTableopBuffer::XclExpTableopBuffer( const XclExpRoot& rRoot ) :
{
}
-XclExpTableopRef XclExpTableopBuffer::CreateOrExtendTableop( const ScTokenArray& rScTokArr, const ScAddress& rScPos )
+XclExpTableopRef XclExpTableopBuffer::CreateOrExtendTableop(
+ const ScTokenArray& rScTokArr, const ScAddress& rScPos )
{
XclExpTableopRef xRec;
@@ -430,7 +467,6 @@ XclExpTableopRef XclExpTableopBuffer::CreateOrExtendTableop( const ScTokenArray&
if( XclTokenArrayHelper::GetMultipleOpRefs( aRefs, rScTokArr ) )
{
// try to find an existing TABLEOP record for this cell position
- bool bFound = false;
for( size_t nPos = 0, nSize = maTableopList.Size(); !xRec && (nPos < nSize); ++nPos )
{
XclExpTableopRef xTempRec = maTableopList.GetRecord( nPos );
@@ -746,10 +782,11 @@ XclExpFormulaCell::XclExpFormulaCell( const XclExpRoot& rRoot,
sal_uInt16 nXclCol, sal_uInt16 nXclRow,
const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
const ScFormulaCell& rScFmlaCell,
- XclExpShrfmlaBuffer& rShrfmlaBfr, XclExpTableopBuffer& rTableopBfr ) :
+ XclExpArrayBuffer& rArrayBfr,
+ XclExpShrfmlaBuffer& rShrfmlaBfr,
+ XclExpTableopBuffer& rTableopBfr ) :
XclExpSingleCellBase( EXC_ID_FORMULA, 0, nXclCol, nXclRow, nForcedXFId ),
- mrScFmlaCell( const_cast< ScFormulaCell& >( rScFmlaCell ) ),
- mbFirstAddRec( false )
+ mrScFmlaCell( const_cast< ScFormulaCell& >( rScFmlaCell ) )
{
// *** Find result number format overwriting cell number format *** -------
@@ -791,70 +828,64 @@ XclExpFormulaCell::XclExpFormulaCell( const XclExpRoot& rRoot,
// first try to create multiple operations
mxAddRec = rTableopBfr.CreateOrExtendTableop( rScTokArr, aScPos );
- if( !mxAddRec )
- {
- ScMatrixMode eMatMode = static_cast< ScMatrixMode >( mrScFmlaCell.GetMatrixFlag() );
-
- EC_Codetype eCodeType = EC_StdFmla;
- ::std::auto_ptr< ExcUPN > xXclTokArr;
- switch( eMatMode )
+ // no multiple operation found - try to create matrix formula
+ if( !mxAddRec ) switch( static_cast< ScMatrixMode >( mrScFmlaCell.GetMatrixFlag() ) )
+ {
+ case MM_FORMULA:
{
- case MM_FORMULA:
- xXclTokArr.reset( new ExcUPN( TRUE, rRoot.mpRD, rScTokArr, eCodeType, aScPos ) );
- break;
- case MM_REFERENCE:
- xXclTokArr.reset( new ExcUPN( rScTokArr, eCodeType ) );
- break;
+ // origin of the matrix - find the used matrix range
+ SCCOL nMatWidth;
+ SCROW nMatHeight;
+ mrScFmlaCell.GetMatColsRows( nMatWidth, nMatHeight );
+ DBG_ASSERT( nMatWidth && nMatHeight, "XclExpFormulaCell::XclExpFormulaCell - empty matrix" );
+ ScRange aMatScRange( aScPos );
+ ScAddress& rMatEnd = aMatScRange.aEnd;
+ rMatEnd.IncCol( static_cast< SCsCOL >( nMatWidth - 1 ) );
+ rMatEnd.IncRow( static_cast< SCsROW >( nMatHeight - 1 ) );
+ // reduce to valid range (range keeps valid, because start position IS valid)
+ rRoot.CheckCellRange( aMatScRange );
+ // create the ARRAY record
+ mxAddRec = rArrayBfr.CreateArray( rScTokArr, aMatScRange );
}
-
- if( !xXclTokArr.get() || (eCodeType != EC_ArrayFmla) )
- xXclTokArr.reset( new ExcUPN( rRoot.mpRD, rScTokArr, eCodeType, &aScPos, FALSE ) );
-
- switch( eCodeType )
+ break;
+ case MM_REFERENCE:
{
- case EC_StdFmla:
- xXclTokArr->GetFmlaData( maFmlaData );
- break;
-
- case EC_ArrayFmla:
- {
- xXclTokArr->GetShrdFmla( maFmlaData );
- if( eMatMode == MM_FORMULA )
- {
- // origin of the matrix - create the ARRAY record
- SCCOL nMatWidth;
- SCROW nMatHeight;
- mrScFmlaCell.GetMatColsRows( nMatWidth, nMatHeight );
- DBG_ASSERT( nMatWidth && nMatHeight, "XclExpFormulaCell::XclExpFormulaCell - empty matrix" );
- ScRange aMatRange( aScPos );
- ScAddress& rMatEnd = aMatRange.aEnd;
- rMatEnd.IncCol( static_cast< SCsCOL >( nMatWidth - 1 ) );
- rMatEnd.IncRow( static_cast< SCsROW >( nMatHeight - 1 ) );
- rRoot.CheckCellRange( aMatRange );
- mxAddRec.reset( new XclExpArray( *xXclTokArr, nXclCol, nXclRow,
- static_cast< sal_uInt16 >( rMatEnd.Col() ), static_cast< sal_uInt16 >( rMatEnd.Row() ) ) );
- }
- }
- break;
-
- case EC_ShrdFmla:
- mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla( rScTokArr, *xXclTokArr, nXclCol, nXclRow );
- break;
+ // other formula cell covered by a matrix - find the ARRAY record
+ mxAddRec = rArrayBfr.FindArray( rScTokArr );
+ // should always be found, if Calc document is not broken
+ DBG_ASSERT( mxAddRec.is(), "XclExpFormulaCell::XclExpFormulaCell - no matrix found" );
}
+ break;
}
- size_t nFmlaSize = maFmlaData.empty() ? 5 : maFmlaData.size();
- SetContSize( static_cast< sal_uInt32 >( 16 + nFmlaSize ) );
- mbFirstAddRec = mxAddRec.is() && (mxAddRec->GetUsedCount() == 1);
+ // no matrix found - try to create shared formula
+ if( !mxAddRec )
+ mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla( rScTokArr, aScPos );
+
+ // no shared formula found - create a simple cell formula
+ if( !mxAddRec )
+ mxTokArr = rRoot.GetFormulaCompiler().CreateCellFormula( rScTokArr, aScPos );
}
void XclExpFormulaCell::Save( XclExpStream& rStrm )
{
+ // create token array for FORMULA cells with additional record
+ if( mxAddRec.is() )
+ mxTokArr = mxAddRec->CreateCellTokenArray( rStrm.GetRoot() );
+
+ // FORMULA record itself
+ DBG_ASSERT( mxTokArr.is(), "XclExpFormulaCell::Save - missing token array" );
+ if( !mxTokArr )
+ mxTokArr = rStrm.GetRoot().GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NA );
+ SetContSize( 16 + mxTokArr->GetSize() );
XclExpSingleCellBase::Save( rStrm );
- // additional records
- if( mxAddRec.is() && mbFirstAddRec )
+
+ // additional record (ARRAY, SHRFMLA, or TABLEOP), only for first FORMULA record
+ if( mxAddRec.is() && mxAddRec->IsBasePos( GetXclCol(), GetXclRow() ) )
mxAddRec->Save( rStrm );
+
+ // STRING record for string result
if( mxStringRec.is() )
mxStringRec->Save( rStrm );
}
@@ -906,24 +937,11 @@ void XclExpFormulaCell::WriteContents( XclExpStream& rStrm )
rStrm << mrScFmlaCell.GetValue();
}
- // flags
+ // flags and formula token array
sal_uInt16 nFlags = EXC_FORMULA_DEFAULTFLAGS;
- if( mxAddRec.is() )
- ::set_flag( nFlags, EXC_FORMULA_SHARED, mxAddRec->GetRecId() == EXC_ID_SHRFMLA );
- rStrm << nFlags << sal_uInt32( 0 );
-
- // formula token array
- if( mxAddRec.is() )
- {
- mxAddRec->WriteCellTokenArray( rStrm, GetXclCol(), GetXclRow() );
- }
- else
- {
- sal_uInt16 nFmlaSize = static_cast< sal_uInt16 >( maFmlaData.size() );
- rStrm << nFmlaSize;
- if( nFmlaSize )
- rStrm.Write( &maFmlaData.front(), nFmlaSize );
- }
+ ::set_flag( nFlags, EXC_FORMULA_RECALC_ALWAYS, mxTokArr->IsVolatile() || (mxAddRec.is() && mxAddRec->IsVolatile()) );
+ ::set_flag( nFlags, EXC_FORMULA_SHARED, mxAddRec.is() && (mxAddRec->GetRecId() == EXC_ID_SHRFMLA) );
+ rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
}
// Multiple cell records ======================================================
@@ -1984,6 +2002,7 @@ XclExpCellTable::XclExpCellTable( const XclExpRoot& rRoot ) :
XclExpRoot( rRoot ),
maColInfoBfr( rRoot ),
maRowBfr( rRoot ),
+ maArrayBfr( rRoot ),
maShrfmlaBfr( rRoot ),
maTableopBfr( rRoot ),
mxDefrowheight( new XclExpDefrowheight ),
@@ -2131,7 +2150,7 @@ XclExpCellTable::XclExpCellTable( const XclExpRoot& rRoot ) :
const ScFormulaCell& rScFmlaCell = *static_cast< const ScFormulaCell* >( pScCell );
xCell.reset( new XclExpFormulaCell(
GetRoot(), nXclCol, nXclRow, pPattern, nMergeBaseXFId,
- rScFmlaCell, maShrfmlaBfr, maTableopBfr ) );
+ rScFmlaCell, maArrayBfr, maShrfmlaBfr, maTableopBfr ) );
}
break;