20#include <config_feature_opencl.h>
24#include <osl/diagnose.h>
32#include <compiler.hxx>
33#include <document.hxx>
43#include <progress.hxx>
50#include <tokenarray.hxx>
68#include <com/sun/star/sheet/FormulaLanguage.hpp>
70#if HAVE_FEATURE_OPENCL
79#define DEBUG_CALCULATION 0
81static bool bDebugCalculationActive =
false;
82static ScAddress aDebugCalculationTriggerAddress(1,2,0);
84struct DebugCalculationEntry
90 sal_uInt16 mnRecursion;
96 mnRecursion(rDoc.GetRecursionHelper().GetRecursionCount())
107static struct DebugCalculation
109 std::vector< DebugCalculationEntry > mvPos;
110 std::vector< DebugCalculationEntry > mvResults;
118 DebugCalculation() : mnGroup(0),
mbActive(bDebugCalculationActive), mbSwitchOff(false),
119 mbPrint(true), mbPrintResults(false) {}
124 for (
auto const& it : mvPos)
127 " [" + OUString::number( it.mnRecursion) +
"," + OUString::number( it.mnGroup) +
"]");
128 fprintf( stderr,
"%s -> ",
aStr.toUtf8().getStr());
130 fprintf( stderr,
"%s",
"END\n");
134 void printResults()
const
136 for (
auto const& it : mvResults)
139 aStr +=
" (" + it.maResult +
")";
140 fprintf( stderr,
"%s, ",
aStr.toUtf8().getStr());
142 fprintf( stderr,
"%s",
"END\n");
147 if (mbActive && !mvPos.empty())
148 mvPos.back().maResult =
"\"" + rStr.
getString() +
"\"";
151 void storeResult(
const double& fVal )
153 if (mbActive && !mvPos.empty())
154 mvPos.back().maResult = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 2,
'.',
true);
159 if (mbActive && !mvPos.empty())
160 mvPos.back().maResult =
"Err:" + OUString::number(
int( nErr ));
175struct DebugCalculationStacker
179 if (!aDC.mbActive && rPos == aDC.maTrigger)
180 aDC.mbActive = aDC.mbSwitchOff =
true;
183 aDC.mvPos.push_back( DebugCalculationEntry( rPos, rDoc, aDC.mnGroup));
188 ~DebugCalculationStacker()
192 if (!aDC.mvPos.empty())
199 if (aDC.mbPrintResults)
202 aDC.mvResults.push_back( aDC.mvPos.back());
204 aDC.mvPos.pop_back();
205 if (aDC.mbPrintResults && aDC.mvPos.empty())
208 std::vector< DebugCalculationEntry >().swap( aDC.mvResults);
210 if (aDC.mbSwitchOff && aDC.mvPos.empty())
211 aDC.mbActive =
false;
233 return rData.toAbs(rDoc, rPos).Col();
238 return rData.toAbs(rDoc, rPos).Row();
243 return rData.toAbs(rDoc, rPos).Tab();
249lcl_checkRangeDimension(
252 const DimensionSelector aWhich)
254 return aWhich(rDoc, rPos, rRef1.
Ref1) == aWhich(rDoc, rPos, rRef2.
Ref1) &&
255 aWhich(rDoc, rPos, rRef1.
Ref2) == aWhich(rDoc, rPos, rRef2.
Ref2);
259lcl_checkRangeDimensions(
262 bool& bCol,
bool& bRow,
bool& bTab)
264 const bool bSameCols(lcl_checkRangeDimension(rDoc, rPos, rRef1, rRef2, lcl_GetCol));
265 const bool bSameRows(lcl_checkRangeDimension(rDoc, rPos, rRef1, rRef2, lcl_GetRow));
266 const bool bSameTabs(lcl_checkRangeDimension(rDoc, rPos, rRef1, rRef2, lcl_GetTab));
269 if (
int(bSameCols) +
int(bSameRows) +
int(bSameTabs) == 2)
283lcl_checkRangeDimensions(
285 const std::vector<formula::FormulaToken*>::const_iterator& rBegin,
286 const std::vector<formula::FormulaToken*>::const_iterator& rEnd,
287 bool& bCol,
bool& bRow,
bool& bTab)
289 std::vector<formula::FormulaToken*>::const_iterator aCur(rBegin);
295 bOk = lcl_checkRangeDimensions(rDoc, rPos, aRef, aRefCur, bCol, bRow, bTab);
297 while (bOk && aCur != rEnd)
303 bOk = lcl_checkRangeDimensions(rDoc, rPos, aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
304 bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
308 return bOk && aCur == rEnd;
317 LessByReference(
const ScDocument& rDoc,
const ScAddress& rPos,
const DimensionSelector& rFunc) :
318 mrDoc(rDoc), maPos(rPos),
maFunc(rFunc) {}
324 return maFunc(mrDoc, maPos, aRef1.Ref1) <
maFunc(mrDoc, maPos, aRef2.Ref1);
333class AdjacentByReference
339 AdjacentByReference(
const ScDocument& rDoc,
const ScAddress& rPos, DimensionSelector aFunc) :
340 mrDoc(rDoc), maPos(rPos),
maFunc(aFunc) {}
346 return maFunc(mrDoc, maPos, aRef2.Ref1) -
maFunc(mrDoc, maPos, aRef1.Ref2) == 1;
353 const ScAddress& rPos,
const std::vector<formula::FormulaToken*>& rReferences,
const DimensionSelector aWhich)
355 auto aBegin(rReferences.cbegin());
356 auto aEnd(rReferences.cend());
357 auto aBegin1(aBegin);
360 return std::equal(aBegin, aEnd, aBegin1, AdjacentByReference(rDoc, rPos, aWhich));
364lcl_fillRangeFromRefList(
366 const ScAddress& aPos,
const std::vector<formula::FormulaToken*>& rReferences,
ScRange& rRange)
370 rRange.
aStart = aStart.toAbs(rDoc, aPos);
373 rRange.
aEnd = aEnd.toAbs(rDoc, aPos);
377lcl_refListFormsOneRange(
379 const ScAddress& rPos, std::vector<formula::FormulaToken*>& rReferences,
382 if (rReferences.size() == 1)
384 lcl_fillRangeFromRefList(rDoc, rPos, rReferences, rRange);
391 if (lcl_checkRangeDimensions(rDoc, rPos, rReferences.begin(), rReferences.end(), bCell, bRow, bTab))
393 DimensionSelector aWhich;
408 OSL_FAIL(
"lcl_checkRangeDimensions shouldn't allow that!");
413 std::sort(rReferences.begin(), rReferences.end(), LessByReference(rDoc, rPos, aWhich));
414 if (lcl_checkIfAdjacent(rDoc, rPos, rReferences, aWhich))
416 lcl_fillRangeFromRefList(rDoc, rPos, rReferences, rRange);
436 if (!rOldDoc.
CopyAdjustRangeName( nSheet, nIndex, pRangeData, rNewDoc, rNewPos, rOldPos, bGlobalNamesToLocal,
true))
443 assert(!
"inserting the range name should not fail");
454 if (!pOldDBCollection)
464 if (!pNewDBCollection)
473 pNewDBData =
new ScDBData(*pDBData);
474 bool ins = aNewNamedDBs.
insert(std::unique_ptr<ScDBData>(pNewDBData));
475 assert(ins); (void)ins;
512 mbPartOfCycle(false),
534 if (
mpCode->GetLen() &&
mpCode->GetCodeError() == FormulaError::NONE && !
mpCode->GetCodeLen())
557 it, std::make_pair(aKey, std::make_unique<sc::FormulaGroupAreaListener>(
558 rRange, (*ppTopCell)->GetDocument(), (*ppTopCell)->aPos,
mnLength, bStartFixed, bEndFixed)));
561 return it->second.get();
580 bTableOpDirty(false),
586 bInChangeTrack(false),
587 bNeedListening(false),
588 mbNeedsNumberFormat(false),
589 mbAllowNumberFormatChange(false),
590 mbPostponedDirty(false),
602 pPreviousTrack(nullptr),
609 const OUString& rFormula,
613 bTableOpDirty( false ),
618 bIsIterCell( false ),
619 bInChangeTrack( false ),
620 bNeedListening( false ),
621 mbNeedsNumberFormat( false ),
622 mbAllowNumberFormatChange(false),
623 mbPostponedDirty(false),
627 cMatrixFlag ( cMatInd ),
630 eTempGrammar( eGrammar),
635 pPreviousTrack(nullptr),
639 Compile( rFormula,
true, eGrammar );
649 bTableOpDirty( false ),
654 bIsIterCell( false ),
655 bInChangeTrack( false ),
656 bNeedListening( false ),
657 mbNeedsNumberFormat( false ),
658 mbAllowNumberFormatChange(false),
659 mbPostponedDirty(false),
663 cMatrixFlag ( cMatInd ),
666 eTempGrammar( eGrammar),
667 pCode(pArray.release()),
671 pPreviousTrack(nullptr),
702 bTableOpDirty( false ),
707 bIsIterCell( false ),
708 bInChangeTrack( false ),
709 bNeedListening( false ),
710 mbNeedsNumberFormat( false ),
711 mbAllowNumberFormatChange(false),
712 mbPostponedDirty(false),
716 cMatrixFlag ( cMatInd ),
719 eTempGrammar( eGrammar),
724 pPreviousTrack(nullptr),
752 bTableOpDirty( false ),
756 bSubTotal(xGroup->mbSubTotal),
757 bIsIterCell( false ),
758 bInChangeTrack( false ),
759 bNeedListening( false ),
760 mbNeedsNumberFormat( false ),
761 mbAllowNumberFormatChange(false),
762 mbPostponedDirty(false),
766 cMatrixFlag ( cInd ),
768 nFormatType(xGroup->mnFormatType),
769 eTempGrammar( eGrammar),
770 pCode(xGroup->mpCode ? &*xGroup->mpCode : new
ScTokenArray(rDoc)),
774 pPreviousTrack(nullptr),
783 bDirty( rCell.bDirty ),
784 bTableOpDirty( false ),
785 bChanged( rCell.bChanged ),
787 bCompile( rCell.bCompile ),
788 bSubTotal( rCell.bSubTotal ),
789 bIsIterCell( false ),
790 bInChangeTrack( false ),
791 bNeedListening( false ),
792 mbNeedsNumberFormat( rCell.mbNeedsNumberFormat ),
793 mbAllowNumberFormatChange(false),
794 mbPostponedDirty(false),
798 cMatrixFlag ( rCell.cMatrixFlag ),
800 nFormatType( rCell.nFormatType ),
801 aResult( rCell.aResult ),
802 eTempGrammar( rCell.eTempGrammar),
806 pPreviousTrack(nullptr),
821 bool bCompileLater =
false;
836 adjustRangeName(pToken, rDoc, rCell.
rDocument,
aPos, rCell.
aPos, bGlobalNamesToLocal);
838 adjustDBRange(pToken, rDoc, rCell.
rDocument);
866 if (
t->IsExternalRef() )
885 bCompileLater = bClipMode;
891 if ( !bCompileLater && bClipMode )
899 if ( !bCompileLater )
951 OUStringBuffer buffer;
971 return pCell->
GetFormula( eGrammar, pContext );
981 OSL_FAIL(
"ScFormulaCell::GetFormula: not a matrix");
990 buffer.insert( 0,
'=');
993 buffer.insert( 0,
'{');
996 return buffer.makeStringAndClear();
1001 OUStringBuffer
aBuf;
1008 return aBuf.makeStringAndClear();
1039 OSL_FAIL(
"ScFormulaCell::GetFormula: not a matrix");
1048 aBuf.insert( 0,
'=');
1051 aBuf.insert( 0,
'{');
1055 return aBuf.makeStringAndClear();
1101 if ( bWasInFormulaTree )
1115 if ( rFormula[0] ==
'=' )
1126 if ( bWasInFormulaTree )
1136 if ( bWasInFormulaTree )
1150 if ( rFormula[0] ==
'=' )
1161 if ( bWasInFormulaTree )
1176 if ( bWasInFormulaTree )
1181 bNoListening =
true;
1193 if ( !bNoListening )
1196 if ( bWasInFormulaTree )
1216 if ( bWasInFormulaTree )
1221 bNoListening =
true;
1233 if ( !bNoListening )
1236 if ( bWasInFormulaTree )
1260 if (bWasInFormulaTree)
1264 OUString aFormula, aFormulaNmsp;
1271 bool bDoCompile =
true;
1273 if ( !
mxGroup && aFormulaNmsp.isEmpty() )
1276 aPreviousCell.
IncRow( -1 );
1283 OUStringBuffer aShouldBeBuf;
1287 const sal_Int32 nLeadingEqual = (aFormula.getLength() > 0 && aFormula[0] ==
'=') ? 1 : 0;
1288 OUString aShouldBe = aShouldBeBuf.makeStringAndClear();
1289 if (aFormula.getLength() == aShouldBe.getLength() + nLeadingEqual &&
1290 aFormula.match( aShouldBe, nLeadingEqual))
1328 if ( !aFormula.isEmpty() && aFormula[0] ==
'=' )
1362 else if (bWasInFormulaTree)
1368 bool bNewCompiled =
false;
1376 bNewCompiled =
true;
1386 bNewCompiled =
true;
1397 OSL_FAIL(
"Formula cell INFINITY!!! Where does this document come from?");
1415 if (bStartListening)
1435class RecursionCounter
1438 bool bStackedInIteration;
1439#if defined DBG_UTIL && !defined NDEBUG
1445#
if defined DBG_UTIL && !defined NDEBUG
1450 if (bStackedInIteration)
1457 if (bStackedInIteration)
1459#if defined DBG_UTIL && !defined NDEBUG
1473struct TemporaryCellGroupMaker
1477 , mEnabled( enable )
1479 if( mEnabled && mCell->GetCellGroup() ==
nullptr )
1481 mCell->CreateCellGroup( 1,
false );
1482 mCell->GetDocument().GetRecursionHelper().AddTemporaryGroupCell( mCell );
1485 ~TemporaryCellGroupMaker() COVERITY_NOEXCEPT_FALSE
1488 mCell->GetDocument().GetRecursionHelper().CleanTemporaryGroupCells();
1491 const bool mEnabled;
1499 bool bGroupInterpreted =
false;
1507 return bGroupInterpreted;
1527 return bGroupInterpreted;
1530#if DEBUG_CALCULATION
1531 static bool bDebugCalculationInit =
true;
1532 if (bDebugCalculationInit)
1534 aDC.maTrigger = aDebugCalculationTriggerAddress;
1535 aDC.mbPrintResults =
true;
1536 bDebugCalculationInit =
false;
1542 return bGroupInterpreted;
1548 return bGroupInterpreted;
1555 return bGroupInterpreted;
1566 return bGroupInterpreted;
1573 return bGroupInterpreted;
1585#if DEBUG_CALCULATION
1592#if DEBUG_CALCULATION
1595 if (!bGroupInterpreted)
1602 return bGroupInterpreted;
1607 if (!bPartOfCycleBefore && bPartOfCycleAfter && rRecursionHelper.
AnyParentFGInCycle())
1610 return bGroupInterpreted;
1625 bool bFreeFlyingInserted =
false;
1631 bool bIterationFromRecursion =
false;
1632 bool bResumeIteration =
false;
1638 bIterationFromRecursion || bResumeIteration)
1642 if (!bIterationFromRecursion && bResumeIteration)
1644 bResumeIteration =
false;
1646 ScFormulaRecursionList::const_iterator aOldStart(
1650 for (ScFormulaRecursionList::const_iterator aIter(
1661 sal_uInt16 nIteration = rRecursionHelper.
GetIteration();
1662 for (ScFormulaRecursionList::const_iterator aIter(
1663 aOldStart); aIter !=
1669 if (!pIterCell->
bDirty || aIter == aOldStart)
1671 pIterCell->
aResult = (*aIter).aPreviousResult;
1675 pIterCell->
bDirty =
true;
1680 bResumeIteration =
false;
1687 if (rRecursionHelper.
GetList().size() > 1)
1690 if (pLastCell !=
this)
1704 for (ScFormulaRecursionList::const_iterator aIter(
1709 pIterCell->
aResult = (*aIter).aPreviousResult;
1713 bIterationFromRecursion =
false;
1715 for ( ; rRecursionHelper.
GetIteration() <= nIterMax && !rDone;
1720 for ( ScFormulaRecursionList::iterator aIter(
1730 (*aIter).aPreviousResult = pIterCell->
aResult;
1748 bResumeIteration =
true;
1753 if (!bResumeIteration)
1757 for (ScFormulaRecursionList::const_iterator aIter(
1765 pIterCell->
bRunning = (*aIter).bOldRunning;
1770 for (ScFormulaRecursionList::const_iterator aIter(
1778 pIterCell->
bRunning = (*aIter).bOldRunning;
1810 bIterationFromRecursion =
false;
1818 for (ScFormulaRecursionList::const_iterator aIter(
1831 pCell->
bRunning = (*aIter).bOldRunning;
1838 if (!bResumeIteration)
1839 bIterationFromRecursion =
true;
1841 else if (bResumeIteration ||
1843 rRecursionHelper.
GetList().erase(
1847 rRecursionHelper.
Clear();
1849 }
while (bIterationFromRecursion || bResumeIteration);
1851 if (bFreeFlyingInserted)
1859 const bool bOnlyThis = (rRecursionHelper.
GetList().size() == 1);
1864 assert(rRecursionHelper.
GetList().empty());
1865 if (rRecursionHelper.
GetList().empty())
1871#if DEBUG_CALCULATION
1873 if (nErr != FormulaError::NONE)
1874 aDC.storeResultError( nErr);
1881 return bGroupInterpreted;
1913 std::unique_ptr<ScInterpreter> pScopedInterpreter;
1923 pInterpreter = pScopedInterpreter.get();
1937 case FormulaError::CircularReference :
1966 bool bContentChanged =
false;
1972 if( pInterpreter->
GetError() != FormulaError::NONE && pInterpreter->
GetError() != FormulaError::CircularReference)
1976 if (pInterpreter->
GetError() == FormulaError::RetryCircular)
2015 if( pInterpreter->
GetError() != nOldErrCode )
2020 bContentChanged =
true;
2049 if (bForceNumberFormat)
2053 if (nRetType == SvNumFormatType::LOGICAL)
2056 if (fVal != 1.0 && fVal != 0.0)
2057 bForceNumberFormat =
false;
2064 case SvNumFormatType::PERCENT:
2065 case SvNumFormatType::CURRENCY:
2066 case SvNumFormatType::SCIENTIFIC:
2067 case SvNumFormatType::FRACTION:
2068 bForceNumberFormat =
false;
2070 case SvNumFormatType::NUMBER:
2072 bForceNumberFormat =
false;
2078 else if (nRetType == SvNumFormatType::TEXT)
2080 bForceNumberFormat =
false;
2082 if (bForceNumberFormat)
2089 if (nOldFormatIndex !=
2091 bForceNumberFormat =
false;
2097 bool bSetFormat =
true;
2122 if (eNewCellResultType !=
svDouble)
2130 if (fVal != 1.0 && fVal != 0.0)
2197 bContentChanged = (eOld != eNew ||
2226 bContentChanged =
true;
2282 pData->DoCalcError(
this );
2290 if (pProgress && pProgress->
Enabled())
2330 OSL_ENSURE(
pCode->
GetCodeError() != FormulaError::NONE,
"no RPN code and no errors ?!?!" );
2343 std::unique_ptr<ScInterpreter> pScopedInterpreter;
2349 pInterpreter = pScopedInterpreter.get();
2390 else if (nCols || nRows)
2422 if (nHint == SfxHintId::ScReference)
2472 if (!(nHint == SfxHintId::ScDataChanged || nHint == SfxHintId::ScTableOpDirty || (
bSubTotal && nHint == SfxHintId::ScHiddenRowsChanged)))
2475 bool bForceTrack =
false;
2476 if ( nHint == SfxHintId::ScTableOpDirty )
2506 switch (rQuery.
getId())
2562 mxGroup->mbPartOfCycle =
false;
2647 if ( (nBits & ScRecalcMode::EMask) != ScRecalcMode::NORMAL )
2649 if ( nBits & ScRecalcMode::ONLOAD_ONCE )
2651 nBits = (nBits &
~ScRecalcMode::EMask) | ScRecalcMode::NORMAL;
2685 OUString aCellString;
2687 const Color* pColor;
2699 pFormatter->
GetOutputString( fValue, nCellFormat, rCellText, &pColor );
2704 pFormatter->
GetOutputString( aCellString, nCellFormat, rCellText, &pColor );
2710 if (!xMat->IsValue(0, 1))
2711 rURL = xMat->GetString(0, 1).getString();
2714 xMat->GetDouble(0, 1), nURLFormat, rURL, &pColor);
2722 pFormatter->
GetOutputString( aCellString, nURLFormat, rURL, &pColor );
2862 static thread_local SCCOL nC;
2863 static thread_local SCROW nR;
2867 if ( aOrg != rOrgPos )
2879 if ( nC == 0 || nR == 0 )
2922#if OSL_DEBUG_LEVEL > 0
2923 SAL_WARN(
"sc",
"broken Matrix, no MatFormula at origin, Pos: "
2935 if ( dC >= 0 && dR >= 0 && dC < nC && dR < nR )
2950 SAL_WARN(
"sc",
"broken Matrix, Pos: "
2954 <<
", MatCols: " <<
static_cast<sal_Int32
>( nC )
2955 <<
", MatRows: " <<
static_cast<sal_Int32
>( nR )
2956 <<
", DiffCols: " <<
static_cast<sal_Int32
>( dC )
2957 <<
", DiffRows: " <<
static_cast<sal_Int32
>( dR ));
2974 if (nErr != FormulaError::NONE)
2982 if (nErr != FormulaError::NONE)
2992 if (rErr != FormulaError::NONE)
3003 if (nErr != FormulaError::NONE)
3012 if (nErr != FormulaError::NONE)
3053 if (pFirstReference)
3057 std::vector<formula::FormulaToken*> aReferences { pFirstReference };
3062 if (lcl_isReference(*pToken))
3064 aReferences.push_back(pToken);
3079 return lcl_refListFormsOneRange(
rDocument,
aPos, aReferences, rRange);
3092 switch (
t->GetType())
3099 if (
t->GetDoubleRef()->Ref1.IsRelName() ||
t->GetDoubleRef()->Ref2.IsRelName())
3133 assert(!
"can't move ScFormulaCell");
3144bool checkCompileColRowName(
3159 while ((t = aIter.GetNextColRowName()) !=
nullptr)
3198 bool bMoved = (aPos != aOldPos);
3204 for (;
t;
t = aIter.GetNextColRowName())
3225void setOldCodeToUndo(
3240 rUndoDoc, aUndoPos, pOldCode ? *pOldCode :
ScTokenArray(rUndoDoc), eTempGrammar, cMatrixFlag);
3255 bool bCellStateChanged =
false;
3258 aUndoPos = *pUndoCellPos;
3264 bool bHasColRowNames =
false;
3268 bHasRefs = bHasColRowNames;
3272 if (!bHasRefs && !bOnRefMove)
3275 return bCellStateChanged;
3277 std::unique_ptr<ScTokenArray> pOldCode;
3281 bool bValChanged =
false;
3282 bool bRefModified =
false;
3295 if (bValChanged || bRefModified)
3296 bCellStateChanged =
true;
3300 bOnRefMove = (bValChanged || (
aPos != aOldPos) || bRefModified);
3302 bool bNewListening =
false;
3303 bool bInDeleteUndo =
false;
3309 if (bHasColRowNames && !bRecompile)
3310 bRecompile = checkCompileColRowName(rCxt,
rDocument, *
pCode, aOldPos,
aPos, bValChanged);
3313 bInDeleteUndo = (pChangeTrack && pChangeTrack->
IsInDeleteUndo());
3316 bool bHasRelName =
false;
3325 bNewListening = (bRefModified || bRecompile
3326 || (bValChanged && bInDeleteUndo) || bHasRelName);
3328 if ( bNewListening )
3333 bool bNeedDirty = (bValChanged || bRecompile || bOnRefMove);
3335 if (pUndoDoc && (bValChanged || bOnRefMove))
3345 if ( !bInDeleteUndo )
3348 if ( bNewListening )
3365 return bCellStateChanged;
3376 aUndoPos = *pUndoCellPos;
3381 if ( bCellInMoveTarget )
3392 bool bHasColRowNames =
false;
3396 bHasRefs = bHasColRowNames;
3400 if (!bHasRefs && !bOnRefMove)
3405 bool bCellStateChanged =
false;
3406 std::unique_ptr<ScTokenArray> pOldCode;
3410 bool bValChanged =
false;
3411 bool bRefModified =
false;
3424 if (bValChanged || bRefModified)
3425 bCellStateChanged =
true;
3429 bOnRefMove = (bValChanged || (
aPos != aOldPos));
3431 bool bColRowNameCompile =
false;
3432 bool bHasRelName =
false;
3433 bool bNewListening =
false;
3434 bool bInDeleteUndo =
false;
3440 if (bHasColRowNames)
3441 bColRowNameCompile = checkCompileColRowName(rCxt,
rDocument, *
pCode, aOldPos,
aPos, bValChanged);
3444 bInDeleteUndo = (pChangeTrack && pChangeTrack->
IsInDeleteUndo());
3452 bNewListening = (bRefModified || bColRowNameCompile
3453 || bValChanged || bHasRelName)
3459 if ( bNewListening )
3463 bool bNeedDirty =
false;
3465 if ( bRefModified || bColRowNameCompile ||
3466 (bValChanged && bHasRelName ) || bOnRefMove)
3469 if (pUndoDoc && !bCellInMoveTarget && (bValChanged || bRefModified || bOnRefMove))
3472 bValChanged =
false;
3481 if ( !bInDeleteUndo )
3484 if ( bNewListening )
3496 return bCellStateChanged;
3507 aUndoPos = *pUndoCellPos;
3522 bHasRefs = bHasRefs || bHasColRowNames;
3525 if (!bHasRefs && !bOnRefMove)
3530 std::unique_ptr<ScTokenArray> pOldCode;
3536 bOnRefMove = (
aPos != aOldPos);
3538 bool bNeedDirty = bOnRefMove;
3540 if (pUndoDoc && bOnRefMove)
3720 if (nTable != rRef1.
Tab())
3722 else if (nTable !=
aPos.
Tab())
3730 if(nTable != rRef2.
Tab())
3732 else if (nTable !=
aPos.
Tab())
3743 if ( bForceIfNameInUse && !
bCompile )
3762 bool bFound =
false;
3794 bool bPosChanged =
false;
3803 if ( aDestRange.
Contains( aOldPos ) )
3811 aOldPos.
Set( nRelPosX, nRelPosY, nRelPosZ );
3815 std::unique_ptr<ScTokenArray> pOld;
3818 bool bRefChanged =
false;
3824 if(
t->GetOpCode() ==
ocName )
3878 bool bRefChanged =
false;
3885 if(
t->GetOpCode() ==
ocName )
3924 sal_uInt16 nTokenIndex =
p->GetIndex();
3925 SCTAB nTab =
p->GetSheet();
3928 if (nRecursion < 126)
3952 pCode = pNew.release();
4002 SAL_INFO(
"sc.opencl",
"You can't create a new group if the cell is already a part of a group");
4008 mxGroup->mbInvariant = bInvariant;
4056 if ( !pThis || !pOther )
4062 if ( nThisLen != nOtherLen )
4072 bool bInvariant =
true;
4075 for ( sal_uInt16
i = 0;
i < nThisLen;
i++ )
4177 if ( !pThis || !pOther )
4183 if ( nThisLen != nOtherLen )
4186 for ( sal_uInt16
i = 0;
i < nThisLen;
i++ )
4268int splitup(
int N,
int K,
int&
A)
4278 const int ideal_num_parts =
N / K;
4279 if (ideal_num_parts * K == N)
4280 return ideal_num_parts;
4282 const int num_parts = ideal_num_parts + 1;
4283 const int nominal_part_size =
N / num_parts;
4285 A =
N - num_parts * nominal_part_size;
4290struct ScDependantsCalculator
4297 const bool mFromFirstRow;
4298 const SCROW mnStartOffset;
4299 const SCROW mnEndOffset;
4300 const SCROW mnSpanLen;
4306 mxGroup(rCell.GetCellGroup()),
4307 mnLen(mxGroup->mnLength),
4312 mFromFirstRow(fromFirstRow),
4313 mnStartOffset(nStartOffset),
4314 mnEndOffset(nEndOffset),
4315 mnSpanLen(nEndOffset - nStartOffset + 1)
4325 bool isSelfReferenceRelative(
const ScAddress& rRefPos,
SCROW nRelRow)
4334 SCROW nTest = nEndRow;
4343 if (nTest <= nEndRow)
4358 bool isSelfReferenceAbsolute(
const ScAddress& rRefPos)
4369 if (rRefPos.
Row() > nEndRow && !mFromFirstRow)
4378 bool isDoubleRefSpanGroupRange(
const ScRange& rAbs,
bool bIsRef1RowRel,
bool bIsRef2RowRel)
4387 SCROW nEndRow = nStartRow + mnLen - 1;
4391 if (bIsRef1RowRel && bIsRef2RowRel &&
4392 ((nRefStartRow <= nStartRow && nRefEndRow >= nEndRow) ||
4393 ((nRefStartRow + mnLen - 1) <= nStartRow &&
4394 (nRefEndRow + mnLen - 1) >= nEndRow)))
4397 if (!bIsRef1RowRel && nRefStartRow <= nStartRow &&
4398 (nRefEndRow >= nEndRow || (nRefEndRow + mnLen - 1) >= nEndRow))
4401 if (!bIsRef2RowRel &&
4402 nRefStartRow <= nStartRow && nRefEndRow >= nEndRow)
4407 if (mFromFirstRow && nRefEndRow >= nStartRow)
4416 SCROW nLastRow = nRow + nRowLen - 1;
4418 if (nLastRow < (nRow + nRowLen - 1))
4423 nRowLen = nLastRow - nRow + 1;
4429 else if (nLastRow == 0)
4443 bool bHasSelfReferences =
false;
4448 for (sal_Int32 nTokenIdx = nCodeLen-1; nTokenIdx >= 0; --nTokenIdx)
4450 auto p = pRPNArray[nTokenIdx];
4451 if (!bInDocShellRecalc)
4459 OpCode nOpCode =
p->GetOpCode();
4460 if (nOpCode == ocIf || nOpCode == ocIfs_MS || nOpCode == ocSwitch_MS)
4464 switch (
p->GetType())
4478 if (isSelfReferenceRelative(aRefPos, aRef.
Row()))
4480 bHasSelfReferences =
true;
4485 SCROW nTrimLen = trimLength(aRefPos.
Tab(), aRefPos.
Col(), aRefPos.
Col(), aRefPos.
Row() + mnStartOffset, mnSpanLen);
4488 aRefPos.
Col(), aRefPos.
Row() + mnStartOffset + nTrimLen - 1, aRefPos.
Tab()));
4492 if (isSelfReferenceAbsolute(aRefPos))
4494 bHasSelfReferences =
true;
4519 bHasSelfReferences =
true;
4523 else if (isSelfReferenceAbsolute(aAbs.
aStart))
4525 bHasSelfReferences =
true;
4532 if (isSelfReferenceRelative(aAbs.
aEnd, aRef.
Ref2.
Row()))
4534 bHasSelfReferences =
true;
4538 else if (isSelfReferenceAbsolute(aAbs.
aEnd))
4540 bHasSelfReferences =
true;
4544 if (isDoubleRefSpanGroupRange(aAbs, bIsRef1RowRel, bIsRef2RowRel))
4546 bHasSelfReferences =
true;
4555 SCROW nArrayLength = nLastRefRow - nFirstRefRow + 1;
4556 assert(nArrayLength > 0);
4562 aAbs.
aEnd.
Col(), nFirstRefRow + nArrayLength - 1, aAbs.
aEnd.
Tab()));
4573 for (
size_t i = 0;
i < aRangeList.
size(); ++
i)
4575 const ScRange & rRange = aRangeList[
i];
4592 if (bHasSelfReferences)
4593 mxGroup->mbPartOfCycle =
true;
4595 return !bHasSelfReferences;
4611 aScope.addMessage(
"This formula-group is part of a cycle");
4617 static constexpr OUStringLiteral MESSAGE =
u"group calc disabled";
4618 aScope.addMessage(MESSAGE);
4630 aScope.addGroupSizeThresholdMessage(*
this);
4637 aScope.addMessage(
"matrix skipped");
4651 aScope.addMessage(
"cell not in document");
4658 nStartOffset = nStartOffset < 0 ? 0 : std::min(nStartOffset, nMaxOffset);
4659 nEndOffset = nEndOffset < 0 ? nMaxOffset : std::min(nEndOffset, nMaxOffset);
4661 if (nEndOffset < nStartOffset)
4664 nEndOffset = nMaxOffset;
4667 if (nEndOffset == nStartOffset)
4674 RecursionCounter aRecursionCounter( rRecursionHelper,
this);
4676 bool bDependencyComputed =
false;
4677 bool bDependencyCheckFailed =
false;
4692 bool bCalcDependencyOnly)
4698 if (bCalcDependencyOnly)
4704 ScDependantsCalculator aCalculator(
rDocument, *
pCode, *
this,
mxGroup->mpTopCell->aPos, fromFirstRow, nStartOffset, nEndOffset);
4705 return aCalculator.DoIt();
4708 bool bOKToParallelize =
false;
4714 rScope.
addMessage(
"found circular formula-group dependencies");
4719 ScDependantsCalculator aCalculator(
rDocument, *
pCode, *
this,
mxGroup->mpTopCell->aPos, fromFirstRow, nStartOffset, nEndOffset);
4720 bOKToParallelize = aCalculator.DoIt();
4727 rScope.
addMessage(
"Recursion limit reached, cannot thread this formula group now");
4734 rScope.
addMessage(
"found circular formula-group dependencies");
4742 rScope.
addMessage(
"multi-group-dependency failed");
4746 if (!bOKToParallelize)
4749 rScope.
addMessage(
"could not do new dependencies calculation thing");
4758 std::map<SCCOL, ScFormulaCell*>& rFGMap,
bool bLeft)
4760 const SCROW nLen = xGroup->mnLength;
4761 const sal_Int32 nWt = xGroup->mnWeight;
4762 ScAddress aAddr(xGroup->mpTopCell->aPos);
4772 while (nColRet >= 0 && nColRet <= nMaxCol)
4789 if (xNGroup->mpTopCell->aPos.Row() != aAddr.
Row())
4792 const SCROW nNLen = xNGroup->mnLength;
4793 const sal_Int32 nNWt = pCell->
GetWeight();
4794 if (nNLen != nLen || nNWt != nWt)
4797 rFGSet.
insert(xNGroup.get());
4798 rFGMap[nColRet] = xNGroup->mpTopCell;
4816 bool& bDependencyComputed,
4817 bool& bDependencyCheckFailed,
4821 static const bool bThreadingProhibited = std::getenv(
"SC_NO_THREADED_CALCULATION");
4822 if (!bDependencyCheckFailed && !bThreadingProhibited &&
4828 bDependencyComputed =
true;
4829 bDependencyCheckFailed =
true;
4833 bDependencyComputed =
true;
4840 const unsigned mnThisThread;
4841 const unsigned mnThreadsTotal;
4847 SCROW mnStartOffset;
4851 Executor(
const std::shared_ptr<comphelper::ThreadTaskTag>& rTag,
4852 unsigned nThisThread,
4853 unsigned nThreadsTotal,
4862 mnThisThread(nThisThread),
4863 mnThreadsTotal(nThreadsTotal),
4864 mpDocument(pDocument2),
4867 mnStartCol(nStartCol),
4869 mnStartOffset(nStartOff),
4870 mnEndOffset(nEndOff)
4874 virtual void doWork()
override
4876 ScRange aCalcRange(mnStartCol, mrTopPos.
Row() + mnStartOffset, mrTopPos.
Tab(),
4877 mnEndCol, mrTopPos.
Row() + mnEndOffset, mrTopPos.
Tab());
4888 SAL_INFO(
"sc.threaded",
"Running " << nThreadCount <<
" threads");
4891 std::map<SCCOL, ScFormulaCell*> aFGMap;
4896 SCCOL nColEnd = nColStart;
4903 if (nColStart != nColEnd)
4906 for (
SCCOL nCurrCol = nColStart; nCurrCol <= nColEnd; ++nCurrCol)
4911 bool bFGOK = aFGMap[nCurrCol]->CheckComputeDependencies(aScope,
false, nStartOffset, nEndOffset,
true);
4914 nColEnd = nColStart =
aPos.
Col();