1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*b3f79822SAndrew Rist * distributed with this work for additional information
6*b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10*b3f79822SAndrew Rist *
11*b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*b3f79822SAndrew Rist *
13*b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17*b3f79822SAndrew Rist * specific language governing permissions and limitations
18*b3f79822SAndrew Rist * under the License.
19*b3f79822SAndrew Rist *
20*b3f79822SAndrew Rist *************************************************************/
21*b3f79822SAndrew Rist
22*b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include <vcl/svapp.hxx>
30cdf0e10cSrcweir
31cdf0e10cSrcweir #if defined( WNT ) && defined( erBEEP )
32cdf0e10cSrcweir #include <svwin.h>
33cdf0e10cSrcweir #define erBEEPER() Beep( 666, 66 )
34cdf0e10cSrcweir #else
35cdf0e10cSrcweir #define erBEEPER()
36cdf0e10cSrcweir #endif
37cdf0e10cSrcweir
38cdf0e10cSrcweir #include "document.hxx"
39cdf0e10cSrcweir #include "brdcst.hxx"
40cdf0e10cSrcweir #include "bcaslot.hxx"
41cdf0e10cSrcweir #include "cell.hxx"
42cdf0e10cSrcweir #include "formula/errorcodes.hxx" // errCircularReference
43cdf0e10cSrcweir #include "scerrors.hxx"
44cdf0e10cSrcweir #include "docoptio.hxx"
45cdf0e10cSrcweir #include "refupdat.hxx"
46cdf0e10cSrcweir #include "table.hxx"
47cdf0e10cSrcweir #include "progress.hxx"
48cdf0e10cSrcweir #include "scmod.hxx" // SC_MOD
49cdf0e10cSrcweir #include "inputopt.hxx" // GetExpandRefs
50cdf0e10cSrcweir #include "conditio.hxx"
51cdf0e10cSrcweir #include "sheetevents.hxx"
52cdf0e10cSrcweir #include <tools/shl.hxx>
53cdf0e10cSrcweir
54cdf0e10cSrcweir
55cdf0e10cSrcweir #include "globstr.hrc"
56cdf0e10cSrcweir
57cdf0e10cSrcweir extern const ScFormulaCell* pLastFormulaTreeTop; // cellform.cxx Err527 WorkAround
58cdf0e10cSrcweir
59cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
60cdf0e10cSrcweir
61cdf0e10cSrcweir #ifdef erDEBUG
62cdf0e10cSrcweir sal_uLong erCountBCAInserts = 0;
63cdf0e10cSrcweir sal_uLong erCountBCAFinds = 0;
64cdf0e10cSrcweir #endif
65cdf0e10cSrcweir
66cdf0e10cSrcweir // -----------------------------------------------------------------------
67cdf0e10cSrcweir
StartListeningArea(const ScRange & rRange,SvtListener * pListener)68cdf0e10cSrcweir void ScDocument::StartListeningArea( const ScRange& rRange,
69cdf0e10cSrcweir SvtListener* pListener
70cdf0e10cSrcweir )
71cdf0e10cSrcweir {
72cdf0e10cSrcweir if ( pBASM )
73cdf0e10cSrcweir pBASM->StartListeningArea( rRange, pListener );
74cdf0e10cSrcweir }
75cdf0e10cSrcweir
76cdf0e10cSrcweir
EndListeningArea(const ScRange & rRange,SvtListener * pListener)77cdf0e10cSrcweir void ScDocument::EndListeningArea( const ScRange& rRange,
78cdf0e10cSrcweir SvtListener* pListener
79cdf0e10cSrcweir )
80cdf0e10cSrcweir {
81cdf0e10cSrcweir if ( pBASM )
82cdf0e10cSrcweir pBASM->EndListeningArea( rRange, pListener );
83cdf0e10cSrcweir }
84cdf0e10cSrcweir
85cdf0e10cSrcweir
Broadcast(sal_uLong nHint,const ScAddress & rAddr,ScBaseCell * pCell)86cdf0e10cSrcweir void ScDocument::Broadcast( sal_uLong nHint, const ScAddress& rAddr,
87cdf0e10cSrcweir ScBaseCell* pCell
88cdf0e10cSrcweir )
89cdf0e10cSrcweir {
90cdf0e10cSrcweir if ( !pBASM )
91cdf0e10cSrcweir return ; // Clipboard or Undo
92cdf0e10cSrcweir ScHint aHint( nHint, rAddr, pCell );
93cdf0e10cSrcweir Broadcast( aHint );
94cdf0e10cSrcweir }
95cdf0e10cSrcweir
96cdf0e10cSrcweir
Broadcast(const ScHint & rHint)97cdf0e10cSrcweir void ScDocument::Broadcast( const ScHint& rHint )
98cdf0e10cSrcweir {
99cdf0e10cSrcweir if ( !pBASM )
100cdf0e10cSrcweir return ; // Clipboard or Undo
101cdf0e10cSrcweir if ( !nHardRecalcState )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir ScBulkBroadcast aBulkBroadcast( pBASM); // scoped bulk broadcast
104cdf0e10cSrcweir sal_Bool bIsBroadcasted = sal_False;
105cdf0e10cSrcweir ScBaseCell* pCell = rHint.GetCell();
106cdf0e10cSrcweir if ( pCell )
107cdf0e10cSrcweir {
108cdf0e10cSrcweir SvtBroadcaster* pBC = pCell->GetBroadcaster();
109cdf0e10cSrcweir if ( pBC )
110cdf0e10cSrcweir {
111cdf0e10cSrcweir pBC->Broadcast( rHint );
112cdf0e10cSrcweir bIsBroadcasted = sal_True;
113cdf0e10cSrcweir }
114cdf0e10cSrcweir }
115cdf0e10cSrcweir if ( pBASM->AreaBroadcast( rHint ) || bIsBroadcasted )
116cdf0e10cSrcweir TrackFormulas( rHint.GetId() );
117cdf0e10cSrcweir }
118cdf0e10cSrcweir
119cdf0e10cSrcweir // Repaint fuer bedingte Formate mit relativen Referenzen:
120cdf0e10cSrcweir if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
121cdf0e10cSrcweir pCondFormList->SourceChanged( rHint.GetAddress() );
122cdf0e10cSrcweir
123cdf0e10cSrcweir if ( rHint.GetAddress() != BCA_BRDCST_ALWAYS )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir SCTAB nTab = rHint.GetAddress().Tab();
126cdf0e10cSrcweir if (pTab[nTab] && pTab[nTab]->IsStreamValid())
127cdf0e10cSrcweir pTab[nTab]->SetStreamValid(sal_False);
128cdf0e10cSrcweir }
129cdf0e10cSrcweir }
130cdf0e10cSrcweir
131cdf0e10cSrcweir
AreaBroadcast(const ScHint & rHint)132cdf0e10cSrcweir void ScDocument::AreaBroadcast( const ScHint& rHint )
133cdf0e10cSrcweir {
134cdf0e10cSrcweir if ( !pBASM )
135cdf0e10cSrcweir return ; // Clipboard or Undo
136cdf0e10cSrcweir if ( !nHardRecalcState )
137cdf0e10cSrcweir {
138cdf0e10cSrcweir ScBulkBroadcast aBulkBroadcast( pBASM); // scoped bulk broadcast
139cdf0e10cSrcweir if ( pBASM->AreaBroadcast( rHint ) )
140cdf0e10cSrcweir TrackFormulas( rHint.GetId() );
141cdf0e10cSrcweir }
142cdf0e10cSrcweir
143cdf0e10cSrcweir // Repaint fuer bedingte Formate mit relativen Referenzen:
144cdf0e10cSrcweir if ( pCondFormList && rHint.GetAddress() != BCA_BRDCST_ALWAYS )
145cdf0e10cSrcweir pCondFormList->SourceChanged( rHint.GetAddress() );
146cdf0e10cSrcweir }
147cdf0e10cSrcweir
148cdf0e10cSrcweir
AreaBroadcastInRange(const ScRange & rRange,const ScHint & rHint)149cdf0e10cSrcweir void ScDocument::AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint )
150cdf0e10cSrcweir {
151cdf0e10cSrcweir if ( !pBASM )
152cdf0e10cSrcweir return ; // Clipboard or Undo
153cdf0e10cSrcweir if ( !nHardRecalcState )
154cdf0e10cSrcweir {
155cdf0e10cSrcweir ScBulkBroadcast aBulkBroadcast( pBASM); // scoped bulk broadcast
156cdf0e10cSrcweir if ( pBASM->AreaBroadcastInRange( rRange, rHint ) )
157cdf0e10cSrcweir TrackFormulas( rHint.GetId() );
158cdf0e10cSrcweir }
159cdf0e10cSrcweir
160cdf0e10cSrcweir // Repaint for conditional formats containing relative references.
161cdf0e10cSrcweir //! This is _THE_ bottle neck!
162cdf0e10cSrcweir if ( pCondFormList )
163cdf0e10cSrcweir {
164cdf0e10cSrcweir SCCOL nCol;
165cdf0e10cSrcweir SCROW nRow;
166cdf0e10cSrcweir SCTAB nTab;
167cdf0e10cSrcweir SCCOL nCol1;
168cdf0e10cSrcweir SCROW nRow1;
169cdf0e10cSrcweir SCTAB nTab1;
170cdf0e10cSrcweir SCCOL nCol2;
171cdf0e10cSrcweir SCROW nRow2;
172cdf0e10cSrcweir SCTAB nTab2;
173cdf0e10cSrcweir rRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
174cdf0e10cSrcweir ScAddress aAddress( rRange.aStart );
175cdf0e10cSrcweir for ( nTab = nTab1; nTab <= nTab2; ++nTab )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir aAddress.SetTab( nTab );
178cdf0e10cSrcweir for ( nCol = nCol1; nCol <= nCol2; ++nCol )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir aAddress.SetCol( nCol );
181cdf0e10cSrcweir for ( nRow = nRow1; nRow <= nRow2; ++nRow )
182cdf0e10cSrcweir {
183cdf0e10cSrcweir aAddress.SetRow( nRow );
184cdf0e10cSrcweir pCondFormList->SourceChanged( aAddress );
185cdf0e10cSrcweir }
186cdf0e10cSrcweir }
187cdf0e10cSrcweir }
188cdf0e10cSrcweir }
189cdf0e10cSrcweir }
190cdf0e10cSrcweir
191cdf0e10cSrcweir
DelBroadcastAreasInRange(const ScRange & rRange)192cdf0e10cSrcweir void ScDocument::DelBroadcastAreasInRange( const ScRange& rRange )
193cdf0e10cSrcweir {
194cdf0e10cSrcweir if ( pBASM )
195cdf0e10cSrcweir pBASM->DelBroadcastAreasInRange( rRange );
196cdf0e10cSrcweir }
197cdf0e10cSrcweir
StartListeningCell(const ScAddress & rAddress,SvtListener * pListener)198cdf0e10cSrcweir void ScDocument::StartListeningCell( const ScAddress& rAddress,
199cdf0e10cSrcweir SvtListener* pListener )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir DBG_ASSERT(pListener, "StartListeningCell: pListener Null");
202cdf0e10cSrcweir SCTAB nTab = rAddress.Tab();
203cdf0e10cSrcweir if (pTab[nTab])
204cdf0e10cSrcweir pTab[nTab]->StartListening( rAddress, pListener );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir
EndListeningCell(const ScAddress & rAddress,SvtListener * pListener)207cdf0e10cSrcweir void ScDocument::EndListeningCell( const ScAddress& rAddress,
208cdf0e10cSrcweir SvtListener* pListener )
209cdf0e10cSrcweir {
210cdf0e10cSrcweir DBG_ASSERT(pListener, "EndListeningCell: pListener Null");
211cdf0e10cSrcweir SCTAB nTab = rAddress.Tab();
212cdf0e10cSrcweir if (pTab[nTab])
213cdf0e10cSrcweir pTab[nTab]->EndListening( rAddress, pListener );
214cdf0e10cSrcweir }
215cdf0e10cSrcweir
216cdf0e10cSrcweir
PutInFormulaTree(ScFormulaCell * pCell)217cdf0e10cSrcweir void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
218cdf0e10cSrcweir {
219cdf0e10cSrcweir DBG_ASSERT( pCell, "PutInFormulaTree: pCell Null" );
220cdf0e10cSrcweir RemoveFromFormulaTree( pCell );
221cdf0e10cSrcweir // anhaengen
222cdf0e10cSrcweir if ( pEOFormulaTree )
223cdf0e10cSrcweir pEOFormulaTree->SetNext( pCell );
224cdf0e10cSrcweir else
225cdf0e10cSrcweir pFormulaTree = pCell; // kein Ende, kein Anfang..
226cdf0e10cSrcweir pCell->SetPrevious( pEOFormulaTree );
227cdf0e10cSrcweir pCell->SetNext( 0 );
228cdf0e10cSrcweir pEOFormulaTree = pCell;
229cdf0e10cSrcweir nFormulaCodeInTree += pCell->GetCode()->GetCodeLen();
230cdf0e10cSrcweir }
231cdf0e10cSrcweir
232cdf0e10cSrcweir
RemoveFromFormulaTree(ScFormulaCell * pCell)233cdf0e10cSrcweir void ScDocument::RemoveFromFormulaTree( ScFormulaCell* pCell )
234cdf0e10cSrcweir {
235cdf0e10cSrcweir DBG_ASSERT( pCell, "RemoveFromFormulaTree: pCell Null" );
236cdf0e10cSrcweir ScFormulaCell* pPrev = pCell->GetPrevious();
237cdf0e10cSrcweir // wenn die Zelle die erste oder sonstwo ist
238cdf0e10cSrcweir if ( pPrev || pFormulaTree == pCell )
239cdf0e10cSrcweir {
240cdf0e10cSrcweir ScFormulaCell* pNext = pCell->GetNext();
241cdf0e10cSrcweir if ( pPrev )
242cdf0e10cSrcweir pPrev->SetNext( pNext ); // gibt Vorlaeufer
243cdf0e10cSrcweir else
244cdf0e10cSrcweir pFormulaTree = pNext; // ist erste Zelle
245cdf0e10cSrcweir if ( pNext )
246cdf0e10cSrcweir pNext->SetPrevious( pPrev ); // gibt Nachfolger
247cdf0e10cSrcweir else
248cdf0e10cSrcweir pEOFormulaTree = pPrev; // ist letzte Zelle
249cdf0e10cSrcweir pCell->SetPrevious( 0 );
250cdf0e10cSrcweir pCell->SetNext( 0 );
251cdf0e10cSrcweir sal_uInt16 nRPN = pCell->GetCode()->GetCodeLen();
252cdf0e10cSrcweir if ( nFormulaCodeInTree >= nRPN )
253cdf0e10cSrcweir nFormulaCodeInTree -= nRPN;
254cdf0e10cSrcweir else
255cdf0e10cSrcweir {
256cdf0e10cSrcweir DBG_ERRORFILE( "RemoveFromFormulaTree: nFormulaCodeInTree < nRPN" );
257cdf0e10cSrcweir nFormulaCodeInTree = 0;
258cdf0e10cSrcweir }
259cdf0e10cSrcweir }
260cdf0e10cSrcweir else if ( !pFormulaTree && nFormulaCodeInTree )
261cdf0e10cSrcweir {
262cdf0e10cSrcweir DBG_ERRORFILE( "!pFormulaTree && nFormulaCodeInTree != 0" );
263cdf0e10cSrcweir nFormulaCodeInTree = 0;
264cdf0e10cSrcweir }
265cdf0e10cSrcweir }
266cdf0e10cSrcweir
267cdf0e10cSrcweir
IsInFormulaTree(ScFormulaCell * pCell) const268cdf0e10cSrcweir sal_Bool ScDocument::IsInFormulaTree( ScFormulaCell* pCell ) const
269cdf0e10cSrcweir {
270cdf0e10cSrcweir return pCell->GetPrevious() || pFormulaTree == pCell;
271cdf0e10cSrcweir }
272cdf0e10cSrcweir
273cdf0e10cSrcweir
CalcFormulaTree(sal_Bool bOnlyForced,sal_Bool bNoProgress)274cdf0e10cSrcweir void ScDocument::CalcFormulaTree( sal_Bool bOnlyForced, sal_Bool bNoProgress )
275cdf0e10cSrcweir {
276cdf0e10cSrcweir DBG_ASSERT( !IsCalculatingFormulaTree(), "CalcFormulaTree recursion" );
277cdf0e10cSrcweir // never ever recurse into this, might end up lost in infinity
278cdf0e10cSrcweir if ( IsCalculatingFormulaTree() )
279cdf0e10cSrcweir return ;
280cdf0e10cSrcweir bCalculatingFormulaTree = sal_True;
281cdf0e10cSrcweir
282cdf0e10cSrcweir SetForcedFormulaPending( sal_False );
283cdf0e10cSrcweir sal_Bool bOldIdleDisabled = IsIdleDisabled();
284cdf0e10cSrcweir DisableIdle( sal_True );
285cdf0e10cSrcweir sal_Bool bOldAutoCalc = GetAutoCalc();
286cdf0e10cSrcweir //! _nicht_ SetAutoCalc( sal_True ) weil das evtl. CalcFormulaTree( sal_True )
287cdf0e10cSrcweir //! aufruft, wenn vorher disabled war und bHasForcedFormulas gesetzt ist
288cdf0e10cSrcweir bAutoCalc = sal_True;
289cdf0e10cSrcweir if ( nHardRecalcState )
290cdf0e10cSrcweir CalcAll();
291cdf0e10cSrcweir else
292cdf0e10cSrcweir {
293cdf0e10cSrcweir ScFormulaCell* pCell = pFormulaTree;
294cdf0e10cSrcweir while ( pCell )
295cdf0e10cSrcweir {
296cdf0e10cSrcweir if ( pCell->GetDirty() )
297cdf0e10cSrcweir pCell = pCell->GetNext(); // alles klar
298cdf0e10cSrcweir else
299cdf0e10cSrcweir {
300cdf0e10cSrcweir if ( pCell->GetCode()->IsRecalcModeAlways() )
301cdf0e10cSrcweir {
302cdf0e10cSrcweir // pCell wird im SetDirty neu angehaengt!
303cdf0e10cSrcweir ScFormulaCell* pNext = pCell->GetNext();
304cdf0e10cSrcweir pCell->SetDirty();
305cdf0e10cSrcweir // falls pNext==0 und neue abhaengige hinten angehaengt
306cdf0e10cSrcweir // wurden, so macht das nichts, da die alle bDirty sind
307cdf0e10cSrcweir pCell = pNext;
308cdf0e10cSrcweir }
309cdf0e10cSrcweir else
310cdf0e10cSrcweir { // andere simpel berechnen
311cdf0e10cSrcweir pCell->SetDirtyVar();
312cdf0e10cSrcweir pCell = pCell->GetNext();
313cdf0e10cSrcweir }
314cdf0e10cSrcweir }
315cdf0e10cSrcweir }
316cdf0e10cSrcweir sal_Bool bProgress = !bOnlyForced && nFormulaCodeInTree && !bNoProgress;
317cdf0e10cSrcweir if ( bProgress )
318cdf0e10cSrcweir ScProgress::CreateInterpretProgress( this, sal_True );
319cdf0e10cSrcweir
320cdf0e10cSrcweir pCell = pFormulaTree;
321cdf0e10cSrcweir ScFormulaCell* pLastNoGood = 0;
322cdf0e10cSrcweir while ( pCell )
323cdf0e10cSrcweir {
324cdf0e10cSrcweir // Interpret setzt bDirty zurueck und callt Remove, auch der referierten!
325cdf0e10cSrcweir // bei RECALCMODE_ALWAYS bleibt die Zelle
326cdf0e10cSrcweir if ( bOnlyForced )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir if ( pCell->GetCode()->IsRecalcModeForced() )
329cdf0e10cSrcweir pCell->Interpret();
330cdf0e10cSrcweir }
331cdf0e10cSrcweir else
332cdf0e10cSrcweir {
333cdf0e10cSrcweir pCell->Interpret();
334cdf0e10cSrcweir }
335cdf0e10cSrcweir if ( pCell->GetPrevious() || pCell == pFormulaTree )
336cdf0e10cSrcweir { // (IsInFormulaTree(pCell)) kein Remove gewesen => next
337cdf0e10cSrcweir pLastNoGood = pCell;
338cdf0e10cSrcweir pCell = pCell->GetNext();
339cdf0e10cSrcweir }
340cdf0e10cSrcweir else
341cdf0e10cSrcweir {
342cdf0e10cSrcweir if ( pFormulaTree )
343cdf0e10cSrcweir {
344cdf0e10cSrcweir if ( pFormulaTree->GetDirty() && !bOnlyForced )
345cdf0e10cSrcweir {
346cdf0e10cSrcweir pCell = pFormulaTree;
347cdf0e10cSrcweir pLastNoGood = 0;
348cdf0e10cSrcweir }
349cdf0e10cSrcweir else
350cdf0e10cSrcweir {
351cdf0e10cSrcweir // IsInFormulaTree(pLastNoGood)
352cdf0e10cSrcweir if ( pLastNoGood && (pLastNoGood->GetPrevious() ||
353cdf0e10cSrcweir pLastNoGood == pFormulaTree) )
354cdf0e10cSrcweir pCell = pLastNoGood->GetNext();
355cdf0e10cSrcweir else
356cdf0e10cSrcweir {
357cdf0e10cSrcweir pCell = pFormulaTree;
358cdf0e10cSrcweir while ( pCell && !pCell->GetDirty() )
359cdf0e10cSrcweir pCell = pCell->GetNext();
360cdf0e10cSrcweir if ( pCell )
361cdf0e10cSrcweir pLastNoGood = pCell->GetPrevious();
362cdf0e10cSrcweir }
363cdf0e10cSrcweir }
364cdf0e10cSrcweir }
365cdf0e10cSrcweir else
366cdf0e10cSrcweir pCell = 0;
367cdf0e10cSrcweir }
368cdf0e10cSrcweir if ( ScProgress::IsUserBreak() )
369cdf0e10cSrcweir pCell = 0;
370cdf0e10cSrcweir }
371cdf0e10cSrcweir if ( bProgress )
372cdf0e10cSrcweir ScProgress::DeleteInterpretProgress();
373cdf0e10cSrcweir }
374cdf0e10cSrcweir bAutoCalc = bOldAutoCalc;
375cdf0e10cSrcweir DisableIdle( bOldIdleDisabled );
376cdf0e10cSrcweir bCalculatingFormulaTree = sal_False;
377cdf0e10cSrcweir }
378cdf0e10cSrcweir
379cdf0e10cSrcweir
ClearFormulaTree()380cdf0e10cSrcweir void ScDocument::ClearFormulaTree()
381cdf0e10cSrcweir {
382cdf0e10cSrcweir ScFormulaCell* pCell;
383cdf0e10cSrcweir ScFormulaCell* pTree = pFormulaTree;
384cdf0e10cSrcweir while ( pTree )
385cdf0e10cSrcweir {
386cdf0e10cSrcweir pCell = pTree;
387cdf0e10cSrcweir pTree = pCell->GetNext();
388cdf0e10cSrcweir if ( !pCell->GetCode()->IsRecalcModeAlways() )
389cdf0e10cSrcweir RemoveFromFormulaTree( pCell );
390cdf0e10cSrcweir }
391cdf0e10cSrcweir }
392cdf0e10cSrcweir
393cdf0e10cSrcweir
AppendToFormulaTrack(ScFormulaCell * pCell)394cdf0e10cSrcweir void ScDocument::AppendToFormulaTrack( ScFormulaCell* pCell )
395cdf0e10cSrcweir {
396cdf0e10cSrcweir DBG_ASSERT( pCell, "AppendToFormulaTrack: pCell Null" );
397cdf0e10cSrcweir // Zelle kann nicht in beiden Listen gleichzeitig sein
398cdf0e10cSrcweir RemoveFromFormulaTrack( pCell );
399cdf0e10cSrcweir RemoveFromFormulaTree( pCell );
400cdf0e10cSrcweir if ( pEOFormulaTrack )
401cdf0e10cSrcweir pEOFormulaTrack->SetNextTrack( pCell );
402cdf0e10cSrcweir else
403cdf0e10cSrcweir pFormulaTrack = pCell; // kein Ende, kein Anfang..
404cdf0e10cSrcweir pCell->SetPreviousTrack( pEOFormulaTrack );
405cdf0e10cSrcweir pCell->SetNextTrack( 0 );
406cdf0e10cSrcweir pEOFormulaTrack = pCell;
407cdf0e10cSrcweir ++nFormulaTrackCount;
408cdf0e10cSrcweir }
409cdf0e10cSrcweir
410cdf0e10cSrcweir
RemoveFromFormulaTrack(ScFormulaCell * pCell)411cdf0e10cSrcweir void ScDocument::RemoveFromFormulaTrack( ScFormulaCell* pCell )
412cdf0e10cSrcweir {
413cdf0e10cSrcweir DBG_ASSERT( pCell, "RemoveFromFormulaTrack: pCell Null" );
414cdf0e10cSrcweir ScFormulaCell* pPrev = pCell->GetPreviousTrack();
415cdf0e10cSrcweir // wenn die Zelle die erste oder sonstwo ist
416cdf0e10cSrcweir if ( pPrev || pFormulaTrack == pCell )
417cdf0e10cSrcweir {
418cdf0e10cSrcweir ScFormulaCell* pNext = pCell->GetNextTrack();
419cdf0e10cSrcweir if ( pPrev )
420cdf0e10cSrcweir pPrev->SetNextTrack( pNext ); // gibt Vorlaeufer
421cdf0e10cSrcweir else
422cdf0e10cSrcweir pFormulaTrack = pNext; // ist erste Zelle
423cdf0e10cSrcweir if ( pNext )
424cdf0e10cSrcweir pNext->SetPreviousTrack( pPrev ); // gibt Nachfolger
425cdf0e10cSrcweir else
426cdf0e10cSrcweir pEOFormulaTrack = pPrev; // ist letzte Zelle
427cdf0e10cSrcweir pCell->SetPreviousTrack( 0 );
428cdf0e10cSrcweir pCell->SetNextTrack( 0 );
429cdf0e10cSrcweir --nFormulaTrackCount;
430cdf0e10cSrcweir }
431cdf0e10cSrcweir }
432cdf0e10cSrcweir
433cdf0e10cSrcweir
IsInFormulaTrack(ScFormulaCell * pCell) const434cdf0e10cSrcweir sal_Bool ScDocument::IsInFormulaTrack( ScFormulaCell* pCell ) const
435cdf0e10cSrcweir {
436cdf0e10cSrcweir return pCell->GetPreviousTrack() || pFormulaTrack == pCell;
437cdf0e10cSrcweir }
438cdf0e10cSrcweir
439cdf0e10cSrcweir
440cdf0e10cSrcweir /*
441cdf0e10cSrcweir Der erste wird gebroadcastet,
442cdf0e10cSrcweir die dadurch entstehenden werden durch das Notify an den Track gehaengt.
443cdf0e10cSrcweir Der nachfolgende broadcastet wieder usw.
444cdf0e10cSrcweir View stoesst Interpret an.
445cdf0e10cSrcweir */
TrackFormulas(sal_uLong nHintId)446cdf0e10cSrcweir void ScDocument::TrackFormulas( sal_uLong nHintId )
447cdf0e10cSrcweir {
448cdf0e10cSrcweir
449cdf0e10cSrcweir if ( pFormulaTrack )
450cdf0e10cSrcweir {
451cdf0e10cSrcweir erBEEPER();
452cdf0e10cSrcweir // outside the loop, check if any sheet has a "calculate" event script
453cdf0e10cSrcweir bool bCalcEvent = HasAnySheetEventScript( SC_SHEETEVENT_CALCULATE, true );
454cdf0e10cSrcweir SvtBroadcaster* pBC;
455cdf0e10cSrcweir ScFormulaCell* pTrack;
456cdf0e10cSrcweir ScFormulaCell* pNext;
457cdf0e10cSrcweir pTrack = pFormulaTrack;
458cdf0e10cSrcweir do
459cdf0e10cSrcweir {
460cdf0e10cSrcweir ScHint aHint( nHintId, pTrack->aPos, pTrack );
461cdf0e10cSrcweir if ( ( pBC = pTrack->GetBroadcaster() ) != NULL )
462cdf0e10cSrcweir pBC->Broadcast( aHint );
463cdf0e10cSrcweir pBASM->AreaBroadcast( aHint );
464cdf0e10cSrcweir // Repaint fuer bedingte Formate mit relativen Referenzen:
465cdf0e10cSrcweir if ( pCondFormList )
466cdf0e10cSrcweir pCondFormList->SourceChanged( pTrack->aPos );
467cdf0e10cSrcweir // for "calculate" event, keep track of which sheets are affected by tracked formulas
468cdf0e10cSrcweir if ( bCalcEvent )
469cdf0e10cSrcweir SetCalcNotification( pTrack->aPos.Tab() );
470cdf0e10cSrcweir pTrack = pTrack->GetNextTrack();
471cdf0e10cSrcweir } while ( pTrack );
472cdf0e10cSrcweir pTrack = pFormulaTrack;
473cdf0e10cSrcweir sal_Bool bHaveForced = sal_False;
474cdf0e10cSrcweir do
475cdf0e10cSrcweir {
476cdf0e10cSrcweir pNext = pTrack->GetNextTrack();
477cdf0e10cSrcweir RemoveFromFormulaTrack( pTrack );
478cdf0e10cSrcweir PutInFormulaTree( pTrack );
479cdf0e10cSrcweir if ( pTrack->GetCode()->IsRecalcModeForced() )
480cdf0e10cSrcweir bHaveForced = sal_True;
481cdf0e10cSrcweir pTrack = pNext;
482cdf0e10cSrcweir } while ( pTrack );
483cdf0e10cSrcweir if ( bHaveForced )
484cdf0e10cSrcweir {
485cdf0e10cSrcweir SetForcedFormulas( sal_True );
486cdf0e10cSrcweir if ( bAutoCalc && !IsAutoCalcShellDisabled() && !IsInInterpreter()
487cdf0e10cSrcweir && !IsCalculatingFormulaTree() )
488cdf0e10cSrcweir CalcFormulaTree( sal_True );
489cdf0e10cSrcweir else
490cdf0e10cSrcweir SetForcedFormulaPending( sal_True );
491cdf0e10cSrcweir }
492cdf0e10cSrcweir }
493cdf0e10cSrcweir DBG_ASSERT( nFormulaTrackCount==0, "TrackFormulas: nFormulaTrackCount!=0" );
494cdf0e10cSrcweir }
495cdf0e10cSrcweir
496cdf0e10cSrcweir
StartAllListeners()497cdf0e10cSrcweir void ScDocument::StartAllListeners()
498cdf0e10cSrcweir {
499cdf0e10cSrcweir for ( SCTAB i = 0; i <= MAXTAB; ++i )
500cdf0e10cSrcweir if ( pTab[i] )
501cdf0e10cSrcweir pTab[i]->StartAllListeners();
502cdf0e10cSrcweir }
503cdf0e10cSrcweir
UpdateBroadcastAreas(UpdateRefMode eUpdateRefMode,const ScRange & rRange,SCsCOL nDx,SCsROW nDy,SCsTAB nDz)504cdf0e10cSrcweir void ScDocument::UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
505cdf0e10cSrcweir const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz
506cdf0e10cSrcweir )
507cdf0e10cSrcweir {
508cdf0e10cSrcweir sal_Bool bExpandRefsOld = IsExpandRefs();
509cdf0e10cSrcweir if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
510cdf0e10cSrcweir SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
511cdf0e10cSrcweir if ( pBASM )
512cdf0e10cSrcweir pBASM->UpdateBroadcastAreas( eUpdateRefMode, rRange, nDx, nDy, nDz );
513cdf0e10cSrcweir SetExpandRefs( bExpandRefsOld );
514cdf0e10cSrcweir }
515cdf0e10cSrcweir
SetAutoCalc(sal_Bool bNewAutoCalc)516cdf0e10cSrcweir void ScDocument::SetAutoCalc( sal_Bool bNewAutoCalc )
517cdf0e10cSrcweir {
518cdf0e10cSrcweir sal_Bool bOld = bAutoCalc;
519cdf0e10cSrcweir bAutoCalc = bNewAutoCalc;
520cdf0e10cSrcweir if ( !bOld && bNewAutoCalc && bHasForcedFormulas )
521cdf0e10cSrcweir {
522cdf0e10cSrcweir if ( IsAutoCalcShellDisabled() )
523cdf0e10cSrcweir SetForcedFormulaPending( sal_True );
524cdf0e10cSrcweir else if ( !IsInInterpreter() )
525cdf0e10cSrcweir CalcFormulaTree( sal_True );
526cdf0e10cSrcweir }
527cdf0e10cSrcweir }
528cdf0e10cSrcweir
529cdf0e10cSrcweir
530cdf0e10cSrcweir
531