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
31cdf0e10cSrcweir #include <svl/intitem.hxx>
32cdf0e10cSrcweir #include <svl/zforlist.hxx>
33cdf0e10cSrcweir #include <vcl/sound.hxx>
34cdf0e10cSrcweir #include <formula/token.hxx>
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include "document.hxx"
37cdf0e10cSrcweir #include "table.hxx"
38cdf0e10cSrcweir #include "globstr.hrc"
39cdf0e10cSrcweir #include "subtotal.hxx"
40cdf0e10cSrcweir #include "docoptio.hxx"
41cdf0e10cSrcweir #include "interpre.hxx"
42cdf0e10cSrcweir #include "markdata.hxx"
43cdf0e10cSrcweir #include "validat.hxx"
44cdf0e10cSrcweir #include "scitems.hxx"
45cdf0e10cSrcweir #include "stlpool.hxx"
46cdf0e10cSrcweir #include "poolhelp.hxx"
47cdf0e10cSrcweir #include "detdata.hxx"
48cdf0e10cSrcweir #include "patattr.hxx"
49cdf0e10cSrcweir #include "chgtrack.hxx"
50cdf0e10cSrcweir #include "progress.hxx"
51cdf0e10cSrcweir #include "paramisc.hxx"
52cdf0e10cSrcweir #include "compiler.hxx"
53cdf0e10cSrcweir #include "externalrefmgr.hxx"
54cdf0e10cSrcweir
55cdf0e10cSrcweir using namespace formula;
56cdf0e10cSrcweir
57cdf0e10cSrcweir // -----------------------------------------------------------------------
58cdf0e10cSrcweir
59cdf0e10cSrcweir // Nach der Regula Falsi Methode
Solver(SCCOL nFCol,SCROW nFRow,SCTAB nFTab,SCCOL nVCol,SCROW nVRow,SCTAB nVTab,const String & sValStr,double & nX)60cdf0e10cSrcweir sal_Bool ScDocument::Solver(SCCOL nFCol, SCROW nFRow, SCTAB nFTab,
61cdf0e10cSrcweir SCCOL nVCol, SCROW nVRow, SCTAB nVTab,
62cdf0e10cSrcweir const String& sValStr, double& nX)
63cdf0e10cSrcweir {
64cdf0e10cSrcweir sal_Bool bRet = sal_False;
65cdf0e10cSrcweir nX = 0.0;
66cdf0e10cSrcweir if (ValidColRow(nFCol, nFRow) && ValidColRow(nVCol, nVRow) &&
67cdf0e10cSrcweir VALIDTAB(nFTab) && VALIDTAB(nVTab) && pTab[nFTab] && pTab[nVTab])
68cdf0e10cSrcweir {
69cdf0e10cSrcweir CellType eFType, eVType;
70cdf0e10cSrcweir GetCellType(nFCol, nFRow, nFTab, eFType);
71cdf0e10cSrcweir GetCellType(nVCol, nVRow, nVTab, eVType);
72cdf0e10cSrcweir // CELLTYPE_NOTE: no value, but referenced by formula
73cdf0e10cSrcweir // #i108005# convert target value to number using default format,
74cdf0e10cSrcweir // as previously done in ScInterpreter::GetDouble
75cdf0e10cSrcweir double nTargetVal = 0.0;
76cdf0e10cSrcweir sal_uInt32 nFIndex = 0;
77cdf0e10cSrcweir if (eFType == CELLTYPE_FORMULA && (eVType == CELLTYPE_VALUE || eVType == CELLTYPE_NOTE) &&
78cdf0e10cSrcweir GetFormatTable()->IsNumberFormat(sValStr, nFIndex, nTargetVal))
79cdf0e10cSrcweir {
80cdf0e10cSrcweir ScSingleRefData aRefData;
81cdf0e10cSrcweir aRefData.InitFlags();
82cdf0e10cSrcweir aRefData.nCol = nVCol;
83cdf0e10cSrcweir aRefData.nRow = nVRow;
84cdf0e10cSrcweir aRefData.nTab = nVTab;
85cdf0e10cSrcweir
86cdf0e10cSrcweir ScTokenArray aArr;
87cdf0e10cSrcweir aArr.AddOpCode( ocBackSolver );
88cdf0e10cSrcweir aArr.AddOpCode( ocOpen );
89cdf0e10cSrcweir aArr.AddSingleReference( aRefData );
90cdf0e10cSrcweir aArr.AddOpCode( ocSep );
91cdf0e10cSrcweir
92cdf0e10cSrcweir aRefData.nCol = nFCol;
93cdf0e10cSrcweir aRefData.nRow = nFRow;
94cdf0e10cSrcweir aRefData.nTab = nFTab;
95cdf0e10cSrcweir
96cdf0e10cSrcweir aArr.AddSingleReference( aRefData );
97cdf0e10cSrcweir aArr.AddOpCode( ocSep );
98cdf0e10cSrcweir aArr.AddDouble( nTargetVal );
99cdf0e10cSrcweir aArr.AddOpCode( ocClose );
100cdf0e10cSrcweir aArr.AddOpCode( ocStop );
101cdf0e10cSrcweir
102cdf0e10cSrcweir ScFormulaCell* pCell = new ScFormulaCell( this, ScAddress(), &aArr );
103cdf0e10cSrcweir
104cdf0e10cSrcweir if (pCell)
105cdf0e10cSrcweir {
106cdf0e10cSrcweir // FIXME FIXME FIXME this might need to be reworked now that we have formula::FormulaErrorToken and ScFormulaResult, double check !!!
107cdf0e10cSrcweir DBG_ERRORFILE("ScDocument::Solver: -> ScFormulaCell::GetValueAlways might need reimplementation");
108cdf0e10cSrcweir pCell->Interpret();
109cdf0e10cSrcweir sal_uInt16 nErrCode = pCell->GetErrCode();
110cdf0e10cSrcweir nX = pCell->GetValueAlways();
111cdf0e10cSrcweir if (nErrCode == 0) // kein fehler beim Rechnen
112cdf0e10cSrcweir bRet = sal_True;
113cdf0e10cSrcweir delete pCell;
114cdf0e10cSrcweir }
115cdf0e10cSrcweir }
116cdf0e10cSrcweir }
117cdf0e10cSrcweir return bRet;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir
InsertMatrixFormula(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark,const String & rFormula,const ScTokenArray * pArr,const formula::FormulaGrammar::Grammar eGram)120cdf0e10cSrcweir void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
121cdf0e10cSrcweir SCCOL nCol2, SCROW nRow2,
122cdf0e10cSrcweir const ScMarkData& rMark,
123cdf0e10cSrcweir const String& rFormula,
124cdf0e10cSrcweir const ScTokenArray* pArr,
125cdf0e10cSrcweir const formula::FormulaGrammar::Grammar eGram )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir PutInOrder(nCol1, nCol2);
128cdf0e10cSrcweir PutInOrder(nRow1, nRow2);
129cdf0e10cSrcweir SCTAB i, nTab1;
130cdf0e10cSrcweir SCCOL j;
131cdf0e10cSrcweir SCROW k;
132cdf0e10cSrcweir i = 0;
133cdf0e10cSrcweir sal_Bool bStop = sal_False;
134cdf0e10cSrcweir while (i <= MAXTAB && !bStop) // erste markierte Tabelle finden
135cdf0e10cSrcweir {
136cdf0e10cSrcweir if (pTab[i] && rMark.GetTableSelect(i))
137cdf0e10cSrcweir bStop = sal_True;
138cdf0e10cSrcweir else
139cdf0e10cSrcweir i++;
140cdf0e10cSrcweir }
141cdf0e10cSrcweir nTab1 = i;
142cdf0e10cSrcweir if (i == MAXTAB + 1)
143cdf0e10cSrcweir {
144cdf0e10cSrcweir Sound::Beep();
145cdf0e10cSrcweir DBG_ERROR("ScDocument::InsertMatrixFormula Keine Tabelle markiert");
146cdf0e10cSrcweir return;
147cdf0e10cSrcweir }
148cdf0e10cSrcweir
149cdf0e10cSrcweir ScFormulaCell* pCell;
150cdf0e10cSrcweir ScAddress aPos( nCol1, nRow1, nTab1 );
151cdf0e10cSrcweir if (pArr)
152cdf0e10cSrcweir pCell = new ScFormulaCell( this, aPos, pArr, eGram, MM_FORMULA );
153cdf0e10cSrcweir else
154cdf0e10cSrcweir pCell = new ScFormulaCell( this, aPos, rFormula, eGram, MM_FORMULA );
155cdf0e10cSrcweir pCell->SetMatColsRows( nCol2 - nCol1 + 1, nRow2 - nRow1 + 1 );
156cdf0e10cSrcweir for (i = 0; i <= MAXTAB; i++)
157cdf0e10cSrcweir {
158cdf0e10cSrcweir if (pTab[i] && rMark.GetTableSelect(i))
159cdf0e10cSrcweir {
160cdf0e10cSrcweir if (i == nTab1)
161cdf0e10cSrcweir pTab[i]->PutCell(nCol1, nRow1, pCell);
162cdf0e10cSrcweir else
163cdf0e10cSrcweir pTab[i]->PutCell(nCol1, nRow1, pCell->CloneWithoutNote(*this, ScAddress( nCol1, nRow1, i), SC_CLONECELL_STARTLISTENING));
164cdf0e10cSrcweir }
165cdf0e10cSrcweir }
166cdf0e10cSrcweir
167cdf0e10cSrcweir ScSingleRefData aRefData;
168cdf0e10cSrcweir aRefData.InitFlags();
169cdf0e10cSrcweir aRefData.nCol = nCol1;
170cdf0e10cSrcweir aRefData.nRow = nRow1;
171cdf0e10cSrcweir aRefData.nTab = nTab1;
172cdf0e10cSrcweir aRefData.SetColRel( sal_True );
173cdf0e10cSrcweir aRefData.SetRowRel( sal_True );
174cdf0e10cSrcweir aRefData.SetTabRel( sal_True );
175cdf0e10cSrcweir aRefData.CalcRelFromAbs( ScAddress( nCol1, nRow1, nTab1 ) );
176cdf0e10cSrcweir
177cdf0e10cSrcweir ScTokenArray aArr;
178cdf0e10cSrcweir ScToken* t = static_cast<ScToken*>(aArr.AddMatrixSingleReference( aRefData));
179cdf0e10cSrcweir
180cdf0e10cSrcweir for (i = 0; i <= MAXTAB; i++)
181cdf0e10cSrcweir {
182cdf0e10cSrcweir if (pTab[i] && rMark.GetTableSelect(i))
183cdf0e10cSrcweir {
184cdf0e10cSrcweir pTab[i]->DoColResize( nCol1, nCol2, static_cast<SCSIZE>(nRow2 - nRow1 + 1) );
185cdf0e10cSrcweir if (i != nTab1)
186cdf0e10cSrcweir {
187cdf0e10cSrcweir aRefData.nTab = i;
188cdf0e10cSrcweir aRefData.nRelTab = i - nTab1;
189cdf0e10cSrcweir t->GetSingleRef() = aRefData;
190cdf0e10cSrcweir }
191cdf0e10cSrcweir for (j = nCol1; j <= nCol2; j++)
192cdf0e10cSrcweir {
193cdf0e10cSrcweir for (k = nRow1; k <= nRow2; k++)
194cdf0e10cSrcweir {
195cdf0e10cSrcweir if (j != nCol1 || k != nRow1) // nicht in der ersten Zelle
196cdf0e10cSrcweir {
197cdf0e10cSrcweir // Array muss geklont werden, damit jede
198cdf0e10cSrcweir // Zelle ein eigenes Array erhaelt!
199cdf0e10cSrcweir aPos = ScAddress( j, k, i );
200cdf0e10cSrcweir t->CalcRelFromAbs( aPos );
201cdf0e10cSrcweir pCell = new ScFormulaCell( this, aPos, aArr.Clone(), eGram, MM_REFERENCE );
202cdf0e10cSrcweir pTab[i]->PutCell(j, k, (ScBaseCell*) pCell);
203cdf0e10cSrcweir }
204cdf0e10cSrcweir }
205cdf0e10cSrcweir }
206cdf0e10cSrcweir }
207cdf0e10cSrcweir }
208cdf0e10cSrcweir }
209cdf0e10cSrcweir
InsertTableOp(const ScTabOpParam & rParam,SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScMarkData & rMark)210cdf0e10cSrcweir void ScDocument::InsertTableOp(const ScTabOpParam& rParam, // Mehrfachoperation
211cdf0e10cSrcweir SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
212cdf0e10cSrcweir const ScMarkData& rMark)
213cdf0e10cSrcweir {
214cdf0e10cSrcweir PutInOrder(nCol1, nCol2);
215cdf0e10cSrcweir PutInOrder(nRow1, nRow2);
216cdf0e10cSrcweir SCTAB i, nTab1;
217cdf0e10cSrcweir SCCOL j;
218cdf0e10cSrcweir SCROW k;
219cdf0e10cSrcweir i = 0;
220cdf0e10cSrcweir sal_Bool bStop = sal_False;
221cdf0e10cSrcweir while (i <= MAXTAB && !bStop) // erste markierte Tabelle finden
222cdf0e10cSrcweir {
223cdf0e10cSrcweir if (pTab[i] && rMark.GetTableSelect(i))
224cdf0e10cSrcweir bStop = sal_True;
225cdf0e10cSrcweir else
226cdf0e10cSrcweir i++;
227cdf0e10cSrcweir }
228cdf0e10cSrcweir nTab1 = i;
229cdf0e10cSrcweir if (i == MAXTAB + 1)
230cdf0e10cSrcweir {
231cdf0e10cSrcweir Sound::Beep();
232cdf0e10cSrcweir DBG_ERROR("ScDocument::InsertTableOp: Keine Tabelle markiert");
233cdf0e10cSrcweir return;
234cdf0e10cSrcweir }
235cdf0e10cSrcweir
236cdf0e10cSrcweir ScRefAddress aRef;
237cdf0e10cSrcweir String aForString = '=';
238cdf0e10cSrcweir aForString += ScCompiler::GetNativeSymbol(ocTableOp);
239cdf0e10cSrcweir aForString += ScCompiler::GetNativeSymbol( ocOpen);
240cdf0e10cSrcweir
241cdf0e10cSrcweir const String& sSep = ScCompiler::GetNativeSymbol( ocSep);
242cdf0e10cSrcweir if (rParam.nMode == 0) // nur Spalte
243cdf0e10cSrcweir {
244cdf0e10cSrcweir aRef.Set( rParam.aRefFormulaCell.GetAddress(), sal_True, sal_False, sal_False );
245cdf0e10cSrcweir aForString += aRef.GetRefString(this, nTab1);
246cdf0e10cSrcweir aForString += sSep;
247cdf0e10cSrcweir aForString += rParam.aRefColCell.GetRefString(this, nTab1);
248cdf0e10cSrcweir aForString += sSep;
249cdf0e10cSrcweir aRef.Set( nCol1, nRow1, nTab1, sal_False, sal_True, sal_True );
250cdf0e10cSrcweir aForString += aRef.GetRefString(this, nTab1);
251cdf0e10cSrcweir nCol1++;
252cdf0e10cSrcweir nCol2 = Min( nCol2, (SCCOL)(rParam.aRefFormulaEnd.Col() -
253cdf0e10cSrcweir rParam.aRefFormulaCell.Col() + nCol1 + 1));
254cdf0e10cSrcweir }
255cdf0e10cSrcweir else if (rParam.nMode == 1) // nur zeilenweise
256cdf0e10cSrcweir {
257cdf0e10cSrcweir aRef.Set( rParam.aRefFormulaCell.GetAddress(), sal_False, sal_True, sal_False );
258cdf0e10cSrcweir aForString += aRef.GetRefString(this, nTab1);
259cdf0e10cSrcweir aForString += sSep;
260cdf0e10cSrcweir aForString += rParam.aRefRowCell.GetRefString(this, nTab1);
261cdf0e10cSrcweir aForString += sSep;
262cdf0e10cSrcweir aRef.Set( nCol1, nRow1, nTab1, sal_True, sal_False, sal_True );
263cdf0e10cSrcweir aForString += aRef.GetRefString(this, nTab1);
264cdf0e10cSrcweir nRow1++;
265cdf0e10cSrcweir nRow2 = Min( nRow2, (SCROW)(rParam.aRefFormulaEnd.Row() -
266cdf0e10cSrcweir rParam.aRefFormulaCell.Row() + nRow1 + 1));
267cdf0e10cSrcweir }
268cdf0e10cSrcweir else // beides
269cdf0e10cSrcweir {
270cdf0e10cSrcweir aForString += rParam.aRefFormulaCell.GetRefString(this, nTab1);
271cdf0e10cSrcweir aForString += sSep;
272cdf0e10cSrcweir aForString += rParam.aRefColCell.GetRefString(this, nTab1);
273cdf0e10cSrcweir aForString += sSep;
274cdf0e10cSrcweir aRef.Set( nCol1, nRow1 + 1, nTab1, sal_False, sal_True, sal_True );
275cdf0e10cSrcweir aForString += aRef.GetRefString(this, nTab1);
276cdf0e10cSrcweir aForString += sSep;
277cdf0e10cSrcweir aForString += rParam.aRefRowCell.GetRefString(this, nTab1);
278cdf0e10cSrcweir aForString += sSep;
279cdf0e10cSrcweir aRef.Set( nCol1 + 1, nRow1, nTab1, sal_True, sal_False, sal_True );
280cdf0e10cSrcweir aForString += aRef.GetRefString(this, nTab1);
281cdf0e10cSrcweir nCol1++; nRow1++;
282cdf0e10cSrcweir }
283cdf0e10cSrcweir aForString += ScCompiler::GetNativeSymbol( ocClose);
284cdf0e10cSrcweir
285cdf0e10cSrcweir ScFormulaCell aRefCell( this, ScAddress( nCol1, nRow1, nTab1 ), aForString,
286cdf0e10cSrcweir formula::FormulaGrammar::GRAM_NATIVE, MM_NONE );
287cdf0e10cSrcweir for( j = nCol1; j <= nCol2; j++ )
288cdf0e10cSrcweir for( k = nRow1; k <= nRow2; k++ )
289cdf0e10cSrcweir for (i = 0; i <= MAXTAB; i++)
290cdf0e10cSrcweir if( pTab[i] && rMark.GetTableSelect(i) )
291cdf0e10cSrcweir pTab[i]->PutCell( j, k, aRefCell.CloneWithoutNote( *this, ScAddress( j, k, i ), SC_CLONECELL_STARTLISTENING ) );
292cdf0e10cSrcweir }
293cdf0e10cSrcweir
MarkUsedExternalReferences(ScTokenArray & rArr)294cdf0e10cSrcweir bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr )
295cdf0e10cSrcweir {
296cdf0e10cSrcweir bool bAllMarked = false;
297cdf0e10cSrcweir if (rArr.GetLen())
298cdf0e10cSrcweir {
299cdf0e10cSrcweir ScExternalRefManager* pRefMgr = NULL;
300cdf0e10cSrcweir rArr.Reset();
301cdf0e10cSrcweir ScToken* t;
302cdf0e10cSrcweir while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL)
303cdf0e10cSrcweir {
304cdf0e10cSrcweir if (t->GetOpCode() == ocExternalRef)
305cdf0e10cSrcweir {
306cdf0e10cSrcweir if (!pRefMgr)
307cdf0e10cSrcweir pRefMgr = GetExternalRefManager();
308cdf0e10cSrcweir switch (t->GetType())
309cdf0e10cSrcweir {
310cdf0e10cSrcweir case svExternalSingleRef:
311cdf0e10cSrcweir bAllMarked = pRefMgr->setCacheTableReferenced(
312cdf0e10cSrcweir t->GetIndex(), t->GetString(), 1);
313cdf0e10cSrcweir break;
314cdf0e10cSrcweir case svExternalDoubleRef:
315cdf0e10cSrcweir {
316cdf0e10cSrcweir const ScComplexRefData& rRef = t->GetDoubleRef();
317cdf0e10cSrcweir size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1;
318cdf0e10cSrcweir bAllMarked = pRefMgr->setCacheTableReferenced(
319cdf0e10cSrcweir t->GetIndex(), t->GetString(), nSheets);
320cdf0e10cSrcweir }
321cdf0e10cSrcweir break;
322cdf0e10cSrcweir case svExternalName:
323cdf0e10cSrcweir /* TODO: external names aren't supported yet, but would
324cdf0e10cSrcweir * have to be marked as well, if so. Mechanism would be
325cdf0e10cSrcweir * different. */
326cdf0e10cSrcweir DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!");
327cdf0e10cSrcweir break;
328cdf0e10cSrcweir default: break;
329cdf0e10cSrcweir }
330cdf0e10cSrcweir }
331cdf0e10cSrcweir }
332cdf0e10cSrcweir }
333cdf0e10cSrcweir return bAllMarked;
334cdf0e10cSrcweir }
335cdf0e10cSrcweir
GetNextSpellingCell(SCCOL & nCol,SCROW & nRow,SCTAB nTab,sal_Bool bInSel,const ScMarkData & rMark) const336cdf0e10cSrcweir sal_Bool ScDocument::GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab,
337cdf0e10cSrcweir sal_Bool bInSel, const ScMarkData& rMark) const
338cdf0e10cSrcweir {
339cdf0e10cSrcweir if (ValidTab(nTab) && pTab[nTab])
340cdf0e10cSrcweir return pTab[nTab]->GetNextSpellingCell( nCol, nRow, bInSel, rMark );
341cdf0e10cSrcweir else
342cdf0e10cSrcweir return sal_False;
343cdf0e10cSrcweir }
344cdf0e10cSrcweir
GetNextMarkedCell(SCCOL & rCol,SCROW & rRow,SCTAB nTab,const ScMarkData & rMark)345cdf0e10cSrcweir sal_Bool ScDocument::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, SCTAB nTab,
346cdf0e10cSrcweir const ScMarkData& rMark )
347cdf0e10cSrcweir {
348cdf0e10cSrcweir if (ValidTab(nTab) && pTab[nTab])
349cdf0e10cSrcweir return pTab[nTab]->GetNextMarkedCell( rCol, rRow, rMark );
350cdf0e10cSrcweir else
351cdf0e10cSrcweir return sal_False;
352cdf0e10cSrcweir }
353cdf0e10cSrcweir
ReplaceStyle(const SvxSearchItem & rSearchItem,SCCOL nCol,SCROW nRow,SCTAB nTab,ScMarkData & rMark,sal_Bool bIsUndoP)354cdf0e10cSrcweir sal_Bool ScDocument::ReplaceStyle(const SvxSearchItem& rSearchItem,
355cdf0e10cSrcweir SCCOL nCol, SCROW nRow, SCTAB nTab,
356cdf0e10cSrcweir ScMarkData& rMark,
357cdf0e10cSrcweir sal_Bool bIsUndoP)
358cdf0e10cSrcweir {
359cdf0e10cSrcweir if (pTab[nTab])
360cdf0e10cSrcweir return pTab[nTab]->ReplaceStyle(rSearchItem, nCol, nRow, rMark, bIsUndoP);
361cdf0e10cSrcweir else
362cdf0e10cSrcweir return sal_False;
363cdf0e10cSrcweir }
364cdf0e10cSrcweir
CompileDBFormula()365cdf0e10cSrcweir void ScDocument::CompileDBFormula()
366cdf0e10cSrcweir {
367cdf0e10cSrcweir for (SCTAB i=0; i<=MAXTAB; i++)
368cdf0e10cSrcweir {
369cdf0e10cSrcweir if (pTab[i]) pTab[i]->CompileDBFormula();
370cdf0e10cSrcweir }
371cdf0e10cSrcweir }
372cdf0e10cSrcweir
CompileDBFormula(sal_Bool bCreateFormulaString)373cdf0e10cSrcweir void ScDocument::CompileDBFormula( sal_Bool bCreateFormulaString )
374cdf0e10cSrcweir {
375cdf0e10cSrcweir for (SCTAB i=0; i<=MAXTAB; i++)
376cdf0e10cSrcweir {
377cdf0e10cSrcweir if (pTab[i]) pTab[i]->CompileDBFormula( bCreateFormulaString );
378cdf0e10cSrcweir }
379cdf0e10cSrcweir }
380cdf0e10cSrcweir
CompileNameFormula(sal_Bool bCreateFormulaString)381cdf0e10cSrcweir void ScDocument::CompileNameFormula( sal_Bool bCreateFormulaString )
382cdf0e10cSrcweir {
383cdf0e10cSrcweir if ( pCondFormList )
384cdf0e10cSrcweir pCondFormList->CompileAll(); // nach ScNameDlg noetig
385cdf0e10cSrcweir
386cdf0e10cSrcweir for (SCTAB i=0; i<=MAXTAB; i++)
387cdf0e10cSrcweir {
388cdf0e10cSrcweir if (pTab[i]) pTab[i]->CompileNameFormula( bCreateFormulaString );
389cdf0e10cSrcweir }
390cdf0e10cSrcweir }
391cdf0e10cSrcweir
CompileColRowNameFormula()392cdf0e10cSrcweir void ScDocument::CompileColRowNameFormula()
393cdf0e10cSrcweir {
394cdf0e10cSrcweir for (SCTAB i=0; i<=MAXTAB; i++)
395cdf0e10cSrcweir {
396cdf0e10cSrcweir if (pTab[i]) pTab[i]->CompileColRowNameFormula();
397cdf0e10cSrcweir }
398cdf0e10cSrcweir }
399cdf0e10cSrcweir
DoColResize(SCTAB nTab,SCCOL nCol1,SCCOL nCol2,SCSIZE nAdd)400cdf0e10cSrcweir void ScDocument::DoColResize( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd )
401cdf0e10cSrcweir {
402cdf0e10cSrcweir if (ValidTab(nTab) && pTab[nTab])
403cdf0e10cSrcweir pTab[nTab]->DoColResize( nCol1, nCol2, nAdd );
404cdf0e10cSrcweir else
405cdf0e10cSrcweir {
406cdf0e10cSrcweir DBG_ERROR("DoColResize: falsche Tabelle");
407cdf0e10cSrcweir }
408cdf0e10cSrcweir }
409cdf0e10cSrcweir
InvalidateTableArea()410cdf0e10cSrcweir void ScDocument::InvalidateTableArea()
411cdf0e10cSrcweir {
412cdf0e10cSrcweir for (SCTAB nTab=0; nTab<=MAXTAB && pTab[nTab]; nTab++)
413cdf0e10cSrcweir {
414cdf0e10cSrcweir pTab[nTab]->InvalidateTableArea();
415cdf0e10cSrcweir if ( pTab[nTab]->IsScenario() )
416cdf0e10cSrcweir pTab[nTab]->InvalidateScenarioRanges();
417cdf0e10cSrcweir }
418cdf0e10cSrcweir }
419cdf0e10cSrcweir
GetLastAttrCell(SCTAB nTab,SCCOL & rEndCol,SCROW & rEndRow) const420*557cb412SWang Lei void ScDocument::GetLastAttrCell( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
421*557cb412SWang Lei {
422*557cb412SWang Lei if ( ValidTab( nTab ) && pTab[nTab] )
423*557cb412SWang Lei {
424*557cb412SWang Lei pTab[nTab]->GetLastAttrCell( rEndCol, rEndRow );
425*557cb412SWang Lei }
426*557cb412SWang Lei }
427*557cb412SWang Lei
GetMaxStringLen(SCTAB nTab,SCCOL nCol,SCROW nRowStart,SCROW nRowEnd,CharSet eCharSet) const428cdf0e10cSrcweir sal_Int32 ScDocument::GetMaxStringLen( SCTAB nTab, SCCOL nCol,
429cdf0e10cSrcweir SCROW nRowStart, SCROW nRowEnd, CharSet eCharSet ) const
430cdf0e10cSrcweir {
431cdf0e10cSrcweir if (ValidTab(nTab) && pTab[nTab])
432cdf0e10cSrcweir return pTab[nTab]->GetMaxStringLen( nCol, nRowStart, nRowEnd, eCharSet );
433cdf0e10cSrcweir else
434cdf0e10cSrcweir return 0;
435cdf0e10cSrcweir }
436cdf0e10cSrcweir
GetMaxNumberStringLen(sal_uInt16 & nPrecision,SCTAB nTab,SCCOL nCol,SCROW nRowStart,SCROW nRowEnd) const437cdf0e10cSrcweir xub_StrLen ScDocument::GetMaxNumberStringLen( sal_uInt16& nPrecision, SCTAB nTab,
438cdf0e10cSrcweir SCCOL nCol,
439cdf0e10cSrcweir SCROW nRowStart, SCROW nRowEnd ) const
440cdf0e10cSrcweir {
441cdf0e10cSrcweir if (ValidTab(nTab) && pTab[nTab])
442cdf0e10cSrcweir return pTab[nTab]->GetMaxNumberStringLen( nPrecision, nCol,
443cdf0e10cSrcweir nRowStart, nRowEnd );
444cdf0e10cSrcweir else
445cdf0e10cSrcweir return 0;
446cdf0e10cSrcweir }
447cdf0e10cSrcweir
GetSelectionFunction(ScSubTotalFunc eFunc,const ScAddress & rCursor,const ScMarkData & rMark,double & rResult)448cdf0e10cSrcweir sal_Bool ScDocument::GetSelectionFunction( ScSubTotalFunc eFunc,
449cdf0e10cSrcweir const ScAddress& rCursor, const ScMarkData& rMark,
450cdf0e10cSrcweir double& rResult )
451cdf0e10cSrcweir {
452cdf0e10cSrcweir ScFunctionData aData(eFunc);
453cdf0e10cSrcweir
454cdf0e10cSrcweir ScRange aSingle( rCursor );
455cdf0e10cSrcweir if ( rMark.IsMarked() )
456cdf0e10cSrcweir rMark.GetMarkArea(aSingle);
457cdf0e10cSrcweir
458cdf0e10cSrcweir SCCOL nStartCol = aSingle.aStart.Col();
459cdf0e10cSrcweir SCROW nStartRow = aSingle.aStart.Row();
460cdf0e10cSrcweir SCCOL nEndCol = aSingle.aEnd.Col();
461cdf0e10cSrcweir SCROW nEndRow = aSingle.aEnd.Row();
462cdf0e10cSrcweir
463cdf0e10cSrcweir for (SCTAB nTab=0; nTab<=MAXTAB && !aData.bError; nTab++)
464cdf0e10cSrcweir if (pTab[nTab] && rMark.GetTableSelect(nTab))
465cdf0e10cSrcweir pTab[nTab]->UpdateSelectionFunction( aData,
466cdf0e10cSrcweir nStartCol, nStartRow, nEndCol, nEndRow, rMark );
467cdf0e10cSrcweir
468cdf0e10cSrcweir //! rMark an UpdateSelectionFunction uebergeben !!!!!
469cdf0e10cSrcweir
470cdf0e10cSrcweir if (!aData.bError)
471cdf0e10cSrcweir switch (eFunc)
472cdf0e10cSrcweir {
473cdf0e10cSrcweir case SUBTOTAL_FUNC_SUM:
474cdf0e10cSrcweir rResult = aData.nVal;
475cdf0e10cSrcweir break;
476cdf0e10cSrcweir case SUBTOTAL_FUNC_CNT:
477cdf0e10cSrcweir case SUBTOTAL_FUNC_CNT2:
478cdf0e10cSrcweir rResult = aData.nCount;
479cdf0e10cSrcweir break;
480cdf0e10cSrcweir case SUBTOTAL_FUNC_AVE:
481cdf0e10cSrcweir if (aData.nCount)
482cdf0e10cSrcweir rResult = aData.nVal / (double) aData.nCount;
483cdf0e10cSrcweir else
484cdf0e10cSrcweir aData.bError = sal_True;
485cdf0e10cSrcweir break;
486cdf0e10cSrcweir case SUBTOTAL_FUNC_MAX:
487cdf0e10cSrcweir case SUBTOTAL_FUNC_MIN:
488cdf0e10cSrcweir if (aData.nCount)
489cdf0e10cSrcweir rResult = aData.nVal;
490cdf0e10cSrcweir else
491cdf0e10cSrcweir aData.bError = sal_True;
492cdf0e10cSrcweir break;
493cdf0e10cSrcweir default:
494cdf0e10cSrcweir {
495cdf0e10cSrcweir // added to avoid warnings
496cdf0e10cSrcweir }
497cdf0e10cSrcweir }
498cdf0e10cSrcweir
499cdf0e10cSrcweir if (aData.bError)
500cdf0e10cSrcweir rResult = 0.0;
501cdf0e10cSrcweir
502cdf0e10cSrcweir return !aData.bError;
503cdf0e10cSrcweir }
504cdf0e10cSrcweir
RoundValueAsShown(double fVal,sal_uLong nFormat)505cdf0e10cSrcweir double ScDocument::RoundValueAsShown( double fVal, sal_uLong nFormat )
506cdf0e10cSrcweir {
507cdf0e10cSrcweir short nType;
508cdf0e10cSrcweir if ( (nType = GetFormatTable()->GetType( nFormat )) != NUMBERFORMAT_DATE
509cdf0e10cSrcweir && nType != NUMBERFORMAT_TIME && nType != NUMBERFORMAT_DATETIME )
510cdf0e10cSrcweir {
511cdf0e10cSrcweir short nPrecision;
512cdf0e10cSrcweir if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
513cdf0e10cSrcweir {
514cdf0e10cSrcweir nPrecision = (short)GetFormatTable()->GetFormatPrecision( nFormat );
515cdf0e10cSrcweir switch ( nType )
516cdf0e10cSrcweir {
517cdf0e10cSrcweir case NUMBERFORMAT_PERCENT: // 0,41% == 0,0041
518cdf0e10cSrcweir nPrecision += 2;
519cdf0e10cSrcweir break;
520cdf0e10cSrcweir case NUMBERFORMAT_SCIENTIFIC: // 1,23e-3 == 0,00123
521cdf0e10cSrcweir {
522cdf0e10cSrcweir if ( fVal > 0.0 )
523cdf0e10cSrcweir nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( fVal ) ) );
524cdf0e10cSrcweir else if ( fVal < 0.0 )
525cdf0e10cSrcweir nPrecision = sal::static_int_cast<short>( nPrecision - (short)floor( log10( -fVal ) ) );
526cdf0e10cSrcweir break;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir }
529cdf0e10cSrcweir }
530cdf0e10cSrcweir else
531cdf0e10cSrcweir {
532cdf0e10cSrcweir nPrecision = (short)GetDocOptions().GetStdPrecision();
533cdf0e10cSrcweir // #i115512# no rounding for automatic decimals
534cdf0e10cSrcweir if (nPrecision == static_cast<short>(SvNumberFormatter::UNLIMITED_PRECISION))
535cdf0e10cSrcweir return fVal;
536cdf0e10cSrcweir }
537cdf0e10cSrcweir double fRound = ::rtl::math::round( fVal, nPrecision );
538cdf0e10cSrcweir if ( ::rtl::math::approxEqual( fVal, fRound ) )
539cdf0e10cSrcweir return fVal; // durch Rundung hoechstens Fehler
540cdf0e10cSrcweir else
541cdf0e10cSrcweir return fRound;
542cdf0e10cSrcweir }
543cdf0e10cSrcweir else
544cdf0e10cSrcweir return fVal;
545cdf0e10cSrcweir }
546cdf0e10cSrcweir
547cdf0e10cSrcweir //
548cdf0e10cSrcweir // bedingte Formate und Gueltigkeitsbereiche
549cdf0e10cSrcweir //
550cdf0e10cSrcweir
AddCondFormat(const ScConditionalFormat & rNew)551cdf0e10cSrcweir sal_uLong ScDocument::AddCondFormat( const ScConditionalFormat& rNew )
552cdf0e10cSrcweir {
553cdf0e10cSrcweir if (rNew.IsEmpty())
554cdf0e10cSrcweir return 0; // leer ist immer 0
555cdf0e10cSrcweir
556cdf0e10cSrcweir if (!pCondFormList)
557cdf0e10cSrcweir pCondFormList = new ScConditionalFormatList;
558cdf0e10cSrcweir
559cdf0e10cSrcweir sal_uLong nMax = 0;
560cdf0e10cSrcweir sal_uInt16 nCount = pCondFormList->Count();
561cdf0e10cSrcweir for (sal_uInt16 i=0; i<nCount; i++)
562cdf0e10cSrcweir {
563cdf0e10cSrcweir const ScConditionalFormat* pForm = (*pCondFormList)[i];
564cdf0e10cSrcweir sal_uLong nKey = pForm->GetKey();
565cdf0e10cSrcweir if ( pForm->EqualEntries( rNew ) )
566cdf0e10cSrcweir return nKey;
567cdf0e10cSrcweir if ( nKey > nMax )
568cdf0e10cSrcweir nMax = nKey;
569cdf0e10cSrcweir }
570cdf0e10cSrcweir
571cdf0e10cSrcweir // Der Aufruf kann aus ScPatternAttr::PutInPool kommen, darum Clone (echte Kopie)
572cdf0e10cSrcweir
573cdf0e10cSrcweir sal_uLong nNewKey = nMax + 1;
574cdf0e10cSrcweir ScConditionalFormat* pInsert = rNew.Clone(this);
575cdf0e10cSrcweir pInsert->SetKey( nNewKey );
576cdf0e10cSrcweir pCondFormList->InsertNew( pInsert );
577cdf0e10cSrcweir return nNewKey;
578cdf0e10cSrcweir }
579cdf0e10cSrcweir
AddValidationEntry(const ScValidationData & rNew)580cdf0e10cSrcweir sal_uLong ScDocument::AddValidationEntry( const ScValidationData& rNew )
581cdf0e10cSrcweir {
582cdf0e10cSrcweir if (rNew.IsEmpty())
583cdf0e10cSrcweir return 0; // leer ist immer 0
584cdf0e10cSrcweir
585cdf0e10cSrcweir if (!pValidationList)
586cdf0e10cSrcweir pValidationList = new ScValidationDataList;
587cdf0e10cSrcweir
588cdf0e10cSrcweir sal_uLong nMax = 0;
589cdf0e10cSrcweir sal_uInt16 nCount = pValidationList->Count();
590cdf0e10cSrcweir for (sal_uInt16 i=0; i<nCount; i++)
591cdf0e10cSrcweir {
592cdf0e10cSrcweir const ScValidationData* pData = (*pValidationList)[i];
593cdf0e10cSrcweir sal_uLong nKey = pData->GetKey();
594cdf0e10cSrcweir if ( pData->EqualEntries( rNew ) )
595cdf0e10cSrcweir return nKey;
596cdf0e10cSrcweir if ( nKey > nMax )
597cdf0e10cSrcweir nMax = nKey;
598cdf0e10cSrcweir }
599cdf0e10cSrcweir
600cdf0e10cSrcweir // Der Aufruf kann aus ScPatternAttr::PutInPool kommen, darum Clone (echte Kopie)
601cdf0e10cSrcweir
602cdf0e10cSrcweir sal_uLong nNewKey = nMax + 1;
603cdf0e10cSrcweir ScValidationData* pInsert = rNew.Clone(this);
604cdf0e10cSrcweir pInsert->SetKey( nNewKey );
605cdf0e10cSrcweir pValidationList->InsertNew( pInsert );
606cdf0e10cSrcweir return nNewKey;
607cdf0e10cSrcweir }
608cdf0e10cSrcweir
GetEffItem(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_uInt16 nWhich) const609cdf0e10cSrcweir const SfxPoolItem* ScDocument::GetEffItem(
610cdf0e10cSrcweir SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
611cdf0e10cSrcweir {
612cdf0e10cSrcweir const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
613cdf0e10cSrcweir if ( pPattern )
614cdf0e10cSrcweir {
615cdf0e10cSrcweir const SfxItemSet& rSet = pPattern->GetItemSet();
616cdf0e10cSrcweir const SfxPoolItem* pItem;
617cdf0e10cSrcweir if ( rSet.GetItemState( ATTR_CONDITIONAL, sal_True, &pItem ) == SFX_ITEM_SET )
618cdf0e10cSrcweir {
619cdf0e10cSrcweir sal_uLong nIndex = ((const SfxUInt32Item*)pItem)->GetValue();
620cdf0e10cSrcweir if (nIndex && pCondFormList)
621cdf0e10cSrcweir {
622cdf0e10cSrcweir const ScConditionalFormat* pForm = pCondFormList->GetFormat( nIndex );
623cdf0e10cSrcweir if ( pForm )
624cdf0e10cSrcweir {
625cdf0e10cSrcweir ScBaseCell* pCell = ((ScDocument*)this)->GetCell(ScAddress(nCol,nRow,nTab));
626cdf0e10cSrcweir String aStyle = pForm->GetCellStyle( pCell, ScAddress(nCol, nRow, nTab) );
627cdf0e10cSrcweir if (aStyle.Len())
628cdf0e10cSrcweir {
629cdf0e10cSrcweir SfxStyleSheetBase* pStyleSheet = xPoolHelper->GetStylePool()->Find(
630cdf0e10cSrcweir aStyle, SFX_STYLE_FAMILY_PARA );
631cdf0e10cSrcweir if ( pStyleSheet && pStyleSheet->GetItemSet().GetItemState(
632cdf0e10cSrcweir nWhich, sal_True, &pItem ) == SFX_ITEM_SET )
633cdf0e10cSrcweir return pItem;
634cdf0e10cSrcweir }
635cdf0e10cSrcweir }
636cdf0e10cSrcweir }
637cdf0e10cSrcweir }
638cdf0e10cSrcweir return &rSet.Get( nWhich );
639cdf0e10cSrcweir }
640cdf0e10cSrcweir DBG_ERROR("kein Pattern");
641cdf0e10cSrcweir return NULL;
642cdf0e10cSrcweir }
643cdf0e10cSrcweir
GetCondResult(SCCOL nCol,SCROW nRow,SCTAB nTab) const644cdf0e10cSrcweir const SfxItemSet* ScDocument::GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
645cdf0e10cSrcweir {
646cdf0e10cSrcweir const ScConditionalFormat* pForm = GetCondFormat( nCol, nRow, nTab );
647cdf0e10cSrcweir if ( pForm )
648cdf0e10cSrcweir {
649cdf0e10cSrcweir ScBaseCell* pCell = ((ScDocument*)this)->GetCell(ScAddress(nCol,nRow,nTab));
650cdf0e10cSrcweir String aStyle = pForm->GetCellStyle( pCell, ScAddress(nCol, nRow, nTab) );
651cdf0e10cSrcweir if (aStyle.Len())
652cdf0e10cSrcweir {
653cdf0e10cSrcweir SfxStyleSheetBase* pStyleSheet = xPoolHelper->GetStylePool()->Find( aStyle, SFX_STYLE_FAMILY_PARA );
654cdf0e10cSrcweir if ( pStyleSheet )
655cdf0e10cSrcweir return &pStyleSheet->GetItemSet();
656cdf0e10cSrcweir // if style is not there, treat like no condition
657cdf0e10cSrcweir }
658cdf0e10cSrcweir }
659cdf0e10cSrcweir return NULL;
660cdf0e10cSrcweir }
661cdf0e10cSrcweir
GetCondFormat(SCCOL nCol,SCROW nRow,SCTAB nTab) const662cdf0e10cSrcweir const ScConditionalFormat* ScDocument::GetCondFormat(
663cdf0e10cSrcweir SCCOL nCol, SCROW nRow, SCTAB nTab ) const
664cdf0e10cSrcweir {
665cdf0e10cSrcweir sal_uLong nIndex = ((const SfxUInt32Item*)GetAttr(nCol,nRow,nTab,ATTR_CONDITIONAL))->GetValue();
666cdf0e10cSrcweir if (nIndex)
667cdf0e10cSrcweir {
668cdf0e10cSrcweir if (pCondFormList)
669cdf0e10cSrcweir return pCondFormList->GetFormat( nIndex );
670cdf0e10cSrcweir else
671cdf0e10cSrcweir {
672cdf0e10cSrcweir DBG_ERROR("pCondFormList ist 0");
673cdf0e10cSrcweir }
674cdf0e10cSrcweir }
675cdf0e10cSrcweir
676cdf0e10cSrcweir return NULL;
677cdf0e10cSrcweir }
678cdf0e10cSrcweir
GetValidationEntry(sal_uLong nIndex) const679cdf0e10cSrcweir const ScValidationData* ScDocument::GetValidationEntry( sal_uLong nIndex ) const
680cdf0e10cSrcweir {
681cdf0e10cSrcweir if ( pValidationList )
682cdf0e10cSrcweir return pValidationList->GetData( nIndex );
683cdf0e10cSrcweir else
684cdf0e10cSrcweir return NULL;
685cdf0e10cSrcweir }
686cdf0e10cSrcweir
FindConditionalFormat(sal_uLong nKey,ScRangeList & rRanges)687cdf0e10cSrcweir void ScDocument::FindConditionalFormat( sal_uLong nKey, ScRangeList& rRanges )
688cdf0e10cSrcweir {
689cdf0e10cSrcweir for (SCTAB i=0; i<=MAXTAB && pTab[i]; i++)
690cdf0e10cSrcweir pTab[i]->FindConditionalFormat( nKey, rRanges );
691cdf0e10cSrcweir }
692cdf0e10cSrcweir
FindConditionalFormat(sal_uLong nKey,ScRangeList & rRanges,SCTAB nTab)693cdf0e10cSrcweir void ScDocument::FindConditionalFormat( sal_uLong nKey, ScRangeList& rRanges, SCTAB nTab )
694cdf0e10cSrcweir {
695cdf0e10cSrcweir if(VALIDTAB(nTab) && pTab[nTab])
696cdf0e10cSrcweir pTab[nTab]->FindConditionalFormat( nKey, rRanges );
697cdf0e10cSrcweir }
698cdf0e10cSrcweir
ConditionalChanged(sal_uLong nKey)699cdf0e10cSrcweir void ScDocument::ConditionalChanged( sal_uLong nKey )
700cdf0e10cSrcweir {
701cdf0e10cSrcweir if ( nKey && pCondFormList && !bIsClip && !bIsUndo ) // nKey==0 -> noop
702cdf0e10cSrcweir {
703cdf0e10cSrcweir ScConditionalFormat* pForm = pCondFormList->GetFormat( nKey );
704cdf0e10cSrcweir if (pForm)
705cdf0e10cSrcweir pForm->InvalidateArea();
706cdf0e10cSrcweir }
707cdf0e10cSrcweir }
708cdf0e10cSrcweir
SetCondFormList(ScConditionalFormatList * pNew)709cdf0e10cSrcweir void ScDocument::SetCondFormList(ScConditionalFormatList* pNew)
710cdf0e10cSrcweir {
711cdf0e10cSrcweir if (pCondFormList)
712cdf0e10cSrcweir {
713cdf0e10cSrcweir pCondFormList->DeleteAndDestroy( 0, pCondFormList->Count() );
714cdf0e10cSrcweir delete pCondFormList;
715cdf0e10cSrcweir }
716cdf0e10cSrcweir
717cdf0e10cSrcweir pCondFormList = pNew;
718cdf0e10cSrcweir }
719cdf0e10cSrcweir
720cdf0e10cSrcweir //------------------------------------------------------------------------
721cdf0e10cSrcweir
HasDetectiveOperations() const722cdf0e10cSrcweir sal_Bool ScDocument::HasDetectiveOperations() const
723cdf0e10cSrcweir {
724cdf0e10cSrcweir return pDetOpList && pDetOpList->Count();
725cdf0e10cSrcweir }
726cdf0e10cSrcweir
AddDetectiveOperation(const ScDetOpData & rData)727cdf0e10cSrcweir void ScDocument::AddDetectiveOperation( const ScDetOpData& rData )
728cdf0e10cSrcweir {
729cdf0e10cSrcweir if (!pDetOpList)
730cdf0e10cSrcweir pDetOpList = new ScDetOpList;
731cdf0e10cSrcweir
732cdf0e10cSrcweir pDetOpList->Append( new ScDetOpData( rData ) );
733cdf0e10cSrcweir }
734cdf0e10cSrcweir
ClearDetectiveOperations()735cdf0e10cSrcweir void ScDocument::ClearDetectiveOperations()
736cdf0e10cSrcweir {
737cdf0e10cSrcweir delete pDetOpList; // loescht auch die Eintraege
738cdf0e10cSrcweir pDetOpList = NULL;
739cdf0e10cSrcweir }
740cdf0e10cSrcweir
SetDetOpList(ScDetOpList * pNew)741cdf0e10cSrcweir void ScDocument::SetDetOpList(ScDetOpList* pNew)
742cdf0e10cSrcweir {
743cdf0e10cSrcweir delete pDetOpList; // loescht auch die Eintraege
744cdf0e10cSrcweir pDetOpList = pNew;
745cdf0e10cSrcweir }
746cdf0e10cSrcweir
747cdf0e10cSrcweir //------------------------------------------------------------------------
748cdf0e10cSrcweir //
749cdf0e10cSrcweir // Vergleich von Dokumenten
750cdf0e10cSrcweir //
751cdf0e10cSrcweir //------------------------------------------------------------------------
752cdf0e10cSrcweir
753cdf0e10cSrcweir // Pfriemel-Faktoren
754cdf0e10cSrcweir #define SC_DOCCOMP_MAXDIFF 256
755cdf0e10cSrcweir #define SC_DOCCOMP_MINGOOD 128
756cdf0e10cSrcweir #define SC_DOCCOMP_COLUMNS 10
757cdf0e10cSrcweir #define SC_DOCCOMP_ROWS 100
758cdf0e10cSrcweir
759cdf0e10cSrcweir
RowDifferences(SCROW nThisRow,SCTAB nThisTab,ScDocument & rOtherDoc,SCROW nOtherRow,SCTAB nOtherTab,SCCOL nMaxCol,SCCOLROW * pOtherCols)760cdf0e10cSrcweir sal_uInt16 ScDocument::RowDifferences( SCROW nThisRow, SCTAB nThisTab,
761cdf0e10cSrcweir ScDocument& rOtherDoc, SCROW nOtherRow, SCTAB nOtherTab,
762cdf0e10cSrcweir SCCOL nMaxCol, SCCOLROW* pOtherCols )
763cdf0e10cSrcweir {
764cdf0e10cSrcweir sal_uLong nDif = 0;
765cdf0e10cSrcweir sal_uLong nUsed = 0;
766cdf0e10cSrcweir for (SCCOL nThisCol=0; nThisCol<=nMaxCol; nThisCol++)
767cdf0e10cSrcweir {
768cdf0e10cSrcweir SCCOL nOtherCol;
769cdf0e10cSrcweir if ( pOtherCols )
770cdf0e10cSrcweir nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
771cdf0e10cSrcweir else
772cdf0e10cSrcweir nOtherCol = nThisCol;
773cdf0e10cSrcweir
774cdf0e10cSrcweir if (ValidCol(nOtherCol)) // nur Spalten vergleichen, die in beiden Dateien sind
775cdf0e10cSrcweir {
776cdf0e10cSrcweir const ScBaseCell* pThisCell = GetCell( ScAddress( nThisCol, nThisRow, nThisTab ) );
777cdf0e10cSrcweir const ScBaseCell* pOtherCell = rOtherDoc.GetCell( ScAddress( nOtherCol, nOtherRow, nOtherTab ) );
778cdf0e10cSrcweir if (!ScBaseCell::CellEqual( pThisCell, pOtherCell ))
779cdf0e10cSrcweir {
780cdf0e10cSrcweir if ( pThisCell && pOtherCell )
781cdf0e10cSrcweir nDif += 3;
782cdf0e10cSrcweir else
783cdf0e10cSrcweir nDif += 4; // Inhalt <-> leer zaehlt mehr
784cdf0e10cSrcweir }
785cdf0e10cSrcweir
786cdf0e10cSrcweir if ( ( pThisCell && pThisCell->GetCellType()!=CELLTYPE_NOTE ) ||
787cdf0e10cSrcweir ( pOtherCell && pOtherCell->GetCellType()!=CELLTYPE_NOTE ) )
788cdf0e10cSrcweir ++nUsed;
789cdf0e10cSrcweir }
790cdf0e10cSrcweir }
791cdf0e10cSrcweir
792cdf0e10cSrcweir if (nUsed > 0)
793cdf0e10cSrcweir return static_cast<sal_uInt16>((nDif*64)/nUsed); // max.256 (SC_DOCCOMP_MAXDIFF)
794cdf0e10cSrcweir
795cdf0e10cSrcweir DBG_ASSERT(!nDif,"Diff ohne Used");
796cdf0e10cSrcweir return 0;
797cdf0e10cSrcweir }
798cdf0e10cSrcweir
ColDifferences(SCCOL nThisCol,SCTAB nThisTab,ScDocument & rOtherDoc,SCCOL nOtherCol,SCTAB nOtherTab,SCROW nMaxRow,SCCOLROW * pOtherRows)799cdf0e10cSrcweir sal_uInt16 ScDocument::ColDifferences( SCCOL nThisCol, SCTAB nThisTab,
800cdf0e10cSrcweir ScDocument& rOtherDoc, SCCOL nOtherCol, SCTAB nOtherTab,
801cdf0e10cSrcweir SCROW nMaxRow, SCCOLROW* pOtherRows )
802cdf0e10cSrcweir {
803cdf0e10cSrcweir //! optimieren mit Iterator oder so
804cdf0e10cSrcweir
805cdf0e10cSrcweir sal_uLong nDif = 0;
806cdf0e10cSrcweir sal_uLong nUsed = 0;
807cdf0e10cSrcweir for (SCROW nThisRow=0; nThisRow<=nMaxRow; nThisRow++)
808cdf0e10cSrcweir {
809cdf0e10cSrcweir SCROW nOtherRow;
810cdf0e10cSrcweir if ( pOtherRows )
811cdf0e10cSrcweir nOtherRow = pOtherRows[nThisRow];
812cdf0e10cSrcweir else
813cdf0e10cSrcweir nOtherRow = nThisRow;
814cdf0e10cSrcweir
815cdf0e10cSrcweir if (ValidRow(nOtherRow)) // nur Zeilen vergleichen, die in beiden Dateien sind
816cdf0e10cSrcweir {
817cdf0e10cSrcweir const ScBaseCell* pThisCell = GetCell( ScAddress( nThisCol, nThisRow, nThisTab ) );
818cdf0e10cSrcweir const ScBaseCell* pOtherCell = rOtherDoc.GetCell( ScAddress( nOtherCol, nOtherRow, nOtherTab ) );
819cdf0e10cSrcweir if (!ScBaseCell::CellEqual( pThisCell, pOtherCell ))
820cdf0e10cSrcweir {
821cdf0e10cSrcweir if ( pThisCell && pOtherCell )
822cdf0e10cSrcweir nDif += 3;
823cdf0e10cSrcweir else
824cdf0e10cSrcweir nDif += 4; // Inhalt <-> leer zaehlt mehr
825cdf0e10cSrcweir }
826cdf0e10cSrcweir
827cdf0e10cSrcweir if ( ( pThisCell && pThisCell->GetCellType()!=CELLTYPE_NOTE ) ||
828cdf0e10cSrcweir ( pOtherCell && pOtherCell->GetCellType()!=CELLTYPE_NOTE ) )
829cdf0e10cSrcweir ++nUsed;
830cdf0e10cSrcweir }
831cdf0e10cSrcweir }
832cdf0e10cSrcweir
833cdf0e10cSrcweir if (nUsed > 0)
834cdf0e10cSrcweir return static_cast<sal_uInt16>((nDif*64)/nUsed); // max.256
835cdf0e10cSrcweir
836cdf0e10cSrcweir DBG_ASSERT(!nDif,"Diff ohne Used");
837cdf0e10cSrcweir return 0;
838cdf0e10cSrcweir }
839cdf0e10cSrcweir
FindOrder(SCCOLROW * pOtherRows,SCCOLROW nThisEndRow,SCCOLROW nOtherEndRow,sal_Bool bColumns,ScDocument & rOtherDoc,SCTAB nThisTab,SCTAB nOtherTab,SCCOLROW nEndCol,SCCOLROW * pTranslate,ScProgress * pProgress,sal_uLong nProAdd)840cdf0e10cSrcweir void ScDocument::FindOrder( SCCOLROW* pOtherRows, SCCOLROW nThisEndRow, SCCOLROW nOtherEndRow,
841cdf0e10cSrcweir sal_Bool bColumns, ScDocument& rOtherDoc, SCTAB nThisTab, SCTAB nOtherTab,
842cdf0e10cSrcweir SCCOLROW nEndCol, SCCOLROW* pTranslate, ScProgress* pProgress, sal_uLong nProAdd )
843cdf0e10cSrcweir {
844cdf0e10cSrcweir // bColumns=sal_True: Zeilen sind Spalten und umgekehrt
845cdf0e10cSrcweir
846cdf0e10cSrcweir SCCOLROW nMaxCont; // wieviel weiter
847cdf0e10cSrcweir SCCOLROW nMinGood; // was ist ein Treffer (incl.)
848cdf0e10cSrcweir if ( bColumns )
849cdf0e10cSrcweir {
850cdf0e10cSrcweir nMaxCont = SC_DOCCOMP_COLUMNS; // 10 Spalten
851cdf0e10cSrcweir nMinGood = SC_DOCCOMP_MINGOOD;
852cdf0e10cSrcweir //! Extra Durchgang mit nMinGood = 0 ????
853cdf0e10cSrcweir }
854cdf0e10cSrcweir else
855cdf0e10cSrcweir {
856cdf0e10cSrcweir nMaxCont = SC_DOCCOMP_ROWS; // 100 Zeilen
857cdf0e10cSrcweir nMinGood = SC_DOCCOMP_MINGOOD;
858cdf0e10cSrcweir }
859cdf0e10cSrcweir sal_Bool bUseTotal = bColumns && !pTranslate; // nur beim ersten Durchgang
860cdf0e10cSrcweir
861cdf0e10cSrcweir
862cdf0e10cSrcweir SCCOLROW nOtherRow = 0;
863cdf0e10cSrcweir sal_uInt16 nComp;
864cdf0e10cSrcweir SCCOLROW nThisRow;
865cdf0e10cSrcweir sal_Bool bTotal = sal_False; // ueber verschiedene nThisRow beibehalten
866cdf0e10cSrcweir SCCOLROW nUnknown = 0;
867cdf0e10cSrcweir for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
868cdf0e10cSrcweir {
869cdf0e10cSrcweir SCCOLROW nTempOther = nOtherRow;
870cdf0e10cSrcweir sal_Bool bFound = sal_False;
871cdf0e10cSrcweir sal_uInt16 nBest = SC_DOCCOMP_MAXDIFF;
872cdf0e10cSrcweir SCCOLROW nMax = Min( nOtherEndRow, static_cast<SCCOLROW>(( nTempOther + nMaxCont + nUnknown )) );
873cdf0e10cSrcweir for (SCCOLROW i=nTempOther; i<=nMax && nBest>0; i++) // bei 0 abbrechen
874cdf0e10cSrcweir {
875cdf0e10cSrcweir if (bColumns)
876cdf0e10cSrcweir nComp = ColDifferences( static_cast<SCCOL>(nThisRow), nThisTab, rOtherDoc, static_cast<SCCOL>(i), nOtherTab, nEndCol, pTranslate );
877cdf0e10cSrcweir else
878cdf0e10cSrcweir nComp = RowDifferences( nThisRow, nThisTab, rOtherDoc, i, nOtherTab, static_cast<SCCOL>(nEndCol), pTranslate );
879cdf0e10cSrcweir if ( nComp < nBest && ( nComp <= nMinGood || bTotal ) )
880cdf0e10cSrcweir {
881cdf0e10cSrcweir nTempOther = i;
882cdf0e10cSrcweir nBest = nComp;
883cdf0e10cSrcweir bFound = sal_True;
884cdf0e10cSrcweir }
885cdf0e10cSrcweir if ( nComp < SC_DOCCOMP_MAXDIFF || bFound )
886cdf0e10cSrcweir bTotal = sal_False;
887cdf0e10cSrcweir else if ( i == nTempOther && bUseTotal )
888cdf0e10cSrcweir bTotal = sal_True; // nur ganz oben
889cdf0e10cSrcweir }
890cdf0e10cSrcweir if ( bFound )
891cdf0e10cSrcweir {
892cdf0e10cSrcweir pOtherRows[nThisRow] = nTempOther;
893cdf0e10cSrcweir nOtherRow = nTempOther + 1;
894cdf0e10cSrcweir nUnknown = 0;
895cdf0e10cSrcweir }
896cdf0e10cSrcweir else
897cdf0e10cSrcweir {
898cdf0e10cSrcweir pOtherRows[nThisRow] = SCROW_MAX;
899cdf0e10cSrcweir ++nUnknown;
900cdf0e10cSrcweir }
901cdf0e10cSrcweir
902cdf0e10cSrcweir if (pProgress)
903cdf0e10cSrcweir pProgress->SetStateOnPercent(nProAdd+static_cast<sal_uLong>(nThisRow));
904cdf0e10cSrcweir }
905cdf0e10cSrcweir
906cdf0e10cSrcweir // Bloecke ohne Uebereinstimmung ausfuellen
907cdf0e10cSrcweir
908cdf0e10cSrcweir SCROW nFillStart = 0;
909cdf0e10cSrcweir SCROW nFillPos = 0;
910cdf0e10cSrcweir sal_Bool bInFill = sal_False;
911cdf0e10cSrcweir for (nThisRow = 0; nThisRow <= nThisEndRow+1; nThisRow++)
912cdf0e10cSrcweir {
913cdf0e10cSrcweir SCROW nThisOther = ( nThisRow <= nThisEndRow ) ? pOtherRows[nThisRow] : (nOtherEndRow+1);
914cdf0e10cSrcweir if ( ValidRow(nThisOther) )
915cdf0e10cSrcweir {
916cdf0e10cSrcweir if ( bInFill )
917cdf0e10cSrcweir {
918cdf0e10cSrcweir if ( nThisOther > nFillStart ) // ist was zu verteilen da?
919cdf0e10cSrcweir {
920cdf0e10cSrcweir SCROW nDiff1 = nThisOther - nFillStart;
921cdf0e10cSrcweir SCROW nDiff2 = nThisRow - nFillPos;
922cdf0e10cSrcweir SCROW nMinDiff = Min(nDiff1, nDiff2);
923cdf0e10cSrcweir for (SCROW i=0; i<nMinDiff; i++)
924cdf0e10cSrcweir pOtherRows[nFillPos+i] = nFillStart+i;
925cdf0e10cSrcweir }
926cdf0e10cSrcweir
927cdf0e10cSrcweir bInFill = sal_False;
928cdf0e10cSrcweir }
929cdf0e10cSrcweir nFillStart = nThisOther + 1;
930cdf0e10cSrcweir nFillPos = nThisRow + 1;
931cdf0e10cSrcweir }
932cdf0e10cSrcweir else
933cdf0e10cSrcweir bInFill = sal_True;
934cdf0e10cSrcweir }
935cdf0e10cSrcweir }
936cdf0e10cSrcweir
CompareDocument(ScDocument & rOtherDoc)937cdf0e10cSrcweir void ScDocument::CompareDocument( ScDocument& rOtherDoc )
938cdf0e10cSrcweir {
939cdf0e10cSrcweir if (!pChangeTrack)
940cdf0e10cSrcweir return;
941cdf0e10cSrcweir
942cdf0e10cSrcweir SCTAB nThisCount = GetTableCount();
943cdf0e10cSrcweir SCTAB nOtherCount = rOtherDoc.GetTableCount();
944cdf0e10cSrcweir SCTAB* pOtherTabs = new SCTAB[nThisCount];
945cdf0e10cSrcweir SCTAB nThisTab;
946cdf0e10cSrcweir
947cdf0e10cSrcweir // Tabellen mit gleichen Namen vergleichen
948cdf0e10cSrcweir String aThisName;
949cdf0e10cSrcweir String aOtherName;
950cdf0e10cSrcweir for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
951cdf0e10cSrcweir {
952cdf0e10cSrcweir SCTAB nOtherTab = SCTAB_MAX;
953cdf0e10cSrcweir if (!IsScenario(nThisTab)) // Szenarien weglassen
954cdf0e10cSrcweir {
955cdf0e10cSrcweir GetName( nThisTab, aThisName );
956cdf0e10cSrcweir for (SCTAB nTemp=0; nTemp<nOtherCount && nOtherTab>MAXTAB; nTemp++)
957cdf0e10cSrcweir if (!rOtherDoc.IsScenario(nTemp))
958cdf0e10cSrcweir {
959cdf0e10cSrcweir rOtherDoc.GetName( nTemp, aOtherName );
960cdf0e10cSrcweir if ( aThisName == aOtherName )
961cdf0e10cSrcweir nOtherTab = nTemp;
962cdf0e10cSrcweir }
963cdf0e10cSrcweir }
964cdf0e10cSrcweir pOtherTabs[nThisTab] = nOtherTab;
965cdf0e10cSrcweir }
966cdf0e10cSrcweir // auffuellen, damit einzeln umbenannte Tabellen nicht wegfallen
967cdf0e10cSrcweir SCTAB nFillStart = 0;
968cdf0e10cSrcweir SCTAB nFillPos = 0;
969cdf0e10cSrcweir sal_Bool bInFill = sal_False;
970cdf0e10cSrcweir for (nThisTab = 0; nThisTab <= nThisCount; nThisTab++)
971cdf0e10cSrcweir {
972cdf0e10cSrcweir SCTAB nThisOther = ( nThisTab < nThisCount ) ? pOtherTabs[nThisTab] : nOtherCount;
973cdf0e10cSrcweir if ( ValidTab(nThisOther) )
974cdf0e10cSrcweir {
975cdf0e10cSrcweir if ( bInFill )
976cdf0e10cSrcweir {
977cdf0e10cSrcweir if ( nThisOther > nFillStart ) // ist was zu verteilen da?
978cdf0e10cSrcweir {
979cdf0e10cSrcweir SCTAB nDiff1 = nThisOther - nFillStart;
980cdf0e10cSrcweir SCTAB nDiff2 = nThisTab - nFillPos;
981cdf0e10cSrcweir SCTAB nMinDiff = Min(nDiff1, nDiff2);
982cdf0e10cSrcweir for (SCTAB i=0; i<nMinDiff; i++)
983cdf0e10cSrcweir if ( !IsScenario(nFillPos+i) && !rOtherDoc.IsScenario(nFillStart+i) )
984cdf0e10cSrcweir pOtherTabs[nFillPos+i] = nFillStart+i;
985cdf0e10cSrcweir }
986cdf0e10cSrcweir
987cdf0e10cSrcweir bInFill = sal_False;
988cdf0e10cSrcweir }
989cdf0e10cSrcweir nFillStart = nThisOther + 1;
990cdf0e10cSrcweir nFillPos = nThisTab + 1;
991cdf0e10cSrcweir }
992cdf0e10cSrcweir else
993cdf0e10cSrcweir bInFill = sal_True;
994cdf0e10cSrcweir }
995cdf0e10cSrcweir
996cdf0e10cSrcweir //
997cdf0e10cSrcweir // Tabellen in der gefundenen Reihenfolge vergleichen
998cdf0e10cSrcweir //
999cdf0e10cSrcweir
1000cdf0e10cSrcweir for (nThisTab=0; nThisTab<nThisCount; nThisTab++)
1001cdf0e10cSrcweir {
1002cdf0e10cSrcweir SCTAB nOtherTab = pOtherTabs[nThisTab];
1003cdf0e10cSrcweir if ( ValidTab(nOtherTab) )
1004cdf0e10cSrcweir {
1005cdf0e10cSrcweir SCCOL nThisEndCol = 0;
1006cdf0e10cSrcweir SCROW nThisEndRow = 0;
1007cdf0e10cSrcweir SCCOL nOtherEndCol = 0;
1008cdf0e10cSrcweir SCROW nOtherEndRow = 0;
1009cdf0e10cSrcweir GetCellArea( nThisTab, nThisEndCol, nThisEndRow );
1010cdf0e10cSrcweir rOtherDoc.GetCellArea( nOtherTab, nOtherEndCol, nOtherEndRow );
1011cdf0e10cSrcweir SCCOL nEndCol = Max(nThisEndCol, nOtherEndCol);
1012cdf0e10cSrcweir SCROW nEndRow = Max(nThisEndRow, nOtherEndRow);
1013cdf0e10cSrcweir SCCOL nThisCol;
1014cdf0e10cSrcweir SCROW nThisRow;
1015cdf0e10cSrcweir sal_uLong n1,n2; // fuer AppendDeleteRange
1016cdf0e10cSrcweir
1017cdf0e10cSrcweir //! ein Progress ueber alle Tabellen ???
1018cdf0e10cSrcweir String aTabName;
1019cdf0e10cSrcweir GetName( nThisTab, aTabName );
1020cdf0e10cSrcweir String aTemplate = ScGlobal::GetRscString(STR_PROGRESS_COMPARING);
1021cdf0e10cSrcweir String aProText = aTemplate.GetToken( 0, '#' );
1022cdf0e10cSrcweir aProText += aTabName;
1023cdf0e10cSrcweir aProText += aTemplate.GetToken( 1, '#' );
1024cdf0e10cSrcweir ScProgress aProgress( GetDocumentShell(),
1025cdf0e10cSrcweir aProText, 3*nThisEndRow ); // 2x FindOrder, 1x hier
1026cdf0e10cSrcweir long nProgressStart = 2*nThisEndRow; // start fuer hier
1027cdf0e10cSrcweir
1028cdf0e10cSrcweir SCCOLROW* pTempRows = new SCCOLROW[nThisEndRow+1];
1029cdf0e10cSrcweir SCCOLROW* pOtherRows = new SCCOLROW[nThisEndRow+1];
1030cdf0e10cSrcweir SCCOLROW* pOtherCols = new SCCOLROW[nThisEndCol+1];
1031cdf0e10cSrcweir
1032cdf0e10cSrcweir // eingefuegte/geloeschte Spalten/Zeilen finden:
1033cdf0e10cSrcweir // Zwei Versuche:
1034cdf0e10cSrcweir // 1) Original Zeilen vergleichen (pTempRows)
1035cdf0e10cSrcweir // 2) Original Spalten vergleichen (pOtherCols)
1036cdf0e10cSrcweir // mit dieser Spaltenreihenfolge Zeilen vergleichen (pOtherRows)
1037cdf0e10cSrcweir
1038cdf0e10cSrcweir //! Spalten vergleichen zweimal mit unterschiedlichem nMinGood ???
1039cdf0e10cSrcweir
1040cdf0e10cSrcweir // 1
1041cdf0e10cSrcweir FindOrder( pTempRows, nThisEndRow, nOtherEndRow, sal_False,
1042cdf0e10cSrcweir rOtherDoc, nThisTab, nOtherTab, nEndCol, NULL, &aProgress, 0 );
1043cdf0e10cSrcweir // 2
1044cdf0e10cSrcweir FindOrder( pOtherCols, nThisEndCol, nOtherEndCol, sal_True,
1045cdf0e10cSrcweir rOtherDoc, nThisTab, nOtherTab, nEndRow, NULL, NULL, 0 );
1046cdf0e10cSrcweir FindOrder( pOtherRows, nThisEndRow, nOtherEndRow, sal_False,
1047cdf0e10cSrcweir rOtherDoc, nThisTab, nOtherTab, nThisEndCol,
1048cdf0e10cSrcweir pOtherCols, &aProgress, nThisEndRow );
1049cdf0e10cSrcweir
1050cdf0e10cSrcweir sal_uLong nMatch1 = 0; // pTempRows, keine Spalten
1051cdf0e10cSrcweir for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
1052cdf0e10cSrcweir if (ValidRow(pTempRows[nThisRow]))
1053cdf0e10cSrcweir nMatch1 += SC_DOCCOMP_MAXDIFF -
1054cdf0e10cSrcweir RowDifferences( nThisRow, nThisTab, rOtherDoc, pTempRows[nThisRow],
1055cdf0e10cSrcweir nOtherTab, nEndCol, NULL );
1056cdf0e10cSrcweir
1057cdf0e10cSrcweir sal_uLong nMatch2 = 0; // pOtherRows, pOtherCols
1058cdf0e10cSrcweir for (nThisRow = 0; nThisRow<=nThisEndRow; nThisRow++)
1059cdf0e10cSrcweir if (ValidRow(pOtherRows[nThisRow]))
1060cdf0e10cSrcweir nMatch2 += SC_DOCCOMP_MAXDIFF -
1061cdf0e10cSrcweir RowDifferences( nThisRow, nThisTab, rOtherDoc, pOtherRows[nThisRow],
1062cdf0e10cSrcweir nOtherTab, nThisEndCol, pOtherCols );
1063cdf0e10cSrcweir
1064cdf0e10cSrcweir if ( nMatch1 >= nMatch2 ) // ohne Spalten ?
1065cdf0e10cSrcweir {
1066cdf0e10cSrcweir // Spalten zuruecksetzen
1067cdf0e10cSrcweir for (nThisCol = 0; nThisCol<=nThisEndCol; nThisCol++)
1068cdf0e10cSrcweir pOtherCols[nThisCol] = nThisCol;
1069cdf0e10cSrcweir
1070cdf0e10cSrcweir // Zeilenarrays vertauschen (geloescht werden sowieso beide)
1071cdf0e10cSrcweir SCCOLROW* pSwap = pTempRows;
1072cdf0e10cSrcweir pTempRows = pOtherRows;
1073cdf0e10cSrcweir pOtherRows = pSwap;
1074cdf0e10cSrcweir }
1075cdf0e10cSrcweir else
1076cdf0e10cSrcweir {
1077cdf0e10cSrcweir // bleibt bei pOtherCols, pOtherRows
1078cdf0e10cSrcweir }
1079cdf0e10cSrcweir
1080cdf0e10cSrcweir
1081cdf0e10cSrcweir // Change-Actions erzeugen
1082cdf0e10cSrcweir // 1) Spalten von rechts
1083cdf0e10cSrcweir // 2) Zeilen von unten
1084cdf0e10cSrcweir // 3) einzelne Zellen in normaler Reihenfolge
1085cdf0e10cSrcweir
1086cdf0e10cSrcweir // Actions fuer eingefuegte/geloeschte Spalten
1087cdf0e10cSrcweir
1088cdf0e10cSrcweir SCCOL nLastOtherCol = static_cast<SCCOL>(nOtherEndCol + 1);
1089cdf0e10cSrcweir // nThisEndCol ... 0
1090cdf0e10cSrcweir for ( nThisCol = nThisEndCol+1; nThisCol > 0; )
1091cdf0e10cSrcweir {
1092cdf0e10cSrcweir --nThisCol;
1093cdf0e10cSrcweir SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
1094cdf0e10cSrcweir if ( ValidCol(nOtherCol) && nOtherCol+1 < nLastOtherCol )
1095cdf0e10cSrcweir {
1096cdf0e10cSrcweir // Luecke -> geloescht
1097cdf0e10cSrcweir ScRange aDelRange( nOtherCol+1, 0, nOtherTab,
1098cdf0e10cSrcweir nLastOtherCol-1, MAXROW, nOtherTab );
1099cdf0e10cSrcweir pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
1100cdf0e10cSrcweir }
1101cdf0e10cSrcweir if ( nOtherCol > MAXCOL ) // eingefuegt
1102cdf0e10cSrcweir {
1103cdf0e10cSrcweir // zusammenfassen
1104cdf0e10cSrcweir if ( nThisCol == nThisEndCol || ValidCol(static_cast<SCCOL>(pOtherCols[nThisCol+1])) )
1105cdf0e10cSrcweir {
1106cdf0e10cSrcweir SCCOL nFirstNew = static_cast<SCCOL>(nThisCol);
1107cdf0e10cSrcweir while ( nFirstNew > 0 && pOtherCols[nFirstNew-1] > MAXCOL )
1108cdf0e10cSrcweir --nFirstNew;
1109cdf0e10cSrcweir SCCOL nDiff = nThisCol - nFirstNew;
1110cdf0e10cSrcweir ScRange aRange( nLastOtherCol, 0, nOtherTab,
1111cdf0e10cSrcweir nLastOtherCol+nDiff, MAXROW, nOtherTab );
1112cdf0e10cSrcweir pChangeTrack->AppendInsert( aRange );
1113cdf0e10cSrcweir }
1114cdf0e10cSrcweir }
1115cdf0e10cSrcweir else
1116cdf0e10cSrcweir nLastOtherCol = nOtherCol;
1117cdf0e10cSrcweir }
1118cdf0e10cSrcweir if ( nLastOtherCol > 0 ) // ganz oben geloescht
1119cdf0e10cSrcweir {
1120cdf0e10cSrcweir ScRange aDelRange( 0, 0, nOtherTab,
1121cdf0e10cSrcweir nLastOtherCol-1, MAXROW, nOtherTab );
1122cdf0e10cSrcweir pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
1123cdf0e10cSrcweir }
1124cdf0e10cSrcweir
1125cdf0e10cSrcweir // Actions fuer eingefuegte/geloeschte Zeilen
1126cdf0e10cSrcweir
1127cdf0e10cSrcweir SCROW nLastOtherRow = nOtherEndRow + 1;
1128cdf0e10cSrcweir // nThisEndRow ... 0
1129cdf0e10cSrcweir for ( nThisRow = nThisEndRow+1; nThisRow > 0; )
1130cdf0e10cSrcweir {
1131cdf0e10cSrcweir --nThisRow;
1132cdf0e10cSrcweir SCROW nOtherRow = pOtherRows[nThisRow];
1133cdf0e10cSrcweir if ( ValidRow(nOtherRow) && nOtherRow+1 < nLastOtherRow )
1134cdf0e10cSrcweir {
1135cdf0e10cSrcweir // Luecke -> geloescht
1136cdf0e10cSrcweir ScRange aDelRange( 0, nOtherRow+1, nOtherTab,
1137cdf0e10cSrcweir MAXCOL, nLastOtherRow-1, nOtherTab );
1138cdf0e10cSrcweir pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
1139cdf0e10cSrcweir }
1140cdf0e10cSrcweir if ( nOtherRow > MAXROW ) // eingefuegt
1141cdf0e10cSrcweir {
1142cdf0e10cSrcweir // zusammenfassen
1143cdf0e10cSrcweir if ( nThisRow == nThisEndRow || ValidRow(pOtherRows[nThisRow+1]) )
1144cdf0e10cSrcweir {
1145cdf0e10cSrcweir SCROW nFirstNew = nThisRow;
1146cdf0e10cSrcweir while ( nFirstNew > 0 && pOtherRows[nFirstNew-1] > MAXROW )
1147cdf0e10cSrcweir --nFirstNew;
1148cdf0e10cSrcweir SCROW nDiff = nThisRow - nFirstNew;
1149cdf0e10cSrcweir ScRange aRange( 0, nLastOtherRow, nOtherTab,
1150cdf0e10cSrcweir MAXCOL, nLastOtherRow+nDiff, nOtherTab );
1151cdf0e10cSrcweir pChangeTrack->AppendInsert( aRange );
1152cdf0e10cSrcweir }
1153cdf0e10cSrcweir }
1154cdf0e10cSrcweir else
1155cdf0e10cSrcweir nLastOtherRow = nOtherRow;
1156cdf0e10cSrcweir }
1157cdf0e10cSrcweir if ( nLastOtherRow > 0 ) // ganz oben geloescht
1158cdf0e10cSrcweir {
1159cdf0e10cSrcweir ScRange aDelRange( 0, 0, nOtherTab,
1160cdf0e10cSrcweir MAXCOL, nLastOtherRow-1, nOtherTab );
1161cdf0e10cSrcweir pChangeTrack->AppendDeleteRange( aDelRange, &rOtherDoc, n1, n2 );
1162cdf0e10cSrcweir }
1163cdf0e10cSrcweir
1164cdf0e10cSrcweir // Zeilen durchgehen um einzelne Zellen zu finden
1165cdf0e10cSrcweir
1166cdf0e10cSrcweir for (nThisRow = 0; nThisRow <= nThisEndRow; nThisRow++)
1167cdf0e10cSrcweir {
1168cdf0e10cSrcweir SCROW nOtherRow = pOtherRows[nThisRow];
1169cdf0e10cSrcweir for (nThisCol = 0; nThisCol <= nThisEndCol; nThisCol++)
1170cdf0e10cSrcweir {
1171cdf0e10cSrcweir SCCOL nOtherCol = static_cast<SCCOL>(pOtherCols[nThisCol]);
1172cdf0e10cSrcweir ScAddress aThisPos( nThisCol, nThisRow, nThisTab );
1173cdf0e10cSrcweir const ScBaseCell* pThisCell = GetCell( aThisPos );
1174cdf0e10cSrcweir const ScBaseCell* pOtherCell = NULL;
1175cdf0e10cSrcweir if ( ValidCol(nOtherCol) && ValidRow(nOtherRow) )
1176cdf0e10cSrcweir {
1177cdf0e10cSrcweir ScAddress aOtherPos( nOtherCol, nOtherRow, nOtherTab );
1178cdf0e10cSrcweir pOtherCell = rOtherDoc.GetCell( aOtherPos );
1179cdf0e10cSrcweir }
1180cdf0e10cSrcweir if ( !ScBaseCell::CellEqual( pThisCell, pOtherCell ) )
1181cdf0e10cSrcweir {
1182cdf0e10cSrcweir ScRange aRange( aThisPos );
1183cdf0e10cSrcweir ScChangeActionContent* pAction = new ScChangeActionContent( aRange );
1184cdf0e10cSrcweir pAction->SetOldValue( pOtherCell, &rOtherDoc, this );
1185cdf0e10cSrcweir pAction->SetNewValue( pThisCell, this );
1186cdf0e10cSrcweir pChangeTrack->Append( pAction );
1187cdf0e10cSrcweir }
1188cdf0e10cSrcweir }
1189cdf0e10cSrcweir aProgress.SetStateOnPercent(nProgressStart+nThisRow);
1190cdf0e10cSrcweir }
1191cdf0e10cSrcweir
1192cdf0e10cSrcweir delete[] pOtherCols;
1193cdf0e10cSrcweir delete[] pOtherRows;
1194cdf0e10cSrcweir delete[] pTempRows;
1195cdf0e10cSrcweir }
1196cdf0e10cSrcweir }
1197cdf0e10cSrcweir
1198cdf0e10cSrcweir //! Inhalt von eingefuegten / geloeschten Tabellen ???
1199cdf0e10cSrcweir //! Aktionen fuer eingefuegte / geloeschte Tabellen ???
1200cdf0e10cSrcweir
1201cdf0e10cSrcweir delete[] pOtherTabs;
1202cdf0e10cSrcweir }
1203cdf0e10cSrcweir
1204cdf0e10cSrcweir
1205cdf0e10cSrcweir
1206cdf0e10cSrcweir
1207cdf0e10cSrcweir
1208