diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-05 22:26:11 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-12 19:46:24 -0400 |
commit | 86a2dc96c7ce312f251b5a063c2aa8332c8817a0 (patch) | |
tree | 6d2660f08e8639b64d2e4d8171bdd5ac67776aa0 /sc/source | |
parent | f4b757d7e7a3f5bc23fea3e540671b0f40133f24 (diff) |
Prepare for importing shared formulas as formula groups from xls.
Still the first step.
Change-Id: I1897c9c2cd3a5b5245febbfba76e1b088054f578
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 95 | ||||
-rw-r--r-- | sc/source/filter/excel/excform.cxx | 132 | ||||
-rw-r--r-- | sc/source/filter/excel/read.cxx | 2 | ||||
-rw-r--r-- | sc/source/filter/inc/excform.hxx | 2 |
4 files changed, 138 insertions, 93 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 0ad7cb68b8cb..cdedb660bc9f 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -384,6 +384,7 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD ScFormulaCellGroup::ScFormulaCellGroup() : mnRefCount(0), + mpCode(NULL), mnStart(0), mnLength(0), mbInvariant(false), @@ -393,6 +394,7 @@ ScFormulaCellGroup::ScFormulaCellGroup() : ScFormulaCellGroup::~ScFormulaCellGroup() { + delete mpCode; } // ============================================================================ @@ -477,6 +479,53 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, pCode->GenHash(); } +ScFormulaCell::ScFormulaCell( + ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup, + const FormulaGrammar::Grammar eGrammar, sal_uInt8 cInd ) : + mxGroup(xGroup), + eTempGrammar( eGrammar), + pCode(xGroup->mpCode ? xGroup->mpCode : new ScTokenArray), + pDocument( pDoc ), + pPrevious(0), + pNext(0), + pPreviousTrack(0), + pNextTrack(0), + nSeenInIteration(0), + cMatrixFlag ( cInd ), + nFormatType ( NUMBERFORMAT_NUMBER ), + bDirty(false), + bChanged( false ), + bRunning( false ), + bCompile( false ), + bSubTotal( false ), + bIsIterCell( false ), + bInChangeTrack( false ), + bTableOpDirty( false ), + bNeedListening( false ), + mbNeedsNumberFormat( false ), + aPos( rPos ) +{ + // UPN-Array generation + if( pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen() ) + { + ScCompiler aComp( pDocument, aPos, *pCode); + aComp.SetGrammar(eTempGrammar); + bSubTotal = aComp.CompileTokenArray(); + nFormatType = aComp.GetNumFormatType(); + } + else + { + pCode->Reset(); + if ( pCode->GetNextOpCodeRPN( ocSubTotal ) ) + bSubTotal = true; + } + + if (bSubTotal) + pDocument->AddSubTotalCell(this); + + pCode->GenHash(); +} + ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags ) : SvtListener(), aResult( rCell.aResult ), @@ -605,7 +654,9 @@ ScFormulaCell::~ScFormulaCell() if (pDocument->HasExternalRefManager()) pDocument->GetExternalRefManager()->removeRefCell(this); - delete pCode; + if (!mxGroup || !mxGroup->mpCode) + // Formula token is not shared. + delete pCode; } ScFormulaCell* ScFormulaCell::Clone() const @@ -1579,8 +1630,8 @@ void ScFormulaCell::SetDirty( bool bDirtyFlag ) void ScFormulaCell::SetDirtyVar() { bDirty = true; - if (xGroup) - xGroup->meCalcState = sc::GroupCalcEnabled; + if (mxGroup) + mxGroup->meCalcState = sc::GroupCalcEnabled; // mark the sheet of this cell to be calculated //#FIXME do we need to revert this remnant of old fake vba events? pDocument->AddCalculateTable( aPos.Tab() ); @@ -2239,8 +2290,8 @@ bool ScFormulaCell::UpdateReferenceOnShift( // This formula cell itself is being shifted during cell range // insertion or deletion. Update its position. aPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta); - if (xGroup && xGroup->mnStart == aOldPos.Row()) - xGroup->mnStart += rCxt.mnRowDelta; + if (mxGroup && mxGroup->mnStart == aOldPos.Row()) + mxGroup->mnStart += rCxt.mnRowDelta; bCellStateChanged = aPos != aOldPos; } @@ -3074,12 +3125,12 @@ void ScFormulaCell::SetNextTrack( ScFormulaCell* pF ) { pNextTr ScFormulaCellGroupRef ScFormulaCell::GetCellGroup() { - return xGroup; + return mxGroup; } void ScFormulaCell::SetCellGroup( const ScFormulaCellGroupRef &xRef ) { - xGroup = xRef; + mxGroup = xRef; } ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell& rOther ) const @@ -3309,10 +3360,10 @@ bool ScFormulaCell::InterpretFormulaGroup() // import / insert / delete etc. and is integral to the data structures pDocument->RebuildFormulaGroups(); - if (!xGroup || !pCode) + if (!mxGroup || !pCode) return false; - if (xGroup->meCalcState == sc::GroupCalcDisabled) + if (mxGroup->meCalcState == sc::GroupCalcDisabled) return false; switch (pCode->GetVectorState()) @@ -3328,28 +3379,28 @@ bool ScFormulaCell::InterpretFormulaGroup() return false; } - if (xGroup->mbInvariant) + if (mxGroup->mbInvariant) return InterpretInvariantFormulaGroup(); sc::FormulaGroupContext aCxt; ScTokenArray aCode; ScAddress aTopPos = aPos; - aTopPos.SetRow(xGroup->mnStart); + aTopPos.SetRow(mxGroup->mnStart); GroupTokenConverter aConverter(aCxt, aCode, *pDocument, *this, aTopPos); if (!aConverter.convert(*pCode)) { - xGroup->meCalcState = sc::GroupCalcDisabled; + mxGroup->meCalcState = sc::GroupCalcDisabled; return false; } - xGroup->meCalcState = sc::GroupCalcRunning; - if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, xGroup, aCode)) + mxGroup->meCalcState = sc::GroupCalcRunning; + if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, mxGroup, aCode)) { - xGroup->meCalcState = sc::GroupCalcDisabled; + mxGroup->meCalcState = sc::GroupCalcDisabled; return false; } - xGroup->meCalcState = sc::GroupCalcEnabled; + mxGroup->meCalcState = sc::GroupCalcEnabled; return true; } @@ -3409,10 +3460,10 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup() aResult.SetToken(aInterpreter.GetResultToken().get()); } - for ( sal_Int32 i = 0; i < xGroup->mnLength; i++ ) + for ( sal_Int32 i = 0; i < mxGroup->mnLength; i++ ) { ScAddress aTmpPos = aPos; - aTmpPos.SetRow(xGroup->mnStart + i); + aTmpPos.SetRow(mxGroup->mnStart + i); ScFormulaCell* pCell = pDocument->GetFormulaCell(aTmpPos); assert( pCell != NULL ); @@ -3642,21 +3693,21 @@ void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt ) bool ScFormulaCell::IsShared() const { - return xGroup.get() != NULL; + return mxGroup.get() != NULL; } bool ScFormulaCell::IsSharedInvariant() const { - return xGroup ? xGroup->mbInvariant : false; + return mxGroup ? mxGroup->mbInvariant : false; } SCROW ScFormulaCell::GetSharedTopRow() const { - return xGroup ? xGroup->mnStart : -1; + return mxGroup ? mxGroup->mnStart : -1; } SCROW ScFormulaCell::GetSharedLength() const { - return xGroup ? xGroup->mnLength : 0; + return mxGroup ? mxGroup->mnLength : 0; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx index b2a161991f52..4f60d7ec56bb 100644 --- a/sc/source/filter/excel/excform.cxx +++ b/sc/source/filter/excel/excform.cxx @@ -101,56 +101,63 @@ void ImportExcel::Formula4() void ImportExcel::Formula( const XclAddress& rXclPos, sal_uInt16 nXF, sal_uInt16 nFormLen, double fCurVal, bool bShrFmla) { - ConvErr eErr = ConvOK; ScAddress aScPos( ScAddress::UNINITIALIZED ); - if( GetAddressConverter().ConvertAddress( aScPos, rXclPos, GetCurrScTab(), true ) ) - { - // Formula will be read next, length in nFormLen - const ScTokenArray* pResult = NULL; - bool bConvert = false; + if (!GetAddressConverter().ConvertAddress(aScPos, rXclPos, GetCurrScTab(), true)) + // Conversion failed. + return; - pFormConv->Reset( aScPos ); + // Formula will be read next, length in nFormLen + const ScTokenArray* pResult = NULL; - if( bShrFmla ) - bConvert = !pFormConv->GetShrFmla( pResult, maStrm, nFormLen ); - else - bConvert = true; + pFormConv->Reset( aScPos ); - if( bConvert ) - eErr = pFormConv->Convert( pResult, maStrm, nFormLen, true, FT_CellFormula); + if (bShrFmla) + { + // This is a shared formula. Get the token array from the shared formula pool. + pResult = pFormConv->GetShrFmla(maStrm, nFormLen); + if (!pResult) + return; + + ScFormulaCell* pCell = new ScFormulaCell( pD, aScPos, pResult ); + pD->EnsureTable(aScPos.Tab()); + pCell = pD->SetFormulaCell(aScPos, pCell); + pCell->SetNeedNumberFormat(false); + if (!rtl::math::isNan(fCurVal)) + pCell->SetResultDouble(fCurVal); + + GetXFRangeBuffer().SetXF(aScPos, nXF); + return; + } - ScFormulaCell* pCell = NULL; + ConvErr eErr = pFormConv->Convert( pResult, maStrm, nFormLen, true, FT_CellFormula); - if (pResult) - { - pCell = new ScFormulaCell( pD, aScPos, pResult ); - pD->EnsureTable(aScPos.Tab()); - pCell = pD->SetFormulaCell(aScPos, pCell); - } - else - { - CellType eCellType = pD->GetCellType(aScPos); - if( eCellType == CELLTYPE_FORMULA ) - { - pCell = pD->GetFormulaCell(aScPos); - if( pCell ) - pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); - } - } + ScFormulaCell* pCell = NULL; + if (pResult) + { + pCell = new ScFormulaCell( pD, aScPos, pResult ); + pD->EnsureTable(aScPos.Tab()); + pCell = pD->SetFormulaCell(aScPos, pCell); + } + else + { + pCell = pD->GetFormulaCell(aScPos); if (pCell) - { - pCell->SetNeedNumberFormat(false); - if( eErr != ConvOK ) - ExcelToSc::SetError( *pCell, eErr ); + pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE ); + } - if (!rtl::math::isNan(fCurVal)) - pCell->SetResultDouble(fCurVal); - } + if (pCell) + { + pCell->SetNeedNumberFormat(false); + if( eErr != ConvOK ) + ExcelToSc::SetError( *pCell, eErr ); - GetXFRangeBuffer().SetXF( aScPos, nXF ); + if (!rtl::math::isNan(fCurVal)) + pCell->SetResultDouble(fCurVal); } + + GetXFRangeBuffer().SetXF(aScPos, nXF); } @@ -1669,45 +1676,32 @@ const ScTokenArray* ExcelToSc::GetBoolErr( XclBoolError eType ) // if a shared formula was found, stream seeks to first byte after <nFormulaLen>, // else stream pointer stays unchanged -sal_Bool ExcelToSc::GetShrFmla( const ScTokenArray*& rpErgebnis, XclImpStream& aIn, sal_Size nFormulaLen ) +const ScTokenArray* ExcelToSc::GetShrFmla( XclImpStream& aIn, sal_Size nFormulaLen ) { - sal_uInt8 nOp; - sal_Bool bRet = sal_True; + if (!nFormulaLen) + return NULL; - if( nFormulaLen == 0 ) - bRet = false; - else - { - aIn.PushPosition(); - - aIn >> nOp; + aIn.PushPosition(); - if( nOp == 0x01 ) // Shared Formula [ 277] - { - sal_uInt16 nCol, nRow; - - aIn >> nRow >> nCol; - - aStack << aPool.StoreName( GetOldRoot().pShrfmlaBuff->Find( - ScAddress(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), GetCurrScTab())), true); - - bRet = sal_True; - } - else - bRet = false; + sal_uInt8 nOp; + aIn >> nOp; + if (nOp != 0x01) // Shared Formula [ 277] + { aIn.PopPosition(); + return NULL; } - if( bRet ) - { - aIn.Ignore( nFormulaLen ); - rpErgebnis = aPool[ aStack.Get() ]; - } - else - rpErgebnis = NULL; + sal_uInt16 nCol, nRow; + aIn >> nRow >> nCol; + + aStack << aPool.StoreName( GetOldRoot().pShrfmlaBuff->Find( + ScAddress(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), GetCurrScTab())), true); + + aIn.PopPosition(); - return bRet; + aIn.Ignore(nFormulaLen); + return aPool[aStack.Get()]; } diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index d1ec8aed8f2b..9c4c5e77b334 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -1140,7 +1140,7 @@ FltError ImportExcel8::Read( void ) case EXC_ID2_ARRAY: case EXC_ID3_ARRAY: Array34(); break; // ARRAY [ 34 ] case 0x0225: Defrowheight345();break;//DEFAULTROWHEI[ 345 ] - case 0x04BC: Shrfmla(); break; // SHRFMLA [ 5 ] + case EXC_ID_SHRFMLA: Shrfmla(); break; // SHRFMLA [ 5 ] case 0x0867: SheetProtection(); break; // SHEETPROTECTION } } diff --git a/sc/source/filter/inc/excform.hxx b/sc/source/filter/inc/excform.hxx index 1b7786fa6aaf..fb866fe812e8 100644 --- a/sc/source/filter/inc/excform.hxx +++ b/sc/source/filter/inc/excform.hxx @@ -63,7 +63,7 @@ public: void GetDummy( const ScTokenArray*& ); const ScTokenArray* GetBoolErr( XclBoolError ); - sal_Bool GetShrFmla( const ScTokenArray*&, XclImpStream& rStrm, sal_Size nFormulaLen ); + const ScTokenArray* GetShrFmla( XclImpStream& rStrm, sal_Size nFormulaLen ); static void SetError( ScFormulaCell& rCell, const ConvErr eErr ); |