1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5b3f79822SAndrew Rist * distributed with this work for additional information
6b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10b3f79822SAndrew Rist *
11b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12b3f79822SAndrew Rist *
13b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist * software distributed under the License is distributed on an
15b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17b3f79822SAndrew Rist * specific language governing permissions and limitations
18b3f79822SAndrew Rist * under the License.
19b3f79822SAndrew Rist *
20b3f79822SAndrew Rist *************************************************************/
21b3f79822SAndrew Rist
22b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir
28cdf0e10cSrcweir
29cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
30cdf0e10cSrcweir #include <algorithm>
31cdf0e10cSrcweir #include <deque>
32cdf0e10cSrcweir
33cdf0e10cSrcweir #include <boost/bind.hpp>
34cdf0e10cSrcweir
35cdf0e10cSrcweir #include <vcl/mapmod.hxx>
36cdf0e10cSrcweir #include <editeng/editobj.hxx>
37cdf0e10cSrcweir #include <editeng/editstat.hxx>
38cdf0e10cSrcweir
39cdf0e10cSrcweir #include "cell.hxx"
40cdf0e10cSrcweir #include "compiler.hxx"
41cdf0e10cSrcweir #include "formula/errorcodes.hxx"
42cdf0e10cSrcweir #include "document.hxx"
43cdf0e10cSrcweir #include "rangenam.hxx"
44cdf0e10cSrcweir #include "rechead.hxx"
45cdf0e10cSrcweir #include "refupdat.hxx"
46cdf0e10cSrcweir #include "scmatrix.hxx"
47cdf0e10cSrcweir #include "editutil.hxx"
48cdf0e10cSrcweir #include "chgtrack.hxx"
49cdf0e10cSrcweir #include "externalrefmgr.hxx"
50cdf0e10cSrcweir
51cdf0e10cSrcweir using namespace formula;
52cdf0e10cSrcweir
53cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
54cdf0e10cSrcweir
55cdf0e10cSrcweir #ifdef USE_MEMPOOL
56cdf0e10cSrcweir const sal_uInt16 nMemPoolEditCell = (0x1000 - 64) / sizeof(ScNoteCell);
IMPL_FIXEDMEMPOOL_NEWDEL(ScEditCell,nMemPoolEditCell,nMemPoolEditCell)57cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScEditCell, nMemPoolEditCell, nMemPoolEditCell )
58cdf0e10cSrcweir #endif
59cdf0e10cSrcweir
60cdf0e10cSrcweir // ============================================================================
61cdf0e10cSrcweir
62cdf0e10cSrcweir ScEditCell::ScEditCell( const EditTextObject* pObject, ScDocument* pDocP,
63cdf0e10cSrcweir const SfxItemPool* pFromPool ) :
64cdf0e10cSrcweir ScBaseCell( CELLTYPE_EDIT ),
65cdf0e10cSrcweir pString( NULL ),
66cdf0e10cSrcweir pDoc( pDocP )
67cdf0e10cSrcweir {
68cdf0e10cSrcweir SetTextObject( pObject, pFromPool );
69cdf0e10cSrcweir }
70cdf0e10cSrcweir
ScEditCell(const ScEditCell & rCell,ScDocument & rDoc)71cdf0e10cSrcweir ScEditCell::ScEditCell( const ScEditCell& rCell, ScDocument& rDoc ) :
72cdf0e10cSrcweir ScBaseCell( rCell ),
73cdf0e10cSrcweir pString( NULL ),
74cdf0e10cSrcweir pDoc( &rDoc )
75cdf0e10cSrcweir {
76cdf0e10cSrcweir SetTextObject( rCell.pData, rCell.pDoc->GetEditPool() );
77cdf0e10cSrcweir }
78cdf0e10cSrcweir
ScEditCell(const String & rString,ScDocument * pDocP)79cdf0e10cSrcweir ScEditCell::ScEditCell( const String& rString, ScDocument* pDocP ) :
80cdf0e10cSrcweir ScBaseCell( CELLTYPE_EDIT ),
81cdf0e10cSrcweir pString( NULL ),
82cdf0e10cSrcweir pDoc( pDocP )
83cdf0e10cSrcweir {
84cdf0e10cSrcweir DBG_ASSERT( rString.Search('\n') != STRING_NOTFOUND ||
85cdf0e10cSrcweir rString.Search(CHAR_CR) != STRING_NOTFOUND,
86cdf0e10cSrcweir "EditCell mit einfachem Text !?!?" );
87cdf0e10cSrcweir
88cdf0e10cSrcweir EditEngine& rEngine = pDoc->GetEditEngine();
89cdf0e10cSrcweir rEngine.SetText( rString );
90cdf0e10cSrcweir pData = rEngine.CreateTextObject();
91cdf0e10cSrcweir }
92cdf0e10cSrcweir
~ScEditCell()93cdf0e10cSrcweir ScEditCell::~ScEditCell()
94cdf0e10cSrcweir {
95cdf0e10cSrcweir delete pData;
96cdf0e10cSrcweir delete pString;
97cdf0e10cSrcweir
98cdf0e10cSrcweir #ifdef DBG_UTIL
99cdf0e10cSrcweir eCellType = CELLTYPE_DESTROYED;
100cdf0e10cSrcweir #endif
101cdf0e10cSrcweir }
102cdf0e10cSrcweir
SetData(const EditTextObject * pObject,const SfxItemPool * pFromPool)103cdf0e10cSrcweir void ScEditCell::SetData( const EditTextObject* pObject,
104cdf0e10cSrcweir const SfxItemPool* pFromPool )
105cdf0e10cSrcweir {
106cdf0e10cSrcweir if ( pString )
107cdf0e10cSrcweir {
108cdf0e10cSrcweir delete pString;
109cdf0e10cSrcweir pString = NULL;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir delete pData;
112cdf0e10cSrcweir SetTextObject( pObject, pFromPool );
113cdf0e10cSrcweir }
114cdf0e10cSrcweir
GetData(const EditTextObject * & rpObject) const115cdf0e10cSrcweir void ScEditCell::GetData( const EditTextObject*& rpObject ) const
116cdf0e10cSrcweir {
117cdf0e10cSrcweir rpObject = pData;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir
GetString(String & rString) const120cdf0e10cSrcweir void ScEditCell::GetString( String& rString ) const
121cdf0e10cSrcweir {
122cdf0e10cSrcweir if ( pString )
123cdf0e10cSrcweir rString = *pString;
124cdf0e10cSrcweir else if ( pData )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir // auch Text von URL-Feldern, Doc-Engine ist eine ScFieldEditEngine
127cdf0e10cSrcweir EditEngine& rEngine = pDoc->GetEditEngine();
128cdf0e10cSrcweir rEngine.SetText( *pData );
129cdf0e10cSrcweir rString = ScEditUtil::GetMultilineString(rEngine); // string with line separators between paragraphs
130cdf0e10cSrcweir // cache short strings for formulas
131cdf0e10cSrcweir if ( rString.Len() < 256 )
132cdf0e10cSrcweir ((ScEditCell*)this)->pString = new String( rString ); //! non-const
133cdf0e10cSrcweir }
134cdf0e10cSrcweir else
135cdf0e10cSrcweir rString.Erase();
136cdf0e10cSrcweir }
137cdf0e10cSrcweir
SetTextObject(const EditTextObject * pObject,const SfxItemPool * pFromPool)138cdf0e10cSrcweir void ScEditCell::SetTextObject( const EditTextObject* pObject,
139cdf0e10cSrcweir const SfxItemPool* pFromPool )
140cdf0e10cSrcweir {
141cdf0e10cSrcweir if ( pObject )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir if ( pFromPool && pDoc->GetEditPool() == pFromPool )
144cdf0e10cSrcweir pData = pObject->Clone();
145cdf0e10cSrcweir else
146cdf0e10cSrcweir { //! anderer Pool
147cdf0e10cSrcweir // Leider gibt es keinen anderen Weg, um den Pool umzuhaengen,
148cdf0e10cSrcweir // als das Object durch eine entsprechende Engine zu schleusen..
149cdf0e10cSrcweir EditEngine& rEngine = pDoc->GetEditEngine();
150cdf0e10cSrcweir if ( pObject->HasOnlineSpellErrors() )
151cdf0e10cSrcweir {
152cdf0e10cSrcweir sal_uLong nControl = rEngine.GetControlWord();
153cdf0e10cSrcweir const sal_uLong nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
154cdf0e10cSrcweir sal_Bool bNewControl = ( (nControl & nSpellControl) != nSpellControl );
155cdf0e10cSrcweir if ( bNewControl )
156cdf0e10cSrcweir rEngine.SetControlWord( nControl | nSpellControl );
157cdf0e10cSrcweir rEngine.SetText( *pObject );
158cdf0e10cSrcweir pData = rEngine.CreateTextObject();
159cdf0e10cSrcweir if ( bNewControl )
160cdf0e10cSrcweir rEngine.SetControlWord( nControl );
161cdf0e10cSrcweir }
162cdf0e10cSrcweir else
163cdf0e10cSrcweir {
164cdf0e10cSrcweir rEngine.SetText( *pObject );
165cdf0e10cSrcweir pData = rEngine.CreateTextObject();
166cdf0e10cSrcweir }
167cdf0e10cSrcweir }
168cdf0e10cSrcweir }
169cdf0e10cSrcweir else
170cdf0e10cSrcweir pData = NULL;
171cdf0e10cSrcweir }
172cdf0e10cSrcweir
173cdf0e10cSrcweir // ============================================================================
174cdf0e10cSrcweir
175cdf0e10cSrcweir namespace
176cdf0e10cSrcweir {
177cdf0e10cSrcweir
178cdf0e10cSrcweir using std::deque;
179cdf0e10cSrcweir
180cdf0e10cSrcweir typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&);
181cdf0e10cSrcweir
182cdf0e10cSrcweir
lcl_GetCol(const ScSingleRefData & rData)183cdf0e10cSrcweir static SCCOLROW lcl_GetCol(const ScSingleRefData& rData)
184cdf0e10cSrcweir {
185cdf0e10cSrcweir return rData.nCol;
186cdf0e10cSrcweir }
187cdf0e10cSrcweir
188cdf0e10cSrcweir
lcl_GetRow(const ScSingleRefData & rData)189cdf0e10cSrcweir static SCCOLROW lcl_GetRow(const ScSingleRefData& rData)
190cdf0e10cSrcweir {
191cdf0e10cSrcweir return rData.nRow;
192cdf0e10cSrcweir }
193cdf0e10cSrcweir
194cdf0e10cSrcweir
lcl_GetTab(const ScSingleRefData & rData)195cdf0e10cSrcweir static SCCOLROW lcl_GetTab(const ScSingleRefData& rData)
196cdf0e10cSrcweir {
197cdf0e10cSrcweir return rData.nTab;
198cdf0e10cSrcweir }
199cdf0e10cSrcweir
200cdf0e10cSrcweir
201cdf0e10cSrcweir /** Check if both references span the same range in selected dimension.
202cdf0e10cSrcweir */
203cdf0e10cSrcweir static bool
lcl_checkRangeDimension(const SingleDoubleRefProvider & rRef1,const SingleDoubleRefProvider & rRef2,const DimensionSelector aWhich)204cdf0e10cSrcweir lcl_checkRangeDimension(
205cdf0e10cSrcweir const SingleDoubleRefProvider& rRef1,
206cdf0e10cSrcweir const SingleDoubleRefProvider& rRef2,
207cdf0e10cSrcweir const DimensionSelector aWhich)
208cdf0e10cSrcweir {
209cdf0e10cSrcweir return
210cdf0e10cSrcweir aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1)
211cdf0e10cSrcweir && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2);
212cdf0e10cSrcweir }
213cdf0e10cSrcweir
214cdf0e10cSrcweir
215cdf0e10cSrcweir static bool
lcl_checkRangeDimensions(const SingleDoubleRefProvider & rRef1,const SingleDoubleRefProvider & rRef2,bool & bCol,bool & bRow,bool & bTab)216cdf0e10cSrcweir lcl_checkRangeDimensions(
217cdf0e10cSrcweir const SingleDoubleRefProvider& rRef1,
218cdf0e10cSrcweir const SingleDoubleRefProvider& rRef2,
219cdf0e10cSrcweir bool& bCol, bool& bRow, bool& bTab)
220cdf0e10cSrcweir {
221cdf0e10cSrcweir const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol));
222cdf0e10cSrcweir const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow));
223cdf0e10cSrcweir const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab));
224cdf0e10cSrcweir
225cdf0e10cSrcweir // Test if exactly two dimensions are equal
226cdf0e10cSrcweir if (!(bSameCols ^ bSameRows ^ bSameTabs)
227cdf0e10cSrcweir && (bSameCols || bSameRows || bSameTabs))
228cdf0e10cSrcweir {
229cdf0e10cSrcweir bCol = !bSameCols;
230cdf0e10cSrcweir bRow = !bSameRows;
231cdf0e10cSrcweir bTab = !bSameTabs;
232cdf0e10cSrcweir return true;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir return false;
235cdf0e10cSrcweir }
236cdf0e10cSrcweir
237cdf0e10cSrcweir
238cdf0e10cSrcweir /** Check if references in given reference list can possibly
239cdf0e10cSrcweir form a range. To do that, two of their dimensions must be the same.
240cdf0e10cSrcweir */
241cdf0e10cSrcweir static bool
lcl_checkRangeDimensions(const deque<ScToken * >::const_iterator aBegin,const deque<ScToken * >::const_iterator aEnd,bool & bCol,bool & bRow,bool & bTab)242cdf0e10cSrcweir lcl_checkRangeDimensions(
243cdf0e10cSrcweir const deque<ScToken*>::const_iterator aBegin,
244cdf0e10cSrcweir const deque<ScToken*>::const_iterator aEnd,
245cdf0e10cSrcweir bool& bCol, bool& bRow, bool& bTab)
246cdf0e10cSrcweir {
247cdf0e10cSrcweir deque<ScToken*>::const_iterator aCur(aBegin);
248cdf0e10cSrcweir ++aCur;
249cdf0e10cSrcweir const SingleDoubleRefProvider aRef(**aBegin);
250cdf0e10cSrcweir bool bOk(false);
251cdf0e10cSrcweir {
252cdf0e10cSrcweir const SingleDoubleRefProvider aRefCur(**aCur);
253cdf0e10cSrcweir bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab);
254cdf0e10cSrcweir }
255cdf0e10cSrcweir while (bOk && aCur != aEnd)
256cdf0e10cSrcweir {
257cdf0e10cSrcweir const SingleDoubleRefProvider aRefCur(**aCur);
258cdf0e10cSrcweir bool bColTmp(false);
259cdf0e10cSrcweir bool bRowTmp(false);
260cdf0e10cSrcweir bool bTabTmp(false);
261cdf0e10cSrcweir bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
262cdf0e10cSrcweir bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
263cdf0e10cSrcweir ++aCur;
264cdf0e10cSrcweir }
265cdf0e10cSrcweir
266cdf0e10cSrcweir if (bOk && aCur == aEnd)
267cdf0e10cSrcweir {
268cdf0e10cSrcweir bCol = bCol;
269cdf0e10cSrcweir bRow = bRow;
270cdf0e10cSrcweir bTab = bTab;
271cdf0e10cSrcweir return true;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir return false;
274cdf0e10cSrcweir }
275cdf0e10cSrcweir
276cdf0e10cSrcweir
277cdf0e10cSrcweir bool
lcl_lessReferenceBy(const ScToken * const pRef1,const ScToken * const pRef2,const DimensionSelector aWhich)278cdf0e10cSrcweir lcl_lessReferenceBy(
279cdf0e10cSrcweir const ScToken* const pRef1, const ScToken* const pRef2,
280cdf0e10cSrcweir const DimensionSelector aWhich)
281cdf0e10cSrcweir {
282cdf0e10cSrcweir const SingleDoubleRefProvider rRef1(*pRef1);
283cdf0e10cSrcweir const SingleDoubleRefProvider rRef2(*pRef2);
284cdf0e10cSrcweir return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1);
285cdf0e10cSrcweir }
286cdf0e10cSrcweir
287cdf0e10cSrcweir
288cdf0e10cSrcweir /** Returns true if range denoted by token pRef2 starts immediately after
289cdf0e10cSrcweir range denoted by token pRef1. Dimension, in which the comparison takes
290cdf0e10cSrcweir place, is given by aWhich.
291cdf0e10cSrcweir */
292cdf0e10cSrcweir bool
lcl_isImmediatelyFollowing(const ScToken * const pRef1,const ScToken * const pRef2,const DimensionSelector aWhich)293cdf0e10cSrcweir lcl_isImmediatelyFollowing(
294cdf0e10cSrcweir const ScToken* const pRef1, const ScToken* const pRef2,
295cdf0e10cSrcweir const DimensionSelector aWhich)
296cdf0e10cSrcweir {
297cdf0e10cSrcweir const SingleDoubleRefProvider rRef1(*pRef1);
298cdf0e10cSrcweir const SingleDoubleRefProvider rRef2(*pRef2);
299cdf0e10cSrcweir return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1;
300cdf0e10cSrcweir }
301cdf0e10cSrcweir
302cdf0e10cSrcweir
303cdf0e10cSrcweir static bool
lcl_checkIfAdjacent(const deque<ScToken * > & rReferences,const DimensionSelector aWhich)304cdf0e10cSrcweir lcl_checkIfAdjacent(
305cdf0e10cSrcweir const deque<ScToken*>& rReferences,
306cdf0e10cSrcweir const DimensionSelector aWhich)
307cdf0e10cSrcweir {
308cdf0e10cSrcweir typedef deque<ScToken*>::const_iterator Iter;
309cdf0e10cSrcweir Iter aBegin(rReferences.begin());
310cdf0e10cSrcweir Iter aEnd(rReferences.end());
311cdf0e10cSrcweir Iter aBegin1(aBegin);
312cdf0e10cSrcweir ++aBegin1, --aEnd;
313cdf0e10cSrcweir return std::equal(
314cdf0e10cSrcweir aBegin, aEnd, aBegin1,
315cdf0e10cSrcweir boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich));
316cdf0e10cSrcweir }
317cdf0e10cSrcweir
318cdf0e10cSrcweir
319cdf0e10cSrcweir static void
lcl_fillRangeFromRefList(const deque<ScToken * > & rReferences,ScRange & rRange)320cdf0e10cSrcweir lcl_fillRangeFromRefList(
321cdf0e10cSrcweir const deque<ScToken*>& rReferences, ScRange& rRange)
322cdf0e10cSrcweir {
323cdf0e10cSrcweir const ScSingleRefData aStart(
324cdf0e10cSrcweir SingleDoubleRefProvider(*rReferences.front()).Ref1);
325cdf0e10cSrcweir rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab);
326cdf0e10cSrcweir const ScSingleRefData aEnd(
327cdf0e10cSrcweir SingleDoubleRefProvider(*rReferences.back()).Ref2);
328cdf0e10cSrcweir rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab);
329cdf0e10cSrcweir }
330cdf0e10cSrcweir
331cdf0e10cSrcweir
332cdf0e10cSrcweir static bool
lcl_refListFormsOneRange(const ScAddress & aPos,deque<ScToken * > & rReferences,ScRange & rRange)333cdf0e10cSrcweir lcl_refListFormsOneRange(
334cdf0e10cSrcweir const ScAddress& aPos, deque<ScToken*>& rReferences,
335cdf0e10cSrcweir ScRange& rRange)
336cdf0e10cSrcweir {
337cdf0e10cSrcweir std::for_each(
338cdf0e10cSrcweir rReferences.begin(), rReferences.end(),
339cdf0e10cSrcweir bind(&ScToken::CalcAbsIfRel, _1, aPos))
340cdf0e10cSrcweir ;
341cdf0e10cSrcweir if (rReferences.size() == 1) {
342cdf0e10cSrcweir lcl_fillRangeFromRefList(rReferences, rRange);
343cdf0e10cSrcweir return true;
344cdf0e10cSrcweir }
345cdf0e10cSrcweir
346cdf0e10cSrcweir bool bCell(false);
347cdf0e10cSrcweir bool bRow(false);
348cdf0e10cSrcweir bool bTab(false);
349cdf0e10cSrcweir if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(),
350cdf0e10cSrcweir bCell, bRow, bTab))
351cdf0e10cSrcweir {
352cdf0e10cSrcweir DimensionSelector aWhich;
353cdf0e10cSrcweir if (bCell)
354cdf0e10cSrcweir {
355cdf0e10cSrcweir aWhich = lcl_GetCol;
356cdf0e10cSrcweir }
357cdf0e10cSrcweir else if (bRow)
358cdf0e10cSrcweir {
359cdf0e10cSrcweir aWhich = lcl_GetRow;
360cdf0e10cSrcweir }
361cdf0e10cSrcweir else if (bTab)
362cdf0e10cSrcweir {
363cdf0e10cSrcweir aWhich = lcl_GetTab;
364cdf0e10cSrcweir }
365cdf0e10cSrcweir else
366cdf0e10cSrcweir {
367cdf0e10cSrcweir OSL_ENSURE(false, "lcl_checkRangeDimensions shouldn't allow that!");
368cdf0e10cSrcweir aWhich = lcl_GetRow; // initialize to avoid warning
369cdf0e10cSrcweir }
370cdf0e10cSrcweir // Sort the references by start of range
371cdf0e10cSrcweir std::sort(rReferences.begin(), rReferences.end(),
372cdf0e10cSrcweir boost::bind(lcl_lessReferenceBy, _1, _2, aWhich));
373cdf0e10cSrcweir if (lcl_checkIfAdjacent(rReferences, aWhich))
374cdf0e10cSrcweir {
375cdf0e10cSrcweir lcl_fillRangeFromRefList(rReferences, rRange);
376cdf0e10cSrcweir return true;
377cdf0e10cSrcweir }
378cdf0e10cSrcweir }
379cdf0e10cSrcweir return false;
380cdf0e10cSrcweir }
381cdf0e10cSrcweir
382cdf0e10cSrcweir
lcl_isReference(const FormulaToken & rToken)383cdf0e10cSrcweir bool lcl_isReference(const FormulaToken& rToken)
384cdf0e10cSrcweir {
385cdf0e10cSrcweir return
386cdf0e10cSrcweir rToken.GetType() == svSingleRef ||
387cdf0e10cSrcweir rToken.GetType() == svDoubleRef;
388cdf0e10cSrcweir }
389cdf0e10cSrcweir
390cdf0e10cSrcweir }
391cdf0e10cSrcweir
IsEmpty()392cdf0e10cSrcweir sal_Bool ScFormulaCell::IsEmpty()
393cdf0e10cSrcweir {
394cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
395cdf0e10cSrcweir Interpret();
396cdf0e10cSrcweir return aResult.GetCellResultType() == formula::svEmptyCell;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir
IsEmptyDisplayedAsString()399cdf0e10cSrcweir sal_Bool ScFormulaCell::IsEmptyDisplayedAsString()
400cdf0e10cSrcweir {
401cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
402cdf0e10cSrcweir Interpret();
403cdf0e10cSrcweir return aResult.IsEmptyDisplayedAsString();
404cdf0e10cSrcweir }
405cdf0e10cSrcweir
IsValue()406cdf0e10cSrcweir sal_Bool ScFormulaCell::IsValue()
407cdf0e10cSrcweir {
408cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
409cdf0e10cSrcweir Interpret();
410cdf0e10cSrcweir return aResult.IsValue();
411cdf0e10cSrcweir }
412cdf0e10cSrcweir
GetValue()413cdf0e10cSrcweir double ScFormulaCell::GetValue()
414cdf0e10cSrcweir {
415cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
416cdf0e10cSrcweir Interpret();
417cdf0e10cSrcweir if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
418cdf0e10cSrcweir !aResult.GetResultError())
419cdf0e10cSrcweir return aResult.GetDouble();
420cdf0e10cSrcweir return 0.0;
421cdf0e10cSrcweir }
422cdf0e10cSrcweir
GetValueAlways()423cdf0e10cSrcweir double ScFormulaCell::GetValueAlways()
424cdf0e10cSrcweir {
425cdf0e10cSrcweir // for goal seek: return result value even if error code is set
426cdf0e10cSrcweir
427cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
428cdf0e10cSrcweir Interpret();
429cdf0e10cSrcweir return aResult.GetDouble();
430cdf0e10cSrcweir }
431cdf0e10cSrcweir
GetString(String & rString)432cdf0e10cSrcweir void ScFormulaCell::GetString( String& rString )
433cdf0e10cSrcweir {
434cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
435cdf0e10cSrcweir Interpret();
436cdf0e10cSrcweir if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
437cdf0e10cSrcweir !aResult.GetResultError())
438cdf0e10cSrcweir rString = aResult.GetString();
439cdf0e10cSrcweir else
440cdf0e10cSrcweir rString.Erase();
441cdf0e10cSrcweir }
442cdf0e10cSrcweir
GetMatrix()443cdf0e10cSrcweir const ScMatrix* ScFormulaCell::GetMatrix()
444cdf0e10cSrcweir {
445cdf0e10cSrcweir if ( pDocument->GetAutoCalc() )
446cdf0e10cSrcweir {
447*03eb9a00SHerbert Dürr if( IsDirtyOrInTableOpDirty()
448cdf0e10cSrcweir // Was stored !bDirty but an accompanying matrix cell was bDirty?
449*03eb9a00SHerbert Dürr || (!bDirty && cMatrixFlag == MM_FORMULA && !aResult.GetMatrix().Is()))
450cdf0e10cSrcweir Interpret();
451cdf0e10cSrcweir }
452cdf0e10cSrcweir return aResult.GetMatrix();
453cdf0e10cSrcweir }
454cdf0e10cSrcweir
GetMatrixOrigin(ScAddress & rPos) const455cdf0e10cSrcweir sal_Bool ScFormulaCell::GetMatrixOrigin( ScAddress& rPos ) const
456cdf0e10cSrcweir {
457cdf0e10cSrcweir switch ( cMatrixFlag )
458cdf0e10cSrcweir {
459cdf0e10cSrcweir case MM_FORMULA :
460cdf0e10cSrcweir rPos = aPos;
461cdf0e10cSrcweir return sal_True;
462cdf0e10cSrcweir // break;
463cdf0e10cSrcweir case MM_REFERENCE :
464cdf0e10cSrcweir {
465cdf0e10cSrcweir pCode->Reset();
466cdf0e10cSrcweir ScToken* t = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
467cdf0e10cSrcweir if( t )
468cdf0e10cSrcweir {
469cdf0e10cSrcweir ScSingleRefData& rRef = t->GetSingleRef();
470cdf0e10cSrcweir rRef.CalcAbsIfRel( aPos );
471cdf0e10cSrcweir if ( rRef.Valid() )
472cdf0e10cSrcweir {
473cdf0e10cSrcweir rPos.Set( rRef.nCol, rRef.nRow, rRef.nTab );
474cdf0e10cSrcweir return sal_True;
475cdf0e10cSrcweir }
476cdf0e10cSrcweir }
477cdf0e10cSrcweir }
478cdf0e10cSrcweir break;
479cdf0e10cSrcweir }
480cdf0e10cSrcweir return sal_False;
481cdf0e10cSrcweir }
482cdf0e10cSrcweir
483cdf0e10cSrcweir
484cdf0e10cSrcweir /*
485cdf0e10cSrcweir Edge-Values:
486cdf0e10cSrcweir
487cdf0e10cSrcweir 8
488cdf0e10cSrcweir 4 16
489cdf0e10cSrcweir 2
490cdf0e10cSrcweir
491cdf0e10cSrcweir innerhalb: 1
492cdf0e10cSrcweir ausserhalb: 0
493cdf0e10cSrcweir (reserviert: offen: 32)
494cdf0e10cSrcweir */
495cdf0e10cSrcweir
GetMatrixEdge(ScAddress & rOrgPos)496cdf0e10cSrcweir sal_uInt16 ScFormulaCell::GetMatrixEdge( ScAddress& rOrgPos )
497cdf0e10cSrcweir {
498cdf0e10cSrcweir switch ( cMatrixFlag )
499cdf0e10cSrcweir {
500cdf0e10cSrcweir case MM_FORMULA :
501cdf0e10cSrcweir case MM_REFERENCE :
502cdf0e10cSrcweir {
503cdf0e10cSrcweir static SCCOL nC;
504cdf0e10cSrcweir static SCROW nR;
505cdf0e10cSrcweir ScAddress aOrg;
506cdf0e10cSrcweir if ( !GetMatrixOrigin( aOrg ) )
507cdf0e10cSrcweir return 0; // dumm gelaufen..
508cdf0e10cSrcweir if ( aOrg != rOrgPos )
509cdf0e10cSrcweir { // erstes Mal oder andere Matrix als letztes Mal
510cdf0e10cSrcweir rOrgPos = aOrg;
511cdf0e10cSrcweir ScFormulaCell* pFCell;
512cdf0e10cSrcweir if ( cMatrixFlag == MM_REFERENCE )
513cdf0e10cSrcweir pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
514cdf0e10cSrcweir else
515cdf0e10cSrcweir pFCell = this; // this MM_FORMULA
516cdf0e10cSrcweir // this gibt's nur einmal, kein Vergleich auf pFCell==this
517cdf0e10cSrcweir if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA
518cdf0e10cSrcweir && pFCell->cMatrixFlag == MM_FORMULA )
519cdf0e10cSrcweir {
520cdf0e10cSrcweir pFCell->GetMatColsRows( nC, nR );
521cdf0e10cSrcweir if ( nC == 0 || nR == 0 )
522cdf0e10cSrcweir { // aus altem Dokument geladen, neu erzeugen
523cdf0e10cSrcweir nC = 1;
524cdf0e10cSrcweir nR = 1;
525cdf0e10cSrcweir ScAddress aTmpOrg;
526cdf0e10cSrcweir ScBaseCell* pCell;
527cdf0e10cSrcweir ScAddress aAdr( aOrg );
528cdf0e10cSrcweir aAdr.IncCol();
529cdf0e10cSrcweir sal_Bool bCont = sal_True;
530cdf0e10cSrcweir do
531cdf0e10cSrcweir {
532cdf0e10cSrcweir pCell = pDocument->GetCell( aAdr );
533cdf0e10cSrcweir if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
534cdf0e10cSrcweir && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
535cdf0e10cSrcweir && GetMatrixOrigin( aTmpOrg ) && aTmpOrg == aOrg )
536cdf0e10cSrcweir {
537cdf0e10cSrcweir nC++;
538cdf0e10cSrcweir aAdr.IncCol();
539cdf0e10cSrcweir }
540cdf0e10cSrcweir else
541cdf0e10cSrcweir bCont = sal_False;
542cdf0e10cSrcweir } while ( bCont );
543cdf0e10cSrcweir aAdr = aOrg;
544cdf0e10cSrcweir aAdr.IncRow();
545cdf0e10cSrcweir bCont = sal_True;
546cdf0e10cSrcweir do
547cdf0e10cSrcweir {
548cdf0e10cSrcweir pCell = pDocument->GetCell( aAdr );
549cdf0e10cSrcweir if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
550cdf0e10cSrcweir && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
551cdf0e10cSrcweir && GetMatrixOrigin( aTmpOrg ) && aTmpOrg == aOrg )
552cdf0e10cSrcweir {
553cdf0e10cSrcweir nR++;
554cdf0e10cSrcweir aAdr.IncRow();
555cdf0e10cSrcweir }
556cdf0e10cSrcweir else
557cdf0e10cSrcweir bCont = sal_False;
558cdf0e10cSrcweir } while ( bCont );
559cdf0e10cSrcweir pFCell->SetMatColsRows( nC, nR );
560cdf0e10cSrcweir }
561cdf0e10cSrcweir }
562cdf0e10cSrcweir else
563cdf0e10cSrcweir {
564cdf0e10cSrcweir #ifdef DBG_UTIL
565cdf0e10cSrcweir String aTmp;
566cdf0e10cSrcweir ByteString aMsg( "broken Matrix, no MatFormula at origin, Pos: " );
567cdf0e10cSrcweir aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
568cdf0e10cSrcweir aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
569cdf0e10cSrcweir aMsg += ", MatOrg: ";
570cdf0e10cSrcweir aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
571cdf0e10cSrcweir aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
572cdf0e10cSrcweir DBG_ERRORFILE( aMsg.GetBuffer() );
573cdf0e10cSrcweir #endif
574cdf0e10cSrcweir return 0; // bad luck ...
575cdf0e10cSrcweir }
576cdf0e10cSrcweir }
577cdf0e10cSrcweir // here we are, healthy and clean, somewhere in between
578cdf0e10cSrcweir SCsCOL dC = aPos.Col() - aOrg.Col();
579cdf0e10cSrcweir SCsROW dR = aPos.Row() - aOrg.Row();
580cdf0e10cSrcweir sal_uInt16 nEdges = 0;
581cdf0e10cSrcweir if ( dC >= 0 && dR >= 0 && dC < nC && dR < nR )
582cdf0e10cSrcweir {
583cdf0e10cSrcweir if ( dC == 0 )
584cdf0e10cSrcweir nEdges |= 4; // linke Kante
585cdf0e10cSrcweir if ( dC+1 == nC )
586cdf0e10cSrcweir nEdges |= 16; // rechte Kante
587cdf0e10cSrcweir if ( dR == 0 )
588cdf0e10cSrcweir nEdges |= 8; // obere Kante
589cdf0e10cSrcweir if ( dR+1 == nR )
590cdf0e10cSrcweir nEdges |= 2; // untere Kante
591cdf0e10cSrcweir if ( !nEdges )
592cdf0e10cSrcweir nEdges = 1; // mittendrin
593cdf0e10cSrcweir }
594cdf0e10cSrcweir #ifdef DBG_UTIL
595cdf0e10cSrcweir else
596cdf0e10cSrcweir {
597cdf0e10cSrcweir String aTmp;
598cdf0e10cSrcweir ByteString aMsg( "broken Matrix, Pos: " );
599cdf0e10cSrcweir aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
600cdf0e10cSrcweir aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
601cdf0e10cSrcweir aMsg += ", MatOrg: ";
602cdf0e10cSrcweir aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
603cdf0e10cSrcweir aMsg += ByteString( aTmp, RTL_TEXTENCODING_ASCII_US );
604cdf0e10cSrcweir aMsg += ", MatCols: ";
605cdf0e10cSrcweir aMsg += ByteString::CreateFromInt32( nC );
606cdf0e10cSrcweir aMsg += ", MatRows: ";
607cdf0e10cSrcweir aMsg += ByteString::CreateFromInt32( nR );
608cdf0e10cSrcweir aMsg += ", DiffCols: ";
609cdf0e10cSrcweir aMsg += ByteString::CreateFromInt32( dC );
610cdf0e10cSrcweir aMsg += ", DiffRows: ";
611cdf0e10cSrcweir aMsg += ByteString::CreateFromInt32( dR );
612cdf0e10cSrcweir DBG_ERRORFILE( aMsg.GetBuffer() );
613cdf0e10cSrcweir }
614cdf0e10cSrcweir #endif
615cdf0e10cSrcweir return nEdges;
616cdf0e10cSrcweir // break;
617cdf0e10cSrcweir }
618cdf0e10cSrcweir default:
619cdf0e10cSrcweir return 0;
620cdf0e10cSrcweir }
621cdf0e10cSrcweir }
622cdf0e10cSrcweir
GetErrCode()623cdf0e10cSrcweir sal_uInt16 ScFormulaCell::GetErrCode()
624cdf0e10cSrcweir {
625cdf0e10cSrcweir if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc())
626cdf0e10cSrcweir Interpret();
627cdf0e10cSrcweir /* FIXME: If ScTokenArray::SetCodeError() was really only for code errors
628cdf0e10cSrcweir * and not also abused for signaling other error conditions we could bail
629cdf0e10cSrcweir * out even before attempting to interpret broken code. */
630cdf0e10cSrcweir sal_uInt16 nErr = pCode->GetCodeError();
631cdf0e10cSrcweir if (nErr)
632cdf0e10cSrcweir return nErr;
633cdf0e10cSrcweir return aResult.GetResultError();
634cdf0e10cSrcweir }
635cdf0e10cSrcweir
GetRawError()636cdf0e10cSrcweir sal_uInt16 ScFormulaCell::GetRawError()
637cdf0e10cSrcweir {
638cdf0e10cSrcweir sal_uInt16 nErr = pCode->GetCodeError();
639cdf0e10cSrcweir if (nErr)
640cdf0e10cSrcweir return nErr;
641cdf0e10cSrcweir return aResult.GetResultError();
642cdf0e10cSrcweir }
643cdf0e10cSrcweir
HasOneReference(ScRange & r) const644cdf0e10cSrcweir sal_Bool ScFormulaCell::HasOneReference( ScRange& r ) const
645cdf0e10cSrcweir {
646cdf0e10cSrcweir pCode->Reset();
647cdf0e10cSrcweir ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
648cdf0e10cSrcweir if( p && !pCode->GetNextReferenceRPN() ) // nur eine!
649cdf0e10cSrcweir {
650cdf0e10cSrcweir p->CalcAbsIfRel( aPos );
651cdf0e10cSrcweir SingleDoubleRefProvider aProv( *p );
652cdf0e10cSrcweir r.aStart.Set( aProv.Ref1.nCol,
653cdf0e10cSrcweir aProv.Ref1.nRow,
654cdf0e10cSrcweir aProv.Ref1.nTab );
655cdf0e10cSrcweir r.aEnd.Set( aProv.Ref2.nCol,
656cdf0e10cSrcweir aProv.Ref2.nRow,
657cdf0e10cSrcweir aProv.Ref2.nTab );
658cdf0e10cSrcweir return sal_True;
659cdf0e10cSrcweir }
660cdf0e10cSrcweir else
661cdf0e10cSrcweir return sal_False;
662cdf0e10cSrcweir }
663cdf0e10cSrcweir
664cdf0e10cSrcweir bool
HasRefListExpressibleAsOneReference(ScRange & rRange) const665cdf0e10cSrcweir ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
666cdf0e10cSrcweir {
667cdf0e10cSrcweir /* If there appears just one reference in the formula, it's the same
668cdf0e10cSrcweir as HasOneReference(). If there are more of them, they can denote
669cdf0e10cSrcweir one range if they are (sole) arguments of one function.
670cdf0e10cSrcweir Union of these references must form one range and their
671cdf0e10cSrcweir intersection must be empty set.
672cdf0e10cSrcweir */
673cdf0e10cSrcweir
674cdf0e10cSrcweir // Detect the simple case of exactly one reference in advance without all
675cdf0e10cSrcweir // overhead.
676cdf0e10cSrcweir // #i107741# Doing so actually makes outlines using SUBTOTAL(x;reference)
677cdf0e10cSrcweir // work again, where the function does not have only references.
678cdf0e10cSrcweir if (HasOneReference( rRange))
679cdf0e10cSrcweir return true;
680cdf0e10cSrcweir
681cdf0e10cSrcweir pCode->Reset();
682cdf0e10cSrcweir // Get first reference, if any
683cdf0e10cSrcweir ScToken* const pFirstReference(
684cdf0e10cSrcweir dynamic_cast<ScToken*>(pCode->GetNextReferenceRPN()));
685cdf0e10cSrcweir if (pFirstReference)
686cdf0e10cSrcweir {
687cdf0e10cSrcweir // Collect all consecutive references, starting by the one
688cdf0e10cSrcweir // already found
689cdf0e10cSrcweir std::deque<ScToken*> aReferences;
690cdf0e10cSrcweir aReferences.push_back(pFirstReference);
691cdf0e10cSrcweir FormulaToken* pToken(pCode->NextRPN());
692cdf0e10cSrcweir FormulaToken* pFunction(0);
693cdf0e10cSrcweir while (pToken)
694cdf0e10cSrcweir {
695cdf0e10cSrcweir if (lcl_isReference(*pToken))
696cdf0e10cSrcweir {
697cdf0e10cSrcweir aReferences.push_back(dynamic_cast<ScToken*>(pToken));
698cdf0e10cSrcweir pToken = pCode->NextRPN();
699cdf0e10cSrcweir }
700cdf0e10cSrcweir else
701cdf0e10cSrcweir {
702cdf0e10cSrcweir if (pToken->IsFunction())
703cdf0e10cSrcweir {
704cdf0e10cSrcweir pFunction = pToken;
705cdf0e10cSrcweir }
706cdf0e10cSrcweir break;
707cdf0e10cSrcweir }
708cdf0e10cSrcweir }
709cdf0e10cSrcweir if (pFunction && !pCode->GetNextReferenceRPN()
710cdf0e10cSrcweir && (pFunction->GetParamCount() == aReferences.size()))
711cdf0e10cSrcweir {
712cdf0e10cSrcweir return lcl_refListFormsOneRange(aPos, aReferences, rRange);
713cdf0e10cSrcweir }
714cdf0e10cSrcweir }
715cdf0e10cSrcweir return false;
716cdf0e10cSrcweir }
717cdf0e10cSrcweir
HasRelNameReference() const718cdf0e10cSrcweir sal_Bool ScFormulaCell::HasRelNameReference() const
719cdf0e10cSrcweir {
720cdf0e10cSrcweir pCode->Reset();
721cdf0e10cSrcweir ScToken* t;
722cdf0e10cSrcweir while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceRPN()) ) != NULL )
723cdf0e10cSrcweir {
724cdf0e10cSrcweir if ( t->GetSingleRef().IsRelName() ||
725cdf0e10cSrcweir (t->GetType() == formula::svDoubleRef &&
726cdf0e10cSrcweir t->GetDoubleRef().Ref2.IsRelName()) )
727cdf0e10cSrcweir return sal_True;
728cdf0e10cSrcweir }
729cdf0e10cSrcweir return sal_False;
730cdf0e10cSrcweir }
731cdf0e10cSrcweir
HasColRowName() const732cdf0e10cSrcweir sal_Bool ScFormulaCell::HasColRowName() const
733cdf0e10cSrcweir {
734cdf0e10cSrcweir pCode->Reset();
735cdf0e10cSrcweir return (pCode->GetNextColRowName() != NULL);
736cdf0e10cSrcweir }
737cdf0e10cSrcweir
UpdateReference(UpdateRefMode eUpdateRefMode,const ScRange & r,SCsCOL nDx,SCsROW nDy,SCsTAB nDz,ScDocument * pUndoDoc,const ScAddress * pUndoCellPos)738cdf0e10cSrcweir void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
739cdf0e10cSrcweir const ScRange& r,
740cdf0e10cSrcweir SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
741cdf0e10cSrcweir ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
742cdf0e10cSrcweir {
743cdf0e10cSrcweir SCCOL nCol1 = r.aStart.Col();
744cdf0e10cSrcweir SCROW nRow1 = r.aStart.Row();
745cdf0e10cSrcweir SCTAB nTab1 = r.aStart.Tab();
746cdf0e10cSrcweir SCCOL nCol2 = r.aEnd.Col();
747cdf0e10cSrcweir SCROW nRow2 = r.aEnd.Row();
748cdf0e10cSrcweir SCTAB nTab2 = r.aEnd.Tab();
749cdf0e10cSrcweir SCCOL nCol = aPos.Col();
750cdf0e10cSrcweir SCROW nRow = aPos.Row();
751cdf0e10cSrcweir SCTAB nTab = aPos.Tab();
752cdf0e10cSrcweir ScAddress aUndoPos( aPos ); // position for undo cell in pUndoDoc
753cdf0e10cSrcweir if ( pUndoCellPos )
754cdf0e10cSrcweir aUndoPos = *pUndoCellPos;
755cdf0e10cSrcweir ScAddress aOldPos( aPos );
756cdf0e10cSrcweir // sal_Bool bPosChanged = sal_False; // ob diese Zelle bewegt wurde
757cdf0e10cSrcweir sal_Bool bIsInsert = sal_False;
758cdf0e10cSrcweir if (eUpdateRefMode == URM_INSDEL)
759cdf0e10cSrcweir {
760cdf0e10cSrcweir bIsInsert = (nDx >= 0 && nDy >= 0 && nDz >= 0);
761cdf0e10cSrcweir if ( nDx && nRow >= nRow1 && nRow <= nRow2 &&
762cdf0e10cSrcweir nTab >= nTab1 && nTab <= nTab2 )
763cdf0e10cSrcweir {
764cdf0e10cSrcweir if (nCol >= nCol1)
765cdf0e10cSrcweir {
766cdf0e10cSrcweir nCol = sal::static_int_cast<SCCOL>( nCol + nDx );
767cdf0e10cSrcweir if ((SCsCOL) nCol < 0)
768cdf0e10cSrcweir nCol = 0;
769cdf0e10cSrcweir else if ( nCol > MAXCOL )
770cdf0e10cSrcweir nCol = MAXCOL;
771cdf0e10cSrcweir aPos.SetCol( nCol );
772cdf0e10cSrcweir // bPosChanged = sal_True;
773cdf0e10cSrcweir }
774cdf0e10cSrcweir }
775cdf0e10cSrcweir if ( nDy && nCol >= nCol1 && nCol <= nCol2 &&
776cdf0e10cSrcweir nTab >= nTab1 && nTab <= nTab2 )
777cdf0e10cSrcweir {
778cdf0e10cSrcweir if (nRow >= nRow1)
779cdf0e10cSrcweir {
780cdf0e10cSrcweir nRow = sal::static_int_cast<SCROW>( nRow + nDy );
781cdf0e10cSrcweir if ((SCsROW) nRow < 0)
782cdf0e10cSrcweir nRow = 0;
783cdf0e10cSrcweir else if ( nRow > MAXROW )
784cdf0e10cSrcweir nRow = MAXROW;
785cdf0e10cSrcweir aPos.SetRow( nRow );
786cdf0e10cSrcweir // bPosChanged = sal_True;
787cdf0e10cSrcweir }
788cdf0e10cSrcweir }
789cdf0e10cSrcweir if ( nDz && nCol >= nCol1 && nCol <= nCol2 &&
790cdf0e10cSrcweir nRow >= nRow1 && nRow <= nRow2 )
791cdf0e10cSrcweir {
792cdf0e10cSrcweir if (nTab >= nTab1)
793cdf0e10cSrcweir {
794cdf0e10cSrcweir SCTAB nMaxTab = pDocument->GetTableCount() - 1;
795cdf0e10cSrcweir nTab = sal::static_int_cast<SCTAB>( nTab + nDz );
796cdf0e10cSrcweir if ((SCsTAB) nTab < 0)
797cdf0e10cSrcweir nTab = 0;
798cdf0e10cSrcweir else if ( nTab > nMaxTab )
799cdf0e10cSrcweir nTab = nMaxTab;
800cdf0e10cSrcweir aPos.SetTab( nTab );
801cdf0e10cSrcweir // bPosChanged = sal_True;
802cdf0e10cSrcweir }
803cdf0e10cSrcweir }
804cdf0e10cSrcweir }
805cdf0e10cSrcweir else if ( r.In( aPos ) )
806cdf0e10cSrcweir {
807cdf0e10cSrcweir aOldPos.Set( nCol - nDx, nRow - nDy, nTab - nDz );
808cdf0e10cSrcweir // bPosChanged = sal_True;
809cdf0e10cSrcweir }
810cdf0e10cSrcweir
811cdf0e10cSrcweir sal_Bool bHasRefs = sal_False;
812cdf0e10cSrcweir sal_Bool bHasColRowNames = sal_False;
813cdf0e10cSrcweir sal_Bool bOnRefMove = sal_False;
814cdf0e10cSrcweir if ( !pDocument->IsClipOrUndo() )
815cdf0e10cSrcweir {
816cdf0e10cSrcweir pCode->Reset();
817cdf0e10cSrcweir bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
818cdf0e10cSrcweir if ( !bHasRefs || eUpdateRefMode == URM_COPY )
819cdf0e10cSrcweir {
820cdf0e10cSrcweir pCode->Reset();
821cdf0e10cSrcweir bHasColRowNames = (pCode->GetNextColRowName() != NULL);
822cdf0e10cSrcweir bHasRefs = bHasRefs || bHasColRowNames;
823cdf0e10cSrcweir }
824cdf0e10cSrcweir bOnRefMove = pCode->IsRecalcModeOnRefMove();
825cdf0e10cSrcweir }
826cdf0e10cSrcweir if( bHasRefs || bOnRefMove )
827cdf0e10cSrcweir {
828cdf0e10cSrcweir ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
829cdf0e10cSrcweir sal_Bool bValChanged;
830cdf0e10cSrcweir ScRangeData* pRangeData;
831cdf0e10cSrcweir sal_Bool bRangeModified; // any range, not only shared formula
832cdf0e10cSrcweir sal_Bool bRefSizeChanged;
833cdf0e10cSrcweir if ( bHasRefs )
834cdf0e10cSrcweir {
835cdf0e10cSrcweir ScCompiler aComp(pDocument, aPos, *pCode);
836cdf0e10cSrcweir aComp.SetGrammar(pDocument->GetGrammar());
837cdf0e10cSrcweir pRangeData = aComp.UpdateReference(eUpdateRefMode, aOldPos, r,
838cdf0e10cSrcweir nDx, nDy, nDz,
839cdf0e10cSrcweir bValChanged, bRefSizeChanged);
840cdf0e10cSrcweir bRangeModified = aComp.HasModifiedRange();
841cdf0e10cSrcweir }
842cdf0e10cSrcweir else
843cdf0e10cSrcweir {
844cdf0e10cSrcweir bValChanged = sal_False;
845cdf0e10cSrcweir pRangeData = NULL;
846cdf0e10cSrcweir bRangeModified = sal_False;
847cdf0e10cSrcweir bRefSizeChanged = sal_False;
848cdf0e10cSrcweir }
849cdf0e10cSrcweir if ( bOnRefMove )
850cdf0e10cSrcweir bOnRefMove = (bValChanged || (aPos != aOldPos));
851cdf0e10cSrcweir // Cell may reference itself, e.g. ocColumn, ocRow without parameter
852cdf0e10cSrcweir
853cdf0e10cSrcweir sal_Bool bColRowNameCompile, bHasRelName, bNewListening, bInDeleteUndo;
854cdf0e10cSrcweir if ( bHasRefs )
855cdf0e10cSrcweir {
856cdf0e10cSrcweir // Upon Insert ColRowNames have to be recompiled in case the
857cdf0e10cSrcweir // insertion occurs right in front of the range.
858cdf0e10cSrcweir bColRowNameCompile =
859cdf0e10cSrcweir (eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0));
860cdf0e10cSrcweir if ( bColRowNameCompile )
861cdf0e10cSrcweir {
862cdf0e10cSrcweir bColRowNameCompile = sal_False;
863cdf0e10cSrcweir ScToken* t;
864cdf0e10cSrcweir ScRangePairList* pColList = pDocument->GetColNameRanges();
865cdf0e10cSrcweir ScRangePairList* pRowList = pDocument->GetRowNameRanges();
866cdf0e10cSrcweir pCode->Reset();
867cdf0e10cSrcweir while ( !bColRowNameCompile && (t = static_cast<ScToken*>(pCode->GetNextColRowName())) != NULL )
868cdf0e10cSrcweir {
869cdf0e10cSrcweir ScSingleRefData& rRef = t->GetSingleRef();
870cdf0e10cSrcweir if ( nDy > 0 && rRef.IsColRel() )
871cdf0e10cSrcweir { // ColName
872cdf0e10cSrcweir rRef.CalcAbsIfRel( aPos );
873cdf0e10cSrcweir ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
874cdf0e10cSrcweir ScRangePair* pR = pColList->Find( aAdr );
875cdf0e10cSrcweir if ( pR )
876cdf0e10cSrcweir { // definiert
877cdf0e10cSrcweir if ( pR->GetRange(1).aStart.Row() == nRow1 )
878cdf0e10cSrcweir bColRowNameCompile = sal_True;
879cdf0e10cSrcweir }
880cdf0e10cSrcweir else
881cdf0e10cSrcweir { // on the fly
882cdf0e10cSrcweir if ( rRef.nRow + 1 == nRow1 )
883cdf0e10cSrcweir bColRowNameCompile = sal_True;
884cdf0e10cSrcweir }
885cdf0e10cSrcweir }
886cdf0e10cSrcweir if ( nDx > 0 && rRef.IsRowRel() )
887cdf0e10cSrcweir { // RowName
888cdf0e10cSrcweir rRef.CalcAbsIfRel( aPos );
889cdf0e10cSrcweir ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
890cdf0e10cSrcweir ScRangePair* pR = pRowList->Find( aAdr );
891cdf0e10cSrcweir if ( pR )
892cdf0e10cSrcweir { // definiert
893cdf0e10cSrcweir if ( pR->GetRange(1).aStart.Col() == nCol1 )
894cdf0e10cSrcweir bColRowNameCompile = sal_True;
895cdf0e10cSrcweir }
896cdf0e10cSrcweir else
897cdf0e10cSrcweir { // on the fly
898cdf0e10cSrcweir if ( rRef.nCol + 1 == nCol1 )
899cdf0e10cSrcweir bColRowNameCompile = sal_True;
900cdf0e10cSrcweir }
901cdf0e10cSrcweir }
902cdf0e10cSrcweir }
903cdf0e10cSrcweir }
904cdf0e10cSrcweir else if ( eUpdateRefMode == URM_MOVE )
905cdf0e10cSrcweir { // bei Move/D&D neu kompilieren wenn ColRowName verschoben wurde
906cdf0e10cSrcweir // oder diese Zelle auf einen zeigt und verschoben wurde
907cdf0e10cSrcweir bColRowNameCompile = bCompile; // evtl. aus Copy-ctor
908cdf0e10cSrcweir if ( !bColRowNameCompile )
909cdf0e10cSrcweir {
910cdf0e10cSrcweir sal_Bool bMoved = (aPos != aOldPos);
911cdf0e10cSrcweir pCode->Reset();
912cdf0e10cSrcweir ScToken* t = static_cast<ScToken*>(pCode->GetNextColRowName());
913cdf0e10cSrcweir if ( t && bMoved )
914cdf0e10cSrcweir bColRowNameCompile = sal_True;
915cdf0e10cSrcweir while ( t && !bColRowNameCompile )
916cdf0e10cSrcweir {
917cdf0e10cSrcweir ScSingleRefData& rRef = t->GetSingleRef();
918cdf0e10cSrcweir rRef.CalcAbsIfRel( aPos );
919cdf0e10cSrcweir if ( rRef.Valid() )
920cdf0e10cSrcweir {
921cdf0e10cSrcweir ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
922cdf0e10cSrcweir if ( r.In( aAdr ) )
923cdf0e10cSrcweir bColRowNameCompile = sal_True;
924cdf0e10cSrcweir }
925cdf0e10cSrcweir t = static_cast<ScToken*>(pCode->GetNextColRowName());
926cdf0e10cSrcweir }
927cdf0e10cSrcweir }
928cdf0e10cSrcweir }
929cdf0e10cSrcweir else if ( eUpdateRefMode == URM_COPY && bHasColRowNames && bValChanged )
930cdf0e10cSrcweir {
931cdf0e10cSrcweir bColRowNameCompile = sal_True;
932cdf0e10cSrcweir }
933cdf0e10cSrcweir ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
934cdf0e10cSrcweir if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
935cdf0e10cSrcweir bInDeleteUndo = sal_True;
936cdf0e10cSrcweir else
937cdf0e10cSrcweir bInDeleteUndo = sal_False;
938cdf0e10cSrcweir // RelNameRefs are always moved
939cdf0e10cSrcweir bHasRelName = HasRelNameReference();
940cdf0e10cSrcweir // Reference changed and new listening needed?
941cdf0e10cSrcweir // Except in Insert/Delete without specialties.
942cdf0e10cSrcweir bNewListening = (bRangeModified || pRangeData || bColRowNameCompile
943cdf0e10cSrcweir || (bValChanged && (eUpdateRefMode != URM_INSDEL ||
944cdf0e10cSrcweir bInDeleteUndo || bRefSizeChanged)) ||
945cdf0e10cSrcweir (bHasRelName && eUpdateRefMode != URM_COPY))
946cdf0e10cSrcweir // #i36299# Don't duplicate action during cut&paste / drag&drop
947cdf0e10cSrcweir // on a cell in the range moved, start/end listeners is done
948cdf0e10cSrcweir // via ScDocument::DeleteArea() and ScDocument::CopyFromClip().
949cdf0e10cSrcweir && !(eUpdateRefMode == URM_MOVE &&
950cdf0e10cSrcweir pDocument->IsInsertingFromOtherDoc() && r.In(aPos));
951cdf0e10cSrcweir if ( bNewListening )
952cdf0e10cSrcweir EndListeningTo( pDocument, pOld, aOldPos );
953cdf0e10cSrcweir }
954cdf0e10cSrcweir else
955cdf0e10cSrcweir {
956cdf0e10cSrcweir bColRowNameCompile = bHasRelName = bNewListening = bInDeleteUndo =
957cdf0e10cSrcweir sal_False;
958cdf0e10cSrcweir }
959cdf0e10cSrcweir
960cdf0e10cSrcweir sal_Bool bNeedDirty;
961cdf0e10cSrcweir // NeedDirty bei Aenderungen ausser Copy und Move/Insert ohne RelNames
962cdf0e10cSrcweir if ( bRangeModified || pRangeData || bColRowNameCompile ||
963cdf0e10cSrcweir (bValChanged && eUpdateRefMode != URM_COPY &&
964cdf0e10cSrcweir (eUpdateRefMode != URM_MOVE || bHasRelName) &&
965cdf0e10cSrcweir (!bIsInsert || bHasRelName || bInDeleteUndo ||
966cdf0e10cSrcweir bRefSizeChanged)) || bOnRefMove)
967cdf0e10cSrcweir bNeedDirty = sal_True;
968cdf0e10cSrcweir else
969cdf0e10cSrcweir bNeedDirty = sal_False;
970cdf0e10cSrcweir if (pUndoDoc && (bValChanged || pRangeData || bOnRefMove))
971cdf0e10cSrcweir {
972cdf0e10cSrcweir // Copy the cell to aUndoPos, which is its current position in the document,
973cdf0e10cSrcweir // so this works when UpdateReference is called before moving the cells
974cdf0e10cSrcweir // (InsertCells/DeleteCells - aPos is changed above) as well as when UpdateReference
975cdf0e10cSrcweir // is called after moving the cells (MoveBlock/PasteFromClip - aOldPos is changed).
976cdf0e10cSrcweir
977cdf0e10cSrcweir // If there is already a formula cell in the undo document, don't overwrite it,
978cdf0e10cSrcweir // the first (oldest) is the important cell.
979cdf0e10cSrcweir if ( pUndoDoc->GetCellType( aUndoPos ) != CELLTYPE_FORMULA )
980cdf0e10cSrcweir {
981cdf0e10cSrcweir ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos,
982cdf0e10cSrcweir pOld, eTempGrammar, cMatrixFlag );
983cdf0e10cSrcweir pFCell->aResult.SetToken( NULL); // to recognize it as changed later (Cut/Paste!)
984cdf0e10cSrcweir pUndoDoc->PutCell( aUndoPos, pFCell );
985cdf0e10cSrcweir }
986cdf0e10cSrcweir }
987cdf0e10cSrcweir // #i116833# If the formula is changed, always invalidate the stream (even if the result is the same).
988cdf0e10cSrcweir // If the formula is moved, the change is recognized separately.
989cdf0e10cSrcweir if (bValChanged && pDocument->IsStreamValid(aPos.Tab()))
990cdf0e10cSrcweir pDocument->SetStreamValid(aPos.Tab(), sal_False);
991cdf0e10cSrcweir bValChanged = sal_False;
992cdf0e10cSrcweir if ( pRangeData )
993cdf0e10cSrcweir { // Replace shared formula with own formula
994cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this ); // update formula count
995cdf0e10cSrcweir delete pCode;
996cdf0e10cSrcweir pCode = pRangeData->GetCode()->Clone();
997cdf0e10cSrcweir // #i18937# #i110008# call MoveRelWrap, but with the old position
998cdf0e10cSrcweir ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
999cdf0e10cSrcweir ScCompiler aComp2(pDocument, aPos, *pCode);
1000cdf0e10cSrcweir aComp2.SetGrammar(pDocument->GetGrammar());
1001cdf0e10cSrcweir aComp2.UpdateSharedFormulaReference( eUpdateRefMode, aOldPos, r,
1002cdf0e10cSrcweir nDx, nDy, nDz );
1003cdf0e10cSrcweir bValChanged = sal_True;
1004cdf0e10cSrcweir bNeedDirty = sal_True;
1005cdf0e10cSrcweir }
1006cdf0e10cSrcweir if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
1007cdf0e10cSrcweir {
1008cdf0e10cSrcweir CompileTokenArray( bNewListening ); // kein Listening
1009cdf0e10cSrcweir bNeedDirty = sal_True;
1010cdf0e10cSrcweir }
1011cdf0e10cSrcweir if ( !bInDeleteUndo )
1012cdf0e10cSrcweir { // In ChangeTrack Delete-Reject listeners are established in
1013cdf0e10cSrcweir // InsertCol/InsertRow
1014cdf0e10cSrcweir if ( bNewListening )
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir if ( eUpdateRefMode == URM_INSDEL )
1017cdf0e10cSrcweir {
1018cdf0e10cSrcweir // Inserts/Deletes re-establish listeners after all
1019cdf0e10cSrcweir // UpdateReference calls.
1020cdf0e10cSrcweir // All replaced shared formula listeners have to be
1021cdf0e10cSrcweir // established after an Insert or Delete. Do nothing here.
1022cdf0e10cSrcweir SetNeedsListening( sal_True);
1023cdf0e10cSrcweir }
1024cdf0e10cSrcweir else
1025cdf0e10cSrcweir StartListeningTo( pDocument );
1026cdf0e10cSrcweir }
1027cdf0e10cSrcweir }
1028cdf0e10cSrcweir if ( bNeedDirty && (!(eUpdateRefMode == URM_INSDEL && bHasRelName) || pRangeData) )
1029cdf0e10cSrcweir { // Referenzen abgeschnitten, ungueltig o.ae.?
1030cdf0e10cSrcweir sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
1031cdf0e10cSrcweir // kein Interpret in SubMinimalRecalc wegen evtl. falscher Referenzen
1032cdf0e10cSrcweir pDocument->SetAutoCalc( sal_False );
1033cdf0e10cSrcweir SetDirty();
1034cdf0e10cSrcweir pDocument->SetAutoCalc( bOldAutoCalc );
1035cdf0e10cSrcweir }
1036cdf0e10cSrcweir
1037cdf0e10cSrcweir delete pOld;
1038cdf0e10cSrcweir }
1039cdf0e10cSrcweir }
1040cdf0e10cSrcweir
UpdateInsertTab(SCTAB nTable)1041cdf0e10cSrcweir void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
1042cdf0e10cSrcweir {
1043cdf0e10cSrcweir sal_Bool bPosChanged = ( aPos.Tab() >= nTable ? sal_True : sal_False );
1044cdf0e10cSrcweir pCode->Reset();
1045cdf0e10cSrcweir if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
1046cdf0e10cSrcweir {
1047cdf0e10cSrcweir EndListeningTo( pDocument );
1048cdf0e10cSrcweir // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateInsertTab !
1049cdf0e10cSrcweir if ( bPosChanged )
1050cdf0e10cSrcweir aPos.IncTab();
1051cdf0e10cSrcweir ScRangeData* pRangeData;
1052cdf0e10cSrcweir ScCompiler aComp(pDocument, aPos, *pCode);
1053cdf0e10cSrcweir aComp.SetGrammar(pDocument->GetGrammar());
1054cdf0e10cSrcweir pRangeData = aComp.UpdateInsertTab( nTable, sal_False );
1055cdf0e10cSrcweir if (pRangeData) // Shared Formula gegen echte Formel
1056cdf0e10cSrcweir { // austauschen
1057cdf0e10cSrcweir sal_Bool bRefChanged;
1058cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this ); // update formula count
1059cdf0e10cSrcweir delete pCode;
1060cdf0e10cSrcweir pCode = new ScTokenArray( *pRangeData->GetCode() );
1061cdf0e10cSrcweir ScCompiler aComp2(pDocument, aPos, *pCode);
1062cdf0e10cSrcweir aComp2.SetGrammar(pDocument->GetGrammar());
1063cdf0e10cSrcweir aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
1064cdf0e10cSrcweir aComp2.UpdateInsertTab( nTable, sal_False );
1065cdf0e10cSrcweir // If the shared formula contained a named range/formula containing
1066cdf0e10cSrcweir // an absolute reference to a sheet, those have to be readjusted.
1067cdf0e10cSrcweir aComp2.UpdateDeleteTab( nTable, sal_False, sal_True, bRefChanged );
1068cdf0e10cSrcweir bCompile = sal_True;
1069cdf0e10cSrcweir }
1070cdf0e10cSrcweir // kein StartListeningTo weil pTab[nTab] noch nicht existiert!
1071cdf0e10cSrcweir }
1072cdf0e10cSrcweir else if ( bPosChanged )
1073cdf0e10cSrcweir aPos.IncTab();
1074cdf0e10cSrcweir }
1075cdf0e10cSrcweir
UpdateDeleteTab(SCTAB nTable,sal_Bool bIsMove)1076cdf0e10cSrcweir sal_Bool ScFormulaCell::UpdateDeleteTab(SCTAB nTable, sal_Bool bIsMove)
1077cdf0e10cSrcweir {
1078cdf0e10cSrcweir sal_Bool bRefChanged = sal_False;
1079cdf0e10cSrcweir sal_Bool bPosChanged = ( aPos.Tab() > nTable ? sal_True : sal_False );
1080cdf0e10cSrcweir pCode->Reset();
1081cdf0e10cSrcweir if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
1082cdf0e10cSrcweir {
1083cdf0e10cSrcweir EndListeningTo( pDocument );
1084cdf0e10cSrcweir // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateDeleteTab !
1085cdf0e10cSrcweir if ( bPosChanged )
1086cdf0e10cSrcweir aPos.IncTab(-1);
1087cdf0e10cSrcweir ScRangeData* pRangeData;
1088cdf0e10cSrcweir ScCompiler aComp(pDocument, aPos, *pCode);
1089cdf0e10cSrcweir aComp.SetGrammar(pDocument->GetGrammar());
1090cdf0e10cSrcweir pRangeData = aComp.UpdateDeleteTab(nTable, bIsMove, sal_False, bRefChanged);
1091cdf0e10cSrcweir if (pRangeData) // Shared Formula gegen echte Formel
1092cdf0e10cSrcweir { // austauschen
1093cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this ); // update formula count
1094cdf0e10cSrcweir delete pCode;
1095cdf0e10cSrcweir pCode = pRangeData->GetCode()->Clone();
1096cdf0e10cSrcweir ScCompiler aComp2(pDocument, aPos, *pCode);
1097cdf0e10cSrcweir aComp2.SetGrammar(pDocument->GetGrammar());
1098cdf0e10cSrcweir aComp2.CompileTokenArray();
1099cdf0e10cSrcweir aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
1100cdf0e10cSrcweir aComp2.UpdateDeleteTab( nTable, sal_False, sal_False, bRefChanged );
1101cdf0e10cSrcweir // If the shared formula contained a named range/formula containing
1102cdf0e10cSrcweir // an absolute reference to a sheet, those have to be readjusted.
1103cdf0e10cSrcweir aComp2.UpdateInsertTab( nTable,sal_True );
1104cdf0e10cSrcweir // bRefChanged kann beim letzten UpdateDeleteTab zurueckgesetzt worden sein
1105cdf0e10cSrcweir bRefChanged = sal_True;
1106cdf0e10cSrcweir bCompile = sal_True;
1107cdf0e10cSrcweir }
1108cdf0e10cSrcweir // kein StartListeningTo weil pTab[nTab] noch nicht korrekt!
1109cdf0e10cSrcweir }
1110cdf0e10cSrcweir else if ( bPosChanged )
1111cdf0e10cSrcweir aPos.IncTab(-1);
1112cdf0e10cSrcweir
1113cdf0e10cSrcweir return bRefChanged;
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos,SCTAB nTabNo)1116cdf0e10cSrcweir void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
1117cdf0e10cSrcweir {
1118cdf0e10cSrcweir pCode->Reset();
1119cdf0e10cSrcweir if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
1120cdf0e10cSrcweir {
1121cdf0e10cSrcweir EndListeningTo( pDocument );
1122cdf0e10cSrcweir // SetTab _nach_ EndListeningTo und _vor_ Compiler UpdateMoveTab !
1123cdf0e10cSrcweir aPos.SetTab( nTabNo );
1124cdf0e10cSrcweir ScRangeData* pRangeData;
1125cdf0e10cSrcweir ScCompiler aComp(pDocument, aPos, *pCode);
1126cdf0e10cSrcweir aComp.SetGrammar(pDocument->GetGrammar());
1127cdf0e10cSrcweir pRangeData = aComp.UpdateMoveTab( nOldPos, nNewPos, sal_False );
1128cdf0e10cSrcweir if (pRangeData) // Shared Formula gegen echte Formel
1129cdf0e10cSrcweir { // austauschen
1130cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this ); // update formula count
1131cdf0e10cSrcweir delete pCode;
1132cdf0e10cSrcweir pCode = pRangeData->GetCode()->Clone();
1133cdf0e10cSrcweir ScCompiler aComp2(pDocument, aPos, *pCode);
1134cdf0e10cSrcweir aComp2.SetGrammar(pDocument->GetGrammar());
1135cdf0e10cSrcweir aComp2.CompileTokenArray();
1136cdf0e10cSrcweir aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
1137cdf0e10cSrcweir aComp2.UpdateMoveTab( nOldPos, nNewPos, sal_True );
1138cdf0e10cSrcweir bCompile = sal_True;
1139cdf0e10cSrcweir }
1140cdf0e10cSrcweir // kein StartListeningTo weil pTab[nTab] noch nicht korrekt!
1141cdf0e10cSrcweir }
1142cdf0e10cSrcweir else
1143cdf0e10cSrcweir aPos.SetTab( nTabNo );
1144cdf0e10cSrcweir }
1145cdf0e10cSrcweir
UpdateInsertTabAbs(SCTAB nTable)1146cdf0e10cSrcweir void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable)
1147cdf0e10cSrcweir {
1148cdf0e10cSrcweir if( !pDocument->IsClipOrUndo() )
1149cdf0e10cSrcweir {
1150cdf0e10cSrcweir pCode->Reset();
1151cdf0e10cSrcweir ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1152cdf0e10cSrcweir while( p )
1153cdf0e10cSrcweir {
1154cdf0e10cSrcweir ScSingleRefData& rRef1 = p->GetSingleRef();
1155cdf0e10cSrcweir if( !rRef1.IsTabRel() && (SCsTAB) nTable <= rRef1.nTab )
1156cdf0e10cSrcweir rRef1.nTab++;
1157cdf0e10cSrcweir if( p->GetType() == formula::svDoubleRef )
1158cdf0e10cSrcweir {
1159cdf0e10cSrcweir ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
1160cdf0e10cSrcweir if( !rRef2.IsTabRel() && (SCsTAB) nTable <= rRef2.nTab )
1161cdf0e10cSrcweir rRef2.nTab++;
1162cdf0e10cSrcweir }
1163cdf0e10cSrcweir p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1164cdf0e10cSrcweir }
1165cdf0e10cSrcweir }
1166cdf0e10cSrcweir }
1167cdf0e10cSrcweir
TestTabRefAbs(SCTAB nTable)1168cdf0e10cSrcweir sal_Bool ScFormulaCell::TestTabRefAbs(SCTAB nTable)
1169cdf0e10cSrcweir {
1170cdf0e10cSrcweir sal_Bool bRet = sal_False;
1171cdf0e10cSrcweir if( !pDocument->IsClipOrUndo() )
1172cdf0e10cSrcweir {
1173cdf0e10cSrcweir pCode->Reset();
1174cdf0e10cSrcweir ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1175cdf0e10cSrcweir while( p )
1176cdf0e10cSrcweir {
1177cdf0e10cSrcweir ScSingleRefData& rRef1 = p->GetSingleRef();
1178cdf0e10cSrcweir if( !rRef1.IsTabRel() )
1179cdf0e10cSrcweir {
1180cdf0e10cSrcweir if( (SCsTAB) nTable != rRef1.nTab )
1181cdf0e10cSrcweir bRet = sal_True;
1182cdf0e10cSrcweir else if (nTable != aPos.Tab())
1183cdf0e10cSrcweir rRef1.nTab = aPos.Tab();
1184cdf0e10cSrcweir }
1185cdf0e10cSrcweir if( p->GetType() == formula::svDoubleRef )
1186cdf0e10cSrcweir {
1187cdf0e10cSrcweir ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
1188cdf0e10cSrcweir if( !rRef2.IsTabRel() )
1189cdf0e10cSrcweir {
1190cdf0e10cSrcweir if( (SCsTAB) nTable != rRef2.nTab )
1191cdf0e10cSrcweir bRet = sal_True;
1192cdf0e10cSrcweir else if (nTable != aPos.Tab())
1193cdf0e10cSrcweir rRef2.nTab = aPos.Tab();
1194cdf0e10cSrcweir }
1195cdf0e10cSrcweir }
1196cdf0e10cSrcweir p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
1197cdf0e10cSrcweir }
1198cdf0e10cSrcweir }
1199cdf0e10cSrcweir return bRet;
1200cdf0e10cSrcweir }
1201cdf0e10cSrcweir
UpdateCompile(sal_Bool bForceIfNameInUse)1202cdf0e10cSrcweir void ScFormulaCell::UpdateCompile( sal_Bool bForceIfNameInUse )
1203cdf0e10cSrcweir {
1204cdf0e10cSrcweir if ( bForceIfNameInUse && !bCompile )
1205cdf0e10cSrcweir bCompile = pCode->HasNameOrColRowName();
1206cdf0e10cSrcweir if ( bCompile )
1207cdf0e10cSrcweir pCode->SetCodeError( 0 ); // make sure it will really be compiled
1208cdf0e10cSrcweir CompileTokenArray();
1209cdf0e10cSrcweir }
1210cdf0e10cSrcweir
1211cdf0e10cSrcweir // Referenzen transponieren - wird nur in Clipboard-Dokumenten aufgerufen
1212cdf0e10cSrcweir
TransposeReference()1213cdf0e10cSrcweir void ScFormulaCell::TransposeReference()
1214cdf0e10cSrcweir {
1215cdf0e10cSrcweir sal_Bool bFound = sal_False;
1216cdf0e10cSrcweir pCode->Reset();
1217cdf0e10cSrcweir ScToken* t;
1218cdf0e10cSrcweir while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
1219cdf0e10cSrcweir {
1220cdf0e10cSrcweir ScSingleRefData& rRef1 = t->GetSingleRef();
1221cdf0e10cSrcweir if ( rRef1.IsColRel() && rRef1.IsRowRel() )
1222cdf0e10cSrcweir {
1223cdf0e10cSrcweir sal_Bool bDouble = (t->GetType() == formula::svDoubleRef);
1224cdf0e10cSrcweir ScSingleRefData& rRef2 = (bDouble ? t->GetDoubleRef().Ref2 : rRef1);
1225cdf0e10cSrcweir if ( !bDouble || (rRef2.IsColRel() && rRef2.IsRowRel()) )
1226cdf0e10cSrcweir {
1227cdf0e10cSrcweir sal_Int16 nTemp;
1228cdf0e10cSrcweir
1229cdf0e10cSrcweir nTemp = rRef1.nRelCol;
1230cdf0e10cSrcweir rRef1.nRelCol = static_cast<SCCOL>(rRef1.nRelRow);
1231cdf0e10cSrcweir rRef1.nRelRow = static_cast<SCROW>(nTemp);
1232cdf0e10cSrcweir
1233cdf0e10cSrcweir if ( bDouble )
1234cdf0e10cSrcweir {
1235cdf0e10cSrcweir nTemp = rRef2.nRelCol;
1236cdf0e10cSrcweir rRef2.nRelCol = static_cast<SCCOL>(rRef2.nRelRow);
1237cdf0e10cSrcweir rRef2.nRelRow = static_cast<SCROW>(nTemp);
1238cdf0e10cSrcweir }
1239cdf0e10cSrcweir
1240cdf0e10cSrcweir bFound = sal_True;
1241cdf0e10cSrcweir }
1242cdf0e10cSrcweir }
1243cdf0e10cSrcweir }
1244cdf0e10cSrcweir
1245cdf0e10cSrcweir if (bFound)
1246cdf0e10cSrcweir bCompile = sal_True;
1247cdf0e10cSrcweir }
1248cdf0e10cSrcweir
UpdateTranspose(const ScRange & rSource,const ScAddress & rDest,ScDocument * pUndoDoc)1249cdf0e10cSrcweir void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
1250cdf0e10cSrcweir ScDocument* pUndoDoc )
1251cdf0e10cSrcweir {
1252cdf0e10cSrcweir EndListeningTo( pDocument );
1253cdf0e10cSrcweir
1254cdf0e10cSrcweir ScAddress aOldPos = aPos;
1255cdf0e10cSrcweir sal_Bool bPosChanged = sal_False; // ob diese Zelle bewegt wurde
1256cdf0e10cSrcweir
1257cdf0e10cSrcweir ScRange aDestRange( rDest, ScAddress(
1258cdf0e10cSrcweir static_cast<SCCOL>(rDest.Col() + rSource.aEnd.Row() - rSource.aStart.Row()),
1259cdf0e10cSrcweir static_cast<SCROW>(rDest.Row() + rSource.aEnd.Col() - rSource.aStart.Col()),
1260cdf0e10cSrcweir rDest.Tab() + rSource.aEnd.Tab() - rSource.aStart.Tab() ) );
1261cdf0e10cSrcweir if ( aDestRange.In( aOldPos ) )
1262cdf0e10cSrcweir {
1263cdf0e10cSrcweir // Position zurueckrechnen
1264cdf0e10cSrcweir SCsCOL nRelPosX = aOldPos.Col();
1265cdf0e10cSrcweir SCsROW nRelPosY = aOldPos.Row();
1266cdf0e10cSrcweir SCsTAB nRelPosZ = aOldPos.Tab();
1267cdf0e10cSrcweir ScRefUpdate::DoTranspose( nRelPosX, nRelPosY, nRelPosZ, pDocument, aDestRange, rSource.aStart );
1268cdf0e10cSrcweir aOldPos.Set( nRelPosX, nRelPosY, nRelPosZ );
1269cdf0e10cSrcweir bPosChanged = sal_True;
1270cdf0e10cSrcweir }
1271cdf0e10cSrcweir
1272cdf0e10cSrcweir ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
1273cdf0e10cSrcweir sal_Bool bRefChanged = sal_False;
1274cdf0e10cSrcweir ScToken* t;
1275cdf0e10cSrcweir
1276cdf0e10cSrcweir ScRangeData* pShared = NULL;
1277cdf0e10cSrcweir pCode->Reset();
1278cdf0e10cSrcweir while( (t = static_cast<ScToken*>(pCode->GetNextReferenceOrName())) != NULL )
1279cdf0e10cSrcweir {
1280cdf0e10cSrcweir if( t->GetOpCode() == ocName )
1281cdf0e10cSrcweir {
1282cdf0e10cSrcweir ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->GetIndex() );
1283cdf0e10cSrcweir if (pName)
1284cdf0e10cSrcweir {
1285cdf0e10cSrcweir if (pName->IsModified())
1286cdf0e10cSrcweir bRefChanged = sal_True;
1287cdf0e10cSrcweir if (pName->HasType(RT_SHAREDMOD))
1288cdf0e10cSrcweir pShared = pName;
1289cdf0e10cSrcweir }
1290cdf0e10cSrcweir }
1291cdf0e10cSrcweir else if( t->GetType() != svIndex )
1292cdf0e10cSrcweir {
1293cdf0e10cSrcweir t->CalcAbsIfRel( aOldPos );
1294cdf0e10cSrcweir sal_Bool bMod;
1295cdf0e10cSrcweir { // own scope for SingleDoubleRefModifier dtor if SingleRef
1296cdf0e10cSrcweir SingleDoubleRefModifier aMod( *t );
1297cdf0e10cSrcweir ScComplexRefData& rRef = aMod.Ref();
1298cdf0e10cSrcweir bMod = (ScRefUpdate::UpdateTranspose( pDocument, rSource,
1299cdf0e10cSrcweir rDest, rRef ) != UR_NOTHING || bPosChanged);
1300cdf0e10cSrcweir }
1301cdf0e10cSrcweir if ( bMod )
1302cdf0e10cSrcweir {
1303cdf0e10cSrcweir t->CalcRelFromAbs( aPos );
1304cdf0e10cSrcweir bRefChanged = sal_True;
1305cdf0e10cSrcweir }
1306cdf0e10cSrcweir }
1307cdf0e10cSrcweir }
1308cdf0e10cSrcweir
1309cdf0e10cSrcweir if (pShared) // Shared Formula gegen echte Formel austauschen
1310cdf0e10cSrcweir {
1311cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this ); // update formula count
1312cdf0e10cSrcweir delete pCode;
1313cdf0e10cSrcweir pCode = new ScTokenArray( *pShared->GetCode() );
1314cdf0e10cSrcweir bRefChanged = sal_True;
1315cdf0e10cSrcweir pCode->Reset();
1316cdf0e10cSrcweir while( (t = static_cast<ScToken*>(pCode->GetNextReference())) != NULL )
1317cdf0e10cSrcweir {
1318cdf0e10cSrcweir if( t->GetType() != svIndex )
1319cdf0e10cSrcweir {
1320cdf0e10cSrcweir t->CalcAbsIfRel( aOldPos );
1321cdf0e10cSrcweir sal_Bool bMod;
1322cdf0e10cSrcweir { // own scope for SingleDoubleRefModifier dtor if SingleRef
1323cdf0e10cSrcweir SingleDoubleRefModifier aMod( *t );
1324cdf0e10cSrcweir ScComplexRefData& rRef = aMod.Ref();
1325cdf0e10cSrcweir bMod = (ScRefUpdate::UpdateTranspose( pDocument, rSource,
1326cdf0e10cSrcweir rDest, rRef ) != UR_NOTHING || bPosChanged);
1327cdf0e10cSrcweir }
1328cdf0e10cSrcweir if ( bMod )
1329cdf0e10cSrcweir t->CalcRelFromAbs( aPos );
1330cdf0e10cSrcweir }
1331cdf0e10cSrcweir }
1332cdf0e10cSrcweir }
1333cdf0e10cSrcweir
1334cdf0e10cSrcweir if (bRefChanged)
1335cdf0e10cSrcweir {
1336cdf0e10cSrcweir if (pUndoDoc)
1337cdf0e10cSrcweir {
1338cdf0e10cSrcweir ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aPos, pOld,
1339cdf0e10cSrcweir eTempGrammar, cMatrixFlag);
1340cdf0e10cSrcweir pFCell->aResult.SetToken( NULL); // to recognize it as changed later (Cut/Paste!)
1341cdf0e10cSrcweir pUndoDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pFCell );
1342cdf0e10cSrcweir }
1343cdf0e10cSrcweir
1344cdf0e10cSrcweir bCompile = sal_True;
1345cdf0e10cSrcweir CompileTokenArray(); // ruft auch StartListeningTo
1346cdf0e10cSrcweir SetDirty();
1347cdf0e10cSrcweir }
1348cdf0e10cSrcweir else
1349cdf0e10cSrcweir StartListeningTo( pDocument ); // Listener wie vorher
1350cdf0e10cSrcweir
1351cdf0e10cSrcweir delete pOld;
1352cdf0e10cSrcweir }
1353cdf0e10cSrcweir
UpdateGrow(const ScRange & rArea,SCCOL nGrowX,SCROW nGrowY)1354cdf0e10cSrcweir void ScFormulaCell::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1355cdf0e10cSrcweir {
1356cdf0e10cSrcweir EndListeningTo( pDocument );
1357cdf0e10cSrcweir
1358cdf0e10cSrcweir sal_Bool bRefChanged = sal_False;
1359cdf0e10cSrcweir ScToken* t;
1360cdf0e10cSrcweir ScRangeData* pShared = NULL;
1361cdf0e10cSrcweir
1362cdf0e10cSrcweir pCode->Reset();
1363cdf0e10cSrcweir while( (t = static_cast<ScToken*>(pCode->GetNextReferenceOrName())) != NULL )
1364cdf0e10cSrcweir {
1365cdf0e10cSrcweir if( t->GetOpCode() == ocName )
1366cdf0e10cSrcweir {
1367cdf0e10cSrcweir ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->GetIndex() );
1368cdf0e10cSrcweir if (pName)
1369cdf0e10cSrcweir {
1370cdf0e10cSrcweir if (pName->IsModified())
1371cdf0e10cSrcweir bRefChanged = sal_True;
1372cdf0e10cSrcweir if (pName->HasType(RT_SHAREDMOD))
1373cdf0e10cSrcweir pShared = pName;
1374cdf0e10cSrcweir }
1375cdf0e10cSrcweir }
1376cdf0e10cSrcweir else if( t->GetType() != svIndex )
1377cdf0e10cSrcweir {
1378cdf0e10cSrcweir t->CalcAbsIfRel( aPos );
1379cdf0e10cSrcweir sal_Bool bMod;
1380cdf0e10cSrcweir { // own scope for SingleDoubleRefModifier dtor if SingleRef
1381cdf0e10cSrcweir SingleDoubleRefModifier aMod( *t );
1382cdf0e10cSrcweir ScComplexRefData& rRef = aMod.Ref();
1383cdf0e10cSrcweir bMod = (ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY,
1384cdf0e10cSrcweir rRef ) != UR_NOTHING);
1385cdf0e10cSrcweir }
1386cdf0e10cSrcweir if ( bMod )
1387cdf0e10cSrcweir {
1388cdf0e10cSrcweir t->CalcRelFromAbs( aPos );
1389cdf0e10cSrcweir bRefChanged = sal_True;
1390cdf0e10cSrcweir }
1391cdf0e10cSrcweir }
1392cdf0e10cSrcweir }
1393cdf0e10cSrcweir
1394cdf0e10cSrcweir if (pShared) // Shared Formula gegen echte Formel austauschen
1395cdf0e10cSrcweir {
1396cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this ); // update formula count
1397cdf0e10cSrcweir delete pCode;
1398cdf0e10cSrcweir pCode = new ScTokenArray( *pShared->GetCode() );
1399cdf0e10cSrcweir bRefChanged = sal_True;
1400cdf0e10cSrcweir pCode->Reset();
1401cdf0e10cSrcweir while( (t = static_cast<ScToken*>(pCode->GetNextReference())) != NULL )
1402cdf0e10cSrcweir {
1403cdf0e10cSrcweir if( t->GetType() != svIndex )
1404cdf0e10cSrcweir {
1405cdf0e10cSrcweir t->CalcAbsIfRel( aPos );
1406cdf0e10cSrcweir sal_Bool bMod;
1407cdf0e10cSrcweir { // own scope for SingleDoubleRefModifier dtor if SingleRef
1408cdf0e10cSrcweir SingleDoubleRefModifier aMod( *t );
1409cdf0e10cSrcweir ScComplexRefData& rRef = aMod.Ref();
1410cdf0e10cSrcweir bMod = (ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY,
1411cdf0e10cSrcweir rRef ) != UR_NOTHING);
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir if ( bMod )
1414cdf0e10cSrcweir t->CalcRelFromAbs( aPos );
1415cdf0e10cSrcweir }
1416cdf0e10cSrcweir }
1417cdf0e10cSrcweir }
1418cdf0e10cSrcweir
1419cdf0e10cSrcweir if (bRefChanged)
1420cdf0e10cSrcweir {
1421cdf0e10cSrcweir bCompile = sal_True;
1422cdf0e10cSrcweir CompileTokenArray(); // ruft auch StartListeningTo
1423cdf0e10cSrcweir SetDirty();
1424cdf0e10cSrcweir }
1425cdf0e10cSrcweir else
1426cdf0e10cSrcweir StartListeningTo( pDocument ); // Listener wie vorher
1427cdf0e10cSrcweir }
1428cdf0e10cSrcweir
lcl_IsRangeNameInUse(sal_uInt16 nIndex,ScTokenArray * pCode,ScRangeName * pNames)1429cdf0e10cSrcweir sal_Bool lcl_IsRangeNameInUse(sal_uInt16 nIndex, ScTokenArray* pCode, ScRangeName* pNames)
1430cdf0e10cSrcweir {
1431cdf0e10cSrcweir for (FormulaToken* p = pCode->First(); p; p = pCode->Next())
1432cdf0e10cSrcweir {
1433cdf0e10cSrcweir if (p->GetOpCode() == ocName)
1434cdf0e10cSrcweir {
1435cdf0e10cSrcweir if (p->GetIndex() == nIndex)
1436cdf0e10cSrcweir return sal_True;
1437cdf0e10cSrcweir else
1438cdf0e10cSrcweir {
1439cdf0e10cSrcweir // RangeData kann Null sein in bestimmten Excel-Dateien (#31168#)
1440cdf0e10cSrcweir ScRangeData* pSubName = pNames->FindIndex(p->GetIndex());
1441cdf0e10cSrcweir if (pSubName && lcl_IsRangeNameInUse(nIndex,
1442cdf0e10cSrcweir pSubName->GetCode(), pNames))
1443cdf0e10cSrcweir return sal_True;
1444cdf0e10cSrcweir }
1445cdf0e10cSrcweir }
1446cdf0e10cSrcweir }
1447cdf0e10cSrcweir return sal_False;
1448cdf0e10cSrcweir }
1449cdf0e10cSrcweir
IsRangeNameInUse(sal_uInt16 nIndex) const1450cdf0e10cSrcweir sal_Bool ScFormulaCell::IsRangeNameInUse(sal_uInt16 nIndex) const
1451cdf0e10cSrcweir {
1452cdf0e10cSrcweir return lcl_IsRangeNameInUse( nIndex, pCode, pDocument->GetRangeName() );
1453cdf0e10cSrcweir }
1454cdf0e10cSrcweir
lcl_FindRangeNamesInUse(std::set<sal_uInt16> & rIndexes,ScTokenArray * pCode,ScRangeName * pNames)1455cdf0e10cSrcweir void lcl_FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes, ScTokenArray* pCode, ScRangeName* pNames)
1456cdf0e10cSrcweir {
1457cdf0e10cSrcweir for (FormulaToken* p = pCode->First(); p; p = pCode->Next())
1458cdf0e10cSrcweir {
1459cdf0e10cSrcweir if (p->GetOpCode() == ocName)
1460cdf0e10cSrcweir {
1461cdf0e10cSrcweir sal_uInt16 nTokenIndex = p->GetIndex();
1462cdf0e10cSrcweir rIndexes.insert( nTokenIndex );
1463cdf0e10cSrcweir
1464cdf0e10cSrcweir ScRangeData* pSubName = pNames->FindIndex(p->GetIndex());
1465cdf0e10cSrcweir if (pSubName)
1466cdf0e10cSrcweir lcl_FindRangeNamesInUse(rIndexes, pSubName->GetCode(), pNames);
1467cdf0e10cSrcweir }
1468cdf0e10cSrcweir }
1469cdf0e10cSrcweir }
1470cdf0e10cSrcweir
FindRangeNamesInUse(std::set<sal_uInt16> & rIndexes) const1471cdf0e10cSrcweir void ScFormulaCell::FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const
1472cdf0e10cSrcweir {
1473cdf0e10cSrcweir lcl_FindRangeNamesInUse( rIndexes, pCode, pDocument->GetRangeName() );
1474cdf0e10cSrcweir }
1475cdf0e10cSrcweir
ReplaceRangeNamesInUse(const ScRangeData::IndexMap & rMap)1476cdf0e10cSrcweir void ScFormulaCell::ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap )
1477cdf0e10cSrcweir {
1478cdf0e10cSrcweir for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1479cdf0e10cSrcweir {
1480cdf0e10cSrcweir if( p->GetOpCode() == ocName )
1481cdf0e10cSrcweir {
1482cdf0e10cSrcweir sal_uInt16 nIndex = p->GetIndex();
1483cdf0e10cSrcweir ScRangeData::IndexMap::const_iterator itr = rMap.find(nIndex);
1484cdf0e10cSrcweir sal_uInt16 nNewIndex = itr == rMap.end() ? nIndex : itr->second;
1485cdf0e10cSrcweir if ( nIndex != nNewIndex )
1486cdf0e10cSrcweir {
1487cdf0e10cSrcweir p->SetIndex( nNewIndex );
1488cdf0e10cSrcweir bCompile = sal_True;
1489cdf0e10cSrcweir }
1490cdf0e10cSrcweir }
1491cdf0e10cSrcweir }
1492cdf0e10cSrcweir if( bCompile )
1493cdf0e10cSrcweir CompileTokenArray();
1494cdf0e10cSrcweir }
1495cdf0e10cSrcweir
CompileDBFormula()1496cdf0e10cSrcweir void ScFormulaCell::CompileDBFormula()
1497cdf0e10cSrcweir {
1498cdf0e10cSrcweir for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1499cdf0e10cSrcweir {
1500cdf0e10cSrcweir if ( p->GetOpCode() == ocDBArea
1501cdf0e10cSrcweir || (p->GetOpCode() == ocName && p->GetIndex() >= SC_START_INDEX_DB_COLL) )
1502cdf0e10cSrcweir {
1503cdf0e10cSrcweir bCompile = sal_True;
1504cdf0e10cSrcweir CompileTokenArray();
1505cdf0e10cSrcweir SetDirty();
1506cdf0e10cSrcweir break;
1507cdf0e10cSrcweir }
1508cdf0e10cSrcweir }
1509cdf0e10cSrcweir }
1510cdf0e10cSrcweir
CompileDBFormula(sal_Bool bCreateFormulaString)1511cdf0e10cSrcweir void ScFormulaCell::CompileDBFormula( sal_Bool bCreateFormulaString )
1512cdf0e10cSrcweir {
1513cdf0e10cSrcweir // zwei Phasen, muessen (!) nacheinander aufgerufen werden:
1514cdf0e10cSrcweir // 1. FormelString mit alten Namen erzeugen
1515cdf0e10cSrcweir // 2. FormelString mit neuen Namen kompilieren
1516cdf0e10cSrcweir if ( bCreateFormulaString )
1517cdf0e10cSrcweir {
1518cdf0e10cSrcweir sal_Bool bRecompile = sal_False;
1519cdf0e10cSrcweir pCode->Reset();
1520cdf0e10cSrcweir for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
1521cdf0e10cSrcweir {
1522cdf0e10cSrcweir switch ( p->GetOpCode() )
1523cdf0e10cSrcweir {
1524cdf0e10cSrcweir case ocBad: // DB-Bereich evtl. zugefuegt
1525cdf0e10cSrcweir case ocColRowName: // #36762# falls Namensgleichheit
1526cdf0e10cSrcweir case ocDBArea: // DB-Bereich
1527cdf0e10cSrcweir bRecompile = sal_True;
1528cdf0e10cSrcweir break;
1529cdf0e10cSrcweir case ocName:
1530cdf0e10cSrcweir if ( p->GetIndex() >= SC_START_INDEX_DB_COLL )
1531cdf0e10cSrcweir bRecompile = sal_True; // DB-Bereich
1532cdf0e10cSrcweir break;
1533cdf0e10cSrcweir default:
1534cdf0e10cSrcweir ; // nothing
1535cdf0e10cSrcweir }
1536cdf0e10cSrcweir }
1537cdf0e10cSrcweir if ( bRecompile )
1538cdf0e10cSrcweir {
1539cdf0e10cSrcweir String aFormula;
1540cdf0e10cSrcweir GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1541cdf0e10cSrcweir if ( GetMatrixFlag() != MM_NONE && aFormula.Len() )
1542cdf0e10cSrcweir {
1543cdf0e10cSrcweir if ( aFormula.GetChar( aFormula.Len()-1 ) == '}' )
1544cdf0e10cSrcweir aFormula.Erase( aFormula.Len()-1 , 1 );
1545cdf0e10cSrcweir if ( aFormula.GetChar(0) == '{' )
1546cdf0e10cSrcweir aFormula.Erase( 0, 1 );
1547cdf0e10cSrcweir }
1548cdf0e10cSrcweir EndListeningTo( pDocument );
1549cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this );
1550cdf0e10cSrcweir pCode->Clear();
1551cdf0e10cSrcweir SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1552cdf0e10cSrcweir }
1553cdf0e10cSrcweir }
1554cdf0e10cSrcweir else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
1555cdf0e10cSrcweir {
1556cdf0e10cSrcweir Compile( aResult.GetHybridFormula(), sal_False, eTempGrammar );
1557cdf0e10cSrcweir aResult.SetToken( NULL);
1558cdf0e10cSrcweir SetDirty();
1559cdf0e10cSrcweir }
1560cdf0e10cSrcweir }
1561cdf0e10cSrcweir
CompileNameFormula(sal_Bool bCreateFormulaString)1562cdf0e10cSrcweir void ScFormulaCell::CompileNameFormula( sal_Bool bCreateFormulaString )
1563cdf0e10cSrcweir {
1564cdf0e10cSrcweir // zwei Phasen, muessen (!) nacheinander aufgerufen werden:
1565cdf0e10cSrcweir // 1. FormelString mit alten RangeNames erzeugen
1566cdf0e10cSrcweir // 2. FormelString mit neuen RangeNames kompilieren
1567cdf0e10cSrcweir if ( bCreateFormulaString )
1568cdf0e10cSrcweir {
1569cdf0e10cSrcweir sal_Bool bRecompile = sal_False;
1570cdf0e10cSrcweir pCode->Reset();
1571cdf0e10cSrcweir for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
1572cdf0e10cSrcweir {
1573cdf0e10cSrcweir switch ( p->GetOpCode() )
1574cdf0e10cSrcweir {
1575cdf0e10cSrcweir case ocBad: // RangeName evtl. zugefuegt
1576cdf0e10cSrcweir case ocColRowName: // #36762# falls Namensgleichheit
1577cdf0e10cSrcweir bRecompile = sal_True;
1578cdf0e10cSrcweir break;
1579cdf0e10cSrcweir default:
1580cdf0e10cSrcweir if ( p->GetType() == svIndex )
1581cdf0e10cSrcweir bRecompile = sal_True; // RangeName
1582cdf0e10cSrcweir }
1583cdf0e10cSrcweir }
1584cdf0e10cSrcweir if ( bRecompile )
1585cdf0e10cSrcweir {
1586cdf0e10cSrcweir String aFormula;
1587cdf0e10cSrcweir GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1588cdf0e10cSrcweir if ( GetMatrixFlag() != MM_NONE && aFormula.Len() )
1589cdf0e10cSrcweir {
1590cdf0e10cSrcweir if ( aFormula.GetChar( aFormula.Len()-1 ) == '}' )
1591cdf0e10cSrcweir aFormula.Erase( aFormula.Len()-1 , 1 );
1592cdf0e10cSrcweir if ( aFormula.GetChar(0) == '{' )
1593cdf0e10cSrcweir aFormula.Erase( 0, 1 );
1594cdf0e10cSrcweir }
1595cdf0e10cSrcweir EndListeningTo( pDocument );
1596cdf0e10cSrcweir pDocument->RemoveFromFormulaTree( this );
1597cdf0e10cSrcweir pCode->Clear();
1598cdf0e10cSrcweir SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
1599cdf0e10cSrcweir }
1600cdf0e10cSrcweir }
1601cdf0e10cSrcweir else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
1602cdf0e10cSrcweir {
1603cdf0e10cSrcweir Compile( aResult.GetHybridFormula(), sal_False, eTempGrammar );
1604cdf0e10cSrcweir aResult.SetToken( NULL);
1605cdf0e10cSrcweir SetDirty();
1606cdf0e10cSrcweir }
1607cdf0e10cSrcweir }
1608cdf0e10cSrcweir
CompileColRowNameFormula()1609cdf0e10cSrcweir void ScFormulaCell::CompileColRowNameFormula()
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir pCode->Reset();
1612cdf0e10cSrcweir for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
1613cdf0e10cSrcweir {
1614cdf0e10cSrcweir if ( p->GetOpCode() == ocColRowName )
1615cdf0e10cSrcweir {
1616cdf0e10cSrcweir bCompile = sal_True;
1617cdf0e10cSrcweir CompileTokenArray();
1618cdf0e10cSrcweir SetDirty();
1619cdf0e10cSrcweir break;
1620cdf0e10cSrcweir }
1621cdf0e10cSrcweir }
1622cdf0e10cSrcweir }
1623cdf0e10cSrcweir
1624cdf0e10cSrcweir // ============================================================================
1625cdf0e10cSrcweir
1626