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 #include <rtl/math.hxx>
28cdf0e10cSrcweir #include <unotools/textsearch.hxx>
29cdf0e10cSrcweir #include <svl/zforlist.hxx>
30cdf0e10cSrcweir #include <svl/zformat.hxx>
31cdf0e10cSrcweir #include <unotools/charclass.hxx>
32cdf0e10cSrcweir #include <unotools/collatorwrapper.hxx>
33cdf0e10cSrcweir #include <com/sun/star/i18n/CollatorOptions.hpp>
34cdf0e10cSrcweir #include <stdlib.h>
35cdf0e10cSrcweir #include <unotools/transliterationwrapper.hxx>
36cdf0e10cSrcweir
37cdf0e10cSrcweir #include "table.hxx"
38cdf0e10cSrcweir #include "scitems.hxx"
39cdf0e10cSrcweir #include "collect.hxx"
40cdf0e10cSrcweir #include "attrib.hxx"
41cdf0e10cSrcweir #include "cell.hxx"
42cdf0e10cSrcweir #include "document.hxx"
43cdf0e10cSrcweir #include "globstr.hrc"
44cdf0e10cSrcweir #include "global.hxx"
45cdf0e10cSrcweir #include "stlpool.hxx"
46cdf0e10cSrcweir #include "compiler.hxx"
47cdf0e10cSrcweir #include "patattr.hxx"
48cdf0e10cSrcweir #include "subtotal.hxx"
49cdf0e10cSrcweir #include "docoptio.hxx"
50cdf0e10cSrcweir #include "markdata.hxx"
51cdf0e10cSrcweir #include "rangelst.hxx"
52cdf0e10cSrcweir #include "attarray.hxx"
53cdf0e10cSrcweir #include "userlist.hxx"
54cdf0e10cSrcweir #include "progress.hxx"
55cdf0e10cSrcweir #include "cellform.hxx"
56cdf0e10cSrcweir #include "postit.hxx"
57cdf0e10cSrcweir #include "queryparam.hxx"
58cdf0e10cSrcweir #include "segmenttree.hxx"
59cdf0e10cSrcweir #include "drwlayer.hxx"
60cdf0e10cSrcweir
61cdf0e10cSrcweir #include <vector>
62cdf0e10cSrcweir
63cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
64cdf0e10cSrcweir
65cdf0e10cSrcweir const sal_uInt16 nMaxSorts = 3; // maximale Anzahl Sortierkriterien in aSortParam
66cdf0e10cSrcweir
67cdf0e10cSrcweir struct ScSortInfo
68cdf0e10cSrcweir {
69cdf0e10cSrcweir ScBaseCell* pCell;
70cdf0e10cSrcweir SCCOLROW nOrg;
71cdf0e10cSrcweir DECL_FIXEDMEMPOOL_NEWDEL( ScSortInfo );
72cdf0e10cSrcweir };
73cdf0e10cSrcweir const sal_uInt16 nMemPoolSortInfo = (0x8000 - 64) / sizeof(ScSortInfo);
74cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScSortInfo, nMemPoolSortInfo, nMemPoolSortInfo )
75cdf0e10cSrcweir
76cdf0e10cSrcweir // END OF STATIC DATA -----------------------------------------------------
77cdf0e10cSrcweir
78cdf0e10cSrcweir
79cdf0e10cSrcweir class ScSortInfoArray
80cdf0e10cSrcweir {
81cdf0e10cSrcweir private:
82cdf0e10cSrcweir ScSortInfo** pppInfo[nMaxSorts];
83cdf0e10cSrcweir SCSIZE nCount;
84cdf0e10cSrcweir SCCOLROW nStart;
85cdf0e10cSrcweir sal_uInt16 nUsedSorts;
86cdf0e10cSrcweir
87cdf0e10cSrcweir public:
ScSortInfoArray(sal_uInt16 nSorts,SCCOLROW nInd1,SCCOLROW nInd2)88cdf0e10cSrcweir ScSortInfoArray( sal_uInt16 nSorts, SCCOLROW nInd1, SCCOLROW nInd2 ) :
89cdf0e10cSrcweir nCount( nInd2 - nInd1 + 1 ), nStart( nInd1 ),
90cdf0e10cSrcweir nUsedSorts( Min( nSorts, nMaxSorts ) )
91cdf0e10cSrcweir {
92cdf0e10cSrcweir for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir ScSortInfo** ppInfo = new ScSortInfo* [nCount];
95cdf0e10cSrcweir for ( SCSIZE j = 0; j < nCount; j++ )
96cdf0e10cSrcweir ppInfo[j] = new ScSortInfo;
97cdf0e10cSrcweir pppInfo[nSort] = ppInfo;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir }
~ScSortInfoArray()100cdf0e10cSrcweir ~ScSortInfoArray()
101cdf0e10cSrcweir {
102cdf0e10cSrcweir for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
103cdf0e10cSrcweir {
104cdf0e10cSrcweir ScSortInfo** ppInfo = pppInfo[nSort];
105cdf0e10cSrcweir for ( SCSIZE j = 0; j < nCount; j++ )
106cdf0e10cSrcweir delete ppInfo[j];
107cdf0e10cSrcweir delete [] ppInfo;
108cdf0e10cSrcweir }
109cdf0e10cSrcweir }
Get(sal_uInt16 nSort,SCCOLROW nInd)110cdf0e10cSrcweir ScSortInfo* Get( sal_uInt16 nSort, SCCOLROW nInd )
111cdf0e10cSrcweir { return (pppInfo[nSort])[ nInd - nStart ]; }
Swap(SCCOLROW nInd1,SCCOLROW nInd2)112cdf0e10cSrcweir void Swap( SCCOLROW nInd1, SCCOLROW nInd2 )
113cdf0e10cSrcweir {
114cdf0e10cSrcweir SCSIZE n1 = static_cast<SCSIZE>(nInd1 - nStart);
115cdf0e10cSrcweir SCSIZE n2 = static_cast<SCSIZE>(nInd2 - nStart);
116cdf0e10cSrcweir for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir ScSortInfo** ppInfo = pppInfo[nSort];
119cdf0e10cSrcweir ScSortInfo* pTmp = ppInfo[n1];
120cdf0e10cSrcweir ppInfo[n1] = ppInfo[n2];
121cdf0e10cSrcweir ppInfo[n2] = pTmp;
122cdf0e10cSrcweir }
123cdf0e10cSrcweir }
GetUsedSorts()124cdf0e10cSrcweir sal_uInt16 GetUsedSorts() { return nUsedSorts; }
GetFirstArray()125cdf0e10cSrcweir ScSortInfo** GetFirstArray() { return pppInfo[0]; }
GetStart()126cdf0e10cSrcweir SCCOLROW GetStart() { return nStart; }
GetCount()127cdf0e10cSrcweir SCSIZE GetCount() { return nCount; }
128cdf0e10cSrcweir };
129cdf0e10cSrcweir
CreateSortInfoArray(SCCOLROW nInd1,SCCOLROW nInd2)130cdf0e10cSrcweir ScSortInfoArray* ScTable::CreateSortInfoArray( SCCOLROW nInd1, SCCOLROW nInd2 )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir sal_uInt16 nUsedSorts = 1;
133cdf0e10cSrcweir while ( nUsedSorts < nMaxSorts && aSortParam.bDoSort[nUsedSorts] )
134cdf0e10cSrcweir nUsedSorts++;
135cdf0e10cSrcweir ScSortInfoArray* pArray = new ScSortInfoArray( nUsedSorts, nInd1, nInd2 );
136cdf0e10cSrcweir if ( aSortParam.bByRow )
137cdf0e10cSrcweir {
138cdf0e10cSrcweir for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
139cdf0e10cSrcweir {
140cdf0e10cSrcweir SCCOL nCol = static_cast<SCCOL>(aSortParam.nField[nSort]);
141cdf0e10cSrcweir ScColumn* pCol = &aCol[nCol];
142cdf0e10cSrcweir for ( SCROW nRow = nInd1; nRow <= nInd2; nRow++ )
143cdf0e10cSrcweir {
144cdf0e10cSrcweir //2do: FillSortInfo an ScColumn und Array abklappern statt Search in GetCell
145cdf0e10cSrcweir ScSortInfo* pInfo = pArray->Get( nSort, nRow );
146cdf0e10cSrcweir pInfo->pCell = pCol->GetCell( nRow );
147cdf0e10cSrcweir pInfo->nOrg = nRow;
148cdf0e10cSrcweir }
149cdf0e10cSrcweir }
150cdf0e10cSrcweir }
151cdf0e10cSrcweir else
152cdf0e10cSrcweir {
153cdf0e10cSrcweir for ( sal_uInt16 nSort = 0; nSort < nUsedSorts; nSort++ )
154cdf0e10cSrcweir {
155cdf0e10cSrcweir SCROW nRow = aSortParam.nField[nSort];
156cdf0e10cSrcweir for ( SCCOL nCol = static_cast<SCCOL>(nInd1);
157cdf0e10cSrcweir nCol <= static_cast<SCCOL>(nInd2); nCol++ )
158cdf0e10cSrcweir {
159cdf0e10cSrcweir ScSortInfo* pInfo = pArray->Get( nSort, nCol );
160cdf0e10cSrcweir pInfo->pCell = GetCell( nCol, nRow );
161cdf0e10cSrcweir pInfo->nOrg = nCol;
162cdf0e10cSrcweir }
163cdf0e10cSrcweir }
164cdf0e10cSrcweir }
165cdf0e10cSrcweir return pArray;
166cdf0e10cSrcweir }
167cdf0e10cSrcweir
168cdf0e10cSrcweir
IsSortCollatorGlobal() const169cdf0e10cSrcweir sal_Bool ScTable::IsSortCollatorGlobal() const
170cdf0e10cSrcweir {
171cdf0e10cSrcweir return pSortCollator == ScGlobal::GetCollator() ||
172cdf0e10cSrcweir pSortCollator == ScGlobal::GetCaseCollator();
173cdf0e10cSrcweir }
174cdf0e10cSrcweir
175cdf0e10cSrcweir
InitSortCollator(const ScSortParam & rPar)176cdf0e10cSrcweir void ScTable::InitSortCollator( const ScSortParam& rPar )
177cdf0e10cSrcweir {
178cdf0e10cSrcweir if ( rPar.aCollatorLocale.Language.getLength() )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir if ( !pSortCollator || IsSortCollatorGlobal() )
181cdf0e10cSrcweir pSortCollator = new CollatorWrapper( pDocument->GetServiceManager() );
182cdf0e10cSrcweir pSortCollator->loadCollatorAlgorithm( rPar.aCollatorAlgorithm,
183cdf0e10cSrcweir rPar.aCollatorLocale, (rPar.bCaseSens ? 0 : SC_COLLATOR_IGNORES) );
184cdf0e10cSrcweir }
185cdf0e10cSrcweir else
186cdf0e10cSrcweir { // SYSTEM
187cdf0e10cSrcweir DestroySortCollator();
188cdf0e10cSrcweir pSortCollator = (rPar.bCaseSens ? ScGlobal::GetCaseCollator() :
189cdf0e10cSrcweir ScGlobal::GetCollator());
190cdf0e10cSrcweir }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir
193cdf0e10cSrcweir
DestroySortCollator()194cdf0e10cSrcweir void ScTable::DestroySortCollator()
195cdf0e10cSrcweir {
196cdf0e10cSrcweir if ( pSortCollator )
197cdf0e10cSrcweir {
198cdf0e10cSrcweir if ( !IsSortCollatorGlobal() )
199cdf0e10cSrcweir delete pSortCollator;
200cdf0e10cSrcweir pSortCollator = NULL;
201cdf0e10cSrcweir }
202cdf0e10cSrcweir }
203cdf0e10cSrcweir
204cdf0e10cSrcweir
SortReorder(ScSortInfoArray * pArray,ScProgress & rProgress)205cdf0e10cSrcweir void ScTable::SortReorder( ScSortInfoArray* pArray, ScProgress& rProgress )
206cdf0e10cSrcweir {
207cdf0e10cSrcweir sal_Bool bByRow = aSortParam.bByRow;
208cdf0e10cSrcweir SCSIZE nCount = pArray->GetCount();
209cdf0e10cSrcweir SCCOLROW nStart = pArray->GetStart();
210cdf0e10cSrcweir ScSortInfo** ppInfo = pArray->GetFirstArray();
211cdf0e10cSrcweir ::std::vector<ScSortInfo*> aTable(nCount);
212cdf0e10cSrcweir SCSIZE nPos;
213cdf0e10cSrcweir for ( nPos = 0; nPos < nCount; nPos++ )
214cdf0e10cSrcweir aTable[ppInfo[nPos]->nOrg - nStart] = ppInfo[nPos];
215cdf0e10cSrcweir
216cdf0e10cSrcweir SCCOLROW nDest = nStart;
217cdf0e10cSrcweir for ( nPos = 0; nPos < nCount; nPos++, nDest++ )
218cdf0e10cSrcweir {
219cdf0e10cSrcweir SCCOLROW nOrg = ppInfo[nPos]->nOrg;
220cdf0e10cSrcweir if ( nDest != nOrg )
221cdf0e10cSrcweir {
222cdf0e10cSrcweir if ( bByRow )
223cdf0e10cSrcweir SwapRow( nDest, nOrg );
224cdf0e10cSrcweir else
225cdf0e10cSrcweir SwapCol( static_cast<SCCOL>(nDest), static_cast<SCCOL>(nOrg) );
226cdf0e10cSrcweir // neue Position des weggeswapten eintragen
227cdf0e10cSrcweir ScSortInfo* p = ppInfo[nPos];
228cdf0e10cSrcweir p->nOrg = nDest;
229cdf0e10cSrcweir ::std::swap(p, aTable[nDest-nStart]);
230cdf0e10cSrcweir p->nOrg = nOrg;
231cdf0e10cSrcweir ::std::swap(p, aTable[nOrg-nStart]);
232cdf0e10cSrcweir DBG_ASSERT( p == ppInfo[nPos], "SortReorder: nOrg MisMatch" );
233cdf0e10cSrcweir }
234cdf0e10cSrcweir rProgress.SetStateOnPercent( nPos );
235cdf0e10cSrcweir }
236cdf0e10cSrcweir }
237cdf0e10cSrcweir
CompareCell(sal_uInt16 nSort,ScBaseCell * pCell1,SCCOL nCell1Col,SCROW nCell1Row,ScBaseCell * pCell2,SCCOL nCell2Col,SCROW nCell2Row)238cdf0e10cSrcweir short ScTable::CompareCell( sal_uInt16 nSort,
239cdf0e10cSrcweir ScBaseCell* pCell1, SCCOL nCell1Col, SCROW nCell1Row,
240cdf0e10cSrcweir ScBaseCell* pCell2, SCCOL nCell2Col, SCROW nCell2Row )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir short nRes = 0;
243cdf0e10cSrcweir
244cdf0e10cSrcweir CellType eType1 = CELLTYPE_NONE, eType2 = CELLTYPE_NONE;
245cdf0e10cSrcweir if (pCell1)
246cdf0e10cSrcweir {
247cdf0e10cSrcweir eType1 = pCell1->GetCellType();
248cdf0e10cSrcweir if (eType1 == CELLTYPE_NOTE)
249cdf0e10cSrcweir pCell1 = NULL;
250cdf0e10cSrcweir }
251cdf0e10cSrcweir if (pCell2)
252cdf0e10cSrcweir {
253cdf0e10cSrcweir eType2 = pCell2->GetCellType();
254cdf0e10cSrcweir if (eType2 == CELLTYPE_NOTE)
255cdf0e10cSrcweir pCell2 = NULL;
256cdf0e10cSrcweir }
257cdf0e10cSrcweir
258cdf0e10cSrcweir if (pCell1)
259cdf0e10cSrcweir {
260cdf0e10cSrcweir if (pCell2)
261cdf0e10cSrcweir {
262cdf0e10cSrcweir sal_Bool bStr1 = ( eType1 != CELLTYPE_VALUE );
263cdf0e10cSrcweir if ( eType1 == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell1)->IsValue() )
264cdf0e10cSrcweir bStr1 = sal_False;
265cdf0e10cSrcweir sal_Bool bStr2 = ( eType2 != CELLTYPE_VALUE );
266cdf0e10cSrcweir if ( eType2 == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell2)->IsValue() )
267cdf0e10cSrcweir bStr2 = sal_False;
268cdf0e10cSrcweir
269cdf0e10cSrcweir if ( bStr1 && bStr2 ) // nur Strings untereinander als String vergleichen!
270cdf0e10cSrcweir {
271cdf0e10cSrcweir String aStr1;
272cdf0e10cSrcweir String aStr2;
273cdf0e10cSrcweir if (eType1 == CELLTYPE_STRING)
274cdf0e10cSrcweir ((ScStringCell*)pCell1)->GetString(aStr1);
275cdf0e10cSrcweir else
276cdf0e10cSrcweir GetString(nCell1Col, nCell1Row, aStr1);
277cdf0e10cSrcweir if (eType2 == CELLTYPE_STRING)
278cdf0e10cSrcweir ((ScStringCell*)pCell2)->GetString(aStr2);
279cdf0e10cSrcweir else
280cdf0e10cSrcweir GetString(nCell2Col, nCell2Row, aStr2);
281cdf0e10cSrcweir sal_Bool bUserDef = aSortParam.bUserDef;
282cdf0e10cSrcweir if (bUserDef)
283cdf0e10cSrcweir {
284cdf0e10cSrcweir ScUserListData* pData =
285cdf0e10cSrcweir (ScUserListData*)(ScGlobal::GetUserList()->At(
286cdf0e10cSrcweir aSortParam.nUserIndex));
287cdf0e10cSrcweir if (pData)
288cdf0e10cSrcweir {
289cdf0e10cSrcweir if ( aSortParam.bCaseSens )
290cdf0e10cSrcweir nRes = sal::static_int_cast<short>( pData->Compare(aStr1, aStr2) );
291cdf0e10cSrcweir else
292cdf0e10cSrcweir nRes = sal::static_int_cast<short>( pData->ICompare(aStr1, aStr2) );
293cdf0e10cSrcweir }
294cdf0e10cSrcweir else
295cdf0e10cSrcweir bUserDef = sal_False;
296cdf0e10cSrcweir
297cdf0e10cSrcweir }
298cdf0e10cSrcweir if (!bUserDef)
299cdf0e10cSrcweir nRes = (short) pSortCollator->compareString( aStr1, aStr2 );
300cdf0e10cSrcweir }
301cdf0e10cSrcweir else if ( bStr1 ) // String <-> Zahl
302cdf0e10cSrcweir nRes = 1; // Zahl vorne
303cdf0e10cSrcweir else if ( bStr2 ) // Zahl <-> String
304cdf0e10cSrcweir nRes = -1; // Zahl vorne
305cdf0e10cSrcweir else // Zahlen untereinander
306cdf0e10cSrcweir {
307cdf0e10cSrcweir double nVal1;
308cdf0e10cSrcweir double nVal2;
309cdf0e10cSrcweir if (eType1 == CELLTYPE_VALUE)
310cdf0e10cSrcweir nVal1 = ((ScValueCell*)pCell1)->GetValue();
311cdf0e10cSrcweir else if (eType1 == CELLTYPE_FORMULA)
312cdf0e10cSrcweir nVal1 = ((ScFormulaCell*)pCell1)->GetValue();
313cdf0e10cSrcweir else
314cdf0e10cSrcweir nVal1 = 0;
315cdf0e10cSrcweir if (eType2 == CELLTYPE_VALUE)
316cdf0e10cSrcweir nVal2 = ((ScValueCell*)pCell2)->GetValue();
317cdf0e10cSrcweir else if (eType2 == CELLTYPE_FORMULA)
318cdf0e10cSrcweir nVal2 = ((ScFormulaCell*)pCell2)->GetValue();
319cdf0e10cSrcweir else
320cdf0e10cSrcweir nVal2 = 0;
321cdf0e10cSrcweir if (nVal1 < nVal2)
322cdf0e10cSrcweir nRes = -1;
323cdf0e10cSrcweir else if (nVal1 > nVal2)
324cdf0e10cSrcweir nRes = 1;
325cdf0e10cSrcweir }
326cdf0e10cSrcweir if ( !aSortParam.bAscending[nSort] )
327cdf0e10cSrcweir nRes = -nRes;
328cdf0e10cSrcweir }
329cdf0e10cSrcweir else
330cdf0e10cSrcweir nRes = -1;
331cdf0e10cSrcweir }
332cdf0e10cSrcweir else
333cdf0e10cSrcweir {
334cdf0e10cSrcweir if ( pCell2 )
335cdf0e10cSrcweir nRes = 1;
336cdf0e10cSrcweir else
337cdf0e10cSrcweir nRes = 0; // beide leer
338cdf0e10cSrcweir }
339cdf0e10cSrcweir return nRes;
340cdf0e10cSrcweir }
341cdf0e10cSrcweir
Compare(ScSortInfoArray * pArray,SCCOLROW nIndex1,SCCOLROW nIndex2)342cdf0e10cSrcweir short ScTable::Compare( ScSortInfoArray* pArray, SCCOLROW nIndex1, SCCOLROW nIndex2 )
343cdf0e10cSrcweir {
344cdf0e10cSrcweir short nRes;
345cdf0e10cSrcweir sal_uInt16 nSort = 0;
346cdf0e10cSrcweir do
347cdf0e10cSrcweir {
348cdf0e10cSrcweir ScSortInfo* pInfo1 = pArray->Get( nSort, nIndex1 );
349cdf0e10cSrcweir ScSortInfo* pInfo2 = pArray->Get( nSort, nIndex2 );
350cdf0e10cSrcweir if ( aSortParam.bByRow )
351cdf0e10cSrcweir nRes = CompareCell( nSort,
352cdf0e10cSrcweir pInfo1->pCell, static_cast<SCCOL>(aSortParam.nField[nSort]), pInfo1->nOrg,
353cdf0e10cSrcweir pInfo2->pCell, static_cast<SCCOL>(aSortParam.nField[nSort]), pInfo2->nOrg );
354cdf0e10cSrcweir else
355cdf0e10cSrcweir nRes = CompareCell( nSort,
356cdf0e10cSrcweir pInfo1->pCell, static_cast<SCCOL>(pInfo1->nOrg), aSortParam.nField[nSort],
357cdf0e10cSrcweir pInfo2->pCell, static_cast<SCCOL>(pInfo2->nOrg), aSortParam.nField[nSort] );
358cdf0e10cSrcweir } while ( nRes == 0 && ++nSort < pArray->GetUsedSorts() );
359cdf0e10cSrcweir if( nRes == 0 )
360cdf0e10cSrcweir {
361cdf0e10cSrcweir ScSortInfo* pInfo1 = pArray->Get( 0, nIndex1 );
362cdf0e10cSrcweir ScSortInfo* pInfo2 = pArray->Get( 0, nIndex2 );
363cdf0e10cSrcweir if( pInfo1->nOrg < pInfo2->nOrg )
364cdf0e10cSrcweir nRes = -1;
365cdf0e10cSrcweir else if( pInfo1->nOrg > pInfo2->nOrg )
366cdf0e10cSrcweir nRes = 1;
367cdf0e10cSrcweir }
368cdf0e10cSrcweir return nRes;
369cdf0e10cSrcweir }
370cdf0e10cSrcweir
QuickSort(ScSortInfoArray * pArray,SCsCOLROW nLo,SCsCOLROW nHi)371cdf0e10cSrcweir void ScTable::QuickSort( ScSortInfoArray* pArray, SCsCOLROW nLo, SCsCOLROW nHi )
372cdf0e10cSrcweir {
373cdf0e10cSrcweir if ((nHi - nLo) == 1)
374cdf0e10cSrcweir {
375cdf0e10cSrcweir if (Compare(pArray, nLo, nHi) > 0)
376cdf0e10cSrcweir pArray->Swap( nLo, nHi );
377cdf0e10cSrcweir }
378cdf0e10cSrcweir else
379cdf0e10cSrcweir {
380cdf0e10cSrcweir SCsCOLROW ni = nLo;
381cdf0e10cSrcweir SCsCOLROW nj = nHi;
382cdf0e10cSrcweir do
383cdf0e10cSrcweir {
384cdf0e10cSrcweir while ((ni <= nHi) && (Compare(pArray, ni, nLo)) < 0)
385cdf0e10cSrcweir ni++;
386cdf0e10cSrcweir while ((nj >= nLo) && (Compare(pArray, nLo, nj)) < 0)
387cdf0e10cSrcweir nj--;
388cdf0e10cSrcweir if (ni <= nj)
389cdf0e10cSrcweir {
390cdf0e10cSrcweir if (ni != nj)
391cdf0e10cSrcweir pArray->Swap( ni, nj );
392cdf0e10cSrcweir ni++;
393cdf0e10cSrcweir nj--;
394cdf0e10cSrcweir }
395cdf0e10cSrcweir } while (ni < nj);
396cdf0e10cSrcweir if ((nj - nLo) < (nHi - ni))
397cdf0e10cSrcweir {
398cdf0e10cSrcweir if (nLo < nj)
399cdf0e10cSrcweir QuickSort(pArray, nLo, nj);
400cdf0e10cSrcweir if (ni < nHi)
401cdf0e10cSrcweir QuickSort(pArray, ni, nHi);
402cdf0e10cSrcweir }
403cdf0e10cSrcweir else
404cdf0e10cSrcweir {
405cdf0e10cSrcweir if (ni < nHi)
406cdf0e10cSrcweir QuickSort(pArray, ni, nHi);
407cdf0e10cSrcweir if (nLo < nj)
408cdf0e10cSrcweir QuickSort(pArray, nLo, nj);
409cdf0e10cSrcweir }
410cdf0e10cSrcweir }
411cdf0e10cSrcweir }
412cdf0e10cSrcweir
SwapCol(SCCOL nCol1,SCCOL nCol2)413cdf0e10cSrcweir void ScTable::SwapCol(SCCOL nCol1, SCCOL nCol2)
414cdf0e10cSrcweir {
415cdf0e10cSrcweir for (SCROW nRow = aSortParam.nRow1; nRow <= aSortParam.nRow2; nRow++)
416cdf0e10cSrcweir {
417cdf0e10cSrcweir aCol[nCol1].SwapCell(nRow, aCol[nCol2]);
418cdf0e10cSrcweir if (aSortParam.bIncludePattern)
419cdf0e10cSrcweir {
420cdf0e10cSrcweir const ScPatternAttr* pPat1 = GetPattern(nCol1, nRow);
421cdf0e10cSrcweir const ScPatternAttr* pPat2 = GetPattern(nCol2, nRow);
422cdf0e10cSrcweir if (pPat1 != pPat2)
423cdf0e10cSrcweir {
424ddf250f3SHerbert Dürr //Add Reference to avoid pPat1 to be deleted by merge same cell attributes for adjacent cells
425ddf250f3SHerbert Dürr if( IsPooledItem( pPat1 ) ) pPat1->AddRef();
426ddf250f3SHerbert Dürr SetPattern(nCol1, nRow, *pPat2, sal_True);
427ddf250f3SHerbert Dürr SetPattern(nCol2, nRow, *pPat1, sal_True);
428ddf250f3SHerbert Dürr if( IsPooledItem( pPat1 ) ) pPat1->ReleaseRef();
429ddf250f3SHerbert Dürr
430cdf0e10cSrcweir }
431cdf0e10cSrcweir }
432cdf0e10cSrcweir }
433cdf0e10cSrcweir }
434cdf0e10cSrcweir
SwapRow(SCROW nRow1,SCROW nRow2)435cdf0e10cSrcweir void ScTable::SwapRow(SCROW nRow1, SCROW nRow2)
436cdf0e10cSrcweir {
437cdf0e10cSrcweir for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; nCol++)
438cdf0e10cSrcweir {
439cdf0e10cSrcweir aCol[nCol].SwapRow(nRow1, nRow2);
440cdf0e10cSrcweir if (aSortParam.bIncludePattern)
441cdf0e10cSrcweir {
442cdf0e10cSrcweir const ScPatternAttr* pPat1 = GetPattern(nCol, nRow1);
443cdf0e10cSrcweir const ScPatternAttr* pPat2 = GetPattern(nCol, nRow2);
444cdf0e10cSrcweir if (pPat1 != pPat2)
445cdf0e10cSrcweir {
446ddf250f3SHerbert Dürr //Add Reference to avoid pPat1 to be deleted by merge same cell attributes for adjacent cells
447ddf250f3SHerbert Dürr if( IsPooledItem( pPat1 ) ) pPat1->AddRef();
448ddf250f3SHerbert Dürr SetPattern(nCol, nRow1, *pPat2, sal_True);
449ddf250f3SHerbert Dürr SetPattern(nCol, nRow2, *pPat1, sal_True);
450ddf250f3SHerbert Dürr if( IsPooledItem( pPat1 ) ) pPat1->ReleaseRef();
451cdf0e10cSrcweir }
452cdf0e10cSrcweir }
453cdf0e10cSrcweir }
454cdf0e10cSrcweir if (bGlobalKeepQuery)
455cdf0e10cSrcweir {
456cdf0e10cSrcweir bool bRow1Hidden = RowHidden(nRow1);
457cdf0e10cSrcweir bool bRow2Hidden = RowHidden(nRow2);
458cdf0e10cSrcweir SetRowHidden(nRow1, nRow1, bRow2Hidden);
459cdf0e10cSrcweir SetRowHidden(nRow2, nRow2, bRow1Hidden);
460cdf0e10cSrcweir
461cdf0e10cSrcweir bool bRow1Filtered = RowFiltered(nRow1);
462cdf0e10cSrcweir bool bRow2Filtered = RowFiltered(nRow2);
463cdf0e10cSrcweir SetRowFiltered(nRow1, nRow1, bRow2Filtered);
464cdf0e10cSrcweir SetRowFiltered(nRow2, nRow2, bRow1Filtered);
465cdf0e10cSrcweir }
466cdf0e10cSrcweir }
467cdf0e10cSrcweir
Compare(SCCOLROW nIndex1,SCCOLROW nIndex2)468cdf0e10cSrcweir short ScTable::Compare(SCCOLROW nIndex1, SCCOLROW nIndex2)
469cdf0e10cSrcweir {
470cdf0e10cSrcweir short nRes;
471cdf0e10cSrcweir sal_uInt16 nSort = 0;
472cdf0e10cSrcweir if (aSortParam.bByRow)
473cdf0e10cSrcweir {
474cdf0e10cSrcweir do
475cdf0e10cSrcweir {
476cdf0e10cSrcweir SCCOL nCol = static_cast<SCCOL>(aSortParam.nField[nSort]);
477cdf0e10cSrcweir ScBaseCell* pCell1 = aCol[nCol].GetCell( nIndex1 );
478cdf0e10cSrcweir ScBaseCell* pCell2 = aCol[nCol].GetCell( nIndex2 );
479cdf0e10cSrcweir nRes = CompareCell( nSort, pCell1, nCol, nIndex1, pCell2, nCol, nIndex2 );
480cdf0e10cSrcweir } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
481cdf0e10cSrcweir }
482cdf0e10cSrcweir else
483cdf0e10cSrcweir {
484cdf0e10cSrcweir do
485cdf0e10cSrcweir {
486cdf0e10cSrcweir SCROW nRow = aSortParam.nField[nSort];
487cdf0e10cSrcweir ScBaseCell* pCell1 = aCol[nIndex1].GetCell( nRow );
488cdf0e10cSrcweir ScBaseCell* pCell2 = aCol[nIndex2].GetCell( nRow );
489cdf0e10cSrcweir nRes = CompareCell( nSort, pCell1, static_cast<SCCOL>(nIndex1),
490cdf0e10cSrcweir nRow, pCell2, static_cast<SCCOL>(nIndex2), nRow );
491cdf0e10cSrcweir } while ( nRes == 0 && ++nSort < nMaxSorts && aSortParam.bDoSort[nSort] );
492cdf0e10cSrcweir }
493cdf0e10cSrcweir return nRes;
494cdf0e10cSrcweir }
495cdf0e10cSrcweir
IsSorted(SCCOLROW nStart,SCCOLROW nEnd)496cdf0e10cSrcweir sal_Bool ScTable::IsSorted( SCCOLROW nStart, SCCOLROW nEnd ) // ueber aSortParam
497cdf0e10cSrcweir {
498cdf0e10cSrcweir for (SCCOLROW i=nStart; i<nEnd; i++)
499cdf0e10cSrcweir {
500cdf0e10cSrcweir if (Compare( i, i+1 ) > 0)
501cdf0e10cSrcweir return sal_False;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir return sal_True;
504cdf0e10cSrcweir }
505cdf0e10cSrcweir
DecoladeRow(ScSortInfoArray * pArray,SCROW nRow1,SCROW nRow2)506cdf0e10cSrcweir void ScTable::DecoladeRow( ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2 )
507cdf0e10cSrcweir {
508cdf0e10cSrcweir SCROW nRow;
509cdf0e10cSrcweir SCROW nMax = nRow2 - nRow1;
510cdf0e10cSrcweir for (SCROW i = nRow1; (i + 4) <= nRow2; i += 4)
511cdf0e10cSrcweir {
512cdf0e10cSrcweir nRow = rand() % nMax;
513cdf0e10cSrcweir pArray->Swap(i, nRow1 + nRow);
514cdf0e10cSrcweir }
515cdf0e10cSrcweir }
516cdf0e10cSrcweir
Sort(const ScSortParam & rSortParam,sal_Bool bKeepQuery)517cdf0e10cSrcweir void ScTable::Sort(const ScSortParam& rSortParam, sal_Bool bKeepQuery)
518cdf0e10cSrcweir {
519cdf0e10cSrcweir aSortParam = rSortParam;
520cdf0e10cSrcweir InitSortCollator( rSortParam );
521cdf0e10cSrcweir bGlobalKeepQuery = bKeepQuery;
522cdf0e10cSrcweir if (rSortParam.bByRow)
523cdf0e10cSrcweir {
524cdf0e10cSrcweir SCROW nLastRow = 0;
525cdf0e10cSrcweir for (SCCOL nCol = aSortParam.nCol1; nCol <= aSortParam.nCol2; nCol++)
526cdf0e10cSrcweir nLastRow = Max(nLastRow, aCol[nCol].GetLastDataPos());
527cdf0e10cSrcweir nLastRow = Min(nLastRow, aSortParam.nRow2);
528cdf0e10cSrcweir SCROW nRow1 = (rSortParam.bHasHeader ?
529cdf0e10cSrcweir aSortParam.nRow1 + 1 : aSortParam.nRow1);
530cdf0e10cSrcweir if (!IsSorted(nRow1, nLastRow))
531cdf0e10cSrcweir {
532cdf0e10cSrcweir ScProgress aProgress( pDocument->GetDocumentShell(),
533cdf0e10cSrcweir ScGlobal::GetRscString(STR_PROGRESS_SORTING), nLastRow - nRow1 );
534cdf0e10cSrcweir ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, nLastRow );
535cdf0e10cSrcweir if ( nLastRow - nRow1 > 255 )
536cdf0e10cSrcweir DecoladeRow( pArray, nRow1, nLastRow );
537cdf0e10cSrcweir QuickSort( pArray, nRow1, nLastRow );
538cdf0e10cSrcweir SortReorder( pArray, aProgress );
539cdf0e10cSrcweir delete pArray;
540cdf0e10cSrcweir // #158377# #i59745# update position of caption objects of cell notes
541cdf0e10cSrcweir ScNoteUtil::UpdateCaptionPositions( *pDocument, ScRange( aSortParam.nCol1, nRow1, nTab, aSortParam.nCol2, nLastRow, nTab ) );
542cdf0e10cSrcweir }
543cdf0e10cSrcweir }
544cdf0e10cSrcweir else
545cdf0e10cSrcweir {
546cdf0e10cSrcweir SCCOL nLastCol;
547cdf0e10cSrcweir for (nLastCol = aSortParam.nCol2;
548cdf0e10cSrcweir (nLastCol > aSortParam.nCol1) && aCol[nLastCol].IsEmptyBlock(aSortParam.nRow1, aSortParam.nRow2); nLastCol--)
549cdf0e10cSrcweir {
550cdf0e10cSrcweir }
551cdf0e10cSrcweir SCCOL nCol1 = (rSortParam.bHasHeader ?
552cdf0e10cSrcweir aSortParam.nCol1 + 1 : aSortParam.nCol1);
553cdf0e10cSrcweir if (!IsSorted(nCol1, nLastCol))
554cdf0e10cSrcweir {
555cdf0e10cSrcweir ScProgress aProgress( pDocument->GetDocumentShell(),
556cdf0e10cSrcweir ScGlobal::GetRscString(STR_PROGRESS_SORTING), nLastCol - nCol1 );
557cdf0e10cSrcweir ScSortInfoArray* pArray = CreateSortInfoArray( nCol1, nLastCol );
558cdf0e10cSrcweir QuickSort( pArray, nCol1, nLastCol );
559cdf0e10cSrcweir SortReorder( pArray, aProgress );
560cdf0e10cSrcweir delete pArray;
561cdf0e10cSrcweir // #158377# #i59745# update position of caption objects of cell notes
562cdf0e10cSrcweir ScNoteUtil::UpdateCaptionPositions( *pDocument, ScRange( nCol1, aSortParam.nRow1, nTab, nLastCol, aSortParam.nRow2, nTab ) );
563cdf0e10cSrcweir }
564cdf0e10cSrcweir }
565cdf0e10cSrcweir DestroySortCollator();
566cdf0e10cSrcweir }
567cdf0e10cSrcweir
568cdf0e10cSrcweir
569cdf0e10cSrcweir // Testen, ob beim Loeschen von Zwischenergebnissen andere Daten mit geloescht werden
570cdf0e10cSrcweir // (fuer Hinweis-Box)
571cdf0e10cSrcweir
TestRemoveSubTotals(const ScSubTotalParam & rParam)572cdf0e10cSrcweir sal_Bool ScTable::TestRemoveSubTotals( const ScSubTotalParam& rParam )
573cdf0e10cSrcweir {
574cdf0e10cSrcweir SCCOL nStartCol = rParam.nCol1;
575cdf0e10cSrcweir SCROW nStartRow = rParam.nRow1 + 1; // Header
576cdf0e10cSrcweir SCCOL nEndCol = rParam.nCol2;
577cdf0e10cSrcweir SCROW nEndRow = rParam.nRow2;
578cdf0e10cSrcweir
579cdf0e10cSrcweir SCCOL nCol;
580cdf0e10cSrcweir SCROW nRow;
581cdf0e10cSrcweir ScBaseCell* pCell;
582cdf0e10cSrcweir
583cdf0e10cSrcweir sal_Bool bWillDelete = sal_False;
584cdf0e10cSrcweir for ( nCol=nStartCol; nCol<=nEndCol && !bWillDelete; nCol++ )
585cdf0e10cSrcweir {
586cdf0e10cSrcweir ScColumnIterator aIter( &aCol[nCol],nStartRow,nEndRow );
587cdf0e10cSrcweir while ( aIter.Next( nRow, pCell ) && !bWillDelete )
588cdf0e10cSrcweir {
589cdf0e10cSrcweir if ( pCell->GetCellType() == CELLTYPE_FORMULA )
590cdf0e10cSrcweir if (((ScFormulaCell*)pCell)->IsSubTotal())
591cdf0e10cSrcweir {
592cdf0e10cSrcweir for (SCCOL nTestCol=0; nTestCol<=MAXCOL; nTestCol++)
593cdf0e10cSrcweir if (nTestCol<nStartCol || nTestCol>nEndCol)
594cdf0e10cSrcweir if (aCol[nTestCol].HasDataAt(nRow))
595cdf0e10cSrcweir bWillDelete = sal_True;
596cdf0e10cSrcweir }
597cdf0e10cSrcweir }
598cdf0e10cSrcweir }
599cdf0e10cSrcweir return bWillDelete;
600cdf0e10cSrcweir }
601cdf0e10cSrcweir
602cdf0e10cSrcweir // alte Ergebnisse loeschen
603cdf0e10cSrcweir // rParam.nRow2 wird veraendert !
604cdf0e10cSrcweir
RemoveSubTotals(ScSubTotalParam & rParam)605cdf0e10cSrcweir void ScTable::RemoveSubTotals( ScSubTotalParam& rParam )
606cdf0e10cSrcweir {
607cdf0e10cSrcweir SCCOL nStartCol = rParam.nCol1;
608cdf0e10cSrcweir SCROW nStartRow = rParam.nRow1 + 1; // Header
609cdf0e10cSrcweir SCCOL nEndCol = rParam.nCol2;
610cdf0e10cSrcweir SCROW nEndRow = rParam.nRow2; // wird veraendert
611cdf0e10cSrcweir
612cdf0e10cSrcweir SCCOL nCol;
613cdf0e10cSrcweir SCROW nRow;
614cdf0e10cSrcweir ScBaseCell* pCell;
615cdf0e10cSrcweir
616cdf0e10cSrcweir for ( nCol=nStartCol; nCol<=nEndCol; nCol++ )
617cdf0e10cSrcweir {
618cdf0e10cSrcweir ScColumnIterator aIter( &aCol[nCol],nStartRow,nEndRow );
619cdf0e10cSrcweir while ( aIter.Next( nRow, pCell ) )
620cdf0e10cSrcweir {
621cdf0e10cSrcweir if ( pCell->GetCellType() == CELLTYPE_FORMULA )
622cdf0e10cSrcweir if (((ScFormulaCell*)pCell)->IsSubTotal())
623cdf0e10cSrcweir {
624cdf0e10cSrcweir RemoveRowBreak(nRow+1, false, true);
625cdf0e10cSrcweir pDocument->DeleteRow( 0,nTab, MAXCOL,nTab, nRow, 1 );
626cdf0e10cSrcweir --nEndRow;
627cdf0e10cSrcweir aIter = ScColumnIterator( &aCol[nCol],nRow,nEndRow );
628cdf0e10cSrcweir }
629cdf0e10cSrcweir }
630cdf0e10cSrcweir }
631cdf0e10cSrcweir
632cdf0e10cSrcweir rParam.nRow2 = nEndRow; // neues Ende
633cdf0e10cSrcweir }
634cdf0e10cSrcweir
635cdf0e10cSrcweir // harte Zahlenformate loeschen (fuer Ergebnisformeln)
636cdf0e10cSrcweir
lcl_RemoveNumberFormat(ScTable * pTab,SCCOL nCol,SCROW nRow)637cdf0e10cSrcweir void lcl_RemoveNumberFormat( ScTable* pTab, SCCOL nCol, SCROW nRow )
638cdf0e10cSrcweir {
639cdf0e10cSrcweir const ScPatternAttr* pPattern = pTab->GetPattern( nCol, nRow );
640cdf0e10cSrcweir if ( pPattern->GetItemSet().GetItemState( ATTR_VALUE_FORMAT, sal_False )
641cdf0e10cSrcweir == SFX_ITEM_SET )
642cdf0e10cSrcweir {
643cdf0e10cSrcweir ScPatternAttr aNewPattern( *pPattern );
644cdf0e10cSrcweir SfxItemSet& rSet = aNewPattern.GetItemSet();
645cdf0e10cSrcweir rSet.ClearItem( ATTR_VALUE_FORMAT );
646cdf0e10cSrcweir rSet.ClearItem( ATTR_LANGUAGE_FORMAT );
647cdf0e10cSrcweir pTab->SetPattern( nCol, nRow, aNewPattern, sal_True );
648cdf0e10cSrcweir }
649cdf0e10cSrcweir }
650cdf0e10cSrcweir
651cdf0e10cSrcweir
652cdf0e10cSrcweir // at least MSC needs this at linkage level to be able to use it in a template
653cdf0e10cSrcweir typedef struct lcl_ScTable_DoSubTotals_RowEntry
654cdf0e10cSrcweir {
655cdf0e10cSrcweir sal_uInt16 nGroupNo;
656cdf0e10cSrcweir SCROW nSubStartRow;
657cdf0e10cSrcweir SCROW nDestRow;
658cdf0e10cSrcweir SCROW nFuncStart;
659cdf0e10cSrcweir SCROW nFuncEnd;
660cdf0e10cSrcweir } RowEntry;
661cdf0e10cSrcweir
662cdf0e10cSrcweir // neue Zwischenergebnisse
663cdf0e10cSrcweir // rParam.nRow2 wird veraendert !
664cdf0e10cSrcweir
DoSubTotals(ScSubTotalParam & rParam)665cdf0e10cSrcweir sal_Bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
666cdf0e10cSrcweir {
667cdf0e10cSrcweir SCCOL nStartCol = rParam.nCol1;
668cdf0e10cSrcweir SCROW nStartRow = rParam.nRow1 + 1; // Header
669cdf0e10cSrcweir SCCOL nEndCol = rParam.nCol2;
670cdf0e10cSrcweir SCROW nEndRow = rParam.nRow2; // wird veraendert
671cdf0e10cSrcweir sal_uInt16 i;
672cdf0e10cSrcweir
673cdf0e10cSrcweir // Leerzeilen am Ende weglassen,
674cdf0e10cSrcweir // damit alle Ueberlaeufe (MAXROW) bei InsertRow gefunden werden (#35180#)
675cdf0e10cSrcweir // Wenn sortiert wurde, sind alle Leerzeilen am Ende.
676cdf0e10cSrcweir SCSIZE nEmpty = GetEmptyLinesInBlock( nStartCol, nStartRow, nEndCol, nEndRow, DIR_BOTTOM );
677cdf0e10cSrcweir nEndRow -= nEmpty;
678cdf0e10cSrcweir
679cdf0e10cSrcweir sal_uInt16 nLevelCount = 0; // Anzahl Gruppierungen
680cdf0e10cSrcweir sal_Bool bDoThis = sal_True;
681cdf0e10cSrcweir for (i=0; i<MAXSUBTOTAL && bDoThis; i++)
682cdf0e10cSrcweir if (rParam.bGroupActive[i])
683cdf0e10cSrcweir nLevelCount = i+1;
684cdf0e10cSrcweir else
685cdf0e10cSrcweir bDoThis = sal_False;
686cdf0e10cSrcweir
687cdf0e10cSrcweir if (nLevelCount==0) // nichts tun
688cdf0e10cSrcweir return sal_True;
689cdf0e10cSrcweir
690cdf0e10cSrcweir SCCOL* nGroupCol = rParam.nField; // Spalten nach denen
691cdf0e10cSrcweir // gruppiert wird
692cdf0e10cSrcweir
693cdf0e10cSrcweir // #44444# Durch (leer) als eigene Kategorie muss immer auf
694cdf0e10cSrcweir // Teilergebniszeilen aus den anderen Spalten getestet werden
695cdf0e10cSrcweir // (frueher nur, wenn eine Spalte mehrfach vorkam)
696cdf0e10cSrcweir sal_Bool bTestPrevSub = ( nLevelCount > 1 );
697cdf0e10cSrcweir
698cdf0e10cSrcweir String aSubString;
699cdf0e10cSrcweir String aOutString;
700cdf0e10cSrcweir
701cdf0e10cSrcweir sal_Bool bIgnoreCase = !rParam.bCaseSens;
702cdf0e10cSrcweir
703cdf0e10cSrcweir String *pCompString[MAXSUBTOTAL]; // Pointer wegen Compiler-Problemen
704cdf0e10cSrcweir for (i=0; i<MAXSUBTOTAL; i++)
705cdf0e10cSrcweir pCompString[i] = new String;
706cdf0e10cSrcweir
707cdf0e10cSrcweir //! sortieren?
708cdf0e10cSrcweir
709cdf0e10cSrcweir ScStyleSheet* pStyle = (ScStyleSheet*) pDocument->GetStyleSheetPool()->Find(
710cdf0e10cSrcweir ScGlobal::GetRscString(STR_STYLENAME_RESULT), SFX_STYLE_FAMILY_PARA );
711cdf0e10cSrcweir
712cdf0e10cSrcweir sal_Bool bSpaceLeft = sal_True; // Erfolg beim Einfuegen?
713cdf0e10cSrcweir
714cdf0e10cSrcweir // #90279# For performance reasons collect formula entries so their
715cdf0e10cSrcweir // references don't have to be tested for updates each time a new row is
716cdf0e10cSrcweir // inserted
717cdf0e10cSrcweir RowEntry aRowEntry;
718cdf0e10cSrcweir ::std::vector< RowEntry > aRowVector;
719cdf0e10cSrcweir
720cdf0e10cSrcweir for (sal_uInt16 nLevel=0; nLevel<=nLevelCount && bSpaceLeft; nLevel++) // incl. Gesamtergebnis
721cdf0e10cSrcweir {
722cdf0e10cSrcweir sal_Bool bTotal = ( nLevel == nLevelCount );
723cdf0e10cSrcweir aRowEntry.nGroupNo = bTotal ? 0 : (nLevelCount-nLevel-1);
724cdf0e10cSrcweir
725cdf0e10cSrcweir // how many results per level
726cdf0e10cSrcweir SCCOL nResCount = rParam.nSubTotals[aRowEntry.nGroupNo];
727cdf0e10cSrcweir // result functions
728cdf0e10cSrcweir ScSubTotalFunc* eResFunc = rParam.pFunctions[aRowEntry.nGroupNo];
729cdf0e10cSrcweir
730cdf0e10cSrcweir if (nResCount > 0) // sonst nur sortieren
731cdf0e10cSrcweir {
732cdf0e10cSrcweir for (i=0; i<=aRowEntry.nGroupNo; i++)
733cdf0e10cSrcweir {
734cdf0e10cSrcweir GetString( nGroupCol[i], nStartRow, aSubString );
735cdf0e10cSrcweir if ( bIgnoreCase )
736cdf0e10cSrcweir *pCompString[i] = ScGlobal::pCharClass->upper( aSubString );
737cdf0e10cSrcweir else
738cdf0e10cSrcweir *pCompString[i] = aSubString;
739cdf0e10cSrcweir } // aSubString bleibt auf dem letzten stehen
740cdf0e10cSrcweir
741cdf0e10cSrcweir sal_Bool bBlockVis = sal_False; // Gruppe eingeblendet?
742cdf0e10cSrcweir aRowEntry.nSubStartRow = nStartRow;
743cdf0e10cSrcweir for (SCROW nRow=nStartRow; nRow<=nEndRow+1 && bSpaceLeft; nRow++)
744cdf0e10cSrcweir {
745cdf0e10cSrcweir sal_Bool bChanged;
746cdf0e10cSrcweir if (nRow>nEndRow)
747cdf0e10cSrcweir bChanged = sal_True;
748cdf0e10cSrcweir else
749cdf0e10cSrcweir {
750cdf0e10cSrcweir bChanged = sal_False;
751cdf0e10cSrcweir if (!bTotal)
752cdf0e10cSrcweir {
753cdf0e10cSrcweir String aString;
754cdf0e10cSrcweir for (i=0; i<=aRowEntry.nGroupNo && !bChanged; i++)
755cdf0e10cSrcweir {
756cdf0e10cSrcweir GetString( nGroupCol[i], nRow, aString );
757cdf0e10cSrcweir if (bIgnoreCase)
758cdf0e10cSrcweir ScGlobal::pCharClass->toUpper( aString );
759cdf0e10cSrcweir // #41427# wenn sortiert, ist "leer" eine eigene Gruppe
760cdf0e10cSrcweir // sonst sind leere Zellen unten erlaubt
761cdf0e10cSrcweir bChanged = ( ( aString.Len() || rParam.bDoSort ) &&
762cdf0e10cSrcweir aString != *pCompString[i] );
763cdf0e10cSrcweir }
764cdf0e10cSrcweir if ( bChanged && bTestPrevSub )
765cdf0e10cSrcweir {
766cdf0e10cSrcweir // No group change on rows that will contain subtotal formulas
767cdf0e10cSrcweir for ( ::std::vector< RowEntry >::const_iterator
768cdf0e10cSrcweir iEntry( aRowVector.begin());
769cdf0e10cSrcweir iEntry != aRowVector.end(); ++iEntry)
770cdf0e10cSrcweir {
771cdf0e10cSrcweir if ( iEntry->nDestRow == nRow )
772cdf0e10cSrcweir {
773cdf0e10cSrcweir bChanged = sal_False;
774cdf0e10cSrcweir break;
775cdf0e10cSrcweir }
776cdf0e10cSrcweir }
777cdf0e10cSrcweir }
778cdf0e10cSrcweir }
779cdf0e10cSrcweir }
780cdf0e10cSrcweir if ( bChanged )
781cdf0e10cSrcweir {
782cdf0e10cSrcweir aRowEntry.nDestRow = nRow;
783cdf0e10cSrcweir aRowEntry.nFuncStart = aRowEntry.nSubStartRow;
784cdf0e10cSrcweir aRowEntry.nFuncEnd = nRow-1;
785cdf0e10cSrcweir
786cdf0e10cSrcweir bSpaceLeft = pDocument->InsertRow( 0, nTab, MAXCOL, nTab,
787cdf0e10cSrcweir aRowEntry.nDestRow, 1 );
788cdf0e10cSrcweir DBShowRow( aRowEntry.nDestRow, bBlockVis );
789cdf0e10cSrcweir bBlockVis = sal_False;
790cdf0e10cSrcweir if ( rParam.bPagebreak && nRow < MAXROW &&
791cdf0e10cSrcweir aRowEntry.nSubStartRow != nStartRow && nLevel == 0)
792cdf0e10cSrcweir SetRowBreak(aRowEntry.nSubStartRow, false, true);
793cdf0e10cSrcweir
794cdf0e10cSrcweir if (bSpaceLeft)
795cdf0e10cSrcweir {
796cdf0e10cSrcweir for ( ::std::vector< RowEntry >::iterator iMove(
797cdf0e10cSrcweir aRowVector.begin() );
798cdf0e10cSrcweir iMove != aRowVector.end(); ++iMove)
799cdf0e10cSrcweir {
800cdf0e10cSrcweir if ( aRowEntry.nDestRow <= iMove->nSubStartRow )
801cdf0e10cSrcweir ++iMove->nSubStartRow;
802cdf0e10cSrcweir if ( aRowEntry.nDestRow <= iMove->nDestRow )
803cdf0e10cSrcweir ++iMove->nDestRow;
804cdf0e10cSrcweir if ( aRowEntry.nDestRow <= iMove->nFuncStart )
805cdf0e10cSrcweir ++iMove->nFuncStart;
806cdf0e10cSrcweir if ( aRowEntry.nDestRow <= iMove->nFuncEnd )
807cdf0e10cSrcweir ++iMove->nFuncEnd;
808cdf0e10cSrcweir }
809cdf0e10cSrcweir // collect formula positions
810cdf0e10cSrcweir aRowVector.push_back( aRowEntry );
811cdf0e10cSrcweir
812cdf0e10cSrcweir if (bTotal) // "Gesamtergebnis"
813cdf0e10cSrcweir aOutString = ScGlobal::GetRscString( STR_TABLE_GESAMTERGEBNIS );
814cdf0e10cSrcweir else
815cdf0e10cSrcweir { // " Ergebnis"
816cdf0e10cSrcweir aOutString = aSubString;
817cdf0e10cSrcweir if (!aOutString.Len())
818cdf0e10cSrcweir aOutString = ScGlobal::GetRscString( STR_EMPTYDATA );
819cdf0e10cSrcweir aOutString += ' ';
820cdf0e10cSrcweir sal_uInt16 nStrId = STR_TABLE_ERGEBNIS;
821cdf0e10cSrcweir if ( nResCount == 1 )
822cdf0e10cSrcweir switch ( eResFunc[0] )
823cdf0e10cSrcweir {
824cdf0e10cSrcweir case SUBTOTAL_FUNC_AVE: nStrId = STR_FUN_TEXT_AVG; break;
825cdf0e10cSrcweir case SUBTOTAL_FUNC_CNT:
826cdf0e10cSrcweir case SUBTOTAL_FUNC_CNT2: nStrId = STR_FUN_TEXT_COUNT; break;
827cdf0e10cSrcweir case SUBTOTAL_FUNC_MAX: nStrId = STR_FUN_TEXT_MAX; break;
828cdf0e10cSrcweir case SUBTOTAL_FUNC_MIN: nStrId = STR_FUN_TEXT_MIN; break;
829cdf0e10cSrcweir case SUBTOTAL_FUNC_PROD: nStrId = STR_FUN_TEXT_PRODUCT; break;
830cdf0e10cSrcweir case SUBTOTAL_FUNC_STD:
831cdf0e10cSrcweir case SUBTOTAL_FUNC_STDP: nStrId = STR_FUN_TEXT_STDDEV; break;
832cdf0e10cSrcweir case SUBTOTAL_FUNC_SUM: nStrId = STR_FUN_TEXT_SUM; break;
833cdf0e10cSrcweir case SUBTOTAL_FUNC_VAR:
834cdf0e10cSrcweir case SUBTOTAL_FUNC_VARP: nStrId = STR_FUN_TEXT_VAR; break;
835cdf0e10cSrcweir default:
836cdf0e10cSrcweir {
837cdf0e10cSrcweir // added to avoid warnings
838cdf0e10cSrcweir }
839cdf0e10cSrcweir }
840cdf0e10cSrcweir aOutString += ScGlobal::GetRscString( nStrId );
841cdf0e10cSrcweir }
842cdf0e10cSrcweir SetString( nGroupCol[aRowEntry.nGroupNo], aRowEntry.nDestRow, nTab, aOutString );
843cdf0e10cSrcweir ApplyStyle( nGroupCol[aRowEntry.nGroupNo], aRowEntry.nDestRow, *pStyle );
844cdf0e10cSrcweir
845cdf0e10cSrcweir ++nRow;
846cdf0e10cSrcweir ++nEndRow;
847cdf0e10cSrcweir aRowEntry.nSubStartRow = nRow;
848cdf0e10cSrcweir for (i=0; i<=aRowEntry.nGroupNo; i++)
849cdf0e10cSrcweir {
850cdf0e10cSrcweir GetString( nGroupCol[i], nRow, aSubString );
851cdf0e10cSrcweir if ( bIgnoreCase )
852cdf0e10cSrcweir *pCompString[i] = ScGlobal::pCharClass->upper( aSubString );
853cdf0e10cSrcweir else
854cdf0e10cSrcweir *pCompString[i] = aSubString;
855cdf0e10cSrcweir }
856cdf0e10cSrcweir }
857cdf0e10cSrcweir }
858cdf0e10cSrcweir bBlockVis = !RowFiltered(nRow);
859cdf0e10cSrcweir }
860cdf0e10cSrcweir }
861cdf0e10cSrcweir else
862cdf0e10cSrcweir {
863cdf0e10cSrcweir // DBG_ERROR( "nSubTotals==0 bei DoSubTotals" );
864cdf0e10cSrcweir }
865cdf0e10cSrcweir }
866cdf0e10cSrcweir
867cdf0e10cSrcweir // now insert the formulas
868cdf0e10cSrcweir ScComplexRefData aRef;
869cdf0e10cSrcweir aRef.InitFlags();
870cdf0e10cSrcweir aRef.Ref1.nTab = nTab;
871cdf0e10cSrcweir aRef.Ref2.nTab = nTab;
872cdf0e10cSrcweir for ( ::std::vector< RowEntry >::const_iterator iEntry( aRowVector.begin());
873cdf0e10cSrcweir iEntry != aRowVector.end(); ++iEntry)
874cdf0e10cSrcweir {
875cdf0e10cSrcweir SCCOL nResCount = rParam.nSubTotals[iEntry->nGroupNo];
876cdf0e10cSrcweir SCCOL* nResCols = rParam.pSubTotals[iEntry->nGroupNo];
877cdf0e10cSrcweir ScSubTotalFunc* eResFunc = rParam.pFunctions[iEntry->nGroupNo];
878cdf0e10cSrcweir for ( SCCOL nResult=0; nResult < nResCount; ++nResult )
879cdf0e10cSrcweir {
880cdf0e10cSrcweir aRef.Ref1.nCol = nResCols[nResult];
881cdf0e10cSrcweir aRef.Ref1.nRow = iEntry->nFuncStart;
882cdf0e10cSrcweir aRef.Ref2.nCol = nResCols[nResult];
883cdf0e10cSrcweir aRef.Ref2.nRow = iEntry->nFuncEnd;
884cdf0e10cSrcweir
885cdf0e10cSrcweir ScTokenArray aArr;
886cdf0e10cSrcweir aArr.AddOpCode( ocSubTotal );
887cdf0e10cSrcweir aArr.AddOpCode( ocOpen );
888cdf0e10cSrcweir aArr.AddDouble( (double) eResFunc[nResult] );
889cdf0e10cSrcweir aArr.AddOpCode( ocSep );
890cdf0e10cSrcweir aArr.AddDoubleReference( aRef );
891cdf0e10cSrcweir aArr.AddOpCode( ocClose );
892cdf0e10cSrcweir aArr.AddOpCode( ocStop );
893cdf0e10cSrcweir ScBaseCell* pCell = new ScFormulaCell( pDocument, ScAddress(
894cdf0e10cSrcweir nResCols[nResult], iEntry->nDestRow, nTab), &aArr );
895cdf0e10cSrcweir PutCell( nResCols[nResult], iEntry->nDestRow, pCell );
896cdf0e10cSrcweir
897cdf0e10cSrcweir if ( nResCols[nResult] != nGroupCol[iEntry->nGroupNo] )
898cdf0e10cSrcweir {
899cdf0e10cSrcweir ApplyStyle( nResCols[nResult], iEntry->nDestRow, *pStyle );
900cdf0e10cSrcweir
901cdf0e10cSrcweir // Zahlformat loeschen
902cdf0e10cSrcweir lcl_RemoveNumberFormat( this, nResCols[nResult], iEntry->nDestRow );
903cdf0e10cSrcweir }
904cdf0e10cSrcweir }
905cdf0e10cSrcweir
906cdf0e10cSrcweir }
907cdf0e10cSrcweir
908cdf0e10cSrcweir //! je nach Einstellung Zwischensummen-Zeilen nach oben verschieben ?
909cdf0e10cSrcweir
910cdf0e10cSrcweir //! Outlines direkt erzeugen?
911cdf0e10cSrcweir
912cdf0e10cSrcweir if (bSpaceLeft)
913cdf0e10cSrcweir DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
914cdf0e10cSrcweir
915cdf0e10cSrcweir for (i=0; i<MAXSUBTOTAL; i++)
916cdf0e10cSrcweir delete pCompString[i];
917cdf0e10cSrcweir
918cdf0e10cSrcweir rParam.nRow2 = nEndRow; // neues Ende
919cdf0e10cSrcweir return bSpaceLeft;
920cdf0e10cSrcweir }
921cdf0e10cSrcweir
922cdf0e10cSrcweir
ValidQuery(SCROW nRow,const ScQueryParam & rParam,sal_Bool * pSpecial,ScBaseCell * pCell,sal_Bool * pbTestEqualCondition)923cdf0e10cSrcweir sal_Bool ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
924cdf0e10cSrcweir sal_Bool* pSpecial /* =NULL */ , ScBaseCell* pCell /* =NULL */ ,
925cdf0e10cSrcweir sal_Bool* pbTestEqualCondition /* = NULL */ )
926cdf0e10cSrcweir {
927cdf0e10cSrcweir if (!rParam.GetEntry(0).bDoQuery)
928cdf0e10cSrcweir return sal_True;
929cdf0e10cSrcweir
930cdf0e10cSrcweir //---------------------------------------------------------------
931cdf0e10cSrcweir
932cdf0e10cSrcweir const SCSIZE nFixedBools = 32;
933cdf0e10cSrcweir sal_Bool aBool[nFixedBools];
934cdf0e10cSrcweir sal_Bool aTest[nFixedBools];
935cdf0e10cSrcweir SCSIZE nEntryCount = rParam.GetEntryCount();
936cdf0e10cSrcweir sal_Bool* pPasst = ( nEntryCount <= nFixedBools ? &aBool[0] : new sal_Bool[nEntryCount] );
937cdf0e10cSrcweir sal_Bool* pTest = ( nEntryCount <= nFixedBools ? &aTest[0] : new sal_Bool[nEntryCount] );
938cdf0e10cSrcweir
939cdf0e10cSrcweir long nPos = -1;
940cdf0e10cSrcweir SCSIZE i = 0;
941cdf0e10cSrcweir sal_Bool bMatchWholeCell = pDocument->GetDocOptions().IsMatchWholeCell();
942cdf0e10cSrcweir CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() :
943cdf0e10cSrcweir ScGlobal::GetCollator());
944cdf0e10cSrcweir ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ?
945cdf0e10cSrcweir ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration());
946cdf0e10cSrcweir
947cdf0e10cSrcweir while ( (i < nEntryCount) && rParam.GetEntry(i).bDoQuery )
948cdf0e10cSrcweir {
949cdf0e10cSrcweir ScQueryEntry& rEntry = rParam.GetEntry(i);
950cdf0e10cSrcweir // we can only handle one single direct query
951cdf0e10cSrcweir if ( !pCell || i > 0 )
952cdf0e10cSrcweir pCell = GetCell( static_cast<SCCOL>(rEntry.nField), nRow );
953cdf0e10cSrcweir
954cdf0e10cSrcweir sal_Bool bOk = sal_False;
955cdf0e10cSrcweir sal_Bool bTestEqual = sal_False;
956cdf0e10cSrcweir
957cdf0e10cSrcweir if ( pSpecial && pSpecial[i] )
958cdf0e10cSrcweir {
959cdf0e10cSrcweir if (rEntry.nVal == SC_EMPTYFIELDS)
960cdf0e10cSrcweir bOk = !( aCol[rEntry.nField].HasDataAt( nRow ) );
961cdf0e10cSrcweir else // if (rEntry.nVal == SC_NONEMPTYFIELDS)
962cdf0e10cSrcweir bOk = aCol[rEntry.nField].HasDataAt( nRow );
963cdf0e10cSrcweir }
964cdf0e10cSrcweir else if ( !rEntry.bQueryByString && (pCell ? pCell->HasValueData() :
965cdf0e10cSrcweir HasValueData( static_cast<SCCOL>(rEntry.nField), nRow)))
966cdf0e10cSrcweir { // by Value
967cdf0e10cSrcweir double nCellVal;
968cdf0e10cSrcweir if ( pCell )
969cdf0e10cSrcweir {
970cdf0e10cSrcweir switch ( pCell->GetCellType() )
971cdf0e10cSrcweir {
972cdf0e10cSrcweir case CELLTYPE_VALUE :
973cdf0e10cSrcweir nCellVal = ((ScValueCell*)pCell)->GetValue();
974cdf0e10cSrcweir break;
975cdf0e10cSrcweir case CELLTYPE_FORMULA :
976cdf0e10cSrcweir nCellVal = ((ScFormulaCell*)pCell)->GetValue();
977cdf0e10cSrcweir break;
978cdf0e10cSrcweir default:
979cdf0e10cSrcweir nCellVal = 0.0;
980cdf0e10cSrcweir }
981cdf0e10cSrcweir
982cdf0e10cSrcweir }
983cdf0e10cSrcweir else
984cdf0e10cSrcweir nCellVal = GetValue( static_cast<SCCOL>(rEntry.nField), nRow );
985cdf0e10cSrcweir
986cdf0e10cSrcweir /* NOTE: lcl_PrepareQuery() prepares a filter query such that if a
987cdf0e10cSrcweir * date+time format was queried rEntry.bQueryByDate is not set. In
988cdf0e10cSrcweir * case other queries wanted to use this mechanism they should do
989cdf0e10cSrcweir * the same, in other words only if rEntry.nVal is an integer value
990cdf0e10cSrcweir * rEntry.bQueryByDate should be true and the time fraction be
991cdf0e10cSrcweir * stripped here. */
992cdf0e10cSrcweir if (rEntry.bQueryByDate)
993cdf0e10cSrcweir {
994cdf0e10cSrcweir sal_uInt32 nNumFmt = GetNumberFormat(static_cast<SCCOL>(rEntry.nField), nRow);
995cdf0e10cSrcweir const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt);
996cdf0e10cSrcweir if (pEntry)
997cdf0e10cSrcweir {
998cdf0e10cSrcweir short nNumFmtType = pEntry->GetType();
999cdf0e10cSrcweir /* NOTE: Omitting the check for absence of
1000cdf0e10cSrcweir * NUMBERFORMAT_TIME would include also date+time formatted
1001cdf0e10cSrcweir * values of the same day. That may be desired in some
1002cdf0e10cSrcweir * cases, querying all time values of a day, but confusing
1003cdf0e10cSrcweir * in other cases. A user can always setup a standard
1004cdf0e10cSrcweir * filter query for x >= date AND x < date+1 */
1005cdf0e10cSrcweir if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
1006cdf0e10cSrcweir {
1007cdf0e10cSrcweir // The format is of date type. Strip off the time
1008cdf0e10cSrcweir // element.
1009cdf0e10cSrcweir nCellVal = ::rtl::math::approxFloor(nCellVal);
1010cdf0e10cSrcweir }
1011cdf0e10cSrcweir }
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir
1014cdf0e10cSrcweir switch (rEntry.eOp)
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir case SC_EQUAL :
1017cdf0e10cSrcweir bOk = ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1018cdf0e10cSrcweir break;
1019cdf0e10cSrcweir case SC_LESS :
1020cdf0e10cSrcweir bOk = (nCellVal < rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1021cdf0e10cSrcweir break;
1022cdf0e10cSrcweir case SC_GREATER :
1023cdf0e10cSrcweir bOk = (nCellVal > rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1024cdf0e10cSrcweir break;
1025cdf0e10cSrcweir case SC_LESS_EQUAL :
1026cdf0e10cSrcweir bOk = (nCellVal < rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1027cdf0e10cSrcweir if ( bOk && pbTestEqualCondition )
1028cdf0e10cSrcweir bTestEqual = ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1029cdf0e10cSrcweir break;
1030cdf0e10cSrcweir case SC_GREATER_EQUAL :
1031cdf0e10cSrcweir bOk = (nCellVal > rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1032cdf0e10cSrcweir if ( bOk && pbTestEqualCondition )
1033cdf0e10cSrcweir bTestEqual = ::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1034cdf0e10cSrcweir break;
1035cdf0e10cSrcweir case SC_NOT_EQUAL :
1036cdf0e10cSrcweir bOk = !::rtl::math::approxEqual( nCellVal, rEntry.nVal );
1037cdf0e10cSrcweir break;
1038cdf0e10cSrcweir default:
1039cdf0e10cSrcweir {
1040cdf0e10cSrcweir // added to avoid warnings
1041cdf0e10cSrcweir }
1042cdf0e10cSrcweir }
1043cdf0e10cSrcweir }
1044cdf0e10cSrcweir else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) ||
1045cdf0e10cSrcweir (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN ||
1046cdf0e10cSrcweir rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH ||
1047cdf0e10cSrcweir rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH) ||
1048cdf0e10cSrcweir (rEntry.bQueryByString && (pCell ? pCell->HasStringData() :
1049cdf0e10cSrcweir HasStringData(
1050cdf0e10cSrcweir static_cast<SCCOL>(rEntry.nField),
1051cdf0e10cSrcweir nRow))))
1052cdf0e10cSrcweir { // by String
1053cdf0e10cSrcweir String aCellStr;
1054cdf0e10cSrcweir if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
1055cdf0e10cSrcweir || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
1056cdf0e10cSrcweir || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
1057cdf0e10cSrcweir bMatchWholeCell = sal_False;
1058cdf0e10cSrcweir if ( pCell )
1059cdf0e10cSrcweir {
1060cdf0e10cSrcweir if (pCell->GetCellType() != CELLTYPE_NOTE)
1061cdf0e10cSrcweir {
1062cdf0e10cSrcweir sal_uLong nFormat = GetNumberFormat( static_cast<SCCOL>(rEntry.nField), nRow );
1063cdf0e10cSrcweir ScCellFormat::GetInputString( pCell, nFormat, aCellStr, *(pDocument->GetFormatTable()) );
1064cdf0e10cSrcweir }
1065cdf0e10cSrcweir }
1066cdf0e10cSrcweir else
1067cdf0e10cSrcweir GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr );
1068cdf0e10cSrcweir
1069cdf0e10cSrcweir sal_Bool bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL)
1070cdf0e10cSrcweir || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS)
1071cdf0e10cSrcweir || (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH)
1072cdf0e10cSrcweir || (rEntry.eOp == SC_ENDS_WITH) || (rEntry.eOp == SC_DOES_NOT_BEGIN_WITH)
1073cdf0e10cSrcweir || (rEntry.eOp == SC_DOES_NOT_END_WITH)));
1074cdf0e10cSrcweir sal_Bool bTestRegExp = (pbTestEqualCondition && rParam.bRegExp
1075cdf0e10cSrcweir && ((rEntry.eOp == SC_LESS_EQUAL)
1076cdf0e10cSrcweir || (rEntry.eOp == SC_GREATER_EQUAL)));
1077cdf0e10cSrcweir if ( bRealRegExp || bTestRegExp )
1078cdf0e10cSrcweir {
1079cdf0e10cSrcweir xub_StrLen nStart = 0;
1080cdf0e10cSrcweir xub_StrLen nEnd = aCellStr.Len();
1081cdf0e10cSrcweir
1082cdf0e10cSrcweir // from 614 on, nEnd is behind the found text
1083cdf0e10cSrcweir sal_Bool bMatch = sal_False;
1084cdf0e10cSrcweir if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
1085cdf0e10cSrcweir {
1086cdf0e10cSrcweir nEnd = 0;
1087cdf0e10cSrcweir nStart = aCellStr.Len();
1088cdf0e10cSrcweir bMatch = (sal_Bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
1089cdf0e10cSrcweir ->SearchBkwrd( aCellStr, &nStart, &nEnd );
1090cdf0e10cSrcweir }
1091cdf0e10cSrcweir else
1092cdf0e10cSrcweir {
1093cdf0e10cSrcweir bMatch = (sal_Bool) rEntry.GetSearchTextPtr( rParam.bCaseSens )
1094cdf0e10cSrcweir ->SearchFrwrd( aCellStr, &nStart, &nEnd );
1095cdf0e10cSrcweir }
1096cdf0e10cSrcweir if ( bMatch && bMatchWholeCell
1097cdf0e10cSrcweir && (nStart != 0 || nEnd != aCellStr.Len()) )
1098cdf0e10cSrcweir bMatch = sal_False; // RegExp must match entire cell string
1099cdf0e10cSrcweir if ( bRealRegExp )
1100cdf0e10cSrcweir switch (rEntry.eOp)
1101cdf0e10cSrcweir {
1102cdf0e10cSrcweir case SC_EQUAL:
1103cdf0e10cSrcweir case SC_CONTAINS:
1104cdf0e10cSrcweir bOk = bMatch;
1105cdf0e10cSrcweir break;
1106cdf0e10cSrcweir case SC_NOT_EQUAL:
1107cdf0e10cSrcweir case SC_DOES_NOT_CONTAIN:
1108cdf0e10cSrcweir bOk = !bMatch;
1109cdf0e10cSrcweir break;
1110cdf0e10cSrcweir case SC_BEGINS_WITH:
1111cdf0e10cSrcweir bOk = ( bMatch && (nStart == 0) );
1112cdf0e10cSrcweir break;
1113cdf0e10cSrcweir case SC_DOES_NOT_BEGIN_WITH:
1114cdf0e10cSrcweir bOk = !( bMatch && (nStart == 0) );
1115cdf0e10cSrcweir break;
1116cdf0e10cSrcweir case SC_ENDS_WITH:
1117cdf0e10cSrcweir bOk = ( bMatch && (nEnd == aCellStr.Len()) );
1118cdf0e10cSrcweir break;
1119cdf0e10cSrcweir case SC_DOES_NOT_END_WITH:
1120cdf0e10cSrcweir bOk = !( bMatch && (nEnd == aCellStr.Len()) );
1121cdf0e10cSrcweir break;
1122cdf0e10cSrcweir default:
1123cdf0e10cSrcweir {
1124cdf0e10cSrcweir // added to avoid warnings
1125cdf0e10cSrcweir }
1126cdf0e10cSrcweir }
1127cdf0e10cSrcweir else
1128cdf0e10cSrcweir bTestEqual = bMatch;
1129cdf0e10cSrcweir }
1130cdf0e10cSrcweir if ( !bRealRegExp )
1131cdf0e10cSrcweir {
1132cdf0e10cSrcweir if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL
1133cdf0e10cSrcweir || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN
1134cdf0e10cSrcweir || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH
1135cdf0e10cSrcweir || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH )
1136cdf0e10cSrcweir {
1137cdf0e10cSrcweir if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 )
1138cdf0e10cSrcweir {
1139cdf0e10cSrcweir // #i18374# When used from functions (match, countif, sumif, vlookup, hlookup, lookup),
1140cdf0e10cSrcweir // the query value is assigned directly, and the string is empty. In that case,
1141cdf0e10cSrcweir // don't find any string (isEqual would find empty string results in formula cells).
1142cdf0e10cSrcweir bOk = sal_False;
1143cdf0e10cSrcweir if ( rEntry.eOp == SC_NOT_EQUAL )
1144cdf0e10cSrcweir bOk = !bOk;
1145cdf0e10cSrcweir }
1146cdf0e10cSrcweir else if ( bMatchWholeCell )
1147cdf0e10cSrcweir {
1148cdf0e10cSrcweir bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr );
1149cdf0e10cSrcweir if ( rEntry.eOp == SC_NOT_EQUAL )
1150cdf0e10cSrcweir bOk = !bOk;
1151cdf0e10cSrcweir }
1152cdf0e10cSrcweir else
1153cdf0e10cSrcweir {
1154cdf0e10cSrcweir String aCell( pTransliteration->transliterate(
1155cdf0e10cSrcweir aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(),
1156cdf0e10cSrcweir NULL ) );
1157cdf0e10cSrcweir String aQuer( pTransliteration->transliterate(
1158cdf0e10cSrcweir *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(),
1159cdf0e10cSrcweir NULL ) );
1160cdf0e10cSrcweir xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH
1161cdf0e10cSrcweir || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0;
1162cdf0e10cSrcweir xub_StrLen nStrPos = aCell.Search( aQuer, nIndex );
1163cdf0e10cSrcweir switch (rEntry.eOp)
1164cdf0e10cSrcweir {
1165cdf0e10cSrcweir case SC_EQUAL:
1166cdf0e10cSrcweir case SC_CONTAINS:
1167cdf0e10cSrcweir bOk = ( nStrPos != STRING_NOTFOUND );
1168cdf0e10cSrcweir break;
1169cdf0e10cSrcweir case SC_NOT_EQUAL:
1170cdf0e10cSrcweir case SC_DOES_NOT_CONTAIN:
1171cdf0e10cSrcweir bOk = ( nStrPos == STRING_NOTFOUND );
1172cdf0e10cSrcweir break;
1173cdf0e10cSrcweir case SC_BEGINS_WITH:
1174cdf0e10cSrcweir bOk = ( nStrPos == 0 );
1175cdf0e10cSrcweir break;
1176cdf0e10cSrcweir case SC_DOES_NOT_BEGIN_WITH:
1177cdf0e10cSrcweir bOk = ( nStrPos != 0 );
1178cdf0e10cSrcweir break;
1179cdf0e10cSrcweir case SC_ENDS_WITH:
1180cdf0e10cSrcweir bOk = ( nStrPos + aQuer.Len() == aCell.Len() );
1181cdf0e10cSrcweir break;
1182cdf0e10cSrcweir case SC_DOES_NOT_END_WITH:
1183cdf0e10cSrcweir bOk = ( nStrPos + aQuer.Len() != aCell.Len() );
1184cdf0e10cSrcweir break;
1185cdf0e10cSrcweir default:
1186cdf0e10cSrcweir {
1187cdf0e10cSrcweir // added to avoid warnings
1188cdf0e10cSrcweir }
1189cdf0e10cSrcweir }
1190cdf0e10cSrcweir }
1191cdf0e10cSrcweir }
1192cdf0e10cSrcweir else
1193cdf0e10cSrcweir { // use collator here because data was probably sorted
1194cdf0e10cSrcweir sal_Int32 nCompare = pCollator->compareString(
1195cdf0e10cSrcweir aCellStr, *rEntry.pStr );
1196cdf0e10cSrcweir switch (rEntry.eOp)
1197cdf0e10cSrcweir {
1198cdf0e10cSrcweir case SC_LESS :
1199cdf0e10cSrcweir bOk = (nCompare < 0);
1200cdf0e10cSrcweir break;
1201cdf0e10cSrcweir case SC_GREATER :
1202cdf0e10cSrcweir bOk = (nCompare > 0);
1203cdf0e10cSrcweir break;
1204cdf0e10cSrcweir case SC_LESS_EQUAL :
1205cdf0e10cSrcweir bOk = (nCompare <= 0);
1206cdf0e10cSrcweir if ( bOk && pbTestEqualCondition && !bTestEqual )
1207cdf0e10cSrcweir bTestEqual = (nCompare == 0);
1208cdf0e10cSrcweir break;
1209cdf0e10cSrcweir case SC_GREATER_EQUAL :
1210cdf0e10cSrcweir bOk = (nCompare >= 0);
1211cdf0e10cSrcweir if ( bOk && pbTestEqualCondition && !bTestEqual )
1212cdf0e10cSrcweir bTestEqual = (nCompare == 0);
1213cdf0e10cSrcweir break;
1214cdf0e10cSrcweir default:
1215cdf0e10cSrcweir {
1216cdf0e10cSrcweir // added to avoid warnings
1217cdf0e10cSrcweir }
1218cdf0e10cSrcweir }
1219cdf0e10cSrcweir }
1220cdf0e10cSrcweir }
1221cdf0e10cSrcweir }
1222cdf0e10cSrcweir else if (rParam.bMixedComparison)
1223cdf0e10cSrcweir {
1224cdf0e10cSrcweir if (rEntry.bQueryByString &&
1225cdf0e10cSrcweir (rEntry.eOp == SC_LESS || rEntry.eOp == SC_LESS_EQUAL) &&
1226cdf0e10cSrcweir (pCell ? pCell->HasValueData() :
1227cdf0e10cSrcweir HasValueData( static_cast<SCCOL>(rEntry.nField), nRow)))
1228cdf0e10cSrcweir {
1229cdf0e10cSrcweir bOk = sal_True;
1230cdf0e10cSrcweir }
1231cdf0e10cSrcweir else if (!rEntry.bQueryByString &&
1232cdf0e10cSrcweir (rEntry.eOp == SC_GREATER || rEntry.eOp == SC_GREATER_EQUAL) &&
1233cdf0e10cSrcweir (pCell ? pCell->HasStringData() :
1234cdf0e10cSrcweir HasStringData( static_cast<SCCOL>(rEntry.nField), nRow)))
1235cdf0e10cSrcweir {
1236cdf0e10cSrcweir bOk = sal_True;
1237cdf0e10cSrcweir }
1238cdf0e10cSrcweir }
1239cdf0e10cSrcweir
1240cdf0e10cSrcweir if (nPos == -1)
1241cdf0e10cSrcweir {
1242cdf0e10cSrcweir nPos++;
1243cdf0e10cSrcweir pPasst[nPos] = bOk;
1244cdf0e10cSrcweir pTest[nPos] = bTestEqual;
1245cdf0e10cSrcweir }
1246cdf0e10cSrcweir else
1247cdf0e10cSrcweir {
1248cdf0e10cSrcweir if (rEntry.eConnect == SC_AND)
1249cdf0e10cSrcweir {
1250cdf0e10cSrcweir pPasst[nPos] = pPasst[nPos] && bOk;
1251cdf0e10cSrcweir pTest[nPos] = pTest[nPos] && bTestEqual;
1252cdf0e10cSrcweir }
1253cdf0e10cSrcweir else
1254cdf0e10cSrcweir {
1255cdf0e10cSrcweir nPos++;
1256cdf0e10cSrcweir pPasst[nPos] = bOk;
1257cdf0e10cSrcweir pTest[nPos] = bTestEqual;
1258cdf0e10cSrcweir }
1259cdf0e10cSrcweir }
1260cdf0e10cSrcweir i++;
1261cdf0e10cSrcweir }
1262cdf0e10cSrcweir
1263cdf0e10cSrcweir for ( long j=1; j <= nPos; j++ )
1264cdf0e10cSrcweir {
1265cdf0e10cSrcweir pPasst[0] = pPasst[0] || pPasst[j];
1266cdf0e10cSrcweir pTest[0] = pTest[0] || pTest[j];
1267cdf0e10cSrcweir }
1268cdf0e10cSrcweir
1269cdf0e10cSrcweir sal_Bool bRet = pPasst[0];
1270cdf0e10cSrcweir if ( pPasst != &aBool[0] )
1271cdf0e10cSrcweir delete [] pPasst;
1272cdf0e10cSrcweir if ( pbTestEqualCondition )
1273cdf0e10cSrcweir *pbTestEqualCondition = pTest[0];
1274cdf0e10cSrcweir if ( pTest != &aTest[0] )
1275cdf0e10cSrcweir delete [] pTest;
1276cdf0e10cSrcweir
1277cdf0e10cSrcweir return bRet;
1278cdf0e10cSrcweir }
1279cdf0e10cSrcweir
TopTenQuery(ScQueryParam & rParam)1280cdf0e10cSrcweir void ScTable::TopTenQuery( ScQueryParam& rParam )
1281cdf0e10cSrcweir {
1282cdf0e10cSrcweir sal_Bool bSortCollatorInitialized = sal_False;
1283cdf0e10cSrcweir SCSIZE nEntryCount = rParam.GetEntryCount();
1284cdf0e10cSrcweir SCROW nRow1 = (rParam.bHasHeader ? rParam.nRow1 + 1 : rParam.nRow1);
1285cdf0e10cSrcweir SCSIZE nCount = static_cast<SCSIZE>(rParam.nRow2 - nRow1 + 1);
1286cdf0e10cSrcweir for ( SCSIZE i=0; (i<nEntryCount) && (rParam.GetEntry(i).bDoQuery); i++ )
1287cdf0e10cSrcweir {
1288cdf0e10cSrcweir ScQueryEntry& rEntry = rParam.GetEntry(i);
1289cdf0e10cSrcweir switch ( rEntry.eOp )
1290cdf0e10cSrcweir {
1291cdf0e10cSrcweir case SC_TOPVAL:
1292cdf0e10cSrcweir case SC_BOTVAL:
1293cdf0e10cSrcweir case SC_TOPPERC:
1294cdf0e10cSrcweir case SC_BOTPERC:
1295cdf0e10cSrcweir {
1296cdf0e10cSrcweir ScSortParam aLocalSortParam( rParam, static_cast<SCCOL>(rEntry.nField) );
1297cdf0e10cSrcweir aSortParam = aLocalSortParam; // used in CreateSortInfoArray, Compare
1298cdf0e10cSrcweir if ( !bSortCollatorInitialized )
1299cdf0e10cSrcweir {
1300cdf0e10cSrcweir bSortCollatorInitialized = sal_True;
1301cdf0e10cSrcweir InitSortCollator( aLocalSortParam );
1302cdf0e10cSrcweir }
1303cdf0e10cSrcweir ScSortInfoArray* pArray = CreateSortInfoArray( nRow1, rParam.nRow2 );
1304cdf0e10cSrcweir DecoladeRow( pArray, nRow1, rParam.nRow2 );
1305cdf0e10cSrcweir QuickSort( pArray, nRow1, rParam.nRow2 );
1306cdf0e10cSrcweir ScSortInfo** ppInfo = pArray->GetFirstArray();
1307cdf0e10cSrcweir SCSIZE nValidCount = nCount;
1308cdf0e10cSrcweir // keine Note-/Leerzellen zaehlen, sind ans Ende sortiert
1309cdf0e10cSrcweir while ( nValidCount > 0 && ( ppInfo[nValidCount-1]->pCell == NULL ||
1310cdf0e10cSrcweir ppInfo[nValidCount-1]->pCell->GetCellType() == CELLTYPE_NOTE ) )
1311cdf0e10cSrcweir nValidCount--;
1312cdf0e10cSrcweir // keine Strings zaehlen, sind zwischen Value und Leer
1313cdf0e10cSrcweir while ( nValidCount > 0
1314cdf0e10cSrcweir && ppInfo[nValidCount-1]->pCell->HasStringData() )
1315cdf0e10cSrcweir nValidCount--;
1316cdf0e10cSrcweir if ( nValidCount > 0 )
1317cdf0e10cSrcweir {
1318cdf0e10cSrcweir if ( rEntry.bQueryByString )
1319cdf0e10cSrcweir { // dat wird nix
1320cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
1321cdf0e10cSrcweir rEntry.nVal = 10; // 10 bzw. 10%
1322cdf0e10cSrcweir }
1323cdf0e10cSrcweir SCSIZE nVal = (rEntry.nVal >= 1 ? static_cast<SCSIZE>(rEntry.nVal) : 1);
1324cdf0e10cSrcweir SCSIZE nOffset = 0;
1325cdf0e10cSrcweir switch ( rEntry.eOp )
1326cdf0e10cSrcweir {
1327cdf0e10cSrcweir case SC_TOPVAL:
1328cdf0e10cSrcweir {
1329cdf0e10cSrcweir rEntry.eOp = SC_GREATER_EQUAL;
1330cdf0e10cSrcweir if ( nVal > nValidCount )
1331cdf0e10cSrcweir nVal = nValidCount;
1332cdf0e10cSrcweir nOffset = nValidCount - nVal; // 1 <= nVal <= nValidCount
1333cdf0e10cSrcweir }
1334cdf0e10cSrcweir break;
1335cdf0e10cSrcweir case SC_BOTVAL:
1336cdf0e10cSrcweir {
1337cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
1338cdf0e10cSrcweir if ( nVal > nValidCount )
1339cdf0e10cSrcweir nVal = nValidCount;
1340cdf0e10cSrcweir nOffset = nVal - 1; // 1 <= nVal <= nValidCount
1341cdf0e10cSrcweir }
1342cdf0e10cSrcweir break;
1343cdf0e10cSrcweir case SC_TOPPERC:
1344cdf0e10cSrcweir {
1345cdf0e10cSrcweir rEntry.eOp = SC_GREATER_EQUAL;
1346cdf0e10cSrcweir if ( nVal > 100 )
1347cdf0e10cSrcweir nVal = 100;
1348cdf0e10cSrcweir nOffset = nValidCount - (nValidCount * nVal / 100);
1349cdf0e10cSrcweir if ( nOffset >= nValidCount )
1350cdf0e10cSrcweir nOffset = nValidCount - 1;
1351cdf0e10cSrcweir }
1352cdf0e10cSrcweir break;
1353cdf0e10cSrcweir case SC_BOTPERC:
1354cdf0e10cSrcweir {
1355cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
1356cdf0e10cSrcweir if ( nVal > 100 )
1357cdf0e10cSrcweir nVal = 100;
1358cdf0e10cSrcweir nOffset = (nValidCount * nVal / 100);
1359cdf0e10cSrcweir if ( nOffset >= nValidCount )
1360cdf0e10cSrcweir nOffset = nValidCount - 1;
1361cdf0e10cSrcweir }
1362cdf0e10cSrcweir break;
1363cdf0e10cSrcweir default:
1364cdf0e10cSrcweir {
1365cdf0e10cSrcweir // added to avoid warnings
1366cdf0e10cSrcweir }
1367cdf0e10cSrcweir }
1368cdf0e10cSrcweir ScBaseCell* pCell = ppInfo[nOffset]->pCell;
1369cdf0e10cSrcweir if ( pCell->HasValueData() )
1370cdf0e10cSrcweir {
1371cdf0e10cSrcweir if ( pCell->GetCellType() == CELLTYPE_VALUE )
1372cdf0e10cSrcweir rEntry.nVal = ((ScValueCell*)pCell)->GetValue();
1373cdf0e10cSrcweir else
1374cdf0e10cSrcweir rEntry.nVal = ((ScFormulaCell*)pCell)->GetValue();
1375cdf0e10cSrcweir }
1376cdf0e10cSrcweir else
1377cdf0e10cSrcweir {
1378cdf0e10cSrcweir DBG_ERRORFILE( "TopTenQuery: pCell kein ValueData" );
1379cdf0e10cSrcweir rEntry.eOp = SC_GREATER_EQUAL;
1380cdf0e10cSrcweir rEntry.nVal = 0;
1381cdf0e10cSrcweir }
1382cdf0e10cSrcweir }
1383cdf0e10cSrcweir else
1384cdf0e10cSrcweir {
1385cdf0e10cSrcweir rEntry.eOp = SC_GREATER_EQUAL;
1386cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
1387cdf0e10cSrcweir rEntry.nVal = 0;
1388cdf0e10cSrcweir }
1389cdf0e10cSrcweir delete pArray;
1390cdf0e10cSrcweir }
1391cdf0e10cSrcweir break;
1392cdf0e10cSrcweir default:
1393cdf0e10cSrcweir {
1394cdf0e10cSrcweir // added to avoid warnings
1395cdf0e10cSrcweir }
1396cdf0e10cSrcweir }
1397cdf0e10cSrcweir }
1398cdf0e10cSrcweir if ( bSortCollatorInitialized )
1399cdf0e10cSrcweir DestroySortCollator();
1400cdf0e10cSrcweir }
1401cdf0e10cSrcweir
lcl_PrepareQuery(ScDocument * pDoc,ScTable * pTab,ScQueryParam & rParam,sal_Bool * pSpecial)1402cdf0e10cSrcweir static void lcl_PrepareQuery( ScDocument* pDoc, ScTable* pTab, ScQueryParam& rParam, sal_Bool* pSpecial )
1403cdf0e10cSrcweir {
1404cdf0e10cSrcweir bool bTopTen = false;
1405cdf0e10cSrcweir SCSIZE nEntryCount = rParam.GetEntryCount();
1406cdf0e10cSrcweir
1407cdf0e10cSrcweir for ( SCSIZE i = 0; i < nEntryCount; ++i )
1408cdf0e10cSrcweir {
1409cdf0e10cSrcweir pSpecial[i] = sal_False;
1410cdf0e10cSrcweir ScQueryEntry& rEntry = rParam.GetEntry(i);
1411cdf0e10cSrcweir if ( rEntry.bDoQuery )
1412cdf0e10cSrcweir {
1413cdf0e10cSrcweir if ( rEntry.bQueryByString )
1414cdf0e10cSrcweir {
1415cdf0e10cSrcweir sal_uInt32 nIndex = 0;
1416cdf0e10cSrcweir rEntry.bQueryByString = !( pDoc->GetFormatTable()->
1417cdf0e10cSrcweir IsNumberFormat( *rEntry.pStr, nIndex, rEntry.nVal ) );
1418cdf0e10cSrcweir if (rEntry.bQueryByDate)
1419cdf0e10cSrcweir {
1420cdf0e10cSrcweir if (!rEntry.bQueryByString && ((nIndex % SV_COUNTRY_LANGUAGE_OFFSET) != 0))
1421cdf0e10cSrcweir {
1422cdf0e10cSrcweir const SvNumberformat* pEntry = pDoc->GetFormatTable()->GetEntry(nIndex);
1423cdf0e10cSrcweir if (pEntry)
1424cdf0e10cSrcweir {
1425cdf0e10cSrcweir short nNumFmtType = pEntry->GetType();
1426cdf0e10cSrcweir if (!((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME)))
1427cdf0e10cSrcweir rEntry.bQueryByDate = false; // not a date only
1428cdf0e10cSrcweir }
1429cdf0e10cSrcweir else
1430cdf0e10cSrcweir rEntry.bQueryByDate = false; // what the ... not a date
1431cdf0e10cSrcweir }
1432cdf0e10cSrcweir else
1433cdf0e10cSrcweir rEntry.bQueryByDate = false; // not a date
1434cdf0e10cSrcweir }
1435cdf0e10cSrcweir }
1436cdf0e10cSrcweir else
1437cdf0e10cSrcweir {
1438cdf0e10cSrcweir // #58736# call from UNO or second call from autofilter
1439cdf0e10cSrcweir if ( rEntry.nVal == SC_EMPTYFIELDS || rEntry.nVal == SC_NONEMPTYFIELDS )
1440cdf0e10cSrcweir {
1441cdf0e10cSrcweir pSpecial[i] = sal_True;
1442cdf0e10cSrcweir }
1443cdf0e10cSrcweir }
1444cdf0e10cSrcweir if ( !bTopTen )
1445cdf0e10cSrcweir {
1446cdf0e10cSrcweir switch ( rEntry.eOp )
1447cdf0e10cSrcweir {
1448cdf0e10cSrcweir case SC_TOPVAL:
1449cdf0e10cSrcweir case SC_BOTVAL:
1450cdf0e10cSrcweir case SC_TOPPERC:
1451cdf0e10cSrcweir case SC_BOTPERC:
1452cdf0e10cSrcweir {
1453cdf0e10cSrcweir bTopTen = true;
1454cdf0e10cSrcweir }
1455cdf0e10cSrcweir break;
1456cdf0e10cSrcweir default:
1457cdf0e10cSrcweir {
1458cdf0e10cSrcweir }
1459cdf0e10cSrcweir }
1460cdf0e10cSrcweir }
1461cdf0e10cSrcweir }
1462cdf0e10cSrcweir }
1463cdf0e10cSrcweir
1464cdf0e10cSrcweir if ( bTopTen )
1465cdf0e10cSrcweir {
1466cdf0e10cSrcweir pTab->TopTenQuery( rParam );
1467cdf0e10cSrcweir }
1468cdf0e10cSrcweir }
1469cdf0e10cSrcweir
Query(ScQueryParam & rParamOrg,sal_Bool bKeepSub)1470cdf0e10cSrcweir SCSIZE ScTable::Query(ScQueryParam& rParamOrg, sal_Bool bKeepSub)
1471cdf0e10cSrcweir {
1472cdf0e10cSrcweir ScQueryParam aParam( rParamOrg );
1473cdf0e10cSrcweir ScStrCollection aScStrCollection;
1474cdf0e10cSrcweir StrData* pStrData = NULL;
1475cdf0e10cSrcweir
1476cdf0e10cSrcweir sal_Bool bStarted = sal_False;
1477cdf0e10cSrcweir sal_Bool bOldResult = sal_True;
1478cdf0e10cSrcweir SCROW nOldStart = 0;
1479cdf0e10cSrcweir SCROW nOldEnd = 0;
1480cdf0e10cSrcweir
1481cdf0e10cSrcweir SCSIZE nCount = 0;
1482cdf0e10cSrcweir SCROW nOutRow = 0;
1483cdf0e10cSrcweir SCROW nHeader = aParam.bHasHeader ? 1 : 0;
1484cdf0e10cSrcweir
1485cdf0e10cSrcweir SCSIZE nEntryCount = aParam.GetEntryCount();
1486cdf0e10cSrcweir sal_Bool* pSpecial = new sal_Bool[nEntryCount];
1487cdf0e10cSrcweir lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
1488cdf0e10cSrcweir
1489cdf0e10cSrcweir if (!aParam.bInplace)
1490cdf0e10cSrcweir {
1491cdf0e10cSrcweir nOutRow = aParam.nDestRow + nHeader;
1492cdf0e10cSrcweir if (nHeader > 0)
1493cdf0e10cSrcweir CopyData( aParam.nCol1, aParam.nRow1, aParam.nCol2, aParam.nRow1,
1494cdf0e10cSrcweir aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
1495cdf0e10cSrcweir }
1496cdf0e10cSrcweir
1497cdf0e10cSrcweir if (aParam.bInplace)
1498cdf0e10cSrcweir IncRecalcLevel(); // #i116164# once for all entries
1499cdf0e10cSrcweir
1500cdf0e10cSrcweir // #i116164# If there are no drawing objects within the area, call SetRowHidden/SetRowFiltered for all rows at the end
1501cdf0e10cSrcweir std::vector<ScShowRowsEntry> aEntries;
1502cdf0e10cSrcweir ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
1503cdf0e10cSrcweir bool bHasObjects = pDrawLayer && pDrawLayer->HasObjectsInRows( nTab, aParam.nRow1 + nHeader, aParam.nRow2, false );
1504cdf0e10cSrcweir
1505cdf0e10cSrcweir for (SCROW j=aParam.nRow1 + nHeader; j<=aParam.nRow2; j++)
1506cdf0e10cSrcweir {
1507cdf0e10cSrcweir sal_Bool bResult; // Filterergebnis
1508cdf0e10cSrcweir sal_Bool bValid = ValidQuery(j, aParam, pSpecial);
1509cdf0e10cSrcweir if (!bValid && bKeepSub) // Subtotals stehenlassen
1510cdf0e10cSrcweir {
1511cdf0e10cSrcweir for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++)
1512cdf0e10cSrcweir {
1513cdf0e10cSrcweir ScBaseCell* pCell;
1514cdf0e10cSrcweir pCell = GetCell( nCol, j );
1515cdf0e10cSrcweir if ( pCell )
1516cdf0e10cSrcweir if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1517cdf0e10cSrcweir if (((ScFormulaCell*)pCell)->IsSubTotal())
1518cdf0e10cSrcweir if (RefVisible((ScFormulaCell*)pCell))
1519cdf0e10cSrcweir bValid = sal_True;
1520cdf0e10cSrcweir }
1521cdf0e10cSrcweir }
1522cdf0e10cSrcweir if (bValid)
1523cdf0e10cSrcweir {
1524cdf0e10cSrcweir if (aParam.bDuplicate)
1525cdf0e10cSrcweir bResult = sal_True;
1526cdf0e10cSrcweir else
1527cdf0e10cSrcweir {
1528cdf0e10cSrcweir String aStr;
1529cdf0e10cSrcweir for (SCCOL k=aParam.nCol1; k <= aParam.nCol2; k++)
1530cdf0e10cSrcweir {
1531cdf0e10cSrcweir String aCellStr;
1532cdf0e10cSrcweir GetString(k, j, aCellStr);
1533cdf0e10cSrcweir aStr += aCellStr;
1534cdf0e10cSrcweir aStr += (sal_Unicode)1;
1535cdf0e10cSrcweir }
1536cdf0e10cSrcweir pStrData = new StrData(aStr);
1537cdf0e10cSrcweir
1538cdf0e10cSrcweir sal_Bool bIsUnique = sal_True;
1539cdf0e10cSrcweir if (pStrData)
1540cdf0e10cSrcweir bIsUnique = aScStrCollection.Insert(pStrData);
1541cdf0e10cSrcweir if (bIsUnique)
1542cdf0e10cSrcweir bResult = sal_True;
1543cdf0e10cSrcweir else
1544cdf0e10cSrcweir {
1545cdf0e10cSrcweir delete pStrData;
1546cdf0e10cSrcweir bResult = sal_False;
1547cdf0e10cSrcweir }
1548cdf0e10cSrcweir }
1549cdf0e10cSrcweir }
1550cdf0e10cSrcweir else
1551cdf0e10cSrcweir bResult = sal_False;
1552cdf0e10cSrcweir
1553cdf0e10cSrcweir if (aParam.bInplace)
1554cdf0e10cSrcweir {
1555cdf0e10cSrcweir if (bResult == bOldResult && bStarted)
1556cdf0e10cSrcweir nOldEnd = j;
1557cdf0e10cSrcweir else
1558cdf0e10cSrcweir {
1559cdf0e10cSrcweir if (bStarted)
1560cdf0e10cSrcweir {
1561cdf0e10cSrcweir DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
1562cdf0e10cSrcweir if (!bHasObjects)
1563cdf0e10cSrcweir aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
1564cdf0e10cSrcweir }
1565cdf0e10cSrcweir nOldStart = nOldEnd = j;
1566cdf0e10cSrcweir bOldResult = bResult;
1567cdf0e10cSrcweir }
1568cdf0e10cSrcweir bStarted = sal_True;
1569cdf0e10cSrcweir }
1570cdf0e10cSrcweir else
1571cdf0e10cSrcweir {
1572cdf0e10cSrcweir if (bResult)
1573cdf0e10cSrcweir {
1574cdf0e10cSrcweir CopyData( aParam.nCol1,j, aParam.nCol2,j, aParam.nDestCol,nOutRow,aParam.nDestTab );
1575cdf0e10cSrcweir ++nOutRow;
1576cdf0e10cSrcweir }
1577cdf0e10cSrcweir }
1578cdf0e10cSrcweir if (bResult)
1579cdf0e10cSrcweir ++nCount;
1580cdf0e10cSrcweir }
1581cdf0e10cSrcweir
1582cdf0e10cSrcweir if (aParam.bInplace && bStarted)
1583cdf0e10cSrcweir {
1584cdf0e10cSrcweir DBShowRows(nOldStart,nOldEnd, bOldResult, bHasObjects);
1585cdf0e10cSrcweir if (!bHasObjects)
1586cdf0e10cSrcweir aEntries.push_back(ScShowRowsEntry(nOldStart, nOldEnd, bOldResult));
1587cdf0e10cSrcweir }
1588cdf0e10cSrcweir
1589cdf0e10cSrcweir // #i116164# execute the collected SetRowHidden/SetRowFiltered calls
1590cdf0e10cSrcweir if (!bHasObjects)
1591cdf0e10cSrcweir {
1592cdf0e10cSrcweir std::vector<ScShowRowsEntry>::const_iterator aEnd = aEntries.end();
1593cdf0e10cSrcweir std::vector<ScShowRowsEntry>::const_iterator aIter = aEntries.begin();
1594cdf0e10cSrcweir if ( aIter != aEnd )
1595cdf0e10cSrcweir {
1596cdf0e10cSrcweir // do only one HeightChanged call with the final difference in heights
1597cdf0e10cSrcweir long nOldHeight = 0;
1598cdf0e10cSrcweir if ( pDrawLayer )
1599cdf0e10cSrcweir nOldHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
1600cdf0e10cSrcweir
1601cdf0e10cSrcweir // clear the range first instead of many changes in the middle of the filled array
1602cdf0e10cSrcweir SetRowHidden(aParam.nRow1 + nHeader, aParam.nRow2, false);
1603cdf0e10cSrcweir SetRowFiltered(aParam.nRow1 + nHeader, aParam.nRow2, false);
1604cdf0e10cSrcweir
1605cdf0e10cSrcweir // insert from back, in case the filter range is large
1606cdf0e10cSrcweir mpHiddenRows->setInsertFromBack(true);
1607cdf0e10cSrcweir mpFilteredRows->setInsertFromBack(true);
1608cdf0e10cSrcweir
1609cdf0e10cSrcweir while (aIter != aEnd)
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir if (!aIter->mbShow)
1612cdf0e10cSrcweir {
1613cdf0e10cSrcweir SCROW nStartRow = aIter->mnRow1;
1614cdf0e10cSrcweir SCROW nEndRow = aIter->mnRow2;
1615cdf0e10cSrcweir SetRowHidden(nStartRow, nEndRow, true);
1616cdf0e10cSrcweir SetRowFiltered(nStartRow, nEndRow, true);
1617cdf0e10cSrcweir }
1618cdf0e10cSrcweir ++aIter;
1619cdf0e10cSrcweir }
1620cdf0e10cSrcweir
1621cdf0e10cSrcweir mpHiddenRows->setInsertFromBack(false);
1622cdf0e10cSrcweir mpFilteredRows->setInsertFromBack(false);
1623cdf0e10cSrcweir
1624cdf0e10cSrcweir if ( pDrawLayer )
1625cdf0e10cSrcweir {
1626cdf0e10cSrcweir // if there are no objects in the filtered range, a single HeightChanged call is enough
1627cdf0e10cSrcweir long nNewHeight = static_cast<long>(GetRowHeight(aParam.nRow1 + nHeader, aParam.nRow2));
1628cdf0e10cSrcweir pDrawLayer->HeightChanged( nTab, aParam.nRow1 + nHeader, nNewHeight - nOldHeight );
1629cdf0e10cSrcweir }
1630cdf0e10cSrcweir }
1631cdf0e10cSrcweir }
1632cdf0e10cSrcweir
1633cdf0e10cSrcweir if (aParam.bInplace)
1634cdf0e10cSrcweir DecRecalcLevel();
1635cdf0e10cSrcweir
1636cdf0e10cSrcweir delete[] pSpecial;
1637cdf0e10cSrcweir
1638cdf0e10cSrcweir return nCount;
1639cdf0e10cSrcweir }
1640cdf0e10cSrcweir
CreateExcelQuery(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,ScQueryParam & rQueryParam)1641cdf0e10cSrcweir sal_Bool ScTable::CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam)
1642cdf0e10cSrcweir {
1643cdf0e10cSrcweir sal_Bool bValid = sal_True;
1644cdf0e10cSrcweir SCCOL* pFields = new SCCOL[nCol2-nCol1+1];
1645cdf0e10cSrcweir String aCellStr;
1646cdf0e10cSrcweir SCCOL nCol = nCol1;
1647cdf0e10cSrcweir DBG_ASSERT( rQueryParam.nTab != SCTAB_MAX, "rQueryParam.nTab no value, not bad but no good" );
1648cdf0e10cSrcweir SCTAB nDBTab = (rQueryParam.nTab == SCTAB_MAX ? nTab : rQueryParam.nTab);
1649cdf0e10cSrcweir SCROW nDBRow1 = rQueryParam.nRow1;
1650cdf0e10cSrcweir SCCOL nDBCol2 = rQueryParam.nCol2;
1651cdf0e10cSrcweir // Erste Zeile muessen Spaltenkoepfe sein
1652cdf0e10cSrcweir while (bValid && (nCol <= nCol2))
1653cdf0e10cSrcweir {
1654cdf0e10cSrcweir String aQueryStr;
1655cdf0e10cSrcweir GetUpperCellString(nCol, nRow1, aQueryStr);
1656cdf0e10cSrcweir sal_Bool bFound = sal_False;
1657cdf0e10cSrcweir SCCOL i = rQueryParam.nCol1;
1658cdf0e10cSrcweir while (!bFound && (i <= nDBCol2))
1659cdf0e10cSrcweir {
1660cdf0e10cSrcweir if ( nTab == nDBTab )
1661cdf0e10cSrcweir GetUpperCellString(i, nDBRow1, aCellStr);
1662cdf0e10cSrcweir else
1663cdf0e10cSrcweir pDocument->GetUpperCellString(i, nDBRow1, nDBTab, aCellStr);
1664cdf0e10cSrcweir bFound = (aCellStr == aQueryStr);
1665cdf0e10cSrcweir if (!bFound) i++;
1666cdf0e10cSrcweir }
1667cdf0e10cSrcweir if (bFound)
1668cdf0e10cSrcweir pFields[nCol - nCol1] = i;
1669cdf0e10cSrcweir else
1670cdf0e10cSrcweir bValid = sal_False;
1671cdf0e10cSrcweir nCol++;
1672cdf0e10cSrcweir }
1673cdf0e10cSrcweir if (bValid)
1674cdf0e10cSrcweir {
1675cdf0e10cSrcweir sal_uLong nVisible = 0;
1676cdf0e10cSrcweir for ( nCol=nCol1; nCol<=nCol2; nCol++ )
1677cdf0e10cSrcweir nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
1678cdf0e10cSrcweir
1679cdf0e10cSrcweir if ( nVisible > SCSIZE_MAX / sizeof(void*) )
1680cdf0e10cSrcweir {
1681cdf0e10cSrcweir DBG_ERROR("zu viele Filterkritierien");
1682cdf0e10cSrcweir nVisible = 0;
1683cdf0e10cSrcweir }
1684cdf0e10cSrcweir
1685cdf0e10cSrcweir SCSIZE nNewEntries = nVisible;
1686cdf0e10cSrcweir rQueryParam.Resize( nNewEntries );
1687cdf0e10cSrcweir
1688cdf0e10cSrcweir SCSIZE nIndex = 0;
1689cdf0e10cSrcweir SCROW nRow = nRow1 + 1;
1690cdf0e10cSrcweir while (nRow <= nRow2)
1691cdf0e10cSrcweir {
1692cdf0e10cSrcweir nCol = nCol1;
1693cdf0e10cSrcweir while (nCol <= nCol2)
1694cdf0e10cSrcweir {
1695cdf0e10cSrcweir GetInputString( nCol, nRow, aCellStr );
1696*ad0f8ea8SWang Lei // ScGlobal::pCharClass->toUpper( aCellStr ); // #i119637
1697cdf0e10cSrcweir if (aCellStr.Len() > 0)
1698cdf0e10cSrcweir {
1699cdf0e10cSrcweir if (nIndex < nNewEntries)
1700cdf0e10cSrcweir {
1701cdf0e10cSrcweir rQueryParam.GetEntry(nIndex).nField = pFields[nCol - nCol1];
1702cdf0e10cSrcweir rQueryParam.FillInExcelSyntax(aCellStr, nIndex);
1703cdf0e10cSrcweir nIndex++;
1704cdf0e10cSrcweir if (nIndex < nNewEntries)
1705cdf0e10cSrcweir rQueryParam.GetEntry(nIndex).eConnect = SC_AND;
1706cdf0e10cSrcweir }
1707cdf0e10cSrcweir else
1708cdf0e10cSrcweir bValid = sal_False;
1709cdf0e10cSrcweir }
1710cdf0e10cSrcweir nCol++;
1711cdf0e10cSrcweir }
1712cdf0e10cSrcweir nRow++;
1713cdf0e10cSrcweir if (nIndex < nNewEntries)
1714cdf0e10cSrcweir rQueryParam.GetEntry(nIndex).eConnect = SC_OR;
1715cdf0e10cSrcweir }
1716cdf0e10cSrcweir }
1717cdf0e10cSrcweir delete [] pFields;
1718cdf0e10cSrcweir return bValid;
1719cdf0e10cSrcweir }
1720cdf0e10cSrcweir
CreateStarQuery(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,ScQueryParam & rQueryParam)1721cdf0e10cSrcweir sal_Bool ScTable::CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam)
1722cdf0e10cSrcweir {
1723cdf0e10cSrcweir // A valid StarQuery must be at least 4 columns wide. To be precise it
1724cdf0e10cSrcweir // should be exactly 4 columns ...
1725cdf0e10cSrcweir // Additionally, if this wasn't checked, a formula pointing to a valid 1-3
1726cdf0e10cSrcweir // column Excel style query range immediately left to itself would result
1727cdf0e10cSrcweir // in a circular reference when the field name or operator or value (first
1728cdf0e10cSrcweir // to third query range column) is obtained (#i58354#). Furthermore, if the
1729cdf0e10cSrcweir // range wasn't sufficiently specified data changes wouldn't flag formula
1730cdf0e10cSrcweir // cells for recalculation.
1731cdf0e10cSrcweir if (nCol2 - nCol1 < 3)
1732cdf0e10cSrcweir return sal_False;
1733cdf0e10cSrcweir
1734cdf0e10cSrcweir sal_Bool bValid;
1735cdf0e10cSrcweir sal_Bool bFound;
1736cdf0e10cSrcweir String aCellStr;
1737cdf0e10cSrcweir SCSIZE nIndex = 0;
1738cdf0e10cSrcweir SCROW nRow = nRow1;
1739cdf0e10cSrcweir DBG_ASSERT( rQueryParam.nTab != SCTAB_MAX, "rQueryParam.nTab no value, not bad but no good" );
1740cdf0e10cSrcweir SCTAB nDBTab = (rQueryParam.nTab == SCTAB_MAX ? nTab : rQueryParam.nTab);
1741cdf0e10cSrcweir SCROW nDBRow1 = rQueryParam.nRow1;
1742cdf0e10cSrcweir SCCOL nDBCol2 = rQueryParam.nCol2;
1743cdf0e10cSrcweir
1744cdf0e10cSrcweir SCSIZE nNewEntries = static_cast<SCSIZE>(nRow2-nRow1+1);
1745cdf0e10cSrcweir rQueryParam.Resize( nNewEntries );
1746cdf0e10cSrcweir
1747cdf0e10cSrcweir do
1748cdf0e10cSrcweir {
1749cdf0e10cSrcweir ScQueryEntry& rEntry = rQueryParam.GetEntry(nIndex);
1750cdf0e10cSrcweir
1751cdf0e10cSrcweir bValid = sal_False;
1752cdf0e10cSrcweir // Erste Spalte UND/ODER
1753cdf0e10cSrcweir if (nIndex > 0)
1754cdf0e10cSrcweir {
1755cdf0e10cSrcweir GetUpperCellString(nCol1, nRow, aCellStr);
1756cdf0e10cSrcweir if ( aCellStr == ScGlobal::GetRscString(STR_TABLE_UND) )
1757cdf0e10cSrcweir {
1758cdf0e10cSrcweir rEntry.eConnect = SC_AND;
1759cdf0e10cSrcweir bValid = sal_True;
1760cdf0e10cSrcweir }
1761cdf0e10cSrcweir else if ( aCellStr == ScGlobal::GetRscString(STR_TABLE_ODER) )
1762cdf0e10cSrcweir {
1763cdf0e10cSrcweir rEntry.eConnect = SC_OR;
1764cdf0e10cSrcweir bValid = sal_True;
1765cdf0e10cSrcweir }
1766cdf0e10cSrcweir }
1767cdf0e10cSrcweir // Zweite Spalte FeldName
1768cdf0e10cSrcweir if ((nIndex < 1) || bValid)
1769cdf0e10cSrcweir {
1770cdf0e10cSrcweir bFound = sal_False;
1771cdf0e10cSrcweir GetUpperCellString(nCol1 + 1, nRow, aCellStr);
1772cdf0e10cSrcweir for (SCCOL i=rQueryParam.nCol1; (i <= nDBCol2) && (!bFound); i++)
1773cdf0e10cSrcweir {
1774cdf0e10cSrcweir String aFieldStr;
1775cdf0e10cSrcweir if ( nTab == nDBTab )
1776cdf0e10cSrcweir GetUpperCellString(i, nDBRow1, aFieldStr);
1777cdf0e10cSrcweir else
1778cdf0e10cSrcweir pDocument->GetUpperCellString(i, nDBRow1, nDBTab, aFieldStr);
1779cdf0e10cSrcweir bFound = (aCellStr == aFieldStr);
1780cdf0e10cSrcweir if (bFound)
1781cdf0e10cSrcweir {
1782cdf0e10cSrcweir rEntry.nField = i;
1783cdf0e10cSrcweir bValid = sal_True;
1784cdf0e10cSrcweir }
1785cdf0e10cSrcweir else
1786cdf0e10cSrcweir bValid = sal_False;
1787cdf0e10cSrcweir }
1788cdf0e10cSrcweir }
1789cdf0e10cSrcweir // Dritte Spalte Operator =<>...
1790cdf0e10cSrcweir if (bValid)
1791cdf0e10cSrcweir {
1792cdf0e10cSrcweir bFound = sal_False;
1793cdf0e10cSrcweir GetUpperCellString(nCol1 + 2, nRow, aCellStr);
1794cdf0e10cSrcweir if (aCellStr.GetChar(0) == '<')
1795cdf0e10cSrcweir {
1796cdf0e10cSrcweir if (aCellStr.GetChar(1) == '>')
1797cdf0e10cSrcweir rEntry.eOp = SC_NOT_EQUAL;
1798cdf0e10cSrcweir else if (aCellStr.GetChar(1) == '=')
1799cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
1800cdf0e10cSrcweir else
1801cdf0e10cSrcweir rEntry.eOp = SC_LESS;
1802cdf0e10cSrcweir }
1803cdf0e10cSrcweir else if (aCellStr.GetChar(0) == '>')
1804cdf0e10cSrcweir {
1805cdf0e10cSrcweir if (aCellStr.GetChar(1) == '=')
1806cdf0e10cSrcweir rEntry.eOp = SC_GREATER_EQUAL;
1807cdf0e10cSrcweir else
1808cdf0e10cSrcweir rEntry.eOp = SC_GREATER;
1809cdf0e10cSrcweir }
1810cdf0e10cSrcweir else if (aCellStr.GetChar(0) == '=')
1811cdf0e10cSrcweir rEntry.eOp = SC_EQUAL;
1812cdf0e10cSrcweir
1813cdf0e10cSrcweir }
1814cdf0e10cSrcweir // Vierte Spalte Wert
1815cdf0e10cSrcweir if (bValid)
1816cdf0e10cSrcweir {
1817cdf0e10cSrcweir GetString(nCol1 + 3, nRow, *rEntry.pStr);
1818cdf0e10cSrcweir rEntry.bDoQuery = sal_True;
1819cdf0e10cSrcweir }
1820cdf0e10cSrcweir nIndex++;
1821cdf0e10cSrcweir nRow++;
1822cdf0e10cSrcweir }
1823cdf0e10cSrcweir while (bValid && (nRow <= nRow2) /* && (nIndex < MAXQUERY) */ );
1824cdf0e10cSrcweir return bValid;
1825cdf0e10cSrcweir }
1826cdf0e10cSrcweir
CreateQueryParam(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,ScQueryParam & rQueryParam)1827cdf0e10cSrcweir sal_Bool ScTable::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam)
1828cdf0e10cSrcweir {
1829cdf0e10cSrcweir SCSIZE i, nCount;
1830cdf0e10cSrcweir PutInOrder(nCol1, nCol2);
1831cdf0e10cSrcweir PutInOrder(nRow1, nRow2);
1832cdf0e10cSrcweir
1833cdf0e10cSrcweir nCount = rQueryParam.GetEntryCount();
1834cdf0e10cSrcweir for (i=0; i < nCount; i++)
1835cdf0e10cSrcweir rQueryParam.GetEntry(i).Clear();
1836cdf0e10cSrcweir
1837cdf0e10cSrcweir // Standard QueryTabelle
1838cdf0e10cSrcweir sal_Bool bValid = CreateStarQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1839cdf0e10cSrcweir // Excel QueryTabelle
1840cdf0e10cSrcweir if (!bValid)
1841cdf0e10cSrcweir bValid = CreateExcelQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1842cdf0e10cSrcweir
1843cdf0e10cSrcweir nCount = rQueryParam.GetEntryCount();
1844cdf0e10cSrcweir if (bValid)
1845cdf0e10cSrcweir {
1846cdf0e10cSrcweir // bQueryByString muss gesetzt sein
1847cdf0e10cSrcweir for (i=0; i < nCount; i++)
1848cdf0e10cSrcweir rQueryParam.GetEntry(i).bQueryByString = sal_True;
1849cdf0e10cSrcweir }
1850cdf0e10cSrcweir else
1851cdf0e10cSrcweir {
1852cdf0e10cSrcweir // nix
1853cdf0e10cSrcweir for (i=0; i < nCount; i++)
1854cdf0e10cSrcweir rQueryParam.GetEntry(i).Clear();
1855cdf0e10cSrcweir }
1856cdf0e10cSrcweir return bValid;
1857cdf0e10cSrcweir }
1858cdf0e10cSrcweir
HasColHeader(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW)1859cdf0e10cSrcweir sal_Bool ScTable::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW /* nEndRow */ )
1860cdf0e10cSrcweir {
1861cdf0e10cSrcweir for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++)
1862cdf0e10cSrcweir {
1863cdf0e10cSrcweir CellType eType = GetCellType( nCol, nStartRow );
1864cdf0e10cSrcweir if (eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT)
1865cdf0e10cSrcweir return sal_False;
1866cdf0e10cSrcweir }
1867cdf0e10cSrcweir return sal_True;
1868cdf0e10cSrcweir }
1869cdf0e10cSrcweir
HasRowHeader(SCCOL nStartCol,SCROW nStartRow,SCCOL,SCROW nEndRow)1870cdf0e10cSrcweir sal_Bool ScTable::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL /* nEndCol */, SCROW nEndRow )
1871cdf0e10cSrcweir {
1872cdf0e10cSrcweir for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++)
1873cdf0e10cSrcweir {
1874cdf0e10cSrcweir CellType eType = GetCellType( nStartCol, nRow );
1875cdf0e10cSrcweir if (eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT)
1876cdf0e10cSrcweir return sal_False;
1877cdf0e10cSrcweir }
1878cdf0e10cSrcweir return sal_True;
1879cdf0e10cSrcweir }
1880cdf0e10cSrcweir
GetFilterEntries(SCCOL nCol,SCROW nRow1,SCROW nRow2,TypedScStrCollection & rStrings,bool & rHasDates)1881cdf0e10cSrcweir void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates)
1882cdf0e10cSrcweir {
1883cdf0e10cSrcweir aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings, rHasDates );
1884cdf0e10cSrcweir }
1885cdf0e10cSrcweir
GetFilteredFilterEntries(SCCOL nCol,SCROW nRow1,SCROW nRow2,const ScQueryParam & rParam,TypedScStrCollection & rStrings,bool & rHasDates)1886cdf0e10cSrcweir void ScTable::GetFilteredFilterEntries(
1887cdf0e10cSrcweir SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates )
1888cdf0e10cSrcweir {
1889cdf0e10cSrcweir // remove the entry for this column from the query parameter
1890cdf0e10cSrcweir ScQueryParam aParam( rParam );
1891cdf0e10cSrcweir SCSIZE nEntryCount = aParam.GetEntryCount();
1892cdf0e10cSrcweir for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1893cdf0e10cSrcweir {
1894cdf0e10cSrcweir ScQueryEntry& rEntry = aParam.GetEntry(i);
1895cdf0e10cSrcweir if ( rEntry.nField == nCol )
1896cdf0e10cSrcweir {
1897cdf0e10cSrcweir aParam.DeleteQuery(i);
1898cdf0e10cSrcweir break;
1899cdf0e10cSrcweir }
1900cdf0e10cSrcweir }
1901cdf0e10cSrcweir nEntryCount = aParam.GetEntryCount();
1902cdf0e10cSrcweir
1903cdf0e10cSrcweir sal_Bool* pSpecial = new sal_Bool[nEntryCount];
1904cdf0e10cSrcweir lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
1905cdf0e10cSrcweir bool bHasDates = false;
1906cdf0e10cSrcweir for ( SCROW j = nRow1; j <= nRow2; ++j )
1907cdf0e10cSrcweir {
1908cdf0e10cSrcweir if ( ValidQuery( j, aParam, pSpecial ) )
1909cdf0e10cSrcweir {
1910cdf0e10cSrcweir bool bThisHasDates = false;
1911cdf0e10cSrcweir aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates );
1912cdf0e10cSrcweir bHasDates |= bThisHasDates;
1913cdf0e10cSrcweir }
1914cdf0e10cSrcweir }
1915cdf0e10cSrcweir
1916cdf0e10cSrcweir rHasDates = bHasDates;
1917cdf0e10cSrcweir delete[] pSpecial;
1918cdf0e10cSrcweir }
1919cdf0e10cSrcweir
GetDataEntries(SCCOL nCol,SCROW nRow,TypedScStrCollection & rStrings,sal_Bool bLimit)1920cdf0e10cSrcweir sal_Bool ScTable::GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStrings, sal_Bool bLimit)
1921cdf0e10cSrcweir {
1922cdf0e10cSrcweir return aCol[nCol].GetDataEntries( nRow, rStrings, bLimit );
1923cdf0e10cSrcweir }
1924cdf0e10cSrcweir
GetCellCount(SCCOL nCol) const1925cdf0e10cSrcweir SCSIZE ScTable::GetCellCount(SCCOL nCol) const
1926cdf0e10cSrcweir {
1927cdf0e10cSrcweir return aCol[nCol].GetCellCount();
1928cdf0e10cSrcweir }
1929cdf0e10cSrcweir
GetCellCount() const1930cdf0e10cSrcweir sal_uLong ScTable::GetCellCount() const
1931cdf0e10cSrcweir {
1932cdf0e10cSrcweir sal_uLong nCellCount = 0;
1933cdf0e10cSrcweir
1934cdf0e10cSrcweir for ( SCCOL nCol=0; nCol<=MAXCOL; nCol++ )
1935cdf0e10cSrcweir nCellCount += aCol[nCol].GetCellCount();
1936cdf0e10cSrcweir
1937cdf0e10cSrcweir return nCellCount;
1938cdf0e10cSrcweir }
1939cdf0e10cSrcweir
GetWeightedCount() const1940cdf0e10cSrcweir sal_uLong ScTable::GetWeightedCount() const
1941cdf0e10cSrcweir {
1942cdf0e10cSrcweir sal_uLong nCellCount = 0;
1943cdf0e10cSrcweir
1944cdf0e10cSrcweir for ( SCCOL nCol=0; nCol<=MAXCOL; nCol++ )
1945cdf0e10cSrcweir if ( aCol[nCol].GetCellCount() ) // GetCellCount ist inline
1946cdf0e10cSrcweir nCellCount += aCol[nCol].GetWeightedCount();
1947cdf0e10cSrcweir
1948cdf0e10cSrcweir return nCellCount;
1949cdf0e10cSrcweir }
1950cdf0e10cSrcweir
GetCodeCount() const1951cdf0e10cSrcweir sal_uLong ScTable::GetCodeCount() const
1952cdf0e10cSrcweir {
1953cdf0e10cSrcweir sal_uLong nCodeCount = 0;
1954cdf0e10cSrcweir
1955cdf0e10cSrcweir for ( SCCOL nCol=0; nCol<=MAXCOL; nCol++ )
1956cdf0e10cSrcweir if ( aCol[nCol].GetCellCount() ) // GetCellCount ist inline
1957cdf0e10cSrcweir nCodeCount += aCol[nCol].GetCodeCount();
1958cdf0e10cSrcweir
1959cdf0e10cSrcweir return nCodeCount;
1960cdf0e10cSrcweir }
1961cdf0e10cSrcweir
GetMaxStringLen(SCCOL nCol,SCROW nRowStart,SCROW nRowEnd,CharSet eCharSet) const1962cdf0e10cSrcweir sal_Int32 ScTable::GetMaxStringLen( SCCOL nCol, SCROW nRowStart,
1963cdf0e10cSrcweir SCROW nRowEnd, CharSet eCharSet ) const
1964cdf0e10cSrcweir {
1965cdf0e10cSrcweir if ( ValidCol(nCol) )
1966cdf0e10cSrcweir return aCol[nCol].GetMaxStringLen( nRowStart, nRowEnd, eCharSet );
1967cdf0e10cSrcweir else
1968cdf0e10cSrcweir return 0;
1969cdf0e10cSrcweir }
1970cdf0e10cSrcweir
GetMaxNumberStringLen(sal_uInt16 & nPrecision,SCCOL nCol,SCROW nRowStart,SCROW nRowEnd) const1971cdf0e10cSrcweir xub_StrLen ScTable::GetMaxNumberStringLen(
1972cdf0e10cSrcweir sal_uInt16& nPrecision, SCCOL nCol, SCROW nRowStart, SCROW nRowEnd ) const
1973cdf0e10cSrcweir {
1974cdf0e10cSrcweir if ( ValidCol(nCol) )
1975cdf0e10cSrcweir return aCol[nCol].GetMaxNumberStringLen( nPrecision, nRowStart, nRowEnd );
1976cdf0e10cSrcweir else
1977cdf0e10cSrcweir return 0;
1978cdf0e10cSrcweir }
1979cdf0e10cSrcweir
UpdateSelectionFunction(ScFunctionData & rData,SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScMarkData & rMark)1980cdf0e10cSrcweir void ScTable::UpdateSelectionFunction( ScFunctionData& rData,
1981cdf0e10cSrcweir SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1982cdf0e10cSrcweir const ScMarkData& rMark )
1983cdf0e10cSrcweir {
1984cdf0e10cSrcweir // Cursor neben einer Markierung nicht beruecksichtigen:
1985cdf0e10cSrcweir //! nur noch MarkData uebergeben, Cursorposition ggf. hineinselektieren!!!
1986cdf0e10cSrcweir sal_Bool bSingle = ( rMark.IsMarked() || !rMark.IsMultiMarked() );
1987cdf0e10cSrcweir
1988cdf0e10cSrcweir // Mehrfachselektion:
1989cdf0e10cSrcweir
1990cdf0e10cSrcweir SCCOL nCol;
1991cdf0e10cSrcweir if ( rMark.IsMultiMarked() )
1992cdf0e10cSrcweir for (nCol=0; nCol<=MAXCOL && !rData.bError; nCol++)
1993cdf0e10cSrcweir if ( !pColFlags || !ColHidden(nCol) )
1994cdf0e10cSrcweir aCol[nCol].UpdateSelectionFunction( rMark, rData, *mpHiddenRows,
1995cdf0e10cSrcweir bSingle && ( nCol >= nStartCol && nCol <= nEndCol ),
1996cdf0e10cSrcweir nStartRow, nEndRow );
1997cdf0e10cSrcweir
1998cdf0e10cSrcweir // Einfachselektion (oder Cursor) nur wenn nicht negativ (und s.o.):
1999cdf0e10cSrcweir
2000cdf0e10cSrcweir if ( bSingle && !rMark.IsMarkNegative() )
2001cdf0e10cSrcweir for (nCol=nStartCol; nCol<=nEndCol && !rData.bError; nCol++)
2002cdf0e10cSrcweir if ( !pColFlags || !ColHidden(nCol) )
2003cdf0e10cSrcweir aCol[nCol].UpdateAreaFunction( rData, *mpHiddenRows, nStartRow, nEndRow );
2004cdf0e10cSrcweir }
2005cdf0e10cSrcweir
FindConditionalFormat(sal_uLong nKey,ScRangeList & rList)2006cdf0e10cSrcweir void ScTable::FindConditionalFormat( sal_uLong nKey, ScRangeList& rList )
2007cdf0e10cSrcweir {
2008cdf0e10cSrcweir SCROW nStartRow = 0, nEndRow = 0;
2009cdf0e10cSrcweir for (SCCOL nCol=0; nCol<=MAXCOL; nCol++)
2010cdf0e10cSrcweir {
2011cdf0e10cSrcweir ScAttrIterator* pIter = aCol[nCol].CreateAttrIterator( 0, MAXROW );
2012cdf0e10cSrcweir const ScPatternAttr* pPattern = pIter->Next( nStartRow, nEndRow );
2013cdf0e10cSrcweir while (pPattern)
2014cdf0e10cSrcweir {
2015cdf0e10cSrcweir if (((SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() == nKey)
2016cdf0e10cSrcweir rList.Join( ScRange(nCol,nStartRow,nTab, nCol,nEndRow,nTab) );
2017cdf0e10cSrcweir pPattern = pIter->Next( nStartRow, nEndRow );
2018cdf0e10cSrcweir }
2019cdf0e10cSrcweir delete pIter;
2020cdf0e10cSrcweir }
2021cdf0e10cSrcweir }
2022cdf0e10cSrcweir
2023cdf0e10cSrcweir
2024cdf0e10cSrcweir
2025cdf0e10cSrcweir
2026