merge the formfield patch from ooo-build
[ooovba.git] / applied_patches / 0013-cws-kohei03-sc.diff
blob0b1f33b68369e2abd40bdffa12c037d7565e6c56
1 diff --git sc/inc/chart2uno.hxx sc/inc/chart2uno.hxx
2 index 93afe64..46b7ff0 100644
3 --- sc/inc/chart2uno.hxx
4 +++ sc/inc/chart2uno.hxx
5 @@ -533,6 +533,14 @@ private:
6 };
8 ::std::list<Item> m_aDataArray;
10 + /**
11 + * Cached data for getData. We may also need to cache data for the
12 + * numerical and textural data series if they turn out to be bottlenecks
13 + * under certain scenarios.
14 + */
15 + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aMixedDataCache;
17 ::com::sun::star::uno::Sequence<sal_Int32> m_aHiddenValues;
19 // properties
20 diff --git sc/inc/chartlis.hxx sc/inc/chartlis.hxx
21 index a8a97d3..51ac644 100644
22 --- sc/inc/chartlis.hxx
23 +++ sc/inc/chartlis.hxx
24 @@ -49,7 +49,7 @@ class ScChartUnoData;
25 #include <com/sun/star/chart/XChartData.hpp>
26 #include <com/sun/star/chart/XChartDataChangeEventListener.hpp>
28 -class ScChartListener : public StrData, public SvtListener
29 +class SC_DLLPUBLIC ScChartListener : public StrData, public SvtListener
31 public:
32 class ExternalRefListener : public ScExternalRefManager::LinkListener
33 diff --git sc/inc/column.hxx sc/inc/column.hxx
34 index e4c7ed4..983ca1f 100644
35 --- sc/inc/column.hxx
36 +++ sc/inc/column.hxx
37 @@ -114,7 +114,7 @@ private:
38 friend class ScDocument; // fuer FillInfo
39 friend class ScDocumentIterator;
40 friend class ScValueIterator;
41 -friend class ScQueryValueIterator;
42 +friend class ScDBQueryDataIterator;
43 friend class ScColumnIterator;
44 friend class ScQueryCellIterator;
45 friend class ScMarkedDataIter;
46 diff --git sc/inc/datauno.hxx sc/inc/datauno.hxx
47 index 3103875..44e0336 100644
48 --- sc/inc/datauno.hxx
49 +++ sc/inc/datauno.hxx
50 @@ -32,6 +32,8 @@
51 #define SC_DATAUNO_HXX
53 #include "global.hxx"
54 +#include "queryparam.hxx"
56 #include <svtools/itemprop.hxx>
57 #include <svtools/lstner.hxx>
58 #include <com/sun/star/sheet/TableFilterField.hpp>
59 diff --git sc/inc/dociter.hxx sc/inc/dociter.hxx
60 index d5d4235..350c611 100644
61 --- sc/inc/dociter.hxx
62 +++ sc/inc/dociter.hxx
63 @@ -35,6 +35,9 @@
64 #include <tools/solar.h>
65 #include "global.hxx"
66 #include "scdllapi.h"
67 +#include "queryparam.hxx"
69 +#include <memory>
71 class ScDocument;
72 class ScBaseCell;
73 @@ -127,34 +130,91 @@ public:
77 -class ScQueryValueIterator // alle Zahlenwerte in einem Bereich durchgehen
78 +// ============================================================================
80 +class ScDBQueryDataIterator
82 +public:
83 + struct Value
84 + {
85 + ::rtl::OUString maString;
86 + double mfValue;
87 + sal_uInt16 mnError;
88 + bool mbIsNumber;
90 + Value();
91 + };
93 private:
94 - ScQueryParam aParam;
95 - ScDocument* pDoc;
96 - const ScAttrArray* pAttrArray;
97 - ULONG nNumFormat; // fuer CalcAsShown
98 - ULONG nNumFmtIndex;
99 - SCCOL nCol;
100 - SCROW nRow;
101 - SCSIZE nColRow;
102 - SCROW nAttrEndRow;
103 - SCTAB nTab;
104 - short nNumFmtType;
105 - BOOL bCalcAsShown;
106 + class DataAccess
108 + public:
109 + DataAccess(const ScDBQueryDataIterator* pParent);
110 + virtual ~DataAccess() = 0;
111 + virtual bool getCurrent(Value& rValue) = 0;
112 + virtual bool getFirst(Value& rValue) = 0;
113 + virtual bool getNext(Value& rValue) = 0;
114 + protected:
115 + const ScDBQueryDataIterator* mpParent;
116 + };
118 + class DataAccessInternal : public DataAccess
120 + public:
121 + DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc);
122 + virtual ~DataAccessInternal();
123 + virtual bool getCurrent(Value& rValue);
124 + virtual bool getFirst(Value& rValue);
125 + virtual bool getNext(Value& rValue);
127 + private:
128 + ScDBQueryParamInternal* mpParam;
129 + ScDocument* mpDoc;
130 + const ScAttrArray* pAttrArray;
131 + ULONG nNumFormat; // for CalcAsShown
132 + ULONG nNumFmtIndex;
133 + SCCOL nCol;
134 + SCROW nRow;
135 + SCSIZE nColRow;
136 + SCROW nAttrEndRow;
137 + SCTAB nTab;
138 + short nNumFmtType;
139 + bool bCalcAsShown;
140 + };
142 + class DataAccessMatrix : public DataAccess
144 + public:
145 + DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam);
146 + virtual ~DataAccessMatrix();
147 + virtual bool getCurrent(Value& rValue);
148 + virtual bool getFirst(Value& rValue);
149 + virtual bool getNext(Value& rValue);
151 + private:
152 + bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const;
154 + ScDBQueryParamMatrix* mpParam;
155 + SCROW mnCurRow;
156 + SCROW mnRows;
157 + SCCOL mnCols;
158 + };
160 + ::std::auto_ptr<ScDBQueryParamBase> mpParam;
161 + ::std::auto_ptr<DataAccess> mpData;
163 + bool GetThis(Value& rValue);
165 - BOOL GetThis(double& rValue, USHORT& rErr);
166 public:
167 - ScQueryValueIterator(ScDocument* pDocument, SCTAB nTable,
168 - const ScQueryParam& aParam);
169 + ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam);
170 /// Does NOT reset rValue if no value found!
171 - BOOL GetFirst(double& rValue, USHORT& rErr);
172 + bool GetFirst(Value& rValue);
173 /// Does NOT reset rValue if no value found!
174 - BOOL GetNext(double& rValue, USHORT& rErr);
175 - void GetCurNumFmtInfo( short& nType, ULONG& nIndex )
176 - { nType = nNumFmtType; nIndex = nNumFmtIndex; }
177 + bool GetNext(Value& rValue);
180 +// ============================================================================
182 class ScCellIterator // alle Zellen in einem Bereich durchgehen
183 { // bei SubTotal aber keine ausgeblendeten und
184 private: // SubTotalZeilen
185 diff --git sc/inc/document.hxx sc/inc/document.hxx
186 index b6f5001..768e1ad 100644
187 --- sc/inc/document.hxx
188 +++ sc/inc/document.hxx
189 @@ -227,7 +227,7 @@ class ScDocument
191 friend class ScDocumentIterator;
192 friend class ScValueIterator;
193 -friend class ScQueryValueIterator;
194 +friend class ScDBQueryDataIterator;
195 friend class ScCellIterator;
196 friend class ScQueryCellIterator;
197 friend class ScHorizontalCellIterator;
198 diff --git sc/inc/dpcachetable.hxx sc/inc/dpcachetable.hxx
199 index 7a60535..0a22fb0 100644
200 --- sc/inc/dpcachetable.hxx
201 +++ sc/inc/dpcachetable.hxx
202 @@ -60,6 +60,7 @@ class ScDPDimension;
203 class ScDPCollection;
204 struct ScDPCacheCell;
205 struct ScDPItemData;
206 +struct ScQueryParam;
207 class Date;
209 // ----------------------------------------------------------------------------
210 diff --git sc/inc/dpshttab.hxx sc/inc/dpshttab.hxx
211 index ede4933..8483ca2 100644
212 --- sc/inc/dpshttab.hxx
213 +++ sc/inc/dpshttab.hxx
214 @@ -35,6 +35,7 @@
215 #include "global.hxx"
216 #include "address.hxx"
217 #include "scdllapi.h"
218 +#include "queryparam.hxx"
220 #include <vector>
222 diff --git sc/inc/global.hxx sc/inc/global.hxx
223 index 57a6ff1..b401cb9 100644
224 --- sc/inc/global.hxx
225 +++ sc/inc/global.hxx
226 @@ -817,47 +817,6 @@ struct ScQueryEntry
227 BOOL operator==( const ScQueryEntry& r ) const;
230 -struct SC_DLLPUBLIC ScQueryParam
232 - SCCOL nCol1;
233 - SCROW nRow1;
234 - SCCOL nCol2;
235 - SCROW nRow2;
236 - SCTAB nTab;
237 - BOOL bHasHeader;
238 - BOOL bByRow;
239 - BOOL bInplace;
240 - BOOL bCaseSens;
241 - BOOL bRegExp;
242 - BOOL bMixedComparison; // whether numbers are smaller than strings
243 - BOOL bDuplicate;
244 - BOOL bDestPers; // nicht gespeichert
245 - SCTAB nDestTab;
246 - SCCOL nDestCol;
247 - SCROW nDestRow;
249 -private:
250 - SCSIZE nEntryCount;
251 - ScQueryEntry* pEntries;
253 -public:
254 - ScQueryParam();
255 - ScQueryParam( const ScQueryParam& r );
256 - ~ScQueryParam();
258 - SCSIZE GetEntryCount() const { return nEntryCount; }
259 - ScQueryEntry& GetEntry(SCSIZE n) const { return pEntries[n]; }
260 - void Resize(SCSIZE nNew);
262 - ScQueryParam& operator= ( const ScQueryParam& r );
263 - BOOL operator== ( const ScQueryParam& rOther ) const;
264 - void Clear ();
265 - void DeleteQuery( SCSIZE nPos );
267 - void MoveToDest();
268 - void FillInExcelSyntax(String& aCellStr, SCSIZE nIndex);
271 // -----------------------------------------------------------------------
273 struct SC_DLLPUBLIC ScSubTotalParam
274 diff --git sc/inc/queryparam.hxx sc/inc/queryparam.hxx
275 new file mode 100644
276 index 0000000..bc50237
277 --- /dev/null
278 +++ sc/inc/queryparam.hxx
279 @@ -0,0 +1,142 @@
280 +/*************************************************************************
282 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
283 + *
284 + * Copyright 2008 by Sun Microsystems, Inc.
286 + * OpenOffice.org - a multi-platform office productivity suite
288 + * $RCSfile: interpre.hxx,v $
289 + * $Revision: 1.35.44.2 $
291 + * This file is part of OpenOffice.org.
293 + * OpenOffice.org is free software: you can redistribute it and/or modify
294 + * it under the terms of the GNU Lesser General Public License version 3
295 + * only, as published by the Free Software Foundation.
297 + * OpenOffice.org is distributed in the hope that it will be useful,
298 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
299 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
300 + * GNU Lesser General Public License version 3 for more details
301 + * (a copy is included in the LICENSE file that accompanied this code).
303 + * You should have received a copy of the GNU Lesser General Public License
304 + * version 3 along with OpenOffice.org. If not, see
305 + * <http://www.openoffice.org/license.html>
306 + * for a copy of the LGPLv3 License.
308 + ************************************************************************/
310 +#ifndef SC_QUERYPARAM_HXX
311 +#define SC_QUERYPARAM_HXX
313 +#include "global.hxx"
314 +#include "scmatrix.hxx"
316 +#include <vector>
318 +struct ScDBQueryParamInternal;
320 +struct ScQueryParamBase
322 + bool bHasHeader;
323 + bool bByRow;
324 + bool bInplace;
325 + bool bCaseSens;
326 + bool bRegExp;
327 + bool bDuplicate;
328 + bool bMixedComparison; // whether numbers are smaller than strings
330 + virtual ~ScQueryParamBase();
332 + SC_DLLPUBLIC SCSIZE GetEntryCount() const;
333 + SC_DLLPUBLIC ScQueryEntry& GetEntry(SCSIZE n) const;
334 + void Resize(SCSIZE nNew);
335 + SC_DLLPUBLIC void DeleteQuery( SCSIZE nPos );
336 + void FillInExcelSyntax(String& aCellStr, SCSIZE nIndex);
338 +protected:
339 + ScQueryParamBase();
340 + ScQueryParamBase(const ScQueryParamBase& r);
342 + mutable ::std::vector<ScQueryEntry> maEntries;
345 +// ============================================================================
347 +struct ScQueryParamTable
349 + SCCOL nCol1;
350 + SCROW nRow1;
351 + SCCOL nCol2;
352 + SCROW nRow2;
353 + SCTAB nTab;
355 + ScQueryParamTable();
356 + ScQueryParamTable(const ScQueryParamTable& r);
357 + virtual ~ScQueryParamTable();
360 +// ============================================================================
362 +struct SC_DLLPUBLIC ScQueryParam : public ScQueryParamBase, public ScQueryParamTable
364 + BOOL bDestPers; // nicht gespeichert
365 + SCTAB nDestTab;
366 + SCCOL nDestCol;
367 + SCROW nDestRow;
369 + ScQueryParam();
370 + ScQueryParam( const ScQueryParam& r );
371 + ScQueryParam( const ScDBQueryParamInternal& r );
372 + virtual ~ScQueryParam();
374 + ScQueryParam& operator= ( const ScQueryParam& r );
375 + BOOL operator== ( const ScQueryParam& rOther ) const;
376 + void Clear();
377 + void ClearDestParams();
378 + void MoveToDest();
381 +// ============================================================================
383 +struct ScDBQueryParamBase : public ScQueryParamBase
385 + enum DataType { INTERNAL, MATRIX };
387 + SCCOL mnField; /// the field in which the values are processed during iteration.
388 + bool mbSkipString;
390 + DataType GetType() const;
392 + virtual ~ScDBQueryParamBase();
394 +protected:
395 + ScDBQueryParamBase(DataType eType);
397 +private:
398 + ScDBQueryParamBase();
400 + DataType meType;
403 +// ============================================================================
405 +struct ScDBQueryParamInternal : public ScDBQueryParamBase, public ScQueryParamTable
407 + ScDBQueryParamInternal();
408 + virtual ~ScDBQueryParamInternal();
411 +// ============================================================================
413 +struct ScDBQueryParamMatrix : public ScDBQueryParamBase
415 + ScMatrixRef mpMatrix;
417 + ScDBQueryParamMatrix();
418 + virtual ~ScDBQueryParamMatrix();
421 +#endif
422 diff --git sc/inc/reftokenhelper.hxx sc/inc/reftokenhelper.hxx
423 index d7b335f..99a5998 100644
424 --- sc/inc/reftokenhelper.hxx
425 +++ sc/inc/reftokenhelper.hxx
426 @@ -70,12 +70,12 @@ public:
428 static void getTokensFromRangeList(::std::vector<ScSharedTokenRef>& pTokens, const ScRangeList& rRanges);
430 - static bool isRef(const ScSharedTokenRef& pToken);
431 - static bool isExternalRef(const ScSharedTokenRef& pToken);
432 + static bool SC_DLLPUBLIC isRef(const ScSharedTokenRef& pToken);
433 + static bool SC_DLLPUBLIC isExternalRef(const ScSharedTokenRef& pToken);
435 - static bool intersects(const ::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
436 + static bool SC_DLLPUBLIC intersects(const ::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
438 - static void join(::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
439 + static void SC_DLLPUBLIC join(::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
441 static bool getDoubleRefDataFromToken(ScComplexRefData& rData, const ScSharedTokenRef& pToken);
443 diff --git sc/inc/table.hxx sc/inc/table.hxx
444 index 8194e25..589d73f 100644
445 --- sc/inc/table.hxx
446 +++ sc/inc/table.hxx
447 @@ -161,7 +161,7 @@ private:
448 friend class ScDocument; // fuer FillInfo
449 friend class ScDocumentIterator;
450 friend class ScValueIterator;
451 -friend class ScQueryValueIterator;
452 +friend class ScDBQueryDataIterator;
453 friend class ScCellIterator;
454 friend class ScQueryCellIterator;
455 friend class ScHorizontalCellIterator;
456 diff --git sc/source/core/data/autonamecache.cxx sc/source/core/data/autonamecache.cxx
457 index ea41e3e..329e7f4 100644
458 --- sc/source/core/data/autonamecache.cxx
459 +++ sc/source/core/data/autonamecache.cxx
460 @@ -40,6 +40,7 @@
461 #include "autonamecache.hxx"
462 #include "dociter.hxx"
463 #include "cell.hxx"
464 +#include "queryparam.hxx"
466 // -----------------------------------------------------------------------
468 diff --git sc/source/core/data/cell.cxx sc/source/core/data/cell.cxx
469 index 2ae9972..09da3d6 100644
470 --- sc/source/core/data/cell.cxx
471 +++ sc/source/core/data/cell.cxx
472 @@ -1851,8 +1851,7 @@ void ScFormulaCell::SetDirty()
474 void ScFormulaCell::SetDirtyAfterLoad()
476 - bDirty = TRUE;
477 - if ( !pDocument->GetHardRecalcState() )
478 + if ( bDirty && !pDocument->GetHardRecalcState() )
479 pDocument->PutInFormulaTree( this );
482 diff --git sc/source/core/data/dociter.cxx sc/source/core/data/dociter.cxx
483 index f7f836e..04a2f32 100644
484 --- sc/source/core/data/dociter.cxx
485 +++ sc/source/core/data/dociter.cxx
486 @@ -47,9 +47,23 @@
487 #include "docoptio.hxx"
488 #include "cellform.hxx"
490 +#include <vector>
492 +using ::rtl::math::approxEqual;
493 +using ::std::vector;
494 +using ::rtl::OUString;
496 // STATIC DATA -----------------------------------------------------------
498 +namespace {
500 +void lcl_toUpper(OUString& rStr)
502 + rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, rStr.getLength());
507 ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
508 SCTAB nStartTable, SCTAB nEndTable ) :
509 pDoc( pDocument ),
510 @@ -482,83 +496,85 @@ BOOL ScValueIterator::GetNext(double& rValue, USHORT& rErr)
514 -//------------------------------------------------------------------------
515 -//------------------------------------------------------------------------
516 +// ============================================================================
518 -ScQueryValueIterator::ScQueryValueIterator(ScDocument* pDocument, SCTAB nTable, const ScQueryParam& rParam) :
519 - aParam (rParam),
520 - pDoc( pDocument ),
521 - nNumFmtIndex(0),
522 - nTab( nTable),
523 - nNumFmtType( NUMBERFORMAT_UNDEFINED ),
524 - bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() )
525 +ScDBQueryDataIterator::DataAccess::DataAccess(const ScDBQueryDataIterator* pParent) :
526 + mpParent(pParent)
528 - nCol = aParam.nCol1;
529 - nRow = aParam.nRow1;
532 +ScDBQueryDataIterator::DataAccess::~DataAccess()
536 +// ----------------------------------------------------------------------------
538 +ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc) :
539 + DataAccess(pParent),
540 + mpParam(pParam),
541 + mpDoc(pDoc)
543 + nCol = mpParam->mnField;
544 + nRow = mpParam->nRow1;
545 + nTab = mpParam->nTab;
547 nColRow = 0; // wird bei GetFirst initialisiert
548 SCSIZE i;
549 - SCSIZE nCount = aParam.GetEntryCount();
550 - for (i=0; (i<nCount) && (aParam.GetEntry(i).bDoQuery); i++)
551 + SCSIZE nCount = mpParam->GetEntryCount();
552 + for (i=0; (i<nCount) && (mpParam->GetEntry(i).bDoQuery); i++)
554 - ScQueryEntry& rEntry = aParam.GetEntry(i);
555 + ScQueryEntry& rEntry = mpParam->GetEntry(i);
556 sal_uInt32 nIndex = 0;
557 rEntry.bQueryByString =
558 - !(pDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
559 + !(mpDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
561 nNumFormat = 0; // werden bei GetNumberFormat initialisiert
562 pAttrArray = 0;
563 nAttrEndRow = 0;
566 -BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
567 +ScDBQueryDataIterator::DataAccessInternal::~DataAccessInternal()
569 - ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
570 - SCCOLROW nFirstQueryField = aParam.GetEntry(0).nField;
573 +bool ScDBQueryDataIterator::DataAccessInternal::getCurrent(Value& rValue)
575 + ScColumn* pCol = &(mpDoc->pTab[nTab])->aCol[nCol];
576 + SCCOLROW nFirstQueryField = mpParam->GetEntry(0).nField;
577 for ( ;; )
579 - if ( nRow > aParam.nRow2 )
580 + if (nRow > mpParam->nRow2)
582 - nRow = aParam.nRow1;
583 - if (aParam.bHasHeader)
584 - nRow++;
585 - do
587 - nCol++;
588 - if ( nCol > aParam.nCol2 )
590 - // rValue = 0.0; // do not change caller's value!
591 - rErr = 0;
592 - return FALSE; // Ende und Aus
594 - pCol = &(pDoc->pTab[nTab])->aCol[nCol];
595 - } while ( pCol->nCount == 0 );
596 - pCol->Search( nRow, nColRow );
597 + // Bottom of the range reached. Bail out.
598 + rValue.mnError = 0;
599 + return false;
602 while ( (nColRow < pCol->nCount) && (pCol->pItems[nColRow].nRow < nRow) )
603 nColRow++;
605 - if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= aParam.nRow2 )
606 + if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= mpParam->nRow2 )
608 nRow = pCol->pItems[nColRow].nRow;
609 ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
610 - if ( (pDoc->pTab[nTab])->ValidQuery( nRow, aParam, NULL,
611 + if ( (mpDoc->pTab[nTab])->ValidQuery( nRow, *mpParam, NULL,
612 (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL) ) )
614 switch (pCell->GetCellType())
616 case CELLTYPE_VALUE:
618 - rValue = ((ScValueCell*)pCell)->GetValue();
619 + rValue.mfValue = ((ScValueCell*)pCell)->GetValue();
620 + rValue.mbIsNumber = true;
621 if ( bCalcAsShown )
623 lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
624 - nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
625 - rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
626 + nAttrEndRow, pCol->pAttrArray, nRow, mpDoc );
627 + rValue.mfValue = mpDoc->RoundValueAsShown( rValue.mfValue, nNumFormat );
629 nNumFmtType = NUMBERFORMAT_NUMBER;
630 nNumFmtIndex = 0;
631 - rErr = 0;
632 + rValue.mnError = 0;
633 return TRUE; // gefunden
635 // break;
636 @@ -566,17 +582,31 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
638 if (((ScFormulaCell*)pCell)->IsValue())
640 - rValue = ((ScFormulaCell*)pCell)->GetValue();
641 - pDoc->GetNumberFormatInfo( nNumFmtType,
642 + rValue.mfValue = ((ScFormulaCell*)pCell)->GetValue();
643 + rValue.mbIsNumber = true;
644 + mpDoc->GetNumberFormatInfo( nNumFmtType,
645 nNumFmtIndex, ScAddress( nCol, nRow, nTab ),
646 pCell );
647 - rErr = ((ScFormulaCell*)pCell)->GetErrCode();
648 + rValue.mnError = ((ScFormulaCell*)pCell)->GetErrCode();
649 return TRUE; // gefunden
651 else
652 nRow++;
654 break;
655 + case CELLTYPE_STRING:
656 + case CELLTYPE_EDIT:
657 + if (mpParam->mbSkipString)
658 + ++nRow;
659 + else
661 + rValue.maString = pCell->GetStringData();
662 + rValue.mfValue = 0.0;
663 + rValue.mnError = 0;
664 + rValue.mbIsNumber = false;
665 + return true;
667 + break;
668 default:
669 nRow++;
670 break;
671 @@ -586,30 +616,309 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
672 nRow++;
674 else
675 - nRow = aParam.nRow2 + 1; // Naechste Spalte
676 + nRow = mpParam->nRow2 + 1; // Naechste Spalte
678 -// return FALSE;
679 + return false;
682 -BOOL ScQueryValueIterator::GetFirst(double& rValue, USHORT& rErr)
683 +bool ScDBQueryDataIterator::DataAccessInternal::getFirst(Value& rValue)
685 - nCol = aParam.nCol1;
686 - nRow = aParam.nRow1;
687 - if (aParam.bHasHeader)
688 + if (mpParam->bHasHeader)
689 nRow++;
690 -// nColRow = 0;
691 - ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
692 +// nColRow = 0;
693 + ScColumn* pCol = &(mpDoc->pTab[nTab])->aCol[nCol];
694 pCol->Search( nRow, nColRow );
695 - return GetThis(rValue, rErr);
696 + return getCurrent(rValue);
699 -BOOL ScQueryValueIterator::GetNext(double& rValue, USHORT& rErr)
700 +bool ScDBQueryDataIterator::DataAccessInternal::getNext(Value& rValue)
702 ++nRow;
703 - return GetThis(rValue, rErr);
704 + return getCurrent(rValue);
707 -//-------------------------------------------------------------------------------
708 +// ----------------------------------------------------------------------------
710 +ScDBQueryDataIterator::DataAccessMatrix::DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam) :
711 + DataAccess(pParent),
712 + mpParam(pParam)
714 + SCSIZE nC, nR;
715 + mpParam->mpMatrix->GetDimensions(nC, nR);
716 + mnRows = static_cast<SCROW>(nR);
717 + mnCols = static_cast<SCCOL>(nC);
720 +ScDBQueryDataIterator::DataAccessMatrix::~DataAccessMatrix()
724 +bool ScDBQueryDataIterator::DataAccessMatrix::getCurrent(Value& rValue)
726 + // Starting from row == mnCurRow, get the first row that satisfies all the
727 + // query parameters.
728 + for ( ;mnCurRow < mnRows; ++mnCurRow)
730 + const ScMatrix& rMat = *mpParam->mpMatrix;
731 + if (rMat.IsEmpty(mpParam->mnField, mnCurRow))
732 + // Don't take empty values into account.
733 + continue;
735 + bool bIsStrVal = rMat.IsString(mpParam->mnField, mnCurRow);
736 + if (bIsStrVal && mpParam->mbSkipString)
737 + continue;
739 + if (isValidQuery(mnCurRow, rMat))
741 + rValue.maString = rMat.GetString(mpParam->mnField, mnCurRow);
742 + rValue.mfValue = rMat.GetDouble(mpParam->mnField, mnCurRow);
743 + rValue.mbIsNumber = !bIsStrVal;
744 + rValue.mnError = 0;
745 + return true;
748 + return false;
751 +bool ScDBQueryDataIterator::DataAccessMatrix::getFirst(Value& rValue)
753 + mnCurRow = mpParam->bHasHeader ? 1 : 0;
754 + return getCurrent(rValue);
757 +bool ScDBQueryDataIterator::DataAccessMatrix::getNext(Value& rValue)
759 + ++mnCurRow;
760 + return getCurrent(rValue);
763 +namespace {
765 +bool lcl_isQueryByValue(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
767 + if (rEntry.bQueryByString)
768 + return false;
770 + if (!rMat.IsValueOrEmpty(nCol, nRow))
771 + return false;
773 + return true;
776 +bool lcl_isQueryByString(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
778 + switch (rEntry.eOp)
780 + case SC_EQUAL:
781 + case SC_NOT_EQUAL:
782 + case SC_CONTAINS:
783 + case SC_DOES_NOT_CONTAIN:
784 + case SC_BEGINS_WITH:
785 + case SC_ENDS_WITH:
786 + case SC_DOES_NOT_BEGIN_WITH:
787 + case SC_DOES_NOT_END_WITH:
788 + return true;
789 + default:
793 + if (rEntry.bQueryByString && rMat.IsString(nCol, nRow))
794 + return true;
796 + return false;
801 +bool ScDBQueryDataIterator::DataAccessMatrix::isValidQuery(SCROW nRow, const ScMatrix& rMat) const
803 + SCSIZE nEntryCount = mpParam->GetEntryCount();
804 + vector<bool> aResults;
805 + aResults.reserve(nEntryCount);
807 + const CollatorWrapper& rCollator =
808 + mpParam->bCaseSens ? *ScGlobal::GetCaseCollator() : *ScGlobal::GetCollator();
810 + for (SCSIZE i = 0; i < nEntryCount; ++i)
812 + const ScQueryEntry& rEntry = mpParam->GetEntry(i);
813 + if (!rEntry.bDoQuery)
814 + continue;
816 + switch (rEntry.eOp)
818 + case SC_EQUAL:
819 + case SC_LESS:
820 + case SC_GREATER:
821 + case SC_LESS_EQUAL:
822 + case SC_GREATER_EQUAL:
823 + case SC_NOT_EQUAL:
824 + break;
825 + default:
826 + // Only the above operators are supported.
827 + continue;
830 + bool bValid = false;
832 + SCSIZE nField = static_cast<SCSIZE>(rEntry.nField);
833 + if (lcl_isQueryByValue(rEntry, rMat, nField, nRow))
835 + // By value
836 + double fMatVal = rMat.GetDouble(nField, nRow);
837 + bool bEqual = approxEqual(fMatVal, rEntry.nVal);
838 + switch (rEntry.eOp)
840 + case SC_EQUAL:
841 + bValid = bEqual;
842 + break;
843 + case SC_LESS:
844 + bValid = (fMatVal < rEntry.nVal) && !bEqual;
845 + break;
846 + case SC_GREATER:
847 + bValid = (fMatVal > rEntry.nVal) && !bEqual;
848 + break;
849 + case SC_LESS_EQUAL:
850 + bValid = (fMatVal < rEntry.nVal) || bEqual;
851 + break;
852 + case SC_GREATER_EQUAL:
853 + bValid = (fMatVal > rEntry.nVal) || bEqual;
854 + break;
855 + case SC_NOT_EQUAL:
856 + bValid = !bEqual;
857 + break;
858 + default:
862 + else if (lcl_isQueryByString(rEntry, rMat, nField, nRow))
864 + // By string
865 + do
867 + if (!rEntry.pStr)
868 + break;
870 + // Equality check first.
872 + OUString aMatStr = rMat.GetString(nField, nRow);
873 + lcl_toUpper(aMatStr);
874 + OUString aQueryStr = *rEntry.pStr;
875 + lcl_toUpper(aQueryStr);
876 + bool bDone = false;
877 + switch (rEntry.eOp)
879 + case SC_EQUAL:
880 + bValid = aMatStr.equals(aQueryStr);
881 + bDone = true;
882 + break;
883 + case SC_NOT_EQUAL:
884 + bValid = !aMatStr.equals(aQueryStr);
885 + bDone = true;
886 + break;
887 + default:
891 + if (bDone)
892 + break;
894 + // Unequality check using collator.
896 + sal_Int32 nCompare = rCollator.compareString(aMatStr, aQueryStr);
897 + switch (rEntry.eOp)
899 + case SC_LESS :
900 + bValid = (nCompare < 0);
901 + break;
902 + case SC_GREATER :
903 + bValid = (nCompare > 0);
904 + break;
905 + case SC_LESS_EQUAL :
906 + bValid = (nCompare <= 0);
907 + break;
908 + case SC_GREATER_EQUAL :
909 + bValid = (nCompare >= 0);
910 + break;
911 + default:
915 + while (false);
917 + else if (mpParam->bMixedComparison)
919 + // Not used at the moment.
922 + if (aResults.empty())
923 + // First query entry.
924 + aResults.push_back(bValid);
925 + else if (rEntry.eConnect == SC_AND)
927 + // For AND op, tuck the result into the last result value.
928 + size_t n = aResults.size();
929 + aResults[n-1] = aResults[n-1] && bValid;
931 + else
932 + // For OR op, store its own result.
933 + aResults.push_back(bValid);
936 + // Row is valid as long as there is at least one result being true.
937 + vector<bool>::const_iterator itr = aResults.begin(), itrEnd = aResults.end();
938 + for (; itr != itrEnd; ++itr)
939 + if (*itr)
940 + return true;
942 + return false;
945 +// ----------------------------------------------------------------------------
947 +ScDBQueryDataIterator::Value::Value() :
948 + mnError(0), mbIsNumber(true)
950 + ::rtl::math::setNan(&mfValue);
953 +// ----------------------------------------------------------------------------
955 +ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam) :
956 + mpParam (pParam)
958 + switch (mpParam->GetType())
960 + case ScDBQueryParamBase::INTERNAL:
962 + ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pParam);
963 + mpData.reset(new DataAccessInternal(this, p, pDocument));
965 + break;
966 + case ScDBQueryParamBase::MATRIX:
968 + ScDBQueryParamMatrix* p = static_cast<ScDBQueryParamMatrix*>(pParam);
969 + mpData.reset(new DataAccessMatrix(this, p));
974 +bool ScDBQueryDataIterator::GetThis(Value& rValue)
976 + return mpData->getCurrent(rValue);
979 +bool ScDBQueryDataIterator::GetFirst(Value& rValue)
981 + return mpData->getFirst(rValue);
984 +bool ScDBQueryDataIterator::GetNext(Value& rValue)
986 + return mpData->getNext(rValue);
989 +// ============================================================================
991 ScCellIterator::ScCellIterator( ScDocument* pDocument,
992 SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
993 diff --git sc/source/core/data/dpcachetable.cxx sc/source/core/data/dpcachetable.cxx
994 index 015c651..fd81c26 100644
995 --- sc/source/core/data/dpcachetable.cxx
996 +++ sc/source/core/data/dpcachetable.cxx
997 @@ -38,6 +38,7 @@
998 #include "dptabdat.hxx"
999 #include "dptabsrc.hxx"
1000 #include "dpobject.hxx"
1001 +#include "queryparam.hxx"
1003 #include <com/sun/star/i18n/LocaleDataItem.hpp>
1004 #include <com/sun/star/sdbc/DataType.hpp>
1005 diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
1006 index f71b842..181c634 100644
1007 --- sc/source/core/data/global2.cxx
1008 +++ sc/source/core/data/global2.cxx
1009 @@ -243,238 +243,6 @@ utl::TextSearch* ScQueryEntry::GetSearchTextPtr( BOOL bCaseSens )
1012 //------------------------------------------------------------------------
1014 -ScQueryParam::ScQueryParam()
1016 - nEntryCount = 0;
1017 - Clear();
1020 -//------------------------------------------------------------------------
1022 -ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
1023 - nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab),
1024 - bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
1025 - bRegExp(r.bRegExp), bMixedComparison(r.bMixedComparison),
1026 - bDuplicate(r.bDuplicate), bDestPers(r.bDestPers),
1027 - nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
1029 - nEntryCount = 0;
1031 - Resize( r.nEntryCount );
1032 - for (USHORT i=0; i<nEntryCount; i++)
1033 - pEntries[i] = r.pEntries[i];
1036 -//------------------------------------------------------------------------
1038 -ScQueryParam::~ScQueryParam()
1040 - delete[] pEntries;
1043 -//------------------------------------------------------------------------
1045 -void ScQueryParam::Clear()
1047 - nCol1=nCol2=nDestCol = 0;
1048 - nRow1=nRow2=nDestRow = 0;
1049 - nDestTab = 0;
1050 - nTab = SCTAB_MAX;
1051 - bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
1052 - bInplace = bByRow = bDuplicate = bDestPers = TRUE;
1054 - Resize( MAXQUERY );
1055 - for (USHORT i=0; i<MAXQUERY; i++)
1056 - pEntries[i].Clear();
1059 -//------------------------------------------------------------------------
1061 -ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
1063 - nCol1 = r.nCol1;
1064 - nRow1 = r.nRow1;
1065 - nCol2 = r.nCol2;
1066 - nRow2 = r.nRow2;
1067 - nTab = r.nTab;
1068 - nDestTab = r.nDestTab;
1069 - nDestCol = r.nDestCol;
1070 - nDestRow = r.nDestRow;
1071 - bHasHeader = r.bHasHeader;
1072 - bInplace = r.bInplace;
1073 - bCaseSens = r.bCaseSens;
1074 - bRegExp = r.bRegExp;
1075 - bMixedComparison = r.bMixedComparison;
1076 - bDuplicate = r.bDuplicate;
1077 - bByRow = r.bByRow;
1078 - bDestPers = r.bDestPers;
1080 - Resize( r.nEntryCount );
1081 - for (USHORT i=0; i<nEntryCount; i++)
1082 - pEntries[i] = r.pEntries[i];
1084 - return *this;
1087 -//------------------------------------------------------------------------
1089 -BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
1091 - BOOL bEqual = FALSE;
1093 - // Anzahl der Queries gleich?
1094 - USHORT nUsed = 0;
1095 - USHORT nOtherUsed = 0;
1096 - while ( nUsed<nEntryCount && pEntries[nUsed].bDoQuery ) ++nUsed;
1097 - while ( nOtherUsed<rOther.nEntryCount && rOther.pEntries[nOtherUsed].bDoQuery )
1098 - ++nOtherUsed;
1100 - if ( (nUsed == nOtherUsed)
1101 - && (nCol1 == rOther.nCol1)
1102 - && (nRow1 == rOther.nRow1)
1103 - && (nCol2 == rOther.nCol2)
1104 - && (nRow2 == rOther.nRow2)
1105 - && (nTab == rOther.nTab)
1106 - && (bHasHeader == rOther.bHasHeader)
1107 - && (bByRow == rOther.bByRow)
1108 - && (bInplace == rOther.bInplace)
1109 - && (bCaseSens == rOther.bCaseSens)
1110 - && (bRegExp == rOther.bRegExp)
1111 - && (bMixedComparison == rOther.bMixedComparison)
1112 - && (bDuplicate == rOther.bDuplicate)
1113 - && (bDestPers == rOther.bDestPers)
1114 - && (nDestTab == rOther.nDestTab)
1115 - && (nDestCol == rOther.nDestCol)
1116 - && (nDestRow == rOther.nDestRow) )
1118 - bEqual = TRUE;
1119 - for ( USHORT i=0; i<nUsed && bEqual; i++ )
1120 - bEqual = pEntries[i] == rOther.pEntries[i];
1122 - return bEqual;
1125 -//------------------------------------------------------------------------
1127 -void ScQueryParam::DeleteQuery( SCSIZE nPos )
1129 - if (nPos<nEntryCount)
1131 - for (SCSIZE i=nPos; i+1<nEntryCount; i++)
1132 - pEntries[i] = pEntries[i+1];
1134 - pEntries[nEntryCount-1].Clear();
1136 - else
1138 - DBG_ERROR("Falscher Parameter bei ScQueryParam::DeleteQuery");
1142 -//------------------------------------------------------------------------
1144 -void ScQueryParam::Resize(SCSIZE nNew)
1146 - if ( nNew < MAXQUERY )
1147 - nNew = MAXQUERY; // nie weniger als MAXQUERY
1149 - ScQueryEntry* pNewEntries = NULL;
1150 - if ( nNew )
1151 - pNewEntries = new ScQueryEntry[nNew];
1153 - SCSIZE nCopy = Min( nEntryCount, nNew );
1154 - for (SCSIZE i=0; i<nCopy; i++)
1155 - pNewEntries[i] = pEntries[i];
1157 - if ( nEntryCount )
1158 - delete[] pEntries;
1159 - nEntryCount = nNew;
1160 - pEntries = pNewEntries;
1163 -//------------------------------------------------------------------------
1165 -void ScQueryParam::MoveToDest()
1167 - if (!bInplace)
1169 - SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
1170 - SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
1171 - SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
1173 - nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
1174 - nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
1175 - nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
1176 - nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
1177 - nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
1178 - for (USHORT i=0; i<nEntryCount; i++)
1179 - pEntries[i].nField += nDifX;
1181 - bInplace = TRUE;
1183 - else
1185 - DBG_ERROR("MoveToDest, bInplace == TRUE");
1189 -//------------------------------------------------------------------------
1191 -void ScQueryParam::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
1193 - if (aCellStr.Len() > 0)
1195 - if ( nIndex >= nEntryCount )
1196 - Resize( nIndex+1 );
1198 - ScQueryEntry& rEntry = pEntries[nIndex];
1200 - rEntry.bDoQuery = TRUE;
1201 - // Operatoren herausfiltern
1202 - if (aCellStr.GetChar(0) == '<')
1204 - if (aCellStr.GetChar(1) == '>')
1206 - *rEntry.pStr = aCellStr.Copy(2);
1207 - rEntry.eOp = SC_NOT_EQUAL;
1209 - else if (aCellStr.GetChar(1) == '=')
1211 - *rEntry.pStr = aCellStr.Copy(2);
1212 - rEntry.eOp = SC_LESS_EQUAL;
1214 - else
1216 - *rEntry.pStr = aCellStr.Copy(1);
1217 - rEntry.eOp = SC_LESS;
1220 - else if (aCellStr.GetChar(0) == '>')
1222 - if (aCellStr.GetChar(1) == '=')
1224 - *rEntry.pStr = aCellStr.Copy(2);
1225 - rEntry.eOp = SC_GREATER_EQUAL;
1227 - else
1229 - *rEntry.pStr = aCellStr.Copy(1);
1230 - rEntry.eOp = SC_GREATER;
1233 - else
1235 - if (aCellStr.GetChar(0) == '=')
1236 - *rEntry.pStr = aCellStr.Copy(1);
1237 - else
1238 - *rEntry.pStr = aCellStr;
1239 - rEntry.eOp = SC_EQUAL;
1244 -//------------------------------------------------------------------------
1245 // struct ScSubTotalParam:
1247 ScSubTotalParam::ScSubTotalParam()
1248 diff --git sc/source/core/data/sortparam.cxx sc/source/core/data/sortparam.cxx
1249 index 9531c71..dfab465 100644
1250 --- sc/source/core/data/sortparam.cxx
1251 +++ sc/source/core/data/sortparam.cxx
1252 @@ -36,6 +36,7 @@
1253 #include "sortparam.hxx"
1254 #include "global.hxx"
1255 #include "address.hxx"
1256 +#include "queryparam.hxx"
1257 #include <tools/debug.hxx>
1260 diff --git sc/source/core/data/table3.cxx sc/source/core/data/table3.cxx
1261 index ca196ea..2d8f0d3 100644
1262 --- sc/source/core/data/table3.cxx
1263 +++ sc/source/core/data/table3.cxx
1264 @@ -60,6 +60,7 @@
1265 #include "progress.hxx"
1266 #include "cellform.hxx"
1267 #include "postit.hxx"
1268 +#include "queryparam.hxx"
1270 #include <vector>
1272 diff --git sc/source/core/inc/doubleref.hxx sc/source/core/inc/doubleref.hxx
1273 new file mode 100644
1274 index 0000000..0aa577b
1275 --- /dev/null
1276 +++ sc/source/core/inc/doubleref.hxx
1277 @@ -0,0 +1,194 @@
1278 +/*************************************************************************
1280 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1281 + *
1282 + * Copyright 2008 by Sun Microsystems, Inc.
1284 + * OpenOffice.org - a multi-platform office productivity suite
1286 + * $RCSfile: interpre.hxx,v $
1287 + * $Revision: 1.35.44.2 $
1289 + * This file is part of OpenOffice.org.
1291 + * OpenOffice.org is free software: you can redistribute it and/or modify
1292 + * it under the terms of the GNU Lesser General Public License version 3
1293 + * only, as published by the Free Software Foundation.
1295 + * OpenOffice.org is distributed in the hope that it will be useful,
1296 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1297 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1298 + * GNU Lesser General Public License version 3 for more details
1299 + * (a copy is included in the LICENSE file that accompanied this code).
1301 + * You should have received a copy of the GNU Lesser General Public License
1302 + * version 3 along with OpenOffice.org. If not, see
1303 + * <http://www.openoffice.org/license.html>
1304 + * for a copy of the LGPLv3 License.
1306 + ************************************************************************/
1308 +#ifndef SC_DOUBLEREF_HXX
1309 +#define SC_DOUBLEREF_HXX
1311 +#include "address.hxx"
1312 +#include "scmatrix.hxx"
1314 +class ScDocument;
1315 +class ScBaseCell;
1316 +class ScDBQueryParamBase;
1317 +class ScQueryParamBase;
1319 +// ============================================================================
1321 +/**
1322 + * Base class for abstracting range data backends for database functions.
1323 + */
1324 +class ScDBRangeBase
1326 +public:
1327 + enum RefType { INTERNAL, EXTERNAL };
1329 + virtual ~ScDBRangeBase() = 0;
1331 + RefType getType() const;
1332 + bool fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const;
1334 + virtual SCCOL getColSize() const = 0;
1335 + virtual SCROW getRowSize() const = 0;
1336 + virtual SCSIZE getVisibleDataCellCount() const = 0;
1338 + /**
1339 + * Get a string value of a specified cell position. Note that the
1340 + * position of the upper left cell of the range is always (0, 0) even if
1341 + * the reference type is of internal range.
1343 + * @param nCol column position (0 to column size-1)
1344 + * @param nRow row position (0 to row size-1)
1345 + */
1346 + virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const = 0;
1348 + virtual SCCOL getFirstFieldColumn() const = 0;
1350 + /**
1351 + * Get a <i>0-based</i> column index that corresponds with the passed field
1352 + * index. Note that the field index passed as the 1st parameter is
1353 + * <i>1-based.</i>
1355 + * @param nIndex 1-based field index.
1356 + *
1357 + * @return 0-based column index
1358 + */
1359 + virtual SCCOL findFieldColumn(SCCOL nIndex) const = 0;
1360 + virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const = 0;
1361 + virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const = 0;
1362 + virtual bool isRangeEqual(const ScRange& rRange) const = 0;
1364 +protected:
1365 + ScDBRangeBase(ScDocument* pDoc, RefType eType);
1366 + ScDocument* getDoc() const;
1368 + /**
1369 + * Populate query options that are always the same for all database
1370 + * queries.
1371 + */
1372 + static void fillQueryOptions(ScQueryParamBase* pParam);
1374 +private:
1375 + ScDBRangeBase(); // disabled
1377 + ScDocument* mpDoc;
1378 + RefType meType;
1381 +// ============================================================================
1383 +class ScDBInternalRange : public ScDBRangeBase
1385 +public:
1386 + explicit ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange);
1387 + virtual ~ScDBInternalRange();
1389 + const ScRange& getRange() const;
1391 + virtual SCCOL getColSize() const;
1392 + virtual SCROW getRowSize() const;
1393 + virtual SCSIZE getVisibleDataCellCount() const;
1395 + /**
1396 + * Get a string value of a specified cell position. Note that the
1397 + * position of the upper left cell of the range is always (0, 0) even if
1398 + * the reference type is of internal range.
1400 + * @param nCol column position (0 to column size-1)
1401 + * @param nRow row position (0 to row size-1)
1402 + */
1403 + virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const;
1405 + virtual SCCOL getFirstFieldColumn() const;
1406 + /**
1407 + * Get a <i>0-based</i> column index that corresponds with the passed field
1408 + * index. Note that the field index passed as the 1st parameter is
1409 + * <i>1-based.</i>
1411 + * @param nIndex 1-based field index.
1412 + *
1413 + * @return 0-based column index
1414 + */
1415 + virtual SCCOL findFieldColumn(SCCOL nIndex) const;
1416 + virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const;
1417 + virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const;
1418 + virtual bool isRangeEqual(const ScRange& rRange) const;
1420 +private:
1421 + sal_uInt16 getCellString(::rtl::OUString& rStr, ScBaseCell* pCell) const;
1423 +private:
1424 + ScRange maRange;
1427 +// ============================================================================
1429 +class ScDBExternalRange : public ScDBRangeBase
1431 +public:
1432 + explicit ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat);
1433 + virtual ~ScDBExternalRange();
1435 + virtual SCCOL getColSize() const;
1436 + virtual SCROW getRowSize() const;
1437 + virtual SCSIZE getVisibleDataCellCount() const;
1439 + /**
1440 + * Get a string value of a specified cell position. Note that the
1441 + * position of the upper left cell of the range is always (0, 0) even if
1442 + * the reference type is of internal range.
1444 + * @param nCol column position (0 to column size-1)
1445 + * @param nRow row position (0 to row size-1)
1446 + */
1447 + virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const;
1449 + virtual SCCOL getFirstFieldColumn() const;
1451 + /**
1452 + * Get a <i>0-based</i> column index that corresponds with the passed field
1453 + * index. Note that the field index passed as the 1st parameter is
1454 + * <i>1-based.</i>
1456 + * @param nIndex 1-based field index.
1457 + *
1458 + * @return 0-based column index
1459 + */
1460 + virtual SCCOL findFieldColumn(SCCOL nIndex) const;
1461 + virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const;
1462 + virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const;
1463 + virtual bool isRangeEqual(const ScRange& rRange) const;
1465 +private:
1466 + const ScMatrixRef mpMatrix;
1467 + SCCOL mnCols;
1468 + SCROW mnRows;
1471 +#endif
1472 diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
1473 index 58bc46f..0252f1d 100644
1474 --- sc/source/core/inc/interpre.hxx
1475 +++ sc/source/core/inc/interpre.hxx
1476 @@ -53,7 +53,10 @@ class SbxVariable;
1477 class ScBaseCell;
1478 class ScFormulaCell;
1479 class SvNumberFormatter;
1480 +class ScDBRangeBase;
1481 struct MatrixDoubleOp;
1482 +struct ScQueryParam;
1483 +struct ScDBQueryParamBase;
1485 struct ScCompare
1487 @@ -302,6 +305,7 @@ void DoubleRefToVars( const ScToken* p,
1488 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1489 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1490 BOOL bDontCheckForTableOp = FALSE );
1491 +ScDBRangeBase* PopDoubleRef();
1492 void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1493 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1494 BOOL bDontCheckForTableOp = FALSE );
1495 @@ -491,7 +495,7 @@ void ScSubTotal();
1496 // compatibility). If this was the case then rMissingField is set to TRUE upon
1497 // return. If rMissingField==FALSE upon call all "missing cases" are considered
1498 // to be an error.
1499 -BOOL GetDBParams( SCTAB& rTab, ScQueryParam& rParam, BOOL& rMissingField );
1500 +ScDBQueryParamBase* GetDBParams( BOOL& rMissingField );
1502 void DBIterator( ScIterFunc );
1503 void ScDBSum();
1504 diff --git sc/source/core/tool/dbcolect.cxx sc/source/core/tool/dbcolect.cxx
1505 index e1e3870..a47a669 100644
1506 --- sc/source/core/tool/dbcolect.cxx
1507 +++ sc/source/core/tool/dbcolect.cxx
1508 @@ -40,6 +40,7 @@
1509 #include "refupdat.hxx"
1510 #include "rechead.hxx"
1511 #include "document.hxx"
1512 +#include "queryparam.hxx"
1513 #include "globstr.hrc"
1516 diff --git sc/source/core/tool/doubleref.cxx sc/source/core/tool/doubleref.cxx
1517 new file mode 100644
1518 index 0000000..e1bba5c
1519 --- /dev/null
1520 +++ sc/source/core/tool/doubleref.cxx
1521 @@ -0,0 +1,568 @@
1522 +/*************************************************************************
1524 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1525 + *
1526 + * Copyright 2008 by Sun Microsystems, Inc.
1528 + * OpenOffice.org - a multi-platform office productivity suite
1530 + * $RCSfile: interpre.hxx,v $
1531 + * $Revision: 1.35.44.2 $
1533 + * This file is part of OpenOffice.org.
1535 + * OpenOffice.org is free software: you can redistribute it and/or modify
1536 + * it under the terms of the GNU Lesser General Public License version 3
1537 + * only, as published by the Free Software Foundation.
1539 + * OpenOffice.org is distributed in the hope that it will be useful,
1540 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1541 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1542 + * GNU Lesser General Public License version 3 for more details
1543 + * (a copy is included in the LICENSE file that accompanied this code).
1545 + * You should have received a copy of the GNU Lesser General Public License
1546 + * version 3 along with OpenOffice.org. If not, see
1547 + * <http://www.openoffice.org/license.html>
1548 + * for a copy of the LGPLv3 License.
1550 + ************************************************************************/
1552 +// MARKER(update_precomp.py): autogen include statement, do not remove
1553 +#include "precompiled_sc.hxx"
1555 +// INCLUDE ---------------------------------------------------------------
1557 +#include "doubleref.hxx"
1558 +#include "cell.hxx"
1559 +#include "global.hxx"
1560 +#include "document.hxx"
1561 +#include "queryparam.hxx"
1562 +#include "globstr.hrc"
1564 +#include <memory>
1565 +#include <vector>
1567 +using ::rtl::OUString;
1568 +using ::std::auto_ptr;
1569 +using ::std::vector;
1571 +namespace {
1573 +void lcl_toUpper(OUString& rStr)
1575 + rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, rStr.getLength());
1578 +bool lcl_createStarQuery(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
1580 + // A valid StarQuery must be at least 4 columns wide. To be precise it
1581 + // should be exactly 4 columns ...
1582 + // Additionally, if this wasn't checked, a formula pointing to a valid 1-3
1583 + // column Excel style query range immediately left to itself would result
1584 + // in a circular reference when the field name or operator or value (first
1585 + // to third query range column) is obtained (#i58354#). Furthermore, if the
1586 + // range wasn't sufficiently specified data changes wouldn't flag formula
1587 + // cells for recalculation.
1589 + if (pQueryRef->getColSize() < 4)
1590 + return false;
1592 + BOOL bValid;
1593 + BOOL bFound;
1594 + OUString aCellStr;
1595 + SCSIZE nIndex = 0;
1596 + SCROW nRow = 0;
1597 + SCROW nRows = pDBRef->getRowSize();
1598 + SCSIZE nNewEntries = static_cast<SCSIZE>(nRows);
1599 + pParam->Resize(nNewEntries);
1601 + do
1603 + ScQueryEntry& rEntry = pParam->GetEntry(nIndex);
1605 + bValid = FALSE;
1607 + if (nIndex > 0)
1609 + // For all entries after the first one, check the and/or connector in the first column.
1610 + aCellStr = pQueryRef->getString(0, nRow);
1611 + lcl_toUpper(aCellStr);
1612 + if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_UND)) )
1614 + rEntry.eConnect = SC_AND;
1615 + bValid = TRUE;
1617 + else if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_ODER)) )
1619 + rEntry.eConnect = SC_OR;
1620 + bValid = TRUE;
1624 + if ((nIndex < 1) || bValid)
1626 + // field name in the 2nd column.
1627 + bFound = FALSE;
1628 + aCellStr = pQueryRef->getString(1, nRow);
1629 + SCCOL nField = pDBRef->findFieldColumn(aCellStr); // TODO: must be case insensitive comparison.
1630 + if (ValidCol(nField))
1632 + rEntry.nField = nField;
1633 + bValid = true;
1635 + else
1636 + bValid = false;
1639 + if (bValid)
1641 + // equality, non-equality operator in the 3rd column.
1642 + bFound = FALSE;
1643 + aCellStr = pQueryRef->getString(2, nRow);
1644 + lcl_toUpper(aCellStr);
1645 + const sal_Unicode* p = aCellStr.getStr();
1646 + if (p[0] == sal_Unicode('<'))
1648 + if (p[1] == sal_Unicode('>'))
1649 + rEntry.eOp = SC_NOT_EQUAL;
1650 + else if (p[1] == sal_Unicode('='))
1651 + rEntry.eOp = SC_LESS_EQUAL;
1652 + else
1653 + rEntry.eOp = SC_LESS;
1655 + else if (p[0] == sal_Unicode('>'))
1657 + if (p[1] == sal_Unicode('='))
1658 + rEntry.eOp = SC_GREATER_EQUAL;
1659 + else
1660 + rEntry.eOp = SC_GREATER;
1662 + else if (p[0] == sal_Unicode('='))
1663 + rEntry.eOp = SC_EQUAL;
1667 + if (bValid)
1669 + // Finally, the right-hand-side value in the 4th column.
1670 + *rEntry.pStr = pQueryRef->getString(3, nRow);
1671 + rEntry.bDoQuery = TRUE;
1673 + nIndex++;
1674 + nRow++;
1676 + while (bValid && (nRow < nRows) /* && (nIndex < MAXQUERY) */ );
1677 + return bValid;
1680 +bool lcl_createExcelQuery(
1681 + ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
1683 + bool bValid = true;
1684 + SCCOL nCols = pQueryRef->getColSize();
1685 + SCROW nRows = pQueryRef->getRowSize();
1686 + vector<SCCOL> aFields(nCols);
1687 + SCCOL nCol = 0;
1688 + while (bValid && (nCol < nCols))
1690 + OUString aQueryStr = pQueryRef->getString(nCol, 0);
1691 + SCCOL nField = pDBRef->findFieldColumn(aQueryStr);
1692 + if (ValidCol(nField))
1693 + aFields[nCol] = nField;
1694 + else
1695 + bValid = false;
1696 + ++nCol;
1699 + if (bValid)
1701 +// ULONG nVisible = 0;
1702 +// for ( nCol=nCol1; nCol<=nCol2; nCol++ )
1703 +// nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
1705 + // Count the number of visible cells (excluding the header row). Each
1706 + // visible cell corresponds with a single query.
1707 + SCSIZE nVisible = pQueryRef->getVisibleDataCellCount();
1708 + if ( nVisible > SCSIZE_MAX / sizeof(void*) )
1710 + DBG_ERROR("zu viele Filterkritierien");
1711 + nVisible = 0;
1714 + SCSIZE nNewEntries = nVisible;
1715 + pParam->Resize( nNewEntries );
1717 + SCSIZE nIndex = 0;
1718 + SCROW nRow = 1;
1719 + String aCellStr;
1720 + while (nRow < nRows)
1722 + nCol = 0;
1723 + while (nCol < nCols)
1725 + aCellStr = pQueryRef->getString(nCol, nRow);
1726 + ScGlobal::pCharClass->toUpper( aCellStr );
1727 + if (aCellStr.Len() > 0)
1729 + if (nIndex < nNewEntries)
1731 + pParam->GetEntry(nIndex).nField = aFields[nCol];
1732 + pParam->FillInExcelSyntax(aCellStr, nIndex);
1733 + nIndex++;
1734 + if (nIndex < nNewEntries)
1735 + pParam->GetEntry(nIndex).eConnect = SC_AND;
1737 + else
1738 + bValid = FALSE;
1740 + nCol++;
1742 + nRow++;
1743 + if (nIndex < nNewEntries)
1744 + pParam->GetEntry(nIndex).eConnect = SC_OR;
1747 + return bValid;
1750 +bool lcl_fillQueryEntries(
1751 + ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
1753 + SCSIZE nCount = pParam->GetEntryCount();
1754 + for (SCSIZE i = 0; i < nCount; ++i)
1755 + pParam->GetEntry(i).Clear();
1757 + // Standard QueryTabelle
1758 + bool bValid = lcl_createStarQuery(pParam, pDBRef, pQueryRef);
1759 + // Excel QueryTabelle
1760 + if (!bValid)
1761 + bValid = lcl_createExcelQuery(pParam, pDBRef, pQueryRef);
1763 + nCount = pParam->GetEntryCount();
1764 + if (bValid)
1766 + // bQueryByString muss gesetzt sein
1767 + for (SCSIZE i = 0; i < nCount; ++i)
1768 + pParam->GetEntry(i).bQueryByString = true;
1770 + else
1772 + // nix
1773 + for (SCSIZE i = 0; i < nCount; ++i)
1774 + pParam->GetEntry(i).Clear();
1776 + return bValid;
1781 +// ============================================================================
1783 +ScDBRangeBase::ScDBRangeBase(ScDocument* pDoc, RefType eType) :
1784 + mpDoc(pDoc), meType(eType)
1788 +ScDBRangeBase::~ScDBRangeBase()
1792 +ScDBRangeBase::RefType ScDBRangeBase::getType() const
1794 + return meType;
1797 +bool ScDBRangeBase::fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const
1799 + if (!pDBRef)
1800 + return false;
1802 + return lcl_fillQueryEntries(pParam, pDBRef, this);
1805 +void ScDBRangeBase::fillQueryOptions(ScQueryParamBase* pParam)
1807 + pParam->bHasHeader = true;
1808 + pParam->bByRow = true;
1809 + pParam->bInplace = true;
1810 + pParam->bCaseSens = false;
1811 + pParam->bRegExp = false;
1812 + pParam->bDuplicate = true;
1813 + pParam->bMixedComparison = false;
1816 +ScDocument* ScDBRangeBase::getDoc() const
1818 + return mpDoc;
1821 +// ============================================================================
1823 +ScDBInternalRange::ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange) :
1824 + ScDBRangeBase(pDoc, INTERNAL), maRange(rRange)
1828 +ScDBInternalRange::~ScDBInternalRange()
1832 +const ScRange& ScDBInternalRange::getRange() const
1834 + return maRange;
1837 +SCCOL ScDBInternalRange::getColSize() const
1839 + return maRange.aEnd.Col() - maRange.aStart.Col() + 1;
1842 +SCROW ScDBInternalRange::getRowSize() const
1844 + return maRange.aEnd.Row() - maRange.aStart.Row() + 1;
1847 +SCSIZE ScDBInternalRange::getVisibleDataCellCount() const
1849 + SCCOL nCols = getColSize();
1850 + SCROW nRows = getRowSize();
1851 + if (nRows <= 1)
1852 + return 0;
1854 + return (nRows-1)*nCols;
1857 +OUString ScDBInternalRange::getString(SCCOL nCol, SCROW nRow) const
1859 + String aStr;
1860 + const ScAddress& s = maRange.aStart;
1861 + getDoc()->GetString(s.Col() + nCol, s.Row() + nRow, maRange.aStart.Tab(), aStr);
1862 + return aStr;
1865 +SCCOL ScDBInternalRange::getFirstFieldColumn() const
1867 + return getRange().aStart.Col();
1870 +SCCOL ScDBInternalRange::findFieldColumn(SCCOL nIndex) const
1872 + const ScRange& rRange = getRange();
1873 + const ScAddress& s = rRange.aStart;
1874 + const ScAddress& e = rRange.aEnd;
1876 + SCCOL nDBCol1 = s.Col();
1877 + SCCOL nDBCol2 = e.Col();
1879 + if ( nIndex <= 0 || nIndex > (nDBCol2 - nDBCol1 + 1) )
1880 + return nDBCol1;
1882 + return Min(nDBCol2, static_cast<SCCOL>(nDBCol1 + nIndex - 1));
1885 +sal_uInt16 ScDBInternalRange::getCellString(OUString& rStr, ScBaseCell* pCell) const
1887 + sal_uInt16 nErr = 0;
1888 + String aStr;
1889 + if (pCell)
1891 + SvNumberFormatter* pFormatter = getDoc()->GetFormatTable();
1892 + switch (pCell->GetCellType())
1894 + case CELLTYPE_STRING:
1895 + ((ScStringCell*) pCell)->GetString(aStr);
1896 + break;
1897 + case CELLTYPE_EDIT:
1898 + ((ScEditCell*) pCell)->GetString(aStr);
1899 + break;
1900 + case CELLTYPE_FORMULA:
1902 + ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
1903 + nErr = pFCell->GetErrCode();
1904 + if (pFCell->IsValue())
1906 + double fVal = pFCell->GetValue();
1907 + ULONG nIndex = pFormatter->GetStandardFormat(
1908 + NUMBERFORMAT_NUMBER,
1909 + ScGlobal::eLnge);
1910 + pFormatter->GetInputLineString(fVal, nIndex, aStr);
1912 + else
1913 + pFCell->GetString(aStr);
1915 + break;
1916 + case CELLTYPE_VALUE:
1918 + double fVal = ((ScValueCell*) pCell)->GetValue();
1919 + ULONG nIndex = pFormatter->GetStandardFormat(
1920 + NUMBERFORMAT_NUMBER,
1921 + ScGlobal::eLnge);
1922 + pFormatter->GetInputLineString(fVal, nIndex, aStr);
1924 + break;
1925 + default:
1929 + rStr = aStr;
1930 + return nErr;
1933 +SCCOL ScDBInternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
1935 + const ScAddress& s = maRange.aStart;
1936 + const ScAddress& e = maRange.aEnd;
1937 + OUString aUpper = rStr;
1938 + lcl_toUpper(aUpper);
1940 + SCCOL nDBCol1 = s.Col();
1941 + SCROW nDBRow1 = s.Row();
1942 + SCTAB nDBTab1 = s.Tab();
1943 + SCCOL nDBCol2 = e.Col();
1945 + SCCOL nField = nDBCol1;
1946 + BOOL bFound = TRUE;
1948 + bFound = FALSE;
1949 + OUString aCellStr;
1950 + ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
1951 + while (!bFound && (aLook.Col() <= nDBCol2))
1953 + ScBaseCell* pCell = getDoc()->GetCell( aLook );
1954 + sal_uInt16 nErr = getCellString( aCellStr, pCell );
1955 + if (pErr)
1956 + *pErr = nErr;
1957 + lcl_toUpper(aCellStr);
1958 + bFound = ScGlobal::GetpTransliteration()->isEqual(aCellStr, aUpper);
1959 + if (!bFound)
1960 + aLook.IncCol();
1962 + nField = aLook.Col();
1964 + return bFound ? nField : -1;
1967 +ScDBQueryParamBase* ScDBInternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
1969 + auto_ptr<ScDBQueryParamInternal> pParam(new ScDBQueryParamInternal);
1971 + // Set the database range first.
1972 + const ScAddress& s = maRange.aStart;
1973 + const ScAddress& e = maRange.aEnd;
1974 + pParam->nCol1 = s.Col();
1975 + pParam->nRow1 = s.Row();
1976 + pParam->nCol2 = e.Col();
1977 + pParam->nRow2 = e.Row();
1978 + pParam->nTab = s.Tab();
1980 + fillQueryOptions(pParam.get());
1982 + // Now construct the query entries from the query range.
1983 + if (!pQueryRef->fillQueryEntries(pParam.get(), this))
1984 + return NULL;
1986 + return pParam.release();
1989 +bool ScDBInternalRange::isRangeEqual(const ScRange& rRange) const
1991 + return maRange == rRange;
1994 +// ============================================================================
1996 +ScDBExternalRange::ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat) :
1997 + ScDBRangeBase(pDoc, EXTERNAL), mpMatrix(pMat)
1999 + SCSIZE nC, nR;
2000 + mpMatrix->GetDimensions(nC, nR);
2001 + mnCols = nC;
2002 + mnRows = nR;
2005 +ScDBExternalRange::~ScDBExternalRange()
2009 +SCCOL ScDBExternalRange::getColSize() const
2011 + return mnCols;
2014 +SCROW ScDBExternalRange::getRowSize() const
2016 + return mnRows;
2019 +SCSIZE ScDBExternalRange::getVisibleDataCellCount() const
2021 + SCCOL nCols = getColSize();
2022 + SCROW nRows = getRowSize();
2023 + if (nRows <= 1)
2024 + return 0;
2026 + return (nRows-1)*nCols;
2029 +OUString ScDBExternalRange::getString(SCCOL nCol, SCROW nRow) const
2031 + if (nCol >= mnCols || nRow >= mnRows)
2032 + return OUString();
2034 + return mpMatrix->GetString(nCol, nRow);
2037 +SCCOL ScDBExternalRange::getFirstFieldColumn() const
2039 + return 0;
2042 +SCCOL ScDBExternalRange::findFieldColumn(SCCOL nIndex) const
2044 + if (nIndex < 1)
2045 + // 1st field
2046 + return 0;
2048 + if (nIndex > mnCols)
2049 + // last field
2050 + return mnCols - 1;
2052 + return nIndex - 1;
2055 +SCCOL ScDBExternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
2057 + if (pErr)
2058 + pErr = 0;
2060 + OUString aUpper = rStr;
2061 + lcl_toUpper(aUpper);
2062 + for (SCCOL i = 0; i < mnCols; ++i)
2064 + OUString aUpperVal = mpMatrix->GetString(i, 0);
2065 + lcl_toUpper(aUpperVal);
2066 + if (aUpper.equals(aUpperVal))
2067 + return i;
2069 + return -1;
2072 +ScDBQueryParamBase* ScDBExternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
2074 + auto_ptr<ScDBQueryParamMatrix> pParam(new ScDBQueryParamMatrix);
2075 + pParam->mpMatrix = mpMatrix;
2076 + fillQueryOptions(pParam.get());
2078 + // Now construct the query entries from the query range.
2079 + if (!pQueryRef->fillQueryEntries(pParam.get(), this))
2080 + return NULL;
2082 + return pParam.release();
2085 +bool ScDBExternalRange::isRangeEqual(const ScRange& /*rRange*/) const
2087 + return false;
2090 diff --git sc/source/core/tool/interpr1.cxx sc/source/core/tool/interpr1.cxx
2091 index 531f089..aad8822 100644
2092 --- sc/source/core/tool/interpr1.cxx
2093 +++ sc/source/core/tool/interpr1.cxx
2094 @@ -68,11 +68,14 @@
2095 #include <string.h>
2096 #include <math.h>
2097 #include <vector>
2098 +#include <memory>
2099 #include "cellkeytranslator.hxx"
2100 #include "lookupcache.hxx"
2101 #include "rangenam.hxx"
2102 #include "compiler.hxx"
2103 #include "externalrefmgr.hxx"
2104 +#include "doubleref.hxx"
2105 +#include "queryparam.hxx"
2107 #define SC_DOUBLE_MAXVALUE 1.7e307
2109 @@ -83,6 +86,8 @@ ScTokenStack* ScInterpreter::pGlobalStack = NULL;
2110 BOOL ScInterpreter::bGlobalStackInUse = FALSE;
2112 using namespace formula;
2113 +using ::std::auto_ptr;
2115 //-----------------------------------------------------------------------------
2116 // Funktionen
2117 //-----------------------------------------------------------------------------
2118 @@ -5826,11 +5831,9 @@ void ScInterpreter::ScSubTotal()
2119 #endif
2122 -BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
2123 - BOOL& rMissingField )
2124 +ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
2126 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBParams" );
2127 - BOOL bRet = FALSE;
2128 BOOL bAllowMissingField = FALSE;
2129 if ( rMissingField )
2131 @@ -5839,14 +5842,10 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
2133 if ( GetByte() == 3 )
2136 - SCCOL nQCol1;
2137 - SCROW nQRow1;
2138 - SCTAB nQTab1;
2139 - SCCOL nQCol2;
2140 - SCROW nQRow2;
2141 - SCTAB nQTab2;
2142 - PopDoubleRef(nQCol1, nQRow1, nQTab1, nQCol2, nQRow2, nQTab2);
2143 + // First, get the query criteria range.
2144 + ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDoubleRef() );
2145 + if (!pQueryRef.get())
2146 + return NULL;
2148 BOOL bByVal = TRUE;
2149 double nVal = 0.0;
2150 @@ -5902,116 +5901,85 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
2151 SetError( errIllegalParameter );
2154 - SCCOL nDBCol1;
2155 - SCROW nDBRow1;
2156 - SCTAB nDBTab1;
2157 - SCCOL nDBCol2;
2158 - SCROW nDBRow2;
2159 - SCTAB nDBTab2;
2160 - PopDoubleRef(nDBCol1, nDBRow1, nDBTab1, nDBCol2, nDBRow2, nDBTab2);
2161 + auto_ptr<ScDBRangeBase> pDBRef( PopDoubleRef() );
2163 - if ( nGlobalError == 0 && bRangeFake )
2164 + if (nGlobalError || !pDBRef.get())
2165 + return NULL;
2167 + if ( bRangeFake )
2169 // range parameter must match entire database range
2170 - if ( aMissingRange == ScRange( nDBCol1, nDBRow1, nDBTab1, nDBCol2,
2171 - nDBRow2, nDBTab2) )
2172 + if (pDBRef->isRangeEqual(aMissingRange))
2173 rMissingField = TRUE;
2174 else
2175 SetError( errIllegalParameter );
2178 - if (nGlobalError == 0)
2179 + if (nGlobalError)
2180 + return NULL;
2182 + SCCOL nField = pDBRef->getFirstFieldColumn();
2183 + if (rMissingField)
2184 + ; // special case
2185 + else if (bByVal)
2186 + nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
2187 + else
2189 + sal_uInt16 nErr = 0;
2190 + nField = pDBRef->findFieldColumn(aStr, &nErr);
2191 + SetError(nErr);
2194 + if (!ValidCol(nField))
2195 + return NULL;
2197 + auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
2199 + if (pParam.get())
2201 - SCCOL nField = nDBCol1;
2202 - BOOL bFound = TRUE;
2203 + // An allowed missing field parameter sets the result field
2204 + // to any of the query fields, just to be able to return
2205 + // some cell from the iterator.
2206 if ( rMissingField )
2207 - ; // special case
2208 - else if ( bByVal )
2210 - if ( nVal <= 0 || nVal > (nDBCol2 - nDBCol1 + 1) )
2211 - bFound = FALSE;
2212 - else
2213 - nField = Min(nDBCol2, (SCCOL)(nDBCol1 + (SCCOL)nVal - 1));
2215 - else
2216 + nField = static_cast<SCCOL>(pParam->GetEntry(0).nField);
2217 + pParam->mnField = nField;
2219 + SCSIZE nCount = pParam->GetEntryCount();
2220 + for ( SCSIZE i=0; i < nCount; i++ )
2222 - bFound = FALSE;
2223 - String aCellStr;
2224 - ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
2225 - while (!bFound && (aLook.Col() <= nDBCol2))
2227 - ScBaseCell* pCell = GetCell( aLook );
2228 - GetCellString( aCellStr, pCell );
2229 - bFound = ScGlobal::GetpTransliteration()->isEqual( aCellStr, aStr );
2230 - if (!bFound)
2231 - aLook.IncCol();
2233 - nField = aLook.Col();
2235 - if (bFound)
2237 - rParam.nCol1 = nDBCol1;
2238 - rParam.nRow1 = nDBRow1;
2239 - rParam.nCol2 = nDBCol2;
2240 - rParam.nRow2 = nDBRow2;
2241 - rParam.nTab = nDBTab1;
2242 - rParam.bHasHeader = TRUE;
2243 - rParam.bByRow = TRUE;
2244 - rParam.bInplace = TRUE;
2245 - rParam.bCaseSens = FALSE;
2246 - rParam.bRegExp = FALSE;
2247 - rParam.bDuplicate = TRUE;
2248 - if (pDok->CreateQueryParam(nQCol1, nQRow1, nQCol2, nQRow2, nQTab1, rParam))
2250 - // An allowed missing field parameter sets the result field
2251 - // to any of the query fields, just to be able to return
2252 - // some cell from the iterator.
2253 - if ( rMissingField )
2254 - nField = static_cast<SCCOL>(rParam.GetEntry(0).nField);
2256 - rParam.nCol1 = nField;
2257 - rParam.nCol2 = nField;
2258 - rTab = nDBTab1;
2259 - bRet = TRUE;
2260 - SCSIZE nCount = rParam.GetEntryCount();
2261 - for ( SCSIZE i=0; i < nCount; i++ )
2263 - ScQueryEntry& rEntry = rParam.GetEntry(i);
2264 - if ( rEntry.bDoQuery )
2266 - sal_uInt32 nIndex = 0;
2267 - rEntry.bQueryByString = !pFormatter->IsNumberFormat(
2268 - *rEntry.pStr, nIndex, rEntry.nVal );
2269 - if ( rEntry.bQueryByString && !rParam.bRegExp )
2270 - rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
2272 - else
2273 - break; // for
2275 + ScQueryEntry& rEntry = pParam->GetEntry(i);
2276 + if ( rEntry.bDoQuery )
2278 + sal_uInt32 nIndex = 0;
2279 + rEntry.bQueryByString = !pFormatter->IsNumberFormat(
2280 + *rEntry.pStr, nIndex, rEntry.nVal );
2281 + if ( rEntry.bQueryByString && !pParam->bRegExp )
2282 + pParam->bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
2284 + else
2285 + break; // for
2287 + return pParam.release();
2290 - return bRet;
2291 + return false;
2295 void ScInterpreter::DBIterator( ScIterFunc eFunc )
2297 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
2298 - SCTAB nTab1;
2299 double nErg = 0.0;
2300 double fMem = 0.0;
2301 BOOL bNull = TRUE;
2302 ULONG nCount = 0;
2303 - ScQueryParam aQueryParam;
2304 BOOL bMissingField = FALSE;
2305 - if ( GetDBParams( nTab1, aQueryParam, bMissingField) )
2306 + auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2307 + if (pQueryParam.get())
2309 - double nVal;
2310 - USHORT nErr;
2311 - ScQueryValueIterator aValIter(pDok, nTab1, aQueryParam);
2312 - if ( aValIter.GetFirst(nVal, nErr) && !nErr )
2313 + ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2314 + ScDBQueryDataIterator::Value aValue;
2315 + if ( aValIter.GetFirst(aValue) && !aValue.mnError )
2317 switch( eFunc )
2319 @@ -6027,24 +5995,24 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
2321 case ifAVERAGE:
2322 case ifSUM:
2323 - if ( bNull && nVal != 0.0 )
2324 + if ( bNull && aValue.mfValue != 0.0 )
2326 bNull = FALSE;
2327 - fMem = nVal;
2328 + fMem = aValue.mfValue;
2330 else
2331 - nErg += nVal;
2332 + nErg += aValue.mfValue;
2333 break;
2334 - case ifSUMSQ: nErg += nVal * nVal; break;
2335 - case ifPRODUCT: nErg *= nVal; break;
2336 - case ifMAX: if( nVal > nErg ) nErg = nVal; break;
2337 - case ifMIN: if( nVal < nErg ) nErg = nVal; break;
2338 + case ifSUMSQ: nErg += aValue.mfValue * aValue.mfValue; break;
2339 + case ifPRODUCT: nErg *= aValue.mfValue; break;
2340 + case ifMAX: if( aValue.mfValue > nErg ) nErg = aValue.mfValue; break;
2341 + case ifMIN: if( aValue.mfValue < nErg ) nErg = aValue.mfValue; break;
2342 default: ; // nothing
2345 - while ( aValIter.GetNext(nVal, nErr) && !nErr );
2346 + while ( aValIter.GetNext(aValue) && !aValue.mnError );
2348 - SetError(nErr);
2349 + SetError(aValue.mnError);
2351 else
2352 SetError( errIllegalParameter);
2353 @@ -6069,13 +6037,12 @@ void ScInterpreter::ScDBSum()
2354 void ScInterpreter::ScDBCount()
2356 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount" );
2357 - SCTAB nTab;
2358 - ScQueryParam aQueryParam;
2359 BOOL bMissingField = TRUE;
2360 - if ( GetDBParams( nTab, aQueryParam, bMissingField) )
2361 + auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2362 + if (pQueryParam.get())
2364 ULONG nCount = 0;
2365 - if ( bMissingField )
2366 + if ( bMissingField && pQueryParam->GetType() == ScDBQueryParamBase::INTERNAL )
2367 { // count all matching records
2368 // TODO: currently the QueryIterators only return cell pointers of
2369 // existing cells, so if a query matches an empty cell there's
2370 @@ -6085,7 +6052,9 @@ void ScInterpreter::ScDBCount()
2371 // have to live with it until we reimplement the iterators to also
2372 // return empty cells, which would mean to adapt all callers of
2373 // iterators.
2374 - ScQueryCellIterator aCellIter( pDok, nTab, aQueryParam);
2375 + ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pQueryParam.get());
2376 + SCTAB nTab = p->nTab;
2377 + ScQueryCellIterator aCellIter( pDok, nTab, *p);
2378 if ( aCellIter.GetFirst() )
2381 @@ -6096,17 +6065,17 @@ void ScInterpreter::ScDBCount()
2383 else
2384 { // count only matching records with a value in the "result" field
2385 - double nVal;
2386 - USHORT nErr = 0;
2387 - ScQueryValueIterator aValIter( pDok, nTab, aQueryParam);
2388 - if ( aValIter.GetFirst( nVal, nErr) && !nErr )
2389 + ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
2390 + ScDBQueryDataIterator::Value aValue;
2391 + if ( aValIter.GetFirst(aValue) && !aValue.mnError )
2395 nCount++;
2396 - } while ( aValIter.GetNext( nVal, nErr) && !nErr );
2397 + }
2398 + while ( aValIter.GetNext(aValue) && !aValue.mnError );
2400 - SetError( nErr );
2401 + SetError(aValue.mnError);
2403 PushDouble( nCount );
2405 @@ -6118,21 +6087,24 @@ void ScInterpreter::ScDBCount()
2406 void ScInterpreter::ScDBCount2()
2408 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount2" );
2409 - SCTAB nTab;
2410 - ScQueryParam aQueryParam;
2411 BOOL bMissingField = TRUE;
2412 - if (GetDBParams( nTab, aQueryParam, bMissingField))
2413 + auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2414 + if (pQueryParam.get())
2416 ULONG nCount = 0;
2417 - ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
2418 - if ( aCellIter.GetFirst() )
2419 + pQueryParam->mbSkipString = false;
2420 + ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
2421 + ScDBQueryDataIterator::Value aValue;
2422 + if ( aValIter.GetFirst(aValue) && !aValue.mnError )
2426 nCount++;
2427 - } while ( aCellIter.GetNext() );
2428 + }
2429 + while ( aValIter.GetNext(aValue) && !aValue.mnError );
2431 - PushDouble(nCount);
2432 + SetError(aValue.mnError);
2433 + PushDouble( nCount );
2435 else
2436 PushIllegalParameter();
2437 @@ -6176,25 +6148,23 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
2439 rValCount = 0.0;
2440 double fSum = 0.0;
2441 - SCTAB nTab;
2442 - ScQueryParam aQueryParam;
2443 BOOL bMissingField = FALSE;
2444 - if (GetDBParams( nTab, aQueryParam, bMissingField))
2445 + auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2446 + if (pQueryParam.get())
2448 - double fVal;
2449 - USHORT nErr;
2450 - ScQueryValueIterator aValIter(pDok, nTab, aQueryParam);
2451 - if (aValIter.GetFirst(fVal, nErr) && !nErr)
2452 + ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2453 + ScDBQueryDataIterator::Value aValue;
2454 + if (aValIter.GetFirst(aValue) && !aValue.mnError)
2458 rValCount++;
2459 - values.push_back(fVal);
2460 - fSum += fVal;
2461 + values.push_back(aValue.mfValue);
2462 + fSum += aValue.mfValue;
2464 - while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
2465 + while ((aValue.mnError == 0) && aValIter.GetNext(aValue));
2467 - SetError(nErr);
2468 + SetError(aValue.mnError);
2470 else
2471 SetError( errIllegalParameter);
2472 diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
2473 index 1f8fb9e..ffc9978 100644
2474 --- sc/source/core/tool/interpr4.cxx
2475 +++ sc/source/core/tool/interpr4.cxx
2476 @@ -68,15 +68,18 @@
2477 #include "jumpmatrix.hxx"
2478 #include "parclass.hxx"
2479 #include "externalrefmgr.hxx"
2480 +#include "doubleref.hxx"
2482 #include <math.h>
2483 #include <float.h>
2484 #include <map>
2485 #include <algorithm>
2486 #include <functional>
2487 +#include <memory>
2489 using namespace com::sun::star;
2490 using namespace formula;
2491 +using ::std::auto_ptr;
2493 #define ADDIN_MAXSTRLEN 256
2495 @@ -1222,6 +1225,44 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
2499 +ScDBRangeBase* ScInterpreter::PopDoubleRef()
2501 + if (!sp)
2502 + {
2503 + SetError(errUnknownStackVariable);
2504 + return NULL;
2507 + --sp;
2508 + FormulaToken* p = pStack[sp];
2509 + switch (p->GetType())
2511 + case svError:
2512 + nGlobalError = p->GetError();
2513 + break;
2514 + case svDoubleRef:
2516 + SCCOL nCol1, nCol2;
2517 + SCROW nRow1, nRow2;
2518 + SCTAB nTab1, nTab2;
2519 + DoubleRefToVars(static_cast<ScToken*>(p),
2520 + nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
2522 + return new ScDBInternalRange(pDok,
2523 + ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
2525 + break;
2526 + case svMatrix:
2528 + ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
2529 + return new ScDBExternalRange(pDok, pMat);
2531 + break;
2532 + default:
2533 + SetError( errIllegalParameter);
2535 + return NULL;
2538 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
2539 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
2540 @@ -2055,78 +2096,37 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
2541 void ScInterpreter::ScDBGet()
2543 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBGet" );
2544 - SCTAB nTab;
2545 - ScQueryParam aQueryParam;
2546 BOOL bMissingField = FALSE;
2547 - if (GetDBParams( nTab, aQueryParam, bMissingField))
2548 + auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2549 + if (!pQueryParam.get())
2551 - ScBaseCell* pCell;
2552 - ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
2553 - if ( (pCell = aCellIter.GetFirst()) != NULL )
2555 - if (aCellIter.GetNext())
2556 - PushIllegalArgument();
2557 - else
2559 - switch (pCell->GetCellType())
2561 - case CELLTYPE_VALUE:
2563 - double rValue = ((ScValueCell*)pCell)->GetValue();
2564 - if ( bCalcAsShown )
2566 - ULONG nFormat;
2567 - nFormat = aCellIter.GetNumberFormat();
2568 - rValue = pDok->RoundValueAsShown( rValue, nFormat );
2570 - PushDouble(rValue);
2572 - break;
2573 - case CELLTYPE_STRING:
2575 - String rString;
2576 - ((ScStringCell*)pCell)->GetString(rString);
2577 - PushString(rString);
2579 - break;
2580 - case CELLTYPE_EDIT:
2582 - String rString;
2583 - ((ScEditCell*)pCell)->GetString(rString);
2584 - PushString(rString);
2586 - break;
2587 - case CELLTYPE_FORMULA:
2589 - USHORT rErr = ((ScFormulaCell*)pCell)->GetErrCode();
2590 - if (rErr)
2591 - PushError(rErr);
2592 - else if (((ScFormulaCell*)pCell)->IsValue())
2594 - double rValue = ((ScFormulaCell*)pCell)->GetValue();
2595 - PushDouble(rValue);
2597 - else
2599 - String rString;
2600 - ((ScFormulaCell*)pCell)->GetString(rString);
2601 - PushString(rString);
2604 - break;
2605 - case CELLTYPE_NONE:
2606 - case CELLTYPE_NOTE:
2607 - default:
2608 - PushIllegalArgument();
2609 - break;
2613 - else
2614 - PushNoValue();
2615 + // Failed to create query param.
2616 + PushIllegalParameter();
2617 + return;
2620 + pQueryParam->mbSkipString = false;
2621 + ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2622 + ScDBQueryDataIterator::Value aValue;
2623 + if (!aValIter.GetFirst(aValue) || aValue.mnError)
2625 + // No match found.
2626 + PushNoValue();
2627 + return;
2630 + ScDBQueryDataIterator::Value aValNext;
2631 + if (aValIter.GetNext(aValNext) && !aValNext.mnError)
2633 + // There should be only one unique match.
2634 + PushIllegalArgument();
2635 + return;
2638 + if (aValue.mbIsNumber)
2639 + PushDouble(aValue.mfValue);
2640 else
2641 - PushIllegalParameter();
2642 + PushString(aValue.maString);
2646 diff --git sc/source/core/tool/makefile.mk sc/source/core/tool/makefile.mk
2647 index b0f8f03..041d2c8 100644
2648 --- sc/source/core/tool/makefile.mk
2649 +++ sc/source/core/tool/makefile.mk
2650 @@ -76,6 +76,7 @@ SLOFILES = \
2651 $(SLO)$/detdata.obj \
2652 $(SLO)$/detfunc.obj \
2653 $(SLO)$/docoptio.obj \
2654 + $(SLO)$/doubleref.obj \
2655 $(SLO)$/editutil.obj \
2656 $(SLO)$/filtopt.obj \
2657 $(SLO)$/formulaparserpool.obj \
2658 @@ -95,6 +96,7 @@ SLOFILES = \
2659 $(SLO)$/printopt.obj \
2660 $(SLO)$/prnsave.obj \
2661 $(SLO)$/progress.obj \
2662 + $(SLO)$/queryparam.obj \
2663 $(SLO)$/rangelst.obj \
2664 $(SLO)$/rangenam.obj \
2665 $(SLO)$/rangeseq.obj \
2666 @@ -123,6 +125,7 @@ EXCEPTIONSFILES= \
2667 $(SLO)$/chartlock.obj \
2668 $(SLO)$/chgtrack.obj \
2669 $(SLO)$/compiler.obj \
2670 + $(SLO)$/doubleref.obj \
2671 $(SLO)$/formulaparserpool.obj \
2672 $(SLO)$/interpr1.obj \
2673 $(SLO)$/interpr2.obj \
2674 @@ -131,6 +134,7 @@ EXCEPTIONSFILES= \
2675 $(SLO)$/interpr5.obj \
2676 $(SLO)$/lookupcache.obj \
2677 $(SLO)$/prnsave.obj \
2678 + $(SLO)$/queryparam.obj \
2679 $(SLO)$/reftokenhelper.obj \
2680 $(SLO)$/stringutil.obj \
2681 $(SLO)$/token.obj
2682 diff --git sc/source/core/tool/queryparam.cxx sc/source/core/tool/queryparam.cxx
2683 new file mode 100644
2684 index 0000000..d9d477d
2685 --- /dev/null
2686 +++ sc/source/core/tool/queryparam.cxx
2687 @@ -0,0 +1,361 @@
2688 +/*************************************************************************
2690 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2691 + *
2692 + * Copyright 2008 by Sun Microsystems, Inc.
2694 + * OpenOffice.org - a multi-platform office productivity suite
2696 + * $RCSfile: interpr4.cxx,v $
2697 + * $Revision: 1.57.92.5 $
2699 + * This file is part of OpenOffice.org.
2701 + * OpenOffice.org is free software: you can redistribute it and/or modify
2702 + * it under the terms of the GNU Lesser General Public License version 3
2703 + * only, as published by the Free Software Foundation.
2705 + * OpenOffice.org is distributed in the hope that it will be useful,
2706 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2707 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2708 + * GNU Lesser General Public License version 3 for more details
2709 + * (a copy is included in the LICENSE file that accompanied this code).
2711 + * You should have received a copy of the GNU Lesser General Public License
2712 + * version 3 along with OpenOffice.org. If not, see
2713 + * <http://www.openoffice.org/license.html>
2714 + * for a copy of the LGPLv3 License.
2716 + ************************************************************************/
2718 +// MARKER(update_precomp.py): autogen include statement, do not remove
2719 +#include "precompiled_sc.hxx"
2721 +// INCLUDE ---------------------------------------------------------------
2723 +#include "queryparam.hxx"
2725 +using ::std::vector;
2727 +// ============================================================================
2729 +ScQueryParamBase::ScQueryParamBase()
2731 + Resize( MAXQUERY );
2732 + for (USHORT i=0; i<MAXQUERY; i++)
2733 + maEntries[i].Clear();
2736 +ScQueryParamBase::ScQueryParamBase(const ScQueryParamBase& r) :
2737 + bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
2738 + bRegExp(r.bRegExp), bDuplicate(r.bDuplicate), bMixedComparison(r.bMixedComparison),
2739 + maEntries(r.maEntries)
2743 +ScQueryParamBase::~ScQueryParamBase()
2747 +SCSIZE ScQueryParamBase::GetEntryCount() const
2749 + return maEntries.size();
2752 +ScQueryEntry& ScQueryParamBase::GetEntry(SCSIZE n) const
2754 + return maEntries[n];
2757 +void ScQueryParamBase::Resize(SCSIZE nNew)
2759 + if ( nNew < MAXQUERY )
2760 + nNew = MAXQUERY; // nie weniger als MAXQUERY
2762 + vector<ScQueryEntry> aNewEntries(nNew);
2763 + SCSIZE nCopy = ::std::min(maEntries.size(), nNew);
2764 + for (SCSIZE i=0; i<nCopy; i++)
2765 + aNewEntries[i] = maEntries[i];
2767 + maEntries.swap(aNewEntries);
2770 +void ScQueryParamBase::DeleteQuery( SCSIZE nPos )
2772 + if (nPos >= maEntries.size())
2773 + return;
2775 + size_t n = maEntries.size();
2776 + vector<ScQueryEntry> aNewEntries;
2777 + aNewEntries.reserve(n-1);
2778 + for (size_t i = 0; i < n; ++i)
2779 + if (i != nPos)
2780 + aNewEntries.push_back(maEntries[i]);
2782 + maEntries.swap(aNewEntries);
2785 +void ScQueryParamBase::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
2787 + if (aCellStr.Len() > 0)
2789 + if ( nIndex >= maEntries.size() )
2790 + Resize( nIndex+1 );
2792 + ScQueryEntry& rEntry = GetEntry(nIndex);
2794 + rEntry.bDoQuery = TRUE;
2795 + // Operatoren herausfiltern
2796 + if (aCellStr.GetChar(0) == '<')
2798 + if (aCellStr.GetChar(1) == '>')
2800 + *rEntry.pStr = aCellStr.Copy(2);
2801 + rEntry.eOp = SC_NOT_EQUAL;
2803 + else if (aCellStr.GetChar(1) == '=')
2805 + *rEntry.pStr = aCellStr.Copy(2);
2806 + rEntry.eOp = SC_LESS_EQUAL;
2808 + else
2810 + *rEntry.pStr = aCellStr.Copy(1);
2811 + rEntry.eOp = SC_LESS;
2814 + else if (aCellStr.GetChar(0) == '>')
2816 + if (aCellStr.GetChar(1) == '=')
2818 + *rEntry.pStr = aCellStr.Copy(2);
2819 + rEntry.eOp = SC_GREATER_EQUAL;
2821 + else
2823 + *rEntry.pStr = aCellStr.Copy(1);
2824 + rEntry.eOp = SC_GREATER;
2827 + else
2829 + if (aCellStr.GetChar(0) == '=')
2830 + *rEntry.pStr = aCellStr.Copy(1);
2831 + else
2832 + *rEntry.pStr = aCellStr;
2833 + rEntry.eOp = SC_EQUAL;
2838 +// ============================================================================
2840 +ScQueryParamTable::ScQueryParamTable()
2844 +ScQueryParamTable::ScQueryParamTable(const ScQueryParamTable& r) :
2845 + nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab)
2849 +ScQueryParamTable::~ScQueryParamTable()
2853 +// ============================================================================
2855 +ScQueryParam::ScQueryParam() :
2856 + ScQueryParamBase(),
2857 + ScQueryParamTable()
2859 + Clear();
2862 +//------------------------------------------------------------------------
2864 +ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
2865 + ScQueryParamBase(r),
2866 + ScQueryParamTable(r),
2867 + bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
2871 +ScQueryParam::ScQueryParam( const ScDBQueryParamInternal& r ) :
2872 + ScQueryParamBase(r),
2873 + ScQueryParamTable(r),
2874 + bDestPers(true),
2875 + nDestTab(0),
2876 + nDestCol(0),
2877 + nDestRow(0)
2882 +//------------------------------------------------------------------------
2884 +ScQueryParam::~ScQueryParam()
2888 +//------------------------------------------------------------------------
2890 +void ScQueryParam::Clear()
2892 + nCol1=nCol2 = 0;
2893 + nRow1=nRow2 = 0;
2894 + nTab = SCTAB_MAX;
2895 + bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
2896 + bInplace = bByRow = bDuplicate = TRUE;
2898 + Resize( MAXQUERY );
2899 + for (USHORT i=0; i<MAXQUERY; i++)
2900 + maEntries[i].Clear();
2902 + ClearDestParams();
2905 +void ScQueryParam::ClearDestParams()
2907 + bDestPers = true;
2908 + nDestTab = 0;
2909 + nDestCol = 0;
2910 + nDestRow = 0;
2913 +//------------------------------------------------------------------------
2915 +ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
2917 + nCol1 = r.nCol1;
2918 + nRow1 = r.nRow1;
2919 + nCol2 = r.nCol2;
2920 + nRow2 = r.nRow2;
2921 + nTab = r.nTab;
2922 + nDestTab = r.nDestTab;
2923 + nDestCol = r.nDestCol;
2924 + nDestRow = r.nDestRow;
2925 + bHasHeader = r.bHasHeader;
2926 + bInplace = r.bInplace;
2927 + bCaseSens = r.bCaseSens;
2928 + bRegExp = r.bRegExp;
2929 + bMixedComparison = r.bMixedComparison;
2930 + bDuplicate = r.bDuplicate;
2931 + bByRow = r.bByRow;
2932 + bDestPers = r.bDestPers;
2934 + maEntries = r.maEntries;
2936 + return *this;
2939 +//------------------------------------------------------------------------
2941 +BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
2943 + BOOL bEqual = FALSE;
2945 + // Anzahl der Queries gleich?
2946 + SCSIZE nUsed = 0;
2947 + SCSIZE nOtherUsed = 0;
2948 + SCSIZE nEntryCount = GetEntryCount();
2949 + SCSIZE nOtherEntryCount = rOther.GetEntryCount();
2951 + while ( nUsed<nEntryCount && maEntries[nUsed].bDoQuery ) ++nUsed;
2952 + while ( nOtherUsed<nOtherEntryCount && rOther.maEntries[nOtherUsed].bDoQuery )
2953 + ++nOtherUsed;
2955 + if ( (nUsed == nOtherUsed)
2956 + && (nCol1 == rOther.nCol1)
2957 + && (nRow1 == rOther.nRow1)
2958 + && (nCol2 == rOther.nCol2)
2959 + && (nRow2 == rOther.nRow2)
2960 + && (nTab == rOther.nTab)
2961 + && (bHasHeader == rOther.bHasHeader)
2962 + && (bByRow == rOther.bByRow)
2963 + && (bInplace == rOther.bInplace)
2964 + && (bCaseSens == rOther.bCaseSens)
2965 + && (bRegExp == rOther.bRegExp)
2966 + && (bMixedComparison == rOther.bMixedComparison)
2967 + && (bDuplicate == rOther.bDuplicate)
2968 + && (bDestPers == rOther.bDestPers)
2969 + && (nDestTab == rOther.nDestTab)
2970 + && (nDestCol == rOther.nDestCol)
2971 + && (nDestRow == rOther.nDestRow) )
2973 + bEqual = TRUE;
2974 + for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
2975 + bEqual = maEntries[i] == rOther.maEntries[i];
2977 + return bEqual;
2980 +//------------------------------------------------------------------------
2982 +void ScQueryParam::MoveToDest()
2984 + if (!bInplace)
2986 + SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
2987 + SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
2988 + SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
2990 + nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
2991 + nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
2992 + nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
2993 + nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
2994 + nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
2995 + size_t n = maEntries.size();
2996 + for (size_t i=0; i<n; i++)
2997 + maEntries[i].nField += nDifX;
2999 + bInplace = TRUE;
3001 + else
3003 + DBG_ERROR("MoveToDest, bInplace == TRUE");
3007 +// ============================================================================
3009 +ScDBQueryParamBase::ScDBQueryParamBase(DataType eType) :
3010 + ScQueryParamBase(),
3011 + mnField(-1),
3012 + mbSkipString(true),
3013 + meType(eType)
3017 +ScDBQueryParamBase::~ScDBQueryParamBase()
3021 +ScDBQueryParamBase::DataType ScDBQueryParamBase::GetType() const
3023 + return meType;
3026 +// ============================================================================
3028 +ScDBQueryParamInternal::ScDBQueryParamInternal() :
3029 + ScDBQueryParamBase(ScDBQueryParamBase::INTERNAL),
3030 + ScQueryParamTable()
3034 +ScDBQueryParamInternal::~ScDBQueryParamInternal()
3038 +// ============================================================================
3040 +ScDBQueryParamMatrix::ScDBQueryParamMatrix() :
3041 + ScDBQueryParamBase(ScDBQueryParamBase::MATRIX)
3045 +ScDBQueryParamMatrix::~ScDBQueryParamMatrix()
3049 diff --git sc/source/filter/excel/colrowst.cxx sc/source/filter/excel/colrowst.cxx
3050 index 174ab20..199dad8 100644
3051 --- sc/source/filter/excel/colrowst.cxx
3052 +++ sc/source/filter/excel/colrowst.cxx
3053 @@ -43,6 +43,7 @@
3054 #include "xltable.hxx"
3055 #include "xistream.hxx"
3056 #include "xistyle.hxx"
3057 +#include "queryparam.hxx"
3059 // for filter manager
3060 #include "excimp8.hxx"
3061 diff --git sc/source/filter/excel/xichart.cxx sc/source/filter/excel/xichart.cxx
3062 index 2d920b0..69ead7f 100644
3063 --- sc/source/filter/excel/xichart.cxx
3064 +++ sc/source/filter/excel/xichart.cxx
3065 @@ -34,6 +34,7 @@
3066 #include "xichart.hxx"
3068 #include <algorithm>
3069 +#include <memory>
3071 #include <com/sun/star/frame/XModel.hpp>
3072 #include <com/sun/star/drawing/Direction3D.hpp>
3073 @@ -72,6 +73,8 @@
3074 #include "tokenarray.hxx"
3075 #include "token.hxx"
3076 #include "compiler.hxx"
3077 +#include "reftokenhelper.hxx"
3078 +#include "chartlis.hxx"
3079 #include "fprogressbar.hxx"
3080 #include "xltracer.hxx"
3081 #include "xistream.hxx"
3082 @@ -123,6 +126,8 @@ using ::com::sun::star::chart2::data::XDataSequence;
3083 using ::formula::FormulaToken;
3084 using ::formula::StackVar;
3086 +using ::std::vector;
3088 // Helpers ====================================================================
3090 namespace {
3091 @@ -791,6 +796,22 @@ Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequen
3092 return ScfApiHelper::VectorToSequence( aStringVec );
3095 +void XclImpChSourceLink::FillSourceLink(vector<ScSharedTokenRef>& rTokens) const
3097 + if (!mxTokenArray.is())
3098 + // no links to fill.
3099 + return;
3101 + mxTokenArray->Reset();
3102 + for (FormulaToken* p = mxTokenArray->First(); p; p = mxTokenArray->Next())
3104 + ScSharedTokenRef pToken(static_cast<ScToken*>(p->Clone()));
3105 + if (ScRefTokenHelper::isRef(pToken))
3106 + // This is a reference token. Store it.
3107 + ScRefTokenHelper::join(rTokens, pToken);
3111 // Text =======================================================================
3113 XclImpChFontBase::~XclImpChFontBase()
3114 @@ -1837,6 +1858,14 @@ Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
3115 return xDataSeries;
3118 +void XclImpChSeries::FillAllSourceLinks(vector<ScSharedTokenRef>& rTokens) const
3120 + mxValueLink->FillSourceLink(rTokens);
3121 + mxCategLink->FillSourceLink(rTokens);
3122 + mxTitleLink->FillSourceLink(rTokens);
3123 + mxBubbleLink->FillSourceLink(rTokens);
3126 void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
3128 XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
3129 @@ -3481,7 +3510,7 @@ XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
3130 return maDefTexts.get( nDefTextId );
3133 -void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress ) const
3134 +void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress, const OUString& rObjName ) const
3136 // initialize conversion (locks the model to suppress any internal updates)
3137 InitConversion( xChartDoc );
3138 @@ -3524,6 +3553,28 @@ void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressB
3140 // unlock the model
3141 FinishConversion( rProgress );
3143 + ScDocument* pDoc = &GetRoot().GetDoc();
3144 + ScChartListenerCollection* pChartCollection = pDoc->GetChartListenerCollection();
3145 + if (pChartCollection)
3147 + // Now, start listening to this chart.
3148 + ::std::auto_ptr< vector<ScSharedTokenRef> > pRefTokens(new vector<ScSharedTokenRef>);
3149 + for (XclImpChSeriesVec::const_iterator itr = maSeries.begin(), itrEnd = maSeries.end(); itr != itrEnd; ++itr)
3151 + const XclImpChSeriesRef& rSeries = *itr;
3152 + rSeries->FillAllSourceLinks(*pRefTokens);
3154 + if (!pRefTokens->empty())
3156 + ::std::auto_ptr<ScChartListener> pListener(
3157 + new ScChartListener(rObjName, pDoc, pRefTokens.release()));
3158 + pListener->SetDirty(true);
3159 + pListener->StartListeningTo();
3160 + pChartCollection->Insert(pListener.release());
3166 void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
3167 @@ -3749,11 +3800,11 @@ sal_Size XclImpChart::GetProgressSize() const
3168 return mxChartData.is() ? mxChartData->GetProgressSize() : 0;
3171 -void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress ) const
3172 +void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress, const OUString& rObjName ) const
3174 Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
3175 if( mxChartData.is() && xChartDoc.is() )
3176 - mxChartData->Convert( xChartDoc, rProgress );
3177 + mxChartData->Convert( xChartDoc, rProgress, rObjName );
3180 void XclImpChart::ReadChChart( XclImpStream& rStrm )
3181 diff --git sc/source/filter/excel/xiescher.cxx sc/source/filter/excel/xiescher.cxx
3182 index 599b33f..48406eb 100644
3183 --- sc/source/filter/excel/xiescher.cxx
3184 +++ sc/source/filter/excel/xiescher.cxx
3185 @@ -1579,7 +1579,7 @@ SdrObject* XclImpChartObj::DoCreateSdrObj( const Rectangle& rAnchorRect, ScfProg
3186 if( svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) )
3188 Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY );
3189 - mxChart->Convert( xModel, rProgress );
3190 + mxChart->Convert( xModel, rProgress, aEmbObjName );
3192 Reference< XEmbedPersist > xPers( xEmbObj, UNO_QUERY );
3193 if( xPers.is() )
3194 diff --git sc/source/filter/inc/excimp8.hxx sc/source/filter/inc/excimp8.hxx
3195 index fadad41..43e630d 100644
3196 --- sc/source/filter/inc/excimp8.hxx
3197 +++ sc/source/filter/inc/excimp8.hxx
3198 @@ -37,6 +37,7 @@
3199 #include "excscen.hxx"
3200 #include "excdefs.hxx"
3201 #include "ftools.hxx"
3202 +#include "queryparam.hxx"
3204 class SotStorage;
3206 diff --git sc/source/filter/inc/xichart.hxx sc/source/filter/inc/xichart.hxx
3207 index 1798242..e923ee1 100644
3208 --- sc/source/filter/inc/xichart.hxx
3209 +++ sc/source/filter/inc/xichart.hxx
3210 @@ -39,6 +39,7 @@
3211 #include <svtools/itemset.hxx>
3213 #include "rangelst.hxx"
3214 +#include "token.hxx"
3215 #include "xlchart.hxx"
3216 #include "xlstyle.hxx"
3217 #include "xistring.hxx"
3218 @@ -403,6 +404,8 @@ public:
3219 XFormattedStringSeq CreateStringSequence( const XclImpChRoot& rRoot,
3220 sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const;
3222 + void FillSourceLink(::std::vector<ScSharedTokenRef>& rTokens) const;
3224 private:
3225 XclChSourceLink maData; /// Contents of the CHSOURCELINK record.
3226 XclImpStringRef mxString; /// Text data (CHSTRING record).
3227 @@ -811,6 +814,8 @@ public:
3228 /** Creates a data series object with initialized source links. */
3229 XDataSeriesRef CreateDataSeries() const;
3231 + void FillAllSourceLinks(::std::vector<ScSharedTokenRef>& rTokens) const;
3233 private:
3234 /** Reads a CHSOURCELINK record. */
3235 void ReadChSourceLink( XclImpStream& rStrm );
3236 @@ -1353,7 +1358,7 @@ public:
3237 inline sal_Size GetProgressSize() const { return 2 * EXC_CHART_PROGRESS_SIZE; }
3239 /** Converts and writes all properties to the passed chart. */
3240 - void Convert( XChartDocRef xChartDoc, ScfProgressBar& rProgress ) const;
3241 + void Convert( XChartDocRef xChartDoc, ScfProgressBar& rProgress, const ::rtl::OUString& rObjName ) const;
3243 private:
3244 /** Reads a CHSERIES group (data series source and formatting). */
3245 @@ -1421,7 +1426,7 @@ public:
3246 inline bool IsPivotChart() const { return mbIsPivotChart; }
3248 /** Creates the chart object in the passed component. */
3249 - void Convert( XModelRef xModel, ScfProgressBar& rProgress ) const;
3250 + void Convert( XModelRef xModel, ScfProgressBar& rProgress, const ::rtl::OUString& rObjName ) const;
3252 private:
3253 /** Reads the CHCHART group (entire chart data). */
3254 diff --git sc/source/filter/xml/XMLExportDataPilot.hxx sc/source/filter/xml/XMLExportDataPilot.hxx
3255 index a3f6cf8..46a2bb0 100644
3256 --- sc/source/filter/xml/XMLExportDataPilot.hxx
3257 +++ sc/source/filter/xml/XMLExportDataPilot.hxx
3258 @@ -44,6 +44,7 @@ class ScDPDimensionSaveData;
3259 class ScDPSaveGroupDimension;
3260 class ScDPSaveNumGroupDimension;
3261 struct ScDPNumGroupInfo;
3262 +struct ScQueryParam;
3264 class ScXMLExportDataPilot
3266 diff --git sc/source/filter/xml/xmldpimp.hxx sc/source/filter/xml/xmldpimp.hxx
3267 index b4df6b1..705dbac 100644
3268 --- sc/source/filter/xml/xmldpimp.hxx
3269 +++ sc/source/filter/xml/xmldpimp.hxx
3270 @@ -40,6 +40,7 @@
3271 #include "global.hxx"
3272 #include "dpobject.hxx"
3273 #include "dpsave.hxx"
3274 +#include "queryparam.hxx"
3276 #include <hash_set>
3278 diff --git sc/source/ui/dbgui/foptmgr.cxx sc/source/ui/dbgui/foptmgr.cxx
3279 index ee5f039..a425836 100644
3280 --- sc/source/ui/dbgui/foptmgr.cxx
3281 +++ sc/source/ui/dbgui/foptmgr.cxx
3282 @@ -45,6 +45,7 @@
3283 #include "dbcolect.hxx"
3284 #include "viewdata.hxx"
3285 #include "document.hxx"
3286 +#include "queryparam.hxx"
3288 #define _FOPTMGR_CXX
3289 #include "foptmgr.hxx"
3290 diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
3291 index 813a6f9..8464799 100644
3292 --- sc/source/ui/docshell/externalrefmgr.cxx
3293 +++ sc/source/ui/docshell/externalrefmgr.cxx
3294 @@ -1057,8 +1057,11 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
3295 else
3297 // The source document has changed.
3298 + ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
3299 + ScDocShellModificator aMod(*pDocShell);
3300 pMgr->switchSrcFile(mnFileId, aFile, aFilter);
3301 maFilterName = aFilter;
3302 + aMod.SetDocumentModified();
3306 diff --git sc/source/ui/inc/pfiltdlg.hxx sc/source/ui/inc/pfiltdlg.hxx
3307 index a9ba0d1..b383173 100644
3308 --- sc/source/ui/inc/pfiltdlg.hxx
3309 +++ sc/source/ui/inc/pfiltdlg.hxx
3310 @@ -53,8 +53,8 @@
3311 #ifndef _COMBOBOX_HXX //autogen
3312 #include <vcl/combobox.hxx>
3313 #endif
3314 -#include "global.hxx" // -> ScQueryParam
3315 #include "address.hxx"
3316 +#include "queryparam.hxx"
3318 //------------------------------------------------------------------
3320 diff --git sc/source/ui/inc/uiitems.hxx sc/source/ui/inc/uiitems.hxx
3321 index 6581436..4cd4e58 100644
3322 --- sc/source/ui/inc/uiitems.hxx
3323 +++ sc/source/ui/inc/uiitems.hxx
3324 @@ -34,6 +34,7 @@
3325 #include "scdllapi.h"
3326 #include "conditio.hxx"
3327 #include "sortparam.hxx"
3328 +#include "queryparam.hxx"
3329 #include "paramisc.hxx"
3330 #include <svtools/poolitem.hxx>
3332 diff --git sc/source/ui/inc/undodat.hxx sc/source/ui/inc/undodat.hxx
3333 index fb42d81..ad46cb7 100644
3334 --- sc/source/ui/inc/undodat.hxx
3335 +++ sc/source/ui/inc/undodat.hxx
3336 @@ -36,6 +36,7 @@
3337 #include "rangelst.hxx" // ScRangeListRef
3338 #include "markdata.hxx"
3339 #include "sortparam.hxx"
3340 +#include "queryparam.hxx"
3341 #include "pivot.hxx"
3343 class ScDocShell;
3344 diff --git sc/source/ui/undo/undobase.cxx sc/source/ui/undo/undobase.cxx
3345 index f20abdb..8b59f80 100644
3346 --- sc/source/ui/undo/undobase.cxx
3347 +++ sc/source/ui/undo/undobase.cxx
3348 @@ -45,6 +45,7 @@
3349 #include "undodraw.hxx"
3350 #include "dbcolect.hxx"
3351 #include "attrib.hxx"
3352 +#include "queryparam.hxx"
3353 #include "globstr.hrc"
3355 // STATIC DATA -----------------------------------------------------------
3356 diff --git sc/source/ui/unoobj/chart2uno.cxx sc/source/ui/unoobj/chart2uno.cxx
3357 index 995a7dc..52e9507 100644
3358 --- sc/source/ui/unoobj/chart2uno.cxx
3359 +++ sc/source/ui/unoobj/chart2uno.cxx
3360 @@ -2927,6 +2927,9 @@ void ScChart2DataSequence::BuildDataCache()
3361 ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
3362 for (;itr != itrEnd; ++itr, ++pArr)
3363 *pArr = *itr;
3365 + // Clear the data series cache when the array is re-built.
3366 + m_aMixedDataCache.realloc(0);
3369 void ScChart2DataSequence::RebuildDataCache()
3370 @@ -3119,7 +3122,6 @@ void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint
3371 if ( m_bGotDataChangedHint && m_pDocument )
3373 m_aDataArray.clear();
3374 - m_aDataArray.clear();
3375 lang::EventObject aEvent;
3376 aEvent.Source.set((cppu::OWeakObject*)this);
3378 @@ -3294,19 +3296,24 @@ uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
3379 throw uno::RuntimeException();
3381 BuildDataCache();
3382 - sal_Int32 nCount = m_aDataArray.size();
3383 - uno::Sequence<uno::Any> aSeq(nCount);
3384 - uno::Any* pArr = aSeq.getArray();
3385 - ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3386 - for (; itr != itrEnd; ++itr, ++pArr)
3388 + if (!m_aMixedDataCache.getLength())
3390 - if (itr->mbIsValue)
3391 - *pArr <<= itr->mfValue;
3392 - else
3393 - *pArr <<= itr->maString;
3395 + // Build a cache for the 1st time...
3397 - return aSeq;
3398 + sal_Int32 nCount = m_aDataArray.size();
3399 + m_aMixedDataCache.realloc(nCount);
3400 + uno::Any* pArr = m_aMixedDataCache.getArray();
3401 + ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
3402 + for (; itr != itrEnd; ++itr, ++pArr)
3404 + if (itr->mbIsValue)
3405 + *pArr <<= itr->mfValue;
3406 + else
3407 + *pArr <<= itr->maString;
3410 + return m_aMixedDataCache;
3413 // XNumericalDataSequence --------------------------------------------------
3414 diff --git sc/source/ui/view/gridwin4.cxx sc/source/ui/view/gridwin4.cxx
3415 index 1cd54a2..5428aa1 100644
3416 --- sc/source/ui/view/gridwin4.cxx
3417 +++ sc/source/ui/view/gridwin4.cxx
3418 @@ -74,6 +74,7 @@
3419 #include "inputopt.hxx"
3420 #include "fillinfo.hxx"
3421 #include "dpcontrol.hxx"
3422 +#include "queryparam.hxx"
3423 #include "sc.hrc"
3424 #include <vcl/virdev.hxx>