summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chart2/source/view/charttypes/PieChart.cxx29
-rw-r--r--chart2/source/view/charttypes/PieChart.hxx4
-rw-r--r--sc/inc/chart2uno.hxx8
-rw-r--r--sc/inc/chartlis.hxx4
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/inc/datauno.hxx6
-rw-r--r--sc/inc/dociter.hxx106
-rw-r--r--sc/inc/document.hxx3
-rw-r--r--sc/inc/dpcachetable.hxx1
-rw-r--r--sc/inc/dpshttab.hxx1
-rw-r--r--sc/inc/global.hxx41
-rw-r--r--sc/inc/queryparam.hxx142
-rw-r--r--sc/inc/reftokenhelper.hxx8
-rw-r--r--sc/inc/table.hxx3
-rw-r--r--sc/source/core/data/autonamecache.cxx1
-rwxr-xr-x[-rw-r--r--]sc/source/core/data/dociter.cxx467
-rw-r--r--sc/source/core/data/document.cxx7
-rw-r--r--sc/source/core/data/dpcachetable.cxx31
-rw-r--r--sc/source/core/data/global2.cxx232
-rw-r--r--sc/source/core/data/sortparam.cxx1
-rw-r--r--sc/source/core/data/table3.cxx6
-rw-r--r--sc/source/core/inc/doubleref.hxx194
-rw-r--r--sc/source/core/inc/interpre.hxx6
-rw-r--r--sc/source/core/tool/dbcolect.cxx1
-rw-r--r--sc/source/core/tool/doubleref.cxx568
-rw-r--r--sc/source/core/tool/interpr1.cxx234
-rwxr-xr-xsc/source/core/tool/interpr4.cxx134
-rw-r--r--sc/source/core/tool/makefile.mk4
-rw-r--r--sc/source/core/tool/queryparam.cxx365
-rw-r--r--sc/source/filter/excel/colrowst.cxx1
-rw-r--r--sc/source/filter/excel/excdoc.cxx2
-rw-r--r--sc/source/filter/excel/xecontent.cxx6
-rw-r--r--sc/source/filter/excel/xestream.cxx11
-rw-r--r--sc/source/filter/excel/xichart.cxx61
-rw-r--r--sc/source/filter/excel/xiescher.cxx6
-rw-r--r--sc/source/filter/inc/excimp8.hxx1
-rw-r--r--sc/source/filter/inc/xcl97rec.hxx13
-rw-r--r--sc/source/filter/inc/xestream.hxx3
-rw-r--r--sc/source/filter/inc/xichart.hxx9
-rw-r--r--sc/source/filter/xcl97/xcl97rec.cxx13
-rw-r--r--sc/source/filter/xml/XMLExportDataPilot.hxx1
-rw-r--r--sc/source/filter/xml/xmldpimp.hxx1
-rw-r--r--sc/source/ui/dbgui/foptmgr.cxx1
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx3
-rw-r--r--sc/source/ui/inc/pfiltdlg.hxx2
-rw-r--r--sc/source/ui/inc/uiitems.hxx1
-rw-r--r--sc/source/ui/inc/undodat.hxx1
-rw-r--r--sc/source/ui/undo/undobase.cxx1
-rw-r--r--sc/source/ui/unoobj/chart2uno.cxx31
-rw-r--r--sc/source/ui/view/gridwin4.cxx1
50 files changed, 2177 insertions, 601 deletions
diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx
index 80f856e94..3596d1758 100644
--- a/chart2/source/view/charttypes/PieChart.cxx
+++ b/chart2/source/view/charttypes/PieChart.cxx
@@ -129,6 +129,8 @@ PieChart::PieChart( const uno::Reference<XChartType>& xChartTypeModel
, m_pPosHelper( new PiePositionHelper( NormalAxis_Z, (m_nDimension==3)?0.0:90.0 ) )
, m_bUseRings(false)
{
+ ::rtl::math::setNan(&m_fMaxOffset);
+
PlotterBase::m_pPosHelper = m_pPosHelper;
VSeriesPlotter::m_pMainPosHelper = m_pPosHelper;
m_pPosHelper->m_fRadiusOffset = 0.0;
@@ -248,27 +250,31 @@ double PieChart::getMinimumX()
{
return 0.5;
}
-double PieChart::getMaxOffset() const
+double PieChart::getMaxOffset()
{
- double fRet = 0.0;
+ if (!::rtl::math::isNan(m_fMaxOffset))
+ // Value already cached. Use it.
+ return m_fMaxOffset;
+
+ m_fMaxOffset = 0.0;
if( m_aZSlots.size()<=0 )
- return fRet;
+ return m_fMaxOffset;
if( m_aZSlots[0].size()<=0 )
- return fRet;
+ return m_fMaxOffset;
const ::std::vector< VDataSeries* >& rSeriesList( m_aZSlots[0][0].m_aSeriesVector );
if( rSeriesList.size()<=0 )
- return fRet;
+ return m_fMaxOffset;
VDataSeries* pSeries = rSeriesList[0];
uno::Reference< beans::XPropertySet > xSeriesProp( pSeries->getPropertiesOfSeries() );
if( !xSeriesProp.is() )
- return fRet;
+ return m_fMaxOffset;
double fExplodePercentage=0.0;
xSeriesProp->getPropertyValue( C2U( "Offset" )) >>= fExplodePercentage;
- if(fExplodePercentage>fRet)
- fRet=fExplodePercentage;
+ if(fExplodePercentage>m_fMaxOffset)
+ m_fMaxOffset=fExplodePercentage;
uno::Sequence< sal_Int32 > aAttributedDataPointIndexList;
if( xSeriesProp->getPropertyValue( C2U( "AttributedDataPoints" ) ) >>= aAttributedDataPointIndexList )
@@ -280,12 +286,12 @@ double PieChart::getMaxOffset() const
{
fExplodePercentage=0.0;
xPointProp->getPropertyValue( C2U( "Offset" )) >>= fExplodePercentage;
- if(fExplodePercentage>fRet)
- fRet=fExplodePercentage;
+ if(fExplodePercentage>m_fMaxOffset)
+ m_fMaxOffset=fExplodePercentage;
}
}
}
- return fRet;
+ return m_fMaxOffset;
}
double PieChart::getMaximumX()
{
@@ -357,6 +363,7 @@ void PieChart::createShapes()
nExplodeableSlot = m_aZSlots[0].size()-1;
m_aLabelInfoList.clear();
+ ::rtl::math::setNan(&m_fMaxOffset);
//=============================================================================
for( double fSlotX=0; aXSlotIter != aXSlotEnd && (m_bUseRings||fSlotX<0.5 ); aXSlotIter++, fSlotX+=1.0 )
diff --git a/chart2/source/view/charttypes/PieChart.hxx b/chart2/source/view/charttypes/PieChart.hxx
index e32a9e8b7..644751511 100644
--- a/chart2/source/view/charttypes/PieChart.hxx
+++ b/chart2/source/view/charttypes/PieChart.hxx
@@ -105,7 +105,7 @@ private: //methods
, double fLogicZ, double fDepth, double fExplodePercentage
, tPropertyNameValueMap* pOverWritePropertiesMap );
- double getMaxOffset() const;
+ double getMaxOffset();
bool detectLabelOverlapsAndMove(const ::com::sun::star::awt::Size& rPageSize);//returns true when there might be more to do
void resetLabelPositionsToPreviousState();
struct PieLabelInfo;
@@ -137,6 +137,8 @@ private: //member
};
::std::vector< PieLabelInfo > m_aLabelInfoList;
+
+ double m_fMaxOffset; /// cached max offset value (init'ed to NaN)
};
//.............................................................................
} //namespace chart
diff --git a/sc/inc/chart2uno.hxx b/sc/inc/chart2uno.hxx
index bb865288b..dc3228ec5 100644
--- a/sc/inc/chart2uno.hxx
+++ b/sc/inc/chart2uno.hxx
@@ -533,6 +533,14 @@ private:
};
::std::list<Item> m_aDataArray;
+
+ /**
+ * Cached data for getData. We may also need to cache data for the
+ * numerical and textural data series if they turn out to be bottlenecks
+ * under certain scenarios.
+ */
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > m_aMixedDataCache;
+
::com::sun::star::uno::Sequence<sal_Int32> m_aHiddenValues;
// properties
diff --git a/sc/inc/chartlis.hxx b/sc/inc/chartlis.hxx
index ae3f70cf3..016158386 100644
--- a/sc/inc/chartlis.hxx
+++ b/sc/inc/chartlis.hxx
@@ -49,7 +49,7 @@ class ScChartUnoData;
#include <com/sun/star/chart/XChartData.hpp>
#include <com/sun/star/chart/XChartDataChangeEventListener.hpp>
-class ScChartListener : public StrData, public SvtListener
+class SC_DLLPUBLIC ScChartListener : public StrData, public SvtListener
{
public:
class ExternalRefListener : public ScExternalRefManager::LinkListener
@@ -186,7 +186,7 @@ public:
const com::sun::star::uno::Reference< com::sun::star::chart::XChartData >& rSource );
void StartTimer();
void UpdateDirtyCharts();
- void SetDirty();
+ void SC_DLLPUBLIC SetDirty();
void SetDiffDirty( const ScChartListenerCollection&,
BOOL bSetChartRangeLists = FALSE );
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 14ad931f9..f48a86b2b 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -114,7 +114,7 @@ private:
friend class ScDocument; // fuer FillInfo
friend class ScDocumentIterator;
friend class ScValueIterator;
-friend class ScQueryValueIterator;
+friend class ScDBQueryDataIterator;
friend class ScColumnIterator;
friend class ScQueryCellIterator;
friend class ScMarkedDataIter;
diff --git a/sc/inc/datauno.hxx b/sc/inc/datauno.hxx
index 10e2e2257..8e0d18d88 100644
--- a/sc/inc/datauno.hxx
+++ b/sc/inc/datauno.hxx
@@ -32,8 +32,8 @@
#define SC_DATAUNO_HXX
#include "global.hxx"
-#include <svl/itemprop.hxx>
-#include <svl/lstner.hxx>
+#include "queryparam.hxx"
+
#include <com/sun/star/sheet/TableFilterField.hpp>
#include <com/sun/star/sheet/GeneralFunction.hpp>
#include <com/sun/star/sheet/XCellRangeReferrer.hpp>
@@ -56,6 +56,8 @@
#include <cppuhelper/implbase4.hxx>
#include <cppuhelper/implbase5.hxx>
#include <cppuhelper/implbase6.hxx>
+#include "svl/itemprop.hxx"
+#include "svl/lstner.hxx"
class ScDBData;
class ScDocShell;
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index d5d42354d..495c57d10 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -35,6 +35,9 @@
#include <tools/solar.h>
#include "global.hxx"
#include "scdllapi.h"
+#include "queryparam.hxx"
+
+#include <memory>
class ScDocument;
class ScBaseCell;
@@ -127,34 +130,97 @@ public:
}
};
-class ScQueryValueIterator // alle Zahlenwerte in einem Bereich durchgehen
+// ============================================================================
+
+class ScDBQueryDataIterator
{
+public:
+ struct Value
+ {
+ ::rtl::OUString maString;
+ double mfValue;
+ sal_uInt16 mnError;
+ bool mbIsNumber;
+
+ Value();
+ };
+
private:
- ScQueryParam aParam;
- ScDocument* pDoc;
- const ScAttrArray* pAttrArray;
- ULONG nNumFormat; // fuer CalcAsShown
- ULONG nNumFmtIndex;
- SCCOL nCol;
- SCROW nRow;
- SCSIZE nColRow;
- SCROW nAttrEndRow;
- SCTAB nTab;
- short nNumFmtType;
- BOOL bCalcAsShown;
+ static SCROW GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow);
+ static ScBaseCell* GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow);
+ static ScAttrArray* GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol);
+ static bool IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell);
+ static SCSIZE SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol);
+
+ class DataAccess
+ {
+ public:
+ DataAccess(const ScDBQueryDataIterator* pParent);
+ virtual ~DataAccess() = 0;
+ virtual bool getCurrent(Value& rValue) = 0;
+ virtual bool getFirst(Value& rValue) = 0;
+ virtual bool getNext(Value& rValue) = 0;
+ protected:
+ const ScDBQueryDataIterator* mpParent;
+ };
+
+ class DataAccessInternal : public DataAccess
+ {
+ public:
+ DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc);
+ virtual ~DataAccessInternal();
+ virtual bool getCurrent(Value& rValue);
+ virtual bool getFirst(Value& rValue);
+ virtual bool getNext(Value& rValue);
+
+ private:
+ ScDBQueryParamInternal* mpParam;
+ ScDocument* mpDoc;
+ const ScAttrArray* pAttrArray;
+ ULONG nNumFormat; // for CalcAsShown
+ ULONG nNumFmtIndex;
+ SCCOL nCol;
+ SCROW nRow;
+ SCSIZE nColRow;
+ SCROW nAttrEndRow;
+ SCTAB nTab;
+ short nNumFmtType;
+ bool bCalcAsShown;
+ };
+
+ class DataAccessMatrix : public DataAccess
+ {
+ public:
+ DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam);
+ virtual ~DataAccessMatrix();
+ virtual bool getCurrent(Value& rValue);
+ virtual bool getFirst(Value& rValue);
+ virtual bool getNext(Value& rValue);
+
+ private:
+ bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const;
+
+ ScDBQueryParamMatrix* mpParam;
+ SCROW mnCurRow;
+ SCROW mnRows;
+ SCCOL mnCols;
+ };
+
+ ::std::auto_ptr<ScDBQueryParamBase> mpParam;
+ ::std::auto_ptr<DataAccess> mpData;
+
+ bool GetThis(Value& rValue);
- BOOL GetThis(double& rValue, USHORT& rErr);
public:
- ScQueryValueIterator(ScDocument* pDocument, SCTAB nTable,
- const ScQueryParam& aParam);
+ ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam);
/// Does NOT reset rValue if no value found!
- BOOL GetFirst(double& rValue, USHORT& rErr);
+ bool GetFirst(Value& rValue);
/// Does NOT reset rValue if no value found!
- BOOL GetNext(double& rValue, USHORT& rErr);
- void GetCurNumFmtInfo( short& nType, ULONG& nIndex )
- { nType = nNumFmtType; nIndex = nNumFmtIndex; }
+ bool GetNext(Value& rValue);
};
+// ============================================================================
+
class ScCellIterator // alle Zellen in einem Bereich durchgehen
{ // bei SubTotal aber keine ausgeblendeten und
private: // SubTotalZeilen
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 23a383306..fe8a9b6b9 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -229,7 +229,7 @@ class ScDocument
{
friend class ScDocumentIterator;
friend class ScValueIterator;
-friend class ScQueryValueIterator;
+friend class ScDBQueryDataIterator;
friend class ScCellIterator;
friend class ScQueryCellIterator;
friend class ScHorizontalCellIterator;
@@ -423,6 +423,7 @@ private:
public:
SC_DLLPUBLIC ULONG GetCellCount() const; // alle Zellen
+ SCSIZE GetCellCount(SCTAB nTab, SCCOL nCol) const;
ULONG GetWeightedCount() const; // Formeln und Edit staerker gewichtet
ULONG GetCodeCount() const; // RPN-Code in Formeln
DECL_LINK( GetUserDefinedColor, USHORT * );
diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx
index 7a605354e..0a22fb06e 100644
--- a/sc/inc/dpcachetable.hxx
+++ b/sc/inc/dpcachetable.hxx
@@ -60,6 +60,7 @@ class ScDPDimension;
class ScDPCollection;
struct ScDPCacheCell;
struct ScDPItemData;
+struct ScQueryParam;
class Date;
// ----------------------------------------------------------------------------
diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx
index ede4933cf..8483ca2a5 100644
--- a/sc/inc/dpshttab.hxx
+++ b/sc/inc/dpshttab.hxx
@@ -35,6 +35,7 @@
#include "global.hxx"
#include "address.hxx"
#include "scdllapi.h"
+#include "queryparam.hxx"
#include <vector>
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 57a6ff146..b401cb92c 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -817,47 +817,6 @@ struct ScQueryEntry
BOOL operator==( const ScQueryEntry& r ) const;
};
-struct SC_DLLPUBLIC ScQueryParam
-{
- SCCOL nCol1;
- SCROW nRow1;
- SCCOL nCol2;
- SCROW nRow2;
- SCTAB nTab;
- BOOL bHasHeader;
- BOOL bByRow;
- BOOL bInplace;
- BOOL bCaseSens;
- BOOL bRegExp;
- BOOL bMixedComparison; // whether numbers are smaller than strings
- BOOL bDuplicate;
- BOOL bDestPers; // nicht gespeichert
- SCTAB nDestTab;
- SCCOL nDestCol;
- SCROW nDestRow;
-
-private:
- SCSIZE nEntryCount;
- ScQueryEntry* pEntries;
-
-public:
- ScQueryParam();
- ScQueryParam( const ScQueryParam& r );
- ~ScQueryParam();
-
- SCSIZE GetEntryCount() const { return nEntryCount; }
- ScQueryEntry& GetEntry(SCSIZE n) const { return pEntries[n]; }
- void Resize(SCSIZE nNew);
-
- ScQueryParam& operator= ( const ScQueryParam& r );
- BOOL operator== ( const ScQueryParam& rOther ) const;
- void Clear ();
- void DeleteQuery( SCSIZE nPos );
-
- void MoveToDest();
- void FillInExcelSyntax(String& aCellStr, SCSIZE nIndex);
-};
-
// -----------------------------------------------------------------------
struct SC_DLLPUBLIC ScSubTotalParam
diff --git a/sc/inc/queryparam.hxx b/sc/inc/queryparam.hxx
new file mode 100644
index 000000000..bc5023728
--- /dev/null
+++ b/sc/inc/queryparam.hxx
@@ -0,0 +1,142 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interpre.hxx,v $
+ * $Revision: 1.35.44.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_QUERYPARAM_HXX
+#define SC_QUERYPARAM_HXX
+
+#include "global.hxx"
+#include "scmatrix.hxx"
+
+#include <vector>
+
+struct ScDBQueryParamInternal;
+
+struct ScQueryParamBase
+{
+ bool bHasHeader;
+ bool bByRow;
+ bool bInplace;
+ bool bCaseSens;
+ bool bRegExp;
+ bool bDuplicate;
+ bool bMixedComparison; // whether numbers are smaller than strings
+
+ virtual ~ScQueryParamBase();
+
+ SC_DLLPUBLIC SCSIZE GetEntryCount() const;
+ SC_DLLPUBLIC ScQueryEntry& GetEntry(SCSIZE n) const;
+ void Resize(SCSIZE nNew);
+ SC_DLLPUBLIC void DeleteQuery( SCSIZE nPos );
+ void FillInExcelSyntax(String& aCellStr, SCSIZE nIndex);
+
+protected:
+ ScQueryParamBase();
+ ScQueryParamBase(const ScQueryParamBase& r);
+
+ mutable ::std::vector<ScQueryEntry> maEntries;
+};
+
+// ============================================================================
+
+struct ScQueryParamTable
+{
+ SCCOL nCol1;
+ SCROW nRow1;
+ SCCOL nCol2;
+ SCROW nRow2;
+ SCTAB nTab;
+
+ ScQueryParamTable();
+ ScQueryParamTable(const ScQueryParamTable& r);
+ virtual ~ScQueryParamTable();
+};
+
+// ============================================================================
+
+struct SC_DLLPUBLIC ScQueryParam : public ScQueryParamBase, public ScQueryParamTable
+{
+ BOOL bDestPers; // nicht gespeichert
+ SCTAB nDestTab;
+ SCCOL nDestCol;
+ SCROW nDestRow;
+
+ ScQueryParam();
+ ScQueryParam( const ScQueryParam& r );
+ ScQueryParam( const ScDBQueryParamInternal& r );
+ virtual ~ScQueryParam();
+
+ ScQueryParam& operator= ( const ScQueryParam& r );
+ BOOL operator== ( const ScQueryParam& rOther ) const;
+ void Clear();
+ void ClearDestParams();
+ void MoveToDest();
+};
+
+// ============================================================================
+
+struct ScDBQueryParamBase : public ScQueryParamBase
+{
+ enum DataType { INTERNAL, MATRIX };
+
+ SCCOL mnField; /// the field in which the values are processed during iteration.
+ bool mbSkipString;
+
+ DataType GetType() const;
+
+ virtual ~ScDBQueryParamBase();
+
+protected:
+ ScDBQueryParamBase(DataType eType);
+
+private:
+ ScDBQueryParamBase();
+
+ DataType meType;
+};
+
+// ============================================================================
+
+struct ScDBQueryParamInternal : public ScDBQueryParamBase, public ScQueryParamTable
+{
+ ScDBQueryParamInternal();
+ virtual ~ScDBQueryParamInternal();
+};
+
+// ============================================================================
+
+struct ScDBQueryParamMatrix : public ScDBQueryParamBase
+{
+ ScMatrixRef mpMatrix;
+
+ ScDBQueryParamMatrix();
+ virtual ~ScDBQueryParamMatrix();
+};
+
+#endif
diff --git a/sc/inc/reftokenhelper.hxx b/sc/inc/reftokenhelper.hxx
index d7b335f9b..99a59982a 100644
--- a/sc/inc/reftokenhelper.hxx
+++ b/sc/inc/reftokenhelper.hxx
@@ -70,12 +70,12 @@ public:
static void getTokensFromRangeList(::std::vector<ScSharedTokenRef>& pTokens, const ScRangeList& rRanges);
- static bool isRef(const ScSharedTokenRef& pToken);
- static bool isExternalRef(const ScSharedTokenRef& pToken);
+ static bool SC_DLLPUBLIC isRef(const ScSharedTokenRef& pToken);
+ static bool SC_DLLPUBLIC isExternalRef(const ScSharedTokenRef& pToken);
- static bool intersects(const ::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
+ static bool SC_DLLPUBLIC intersects(const ::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
- static void join(::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
+ static void SC_DLLPUBLIC join(::std::vector<ScSharedTokenRef>& rTokens, const ScSharedTokenRef& pToken);
static bool getDoubleRefDataFromToken(ScComplexRefData& rData, const ScSharedTokenRef& pToken);
};
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 3b5532d25..034d5fdca 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -162,7 +162,7 @@ private:
friend class ScDocument; // fuer FillInfo
friend class ScDocumentIterator;
friend class ScValueIterator;
-friend class ScQueryValueIterator;
+friend class ScDBQueryDataIterator;
friend class ScCellIterator;
friend class ScQueryCellIterator;
friend class ScHorizontalCellIterator;
@@ -178,6 +178,7 @@ public:
ScOutlineTable* GetOutlineTable() { return pOutlineTable; }
+ SCSIZE GetCellCount(SCCOL nCol) const;
ULONG GetCellCount() const;
ULONG GetWeightedCount() const;
ULONG GetCodeCount() const; // RPN-Code in Formeln
diff --git a/sc/source/core/data/autonamecache.cxx b/sc/source/core/data/autonamecache.cxx
index ea41e3e4f..329e7f469 100644
--- a/sc/source/core/data/autonamecache.cxx
+++ b/sc/source/core/data/autonamecache.cxx
@@ -40,6 +40,7 @@
#include "autonamecache.hxx"
#include "dociter.hxx"
#include "cell.hxx"
+#include "queryparam.hxx"
// -----------------------------------------------------------------------
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 6f79316e0..fab5ad92d 100644..100755
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -47,9 +47,23 @@
#include "docoptio.hxx"
#include "cellform.hxx"
+#include <vector>
+
+using ::rtl::math::approxEqual;
+using ::std::vector;
+using ::rtl::OUString;
// STATIC DATA -----------------------------------------------------------
+namespace {
+
+void lcl_toUpper(OUString& rStr)
+{
+ rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, static_cast<USHORT>(rStr.getLength()));
+}
+
+}
+
ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
SCTAB nStartTable, SCTAB nEndTable ) :
pDoc( pDocument ),
@@ -482,83 +496,121 @@ BOOL ScValueIterator::GetNext(double& rValue, USHORT& rErr)
}
*/
-//------------------------------------------------------------------------
-//------------------------------------------------------------------------
+// ============================================================================
-ScQueryValueIterator::ScQueryValueIterator(ScDocument* pDocument, SCTAB nTable, const ScQueryParam& rParam) :
- aParam (rParam),
- pDoc( pDocument ),
- nNumFmtIndex(0),
- nTab( nTable),
- nNumFmtType( NUMBERFORMAT_UNDEFINED ),
- bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() )
+ScDBQueryDataIterator::DataAccess::DataAccess(const ScDBQueryDataIterator* pParent) :
+ mpParent(pParent)
{
- nCol = aParam.nCol1;
- nRow = aParam.nRow1;
+}
+
+ScDBQueryDataIterator::DataAccess::~DataAccess()
+{
+}
+
+SCROW ScDBQueryDataIterator::GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow)
+{
+ ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
+ return pCol->pItems[nColRow].nRow;
+}
+
+ScBaseCell* ScDBQueryDataIterator::GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow)
+{
+ ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
+ return pCol->pItems[nColRow].pCell;
+}
+
+ScAttrArray* ScDBQueryDataIterator::GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol)
+{
+ ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
+ return pCol->pAttrArray;
+}
+
+bool ScDBQueryDataIterator::IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell)
+{
+ return rDoc.pTab[nTab]->ValidQuery(nRow, rParam, NULL, pCell);
+}
+
+SCSIZE ScDBQueryDataIterator::SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol)
+{
+ ScColumn* pCol = &rDoc.pTab[nTab]->aCol[nCol];
+ SCSIZE nColRow;
+ pCol->Search(nRow, nColRow);
+ return nColRow;
+}
+
+// ----------------------------------------------------------------------------
+
+ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc) :
+ DataAccess(pParent),
+ mpParam(pParam),
+ mpDoc(pDoc)
+{
+ nCol = mpParam->mnField;
+ nRow = mpParam->nRow1;
+ nTab = mpParam->nTab;
+
nColRow = 0; // wird bei GetFirst initialisiert
SCSIZE i;
- SCSIZE nCount = aParam.GetEntryCount();
- for (i=0; (i<nCount) && (aParam.GetEntry(i).bDoQuery); i++)
+ SCSIZE nCount = mpParam->GetEntryCount();
+ for (i=0; (i<nCount) && (mpParam->GetEntry(i).bDoQuery); i++)
{
- ScQueryEntry& rEntry = aParam.GetEntry(i);
+ ScQueryEntry& rEntry = mpParam->GetEntry(i);
sal_uInt32 nIndex = 0;
rEntry.bQueryByString =
- !(pDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
+ !(mpDoc->GetFormatTable()->IsNumberFormat(*rEntry.pStr, nIndex, rEntry.nVal));
}
nNumFormat = 0; // werden bei GetNumberFormat initialisiert
pAttrArray = 0;
nAttrEndRow = 0;
}
-BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
+ScDBQueryDataIterator::DataAccessInternal::~DataAccessInternal()
{
- ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
- SCCOLROW nFirstQueryField = aParam.GetEntry(0).nField;
+}
+
+bool ScDBQueryDataIterator::DataAccessInternal::getCurrent(Value& rValue)
+{
+ SCCOLROW nFirstQueryField = mpParam->GetEntry(0).nField;
for ( ;; )
{
- if ( nRow > aParam.nRow2 )
+ if (nRow > mpParam->nRow2)
{
- nRow = aParam.nRow1;
- if (aParam.bHasHeader)
- nRow++;
- do
- {
- nCol++;
- if ( nCol > aParam.nCol2 )
- {
- // rValue = 0.0; // do not change caller's value!
- rErr = 0;
- return FALSE; // Ende und Aus
- }
- pCol = &(pDoc->pTab[nTab])->aCol[nCol];
- } while ( pCol->nCount == 0 );
- pCol->Search( nRow, nColRow );
+ // Bottom of the range reached. Bail out.
+ rValue.mnError = 0;
+ return false;
}
- while ( (nColRow < pCol->nCount) && (pCol->pItems[nColRow].nRow < nRow) )
- nColRow++;
+ SCSIZE nCellCount = mpDoc->GetCellCount(nTab, nCol);
+ SCROW nThisRow = ScDBQueryDataIterator::GetRowByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
+ while ( (nColRow < nCellCount) && (nThisRow < nRow) )
+ nThisRow = ScDBQueryDataIterator::GetRowByColEntryIndex(*mpDoc, nTab, nCol, ++nColRow);
- if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= aParam.nRow2 )
+ if ( nColRow < nCellCount && nThisRow <= mpParam->nRow2 )
{
- nRow = pCol->pItems[nColRow].nRow;
- ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
- if ( (pDoc->pTab[nTab])->ValidQuery( nRow, aParam, NULL,
- (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL) ) )
+ nRow = nThisRow;
+ ScBaseCell* pCell = NULL;
+ if (nCol == static_cast<SCCOL>(nFirstQueryField))
+ pCell = ScDBQueryDataIterator::GetCellByColEntryIndex(*mpDoc, nTab, nCol, nColRow);
+
+ if (ScDBQueryDataIterator::IsQueryValid(*mpDoc, *mpParam, nTab, nRow, pCell))
{
switch (pCell->GetCellType())
{
case CELLTYPE_VALUE:
{
- rValue = ((ScValueCell*)pCell)->GetValue();
+ rValue.mfValue = ((ScValueCell*)pCell)->GetValue();
+ rValue.mbIsNumber = true;
if ( bCalcAsShown )
{
+ const ScAttrArray* pNewAttrArray =
+ ScDBQueryDataIterator::GetAttrArrayByCol(*mpDoc, nTab, nCol);
lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
- nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
- rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
+ nAttrEndRow, pNewAttrArray, nRow, mpDoc );
+ rValue.mfValue = mpDoc->RoundValueAsShown( rValue.mfValue, nNumFormat );
}
nNumFmtType = NUMBERFORMAT_NUMBER;
nNumFmtIndex = 0;
- rErr = 0;
+ rValue.mnError = 0;
return TRUE; // gefunden
}
// break;
@@ -566,17 +618,31 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
{
if (((ScFormulaCell*)pCell)->IsValue())
{
- rValue = ((ScFormulaCell*)pCell)->GetValue();
- pDoc->GetNumberFormatInfo( nNumFmtType,
+ rValue.mfValue = ((ScFormulaCell*)pCell)->GetValue();
+ rValue.mbIsNumber = true;
+ mpDoc->GetNumberFormatInfo( nNumFmtType,
nNumFmtIndex, ScAddress( nCol, nRow, nTab ),
pCell );
- rErr = ((ScFormulaCell*)pCell)->GetErrCode();
+ rValue.mnError = ((ScFormulaCell*)pCell)->GetErrCode();
return TRUE; // gefunden
}
else
nRow++;
}
break;
+ case CELLTYPE_STRING:
+ case CELLTYPE_EDIT:
+ if (mpParam->mbSkipString)
+ ++nRow;
+ else
+ {
+ rValue.maString = pCell->GetStringData();
+ rValue.mfValue = 0.0;
+ rValue.mnError = 0;
+ rValue.mbIsNumber = false;
+ return true;
+ }
+ break;
default:
nRow++;
break;
@@ -586,30 +652,309 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
nRow++;
}
else
- nRow = aParam.nRow2 + 1; // Naechste Spalte
+ nRow = mpParam->nRow2 + 1; // Naechste Spalte
}
-// return FALSE;
+// statement unreachable
+// return false;
}
-BOOL ScQueryValueIterator::GetFirst(double& rValue, USHORT& rErr)
+bool ScDBQueryDataIterator::DataAccessInternal::getFirst(Value& rValue)
{
- nCol = aParam.nCol1;
- nRow = aParam.nRow1;
- if (aParam.bHasHeader)
+ if (mpParam->bHasHeader)
nRow++;
-// nColRow = 0;
- ScColumn* pCol = &(pDoc->pTab[nTab])->aCol[nCol];
- pCol->Search( nRow, nColRow );
- return GetThis(rValue, rErr);
+
+ nColRow = ScDBQueryDataIterator::SearchColEntryIndex(*mpDoc, nTab, nRow, nCol);
+ return getCurrent(rValue);
}
-BOOL ScQueryValueIterator::GetNext(double& rValue, USHORT& rErr)
+bool ScDBQueryDataIterator::DataAccessInternal::getNext(Value& rValue)
{
++nRow;
- return GetThis(rValue, rErr);
+ return getCurrent(rValue);
}
-//-------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------
+
+ScDBQueryDataIterator::DataAccessMatrix::DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam) :
+ DataAccess(pParent),
+ mpParam(pParam)
+{
+ SCSIZE nC, nR;
+ mpParam->mpMatrix->GetDimensions(nC, nR);
+ mnRows = static_cast<SCROW>(nR);
+ mnCols = static_cast<SCCOL>(nC);
+}
+
+ScDBQueryDataIterator::DataAccessMatrix::~DataAccessMatrix()
+{
+}
+
+bool ScDBQueryDataIterator::DataAccessMatrix::getCurrent(Value& rValue)
+{
+ // Starting from row == mnCurRow, get the first row that satisfies all the
+ // query parameters.
+ for ( ;mnCurRow < mnRows; ++mnCurRow)
+ {
+ const ScMatrix& rMat = *mpParam->mpMatrix;
+ if (rMat.IsEmpty(mpParam->mnField, mnCurRow))
+ // Don't take empty values into account.
+ continue;
+
+ bool bIsStrVal = rMat.IsString(mpParam->mnField, mnCurRow);
+ if (bIsStrVal && mpParam->mbSkipString)
+ continue;
+
+ if (isValidQuery(mnCurRow, rMat))
+ {
+ rValue.maString = rMat.GetString(mpParam->mnField, mnCurRow);
+ rValue.mfValue = rMat.GetDouble(mpParam->mnField, mnCurRow);
+ rValue.mbIsNumber = !bIsStrVal;
+ rValue.mnError = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ScDBQueryDataIterator::DataAccessMatrix::getFirst(Value& rValue)
+{
+ mnCurRow = mpParam->bHasHeader ? 1 : 0;
+ return getCurrent(rValue);
+}
+
+bool ScDBQueryDataIterator::DataAccessMatrix::getNext(Value& rValue)
+{
+ ++mnCurRow;
+ return getCurrent(rValue);
+}
+
+namespace {
+
+bool lcl_isQueryByValue(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
+{
+ if (rEntry.bQueryByString)
+ return false;
+
+ if (!rMat.IsValueOrEmpty(nCol, nRow))
+ return false;
+
+ return true;
+}
+
+bool lcl_isQueryByString(const ScQueryEntry& rEntry, const ScMatrix& rMat, SCSIZE nCol, SCSIZE nRow)
+{
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_NOT_EQUAL:
+ case SC_CONTAINS:
+ case SC_DOES_NOT_CONTAIN:
+ case SC_BEGINS_WITH:
+ case SC_ENDS_WITH:
+ case SC_DOES_NOT_BEGIN_WITH:
+ case SC_DOES_NOT_END_WITH:
+ return true;
+ default:
+ ;
+ }
+
+ if (rEntry.bQueryByString && rMat.IsString(nCol, nRow))
+ return true;
+
+ return false;
+}
+
+}
+
+bool ScDBQueryDataIterator::DataAccessMatrix::isValidQuery(SCROW nRow, const ScMatrix& rMat) const
+{
+ SCSIZE nEntryCount = mpParam->GetEntryCount();
+ vector<bool> aResults;
+ aResults.reserve(nEntryCount);
+
+ const CollatorWrapper& rCollator =
+ mpParam->bCaseSens ? *ScGlobal::GetCaseCollator() : *ScGlobal::GetCollator();
+
+ for (SCSIZE i = 0; i < nEntryCount; ++i)
+ {
+ const ScQueryEntry& rEntry = mpParam->GetEntry(i);
+ if (!rEntry.bDoQuery)
+ continue;
+
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ case SC_LESS:
+ case SC_GREATER:
+ case SC_LESS_EQUAL:
+ case SC_GREATER_EQUAL:
+ case SC_NOT_EQUAL:
+ break;
+ default:
+ // Only the above operators are supported.
+ continue;
+ }
+
+ bool bValid = false;
+
+ SCSIZE nField = static_cast<SCSIZE>(rEntry.nField);
+ if (lcl_isQueryByValue(rEntry, rMat, nField, nRow))
+ {
+ // By value
+ double fMatVal = rMat.GetDouble(nField, nRow);
+ bool bEqual = approxEqual(fMatVal, rEntry.nVal);
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ bValid = bEqual;
+ break;
+ case SC_LESS:
+ bValid = (fMatVal < rEntry.nVal) && !bEqual;
+ break;
+ case SC_GREATER:
+ bValid = (fMatVal > rEntry.nVal) && !bEqual;
+ break;
+ case SC_LESS_EQUAL:
+ bValid = (fMatVal < rEntry.nVal) || bEqual;
+ break;
+ case SC_GREATER_EQUAL:
+ bValid = (fMatVal > rEntry.nVal) || bEqual;
+ break;
+ case SC_NOT_EQUAL:
+ bValid = !bEqual;
+ break;
+ default:
+ ;
+ }
+ }
+ else if (lcl_isQueryByString(rEntry, rMat, nField, nRow))
+ {
+ // By string
+ do
+ {
+ if (!rEntry.pStr)
+ break;
+
+ // Equality check first.
+
+ OUString aMatStr = rMat.GetString(nField, nRow);
+ lcl_toUpper(aMatStr);
+ OUString aQueryStr = *rEntry.pStr;
+ lcl_toUpper(aQueryStr);
+ bool bDone = false;
+ switch (rEntry.eOp)
+ {
+ case SC_EQUAL:
+ bValid = aMatStr.equals(aQueryStr);
+ bDone = true;
+ break;
+ case SC_NOT_EQUAL:
+ bValid = !aMatStr.equals(aQueryStr);
+ bDone = true;
+ break;
+ default:
+ ;
+ }
+
+ if (bDone)
+ break;
+
+ // Unequality check using collator.
+
+ sal_Int32 nCompare = rCollator.compareString(aMatStr, aQueryStr);
+ switch (rEntry.eOp)
+ {
+ case SC_LESS :
+ bValid = (nCompare < 0);
+ break;
+ case SC_GREATER :
+ bValid = (nCompare > 0);
+ break;
+ case SC_LESS_EQUAL :
+ bValid = (nCompare <= 0);
+ break;
+ case SC_GREATER_EQUAL :
+ bValid = (nCompare >= 0);
+ break;
+ default:
+ ;
+ }
+ }
+ while (false);
+ }
+ else if (mpParam->bMixedComparison)
+ {
+ // Not used at the moment.
+ }
+
+ if (aResults.empty())
+ // First query entry.
+ aResults.push_back(bValid);
+ else if (rEntry.eConnect == SC_AND)
+ {
+ // For AND op, tuck the result into the last result value.
+ size_t n = aResults.size();
+ aResults[n-1] = aResults[n-1] && bValid;
+ }
+ else
+ // For OR op, store its own result.
+ aResults.push_back(bValid);
+ }
+
+ // Row is valid as long as there is at least one result being true.
+ vector<bool>::const_iterator itr = aResults.begin(), itrEnd = aResults.end();
+ for (; itr != itrEnd; ++itr)
+ if (*itr)
+ return true;
+
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+ScDBQueryDataIterator::Value::Value() :
+ mnError(0), mbIsNumber(true)
+{
+ ::rtl::math::setNan(&mfValue);
+}
+
+// ----------------------------------------------------------------------------
+
+ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam) :
+ mpParam (pParam)
+{
+ switch (mpParam->GetType())
+ {
+ case ScDBQueryParamBase::INTERNAL:
+ {
+ ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pParam);
+ mpData.reset(new DataAccessInternal(this, p, pDocument));
+ }
+ break;
+ case ScDBQueryParamBase::MATRIX:
+ {
+ ScDBQueryParamMatrix* p = static_cast<ScDBQueryParamMatrix*>(pParam);
+ mpData.reset(new DataAccessMatrix(this, p));
+ }
+ }
+}
+
+bool ScDBQueryDataIterator::GetThis(Value& rValue)
+{
+ return mpData->getCurrent(rValue);
+}
+
+bool ScDBQueryDataIterator::GetFirst(Value& rValue)
+{
+ return mpData->getFirst(rValue);
+}
+
+bool ScDBQueryDataIterator::GetNext(Value& rValue)
+{
+ return mpData->getNext(rValue);
+}
+
+// ============================================================================
ScCellIterator::ScCellIterator( ScDocument* pDocument,
SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index bf2ec7102..b78d11539 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -4703,6 +4703,13 @@ ULONG ScDocument::GetCellCount() const
return nCellCount;
}
+SCSIZE ScDocument::GetCellCount(SCTAB nTab, SCCOL nCol) const
+{
+ if (!ValidTab(nTab) || !pTab[nTab])
+ return 0;
+
+ return pTab[nTab]->GetCellCount(nCol);
+}
ULONG ScDocument::GetCodeCount() const
{
diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx
index 015c6512d..e4fac9ee1 100644
--- a/sc/source/core/data/dpcachetable.cxx
+++ b/sc/source/core/data/dpcachetable.cxx
@@ -38,6 +38,7 @@
#include "dptabdat.hxx"
#include "dptabsrc.hxx"
#include "dpobject.hxx"
+#include "queryparam.hxx"
#include <com/sun/star/i18n/LocaleDataItem.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
@@ -209,9 +210,39 @@ sal_Int32 ScDPCacheTable::getColSize() const
return maTable.empty() ? 0 : maTable[0].size();
}
+namespace {
+
+/**
+ * While the macro interpret level is incremented, the formula cells are
+ * (semi-)guaranteed to be interpreted.
+ */
+class MacroInterpretIncrementer
+{
+public:
+ MacroInterpretIncrementer(ScDocument* pDoc) :
+ mpDoc(pDoc)
+ {
+ mpDoc->IncMacroInterpretLevel();
+ }
+ ~MacroInterpretIncrementer()
+ {
+ mpDoc->DecMacroInterpretLevel();
+ }
+private:
+ ScDocument* mpDoc;
+};
+
+}
+
void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const ScQueryParam& rQuery, BOOL* pSpecial,
bool bIgnoreEmptyRows)
{
+ // Make sure the formula cells within the data range are interpreted
+ // during this call, for this method may be called from the interpretation
+ // of GETPIVOTDATA, which disables nested formula interpretation without
+ // increasing the macro level.
+ MacroInterpretIncrementer aMacroInc(pDoc);
+
SCTAB nTab = rRange.aStart.Tab();
SCCOL nStartCol = rRange.aStart.Col();
SCROW nStartRow = rRange.aStart.Row();
diff --git a/sc/source/core/data/global2.cxx b/sc/source/core/data/global2.cxx
index bf69367bf..4c2e2d3c0 100644
--- a/sc/source/core/data/global2.cxx
+++ b/sc/source/core/data/global2.cxx
@@ -243,238 +243,6 @@ utl::TextSearch* ScQueryEntry::GetSearchTextPtr( BOOL bCaseSens )
}
//------------------------------------------------------------------------
-
-ScQueryParam::ScQueryParam()
-{
- nEntryCount = 0;
- Clear();
-}
-
-//------------------------------------------------------------------------
-
-ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
- nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab),
- bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
- bRegExp(r.bRegExp), bMixedComparison(r.bMixedComparison),
- bDuplicate(r.bDuplicate), bDestPers(r.bDestPers),
- nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
-{
- nEntryCount = 0;
-
- Resize( r.nEntryCount );
- for (USHORT i=0; i<nEntryCount; i++)
- pEntries[i] = r.pEntries[i];
-}
-
-//------------------------------------------------------------------------
-
-ScQueryParam::~ScQueryParam()
-{
- delete[] pEntries;
-}
-
-//------------------------------------------------------------------------
-
-void ScQueryParam::Clear()
-{
- nCol1=nCol2=nDestCol = 0;
- nRow1=nRow2=nDestRow = 0;
- nDestTab = 0;
- nTab = SCTAB_MAX;
- bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
- bInplace = bByRow = bDuplicate = bDestPers = TRUE;
-
- Resize( MAXQUERY );
- for (USHORT i=0; i<MAXQUERY; i++)
- pEntries[i].Clear();
-}
-
-//------------------------------------------------------------------------
-
-ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
-{
- nCol1 = r.nCol1;
- nRow1 = r.nRow1;
- nCol2 = r.nCol2;
- nRow2 = r.nRow2;
- nTab = r.nTab;
- nDestTab = r.nDestTab;
- nDestCol = r.nDestCol;
- nDestRow = r.nDestRow;
- bHasHeader = r.bHasHeader;
- bInplace = r.bInplace;
- bCaseSens = r.bCaseSens;
- bRegExp = r.bRegExp;
- bMixedComparison = r.bMixedComparison;
- bDuplicate = r.bDuplicate;
- bByRow = r.bByRow;
- bDestPers = r.bDestPers;
-
- Resize( r.nEntryCount );
- for (USHORT i=0; i<nEntryCount; i++)
- pEntries[i] = r.pEntries[i];
-
- return *this;
-}
-
-//------------------------------------------------------------------------
-
-BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
-{
- BOOL bEqual = FALSE;
-
- // Anzahl der Queries gleich?
- USHORT nUsed = 0;
- USHORT nOtherUsed = 0;
- while ( nUsed<nEntryCount && pEntries[nUsed].bDoQuery ) ++nUsed;
- while ( nOtherUsed<rOther.nEntryCount && rOther.pEntries[nOtherUsed].bDoQuery )
- ++nOtherUsed;
-
- if ( (nUsed == nOtherUsed)
- && (nCol1 == rOther.nCol1)
- && (nRow1 == rOther.nRow1)
- && (nCol2 == rOther.nCol2)
- && (nRow2 == rOther.nRow2)
- && (nTab == rOther.nTab)
- && (bHasHeader == rOther.bHasHeader)
- && (bByRow == rOther.bByRow)
- && (bInplace == rOther.bInplace)
- && (bCaseSens == rOther.bCaseSens)
- && (bRegExp == rOther.bRegExp)
- && (bMixedComparison == rOther.bMixedComparison)
- && (bDuplicate == rOther.bDuplicate)
- && (bDestPers == rOther.bDestPers)
- && (nDestTab == rOther.nDestTab)
- && (nDestCol == rOther.nDestCol)
- && (nDestRow == rOther.nDestRow) )
- {
- bEqual = TRUE;
- for ( USHORT i=0; i<nUsed && bEqual; i++ )
- bEqual = pEntries[i] == rOther.pEntries[i];
- }
- return bEqual;
-}
-
-//------------------------------------------------------------------------
-
-void ScQueryParam::DeleteQuery( SCSIZE nPos )
-{
- if (nPos<nEntryCount)
- {
- for (SCSIZE i=nPos; i+1<nEntryCount; i++)
- pEntries[i] = pEntries[i+1];
-
- pEntries[nEntryCount-1].Clear();
- }
- else
- {
- DBG_ERROR("Falscher Parameter bei ScQueryParam::DeleteQuery");
- }
-}
-
-//------------------------------------------------------------------------
-
-void ScQueryParam::Resize(SCSIZE nNew)
-{
- if ( nNew < MAXQUERY )
- nNew = MAXQUERY; // nie weniger als MAXQUERY
-
- ScQueryEntry* pNewEntries = NULL;
- if ( nNew )
- pNewEntries = new ScQueryEntry[nNew];
-
- SCSIZE nCopy = Min( nEntryCount, nNew );
- for (SCSIZE i=0; i<nCopy; i++)
- pNewEntries[i] = pEntries[i];
-
- if ( nEntryCount )
- delete[] pEntries;
- nEntryCount = nNew;
- pEntries = pNewEntries;
-}
-
-//------------------------------------------------------------------------
-
-void ScQueryParam::MoveToDest()
-{
- if (!bInplace)
- {
- SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
- SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
- SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
-
- nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
- nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
- nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
- nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
- nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
- for (USHORT i=0; i<nEntryCount; i++)
- pEntries[i].nField += nDifX;
-
- bInplace = TRUE;
- }
- else
- {
- DBG_ERROR("MoveToDest, bInplace == TRUE");
- }
-}
-
-//------------------------------------------------------------------------
-
-void ScQueryParam::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
-{
- if (aCellStr.Len() > 0)
- {
- if ( nIndex >= nEntryCount )
- Resize( nIndex+1 );
-
- ScQueryEntry& rEntry = pEntries[nIndex];
-
- rEntry.bDoQuery = TRUE;
- // Operatoren herausfiltern
- if (aCellStr.GetChar(0) == '<')
- {
- if (aCellStr.GetChar(1) == '>')
- {
- *rEntry.pStr = aCellStr.Copy(2);
- rEntry.eOp = SC_NOT_EQUAL;
- }
- else if (aCellStr.GetChar(1) == '=')
- {
- *rEntry.pStr = aCellStr.Copy(2);
- rEntry.eOp = SC_LESS_EQUAL;
- }
- else
- {
- *rEntry.pStr = aCellStr.Copy(1);
- rEntry.eOp = SC_LESS;
- }
- }
- else if (aCellStr.GetChar(0) == '>')
- {
- if (aCellStr.GetChar(1) == '=')
- {
- *rEntry.pStr = aCellStr.Copy(2);
- rEntry.eOp = SC_GREATER_EQUAL;
- }
- else
- {
- *rEntry.pStr = aCellStr.Copy(1);
- rEntry.eOp = SC_GREATER;
- }
- }
- else
- {
- if (aCellStr.GetChar(0) == '=')
- *rEntry.pStr = aCellStr.Copy(1);
- else
- *rEntry.pStr = aCellStr;
- rEntry.eOp = SC_EQUAL;
- }
- }
-}
-
-//------------------------------------------------------------------------
// struct ScSubTotalParam:
ScSubTotalParam::ScSubTotalParam()
diff --git a/sc/source/core/data/sortparam.cxx b/sc/source/core/data/sortparam.cxx
index 9531c7175..dfab465d0 100644
--- a/sc/source/core/data/sortparam.cxx
+++ b/sc/source/core/data/sortparam.cxx
@@ -36,6 +36,7 @@
#include "sortparam.hxx"
#include "global.hxx"
#include "address.hxx"
+#include "queryparam.hxx"
#include <tools/debug.hxx>
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index e5943d721..1525f0c62 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -60,6 +60,7 @@
#include "progress.hxx"
#include "cellform.hxx"
#include "postit.hxx"
+#include "queryparam.hxx"
#include <vector>
@@ -1818,6 +1819,11 @@ BOOL ScTable::GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStri
return aCol[nCol].GetDataEntries( nRow, rStrings, bLimit );
}
+SCSIZE ScTable::GetCellCount(SCCOL nCol) const
+{
+ return aCol[nCol].GetCellCount();
+}
+
ULONG ScTable::GetCellCount() const
{
ULONG nCellCount = 0;
diff --git a/sc/source/core/inc/doubleref.hxx b/sc/source/core/inc/doubleref.hxx
new file mode 100644
index 000000000..d79b90790
--- /dev/null
+++ b/sc/source/core/inc/doubleref.hxx
@@ -0,0 +1,194 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interpre.hxx,v $
+ * $Revision: 1.35.44.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SC_DOUBLEREF_HXX
+#define SC_DOUBLEREF_HXX
+
+#include "address.hxx"
+#include "scmatrix.hxx"
+
+class ScDocument;
+class ScBaseCell;
+struct ScDBQueryParamBase;
+struct ScQueryParamBase;
+
+// ============================================================================
+
+/**
+ * Base class for abstracting range data backends for database functions.
+ */
+class ScDBRangeBase
+{
+public:
+ enum RefType { INTERNAL, EXTERNAL };
+
+ virtual ~ScDBRangeBase() = 0;
+
+ RefType getType() const;
+ bool fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const;
+
+ virtual SCCOL getColSize() const = 0;
+ virtual SCROW getRowSize() const = 0;
+ virtual SCSIZE getVisibleDataCellCount() const = 0;
+
+ /**
+ * Get a string value of a specified cell position. Note that the
+ * position of the upper left cell of the range is always (0, 0) even if
+ * the reference type is of internal range.
+ *
+ * @param nCol column position (0 to column size-1)
+ * @param nRow row position (0 to row size-1)
+ */
+ virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const = 0;
+
+ virtual SCCOL getFirstFieldColumn() const = 0;
+
+ /**
+ * Get a <i>0-based</i> column index that corresponds with the passed field
+ * index. Note that the field index passed as the 1st parameter is
+ * <i>1-based.</i>
+ *
+ * @param nIndex 1-based field index.
+ *
+ * @return 0-based column index
+ */
+ virtual SCCOL findFieldColumn(SCCOL nIndex) const = 0;
+ virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const = 0;
+ virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const = 0;
+ virtual bool isRangeEqual(const ScRange& rRange) const = 0;
+
+protected:
+ ScDBRangeBase(ScDocument* pDoc, RefType eType);
+ ScDocument* getDoc() const;
+
+ /**
+ * Populate query options that are always the same for all database
+ * queries.
+ */
+ static void fillQueryOptions(ScQueryParamBase* pParam);
+
+private:
+ ScDBRangeBase(); // disabled
+
+ ScDocument* mpDoc;
+ RefType meType;
+};
+
+// ============================================================================
+
+class ScDBInternalRange : public ScDBRangeBase
+{
+public:
+ explicit ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange);
+ virtual ~ScDBInternalRange();
+
+ const ScRange& getRange() const;
+
+ virtual SCCOL getColSize() const;
+ virtual SCROW getRowSize() const;
+ virtual SCSIZE getVisibleDataCellCount() const;
+
+ /**
+ * Get a string value of a specified cell position. Note that the
+ * position of the upper left cell of the range is always (0, 0) even if
+ * the reference type is of internal range.
+ *
+ * @param nCol column position (0 to column size-1)
+ * @param nRow row position (0 to row size-1)
+ */
+ virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const;
+
+ virtual SCCOL getFirstFieldColumn() const;
+ /**
+ * Get a <i>0-based</i> column index that corresponds with the passed field
+ * index. Note that the field index passed as the 1st parameter is
+ * <i>1-based.</i>
+ *
+ * @param nIndex 1-based field index.
+ *
+ * @return 0-based column index
+ */
+ virtual SCCOL findFieldColumn(SCCOL nIndex) const;
+ virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const;
+ virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const;
+ virtual bool isRangeEqual(const ScRange& rRange) const;
+
+private:
+ sal_uInt16 getCellString(::rtl::OUString& rStr, ScBaseCell* pCell) const;
+
+private:
+ ScRange maRange;
+};
+
+// ============================================================================
+
+class ScDBExternalRange : public ScDBRangeBase
+{
+public:
+ explicit ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat);
+ virtual ~ScDBExternalRange();
+
+ virtual SCCOL getColSize() const;
+ virtual SCROW getRowSize() const;
+ virtual SCSIZE getVisibleDataCellCount() const;
+
+ /**
+ * Get a string value of a specified cell position. Note that the
+ * position of the upper left cell of the range is always (0, 0) even if
+ * the reference type is of internal range.
+ *
+ * @param nCol column position (0 to column size-1)
+ * @param nRow row position (0 to row size-1)
+ */
+ virtual ::rtl::OUString getString(SCCOL nCol, SCROW nRow) const;
+
+ virtual SCCOL getFirstFieldColumn() const;
+
+ /**
+ * Get a <i>0-based</i> column index that corresponds with the passed field
+ * index. Note that the field index passed as the 1st parameter is
+ * <i>1-based.</i>
+ *
+ * @param nIndex 1-based field index.
+ *
+ * @return 0-based column index
+ */
+ virtual SCCOL findFieldColumn(SCCOL nIndex) const;
+ virtual SCCOL findFieldColumn(const ::rtl::OUString& rStr, sal_uInt16* pErr = NULL) const;
+ virtual ScDBQueryParamBase* createQueryParam(const ScDBRangeBase* pQueryRef) const;
+ virtual bool isRangeEqual(const ScRange& rRange) const;
+
+private:
+ const ScMatrixRef mpMatrix;
+ SCCOL mnCols;
+ SCROW mnRows;
+};
+
+#endif
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 58bc46fcb..0252f1d88 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -53,7 +53,10 @@ class SbxVariable;
class ScBaseCell;
class ScFormulaCell;
class SvNumberFormatter;
+class ScDBRangeBase;
struct MatrixDoubleOp;
+struct ScQueryParam;
+struct ScDBQueryParamBase;
struct ScCompare
{
@@ -302,6 +305,7 @@ void DoubleRefToVars( const ScToken* p,
SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
BOOL bDontCheckForTableOp = FALSE );
+ScDBRangeBase* PopDoubleRef();
void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
BOOL bDontCheckForTableOp = FALSE );
@@ -491,7 +495,7 @@ void ScSubTotal();
// compatibility). If this was the case then rMissingField is set to TRUE upon
// return. If rMissingField==FALSE upon call all "missing cases" are considered
// to be an error.
-BOOL GetDBParams( SCTAB& rTab, ScQueryParam& rParam, BOOL& rMissingField );
+ScDBQueryParamBase* GetDBParams( BOOL& rMissingField );
void DBIterator( ScIterFunc );
void ScDBSum();
diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx
index e1e3870b4..a47a669a9 100644
--- a/sc/source/core/tool/dbcolect.cxx
+++ b/sc/source/core/tool/dbcolect.cxx
@@ -40,6 +40,7 @@
#include "refupdat.hxx"
#include "rechead.hxx"
#include "document.hxx"
+#include "queryparam.hxx"
#include "globstr.hrc"
diff --git a/sc/source/core/tool/doubleref.cxx b/sc/source/core/tool/doubleref.cxx
new file mode 100644
index 000000000..01528db9f
--- /dev/null
+++ b/sc/source/core/tool/doubleref.cxx
@@ -0,0 +1,568 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interpre.hxx,v $
+ * $Revision: 1.35.44.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "doubleref.hxx"
+#include "cell.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "queryparam.hxx"
+#include "globstr.hrc"
+
+#include <memory>
+#include <vector>
+
+using ::rtl::OUString;
+using ::std::auto_ptr;
+using ::std::vector;
+
+namespace {
+
+void lcl_toUpper(OUString& rStr)
+{
+ rStr = ScGlobal::pCharClass->toUpper(rStr.trim(), 0, static_cast<xub_StrLen>(rStr.getLength()));
+}
+
+bool lcl_createStarQuery(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
+{
+ // A valid StarQuery must be at least 4 columns wide. To be precise it
+ // should be exactly 4 columns ...
+ // Additionally, if this wasn't checked, a formula pointing to a valid 1-3
+ // column Excel style query range immediately left to itself would result
+ // in a circular reference when the field name or operator or value (first
+ // to third query range column) is obtained (#i58354#). Furthermore, if the
+ // range wasn't sufficiently specified data changes wouldn't flag formula
+ // cells for recalculation.
+
+ if (pQueryRef->getColSize() < 4)
+ return false;
+
+ BOOL bValid;
+ BOOL bFound;
+ OUString aCellStr;
+ SCSIZE nIndex = 0;
+ SCROW nRow = 0;
+ SCROW nRows = pDBRef->getRowSize();
+ SCSIZE nNewEntries = static_cast<SCSIZE>(nRows);
+ pParam->Resize(nNewEntries);
+
+ do
+ {
+ ScQueryEntry& rEntry = pParam->GetEntry(nIndex);
+
+ bValid = FALSE;
+
+ if (nIndex > 0)
+ {
+ // For all entries after the first one, check the and/or connector in the first column.
+ aCellStr = pQueryRef->getString(0, nRow);
+ lcl_toUpper(aCellStr);
+ if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_UND)) )
+ {
+ rEntry.eConnect = SC_AND;
+ bValid = TRUE;
+ }
+ else if ( aCellStr.equals(ScGlobal::GetRscString(STR_TABLE_ODER)) )
+ {
+ rEntry.eConnect = SC_OR;
+ bValid = TRUE;
+ }
+ }
+
+ if ((nIndex < 1) || bValid)
+ {
+ // field name in the 2nd column.
+ bFound = FALSE;
+ aCellStr = pQueryRef->getString(1, nRow);
+ SCCOL nField = pDBRef->findFieldColumn(aCellStr); // TODO: must be case insensitive comparison.
+ if (ValidCol(nField))
+ {
+ rEntry.nField = nField;
+ bValid = true;
+ }
+ else
+ bValid = false;
+ }
+
+ if (bValid)
+ {
+ // equality, non-equality operator in the 3rd column.
+ bFound = FALSE;
+ aCellStr = pQueryRef->getString(2, nRow);
+ lcl_toUpper(aCellStr);
+ const sal_Unicode* p = aCellStr.getStr();
+ if (p[0] == sal_Unicode('<'))
+ {
+ if (p[1] == sal_Unicode('>'))
+ rEntry.eOp = SC_NOT_EQUAL;
+ else if (p[1] == sal_Unicode('='))
+ rEntry.eOp = SC_LESS_EQUAL;
+ else
+ rEntry.eOp = SC_LESS;
+ }
+ else if (p[0] == sal_Unicode('>'))
+ {
+ if (p[1] == sal_Unicode('='))
+ rEntry.eOp = SC_GREATER_EQUAL;
+ else
+ rEntry.eOp = SC_GREATER;
+ }
+ else if (p[0] == sal_Unicode('='))
+ rEntry.eOp = SC_EQUAL;
+
+ }
+
+ if (bValid)
+ {
+ // Finally, the right-hand-side value in the 4th column.
+ *rEntry.pStr = pQueryRef->getString(3, nRow);
+ rEntry.bDoQuery = TRUE;
+ }
+ nIndex++;
+ nRow++;
+ }
+ while (bValid && (nRow < nRows) /* && (nIndex < MAXQUERY) */ );
+ return bValid;
+}
+
+bool lcl_createExcelQuery(
+ ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
+{
+ bool bValid = true;
+ SCCOL nCols = pQueryRef->getColSize();
+ SCROW nRows = pQueryRef->getRowSize();
+ vector<SCCOL> aFields(nCols);
+ SCCOL nCol = 0;
+ while (bValid && (nCol < nCols))
+ {
+ OUString aQueryStr = pQueryRef->getString(nCol, 0);
+ SCCOL nField = pDBRef->findFieldColumn(aQueryStr);
+ if (ValidCol(nField))
+ aFields[nCol] = nField;
+ else
+ bValid = false;
+ ++nCol;
+ }
+
+ if (bValid)
+ {
+// ULONG nVisible = 0;
+// for ( nCol=nCol1; nCol<=nCol2; nCol++ )
+// nVisible += aCol[nCol].VisibleCount( nRow1+1, nRow2 );
+
+ // Count the number of visible cells (excluding the header row). Each
+ // visible cell corresponds with a single query.
+ SCSIZE nVisible = pQueryRef->getVisibleDataCellCount();
+ if ( nVisible > SCSIZE_MAX / sizeof(void*) )
+ {
+ DBG_ERROR("zu viele Filterkritierien");
+ nVisible = 0;
+ }
+
+ SCSIZE nNewEntries = nVisible;
+ pParam->Resize( nNewEntries );
+
+ SCSIZE nIndex = 0;
+ SCROW nRow = 1;
+ String aCellStr;
+ while (nRow < nRows)
+ {
+ nCol = 0;
+ while (nCol < nCols)
+ {
+ aCellStr = pQueryRef->getString(nCol, nRow);
+ ScGlobal::pCharClass->toUpper( aCellStr );
+ if (aCellStr.Len() > 0)
+ {
+ if (nIndex < nNewEntries)
+ {
+ pParam->GetEntry(nIndex).nField = aFields[nCol];
+ pParam->FillInExcelSyntax(aCellStr, nIndex);
+ nIndex++;
+ if (nIndex < nNewEntries)
+ pParam->GetEntry(nIndex).eConnect = SC_AND;
+ }
+ else
+ bValid = FALSE;
+ }
+ nCol++;
+ }
+ nRow++;
+ if (nIndex < nNewEntries)
+ pParam->GetEntry(nIndex).eConnect = SC_OR;
+ }
+ }
+ return bValid;
+}
+
+bool lcl_fillQueryEntries(
+ ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef, const ScDBRangeBase* pQueryRef)
+{
+ SCSIZE nCount = pParam->GetEntryCount();
+ for (SCSIZE i = 0; i < nCount; ++i)
+ pParam->GetEntry(i).Clear();
+
+ // Standard QueryTabelle
+ bool bValid = lcl_createStarQuery(pParam, pDBRef, pQueryRef);
+ // Excel QueryTabelle
+ if (!bValid)
+ bValid = lcl_createExcelQuery(pParam, pDBRef, pQueryRef);
+
+ nCount = pParam->GetEntryCount();
+ if (bValid)
+ {
+ // bQueryByString muss gesetzt sein
+ for (SCSIZE i = 0; i < nCount; ++i)
+ pParam->GetEntry(i).bQueryByString = true;
+ }
+ else
+ {
+ // nix
+ for (SCSIZE i = 0; i < nCount; ++i)
+ pParam->GetEntry(i).Clear();
+ }
+ return bValid;
+}
+
+}
+
+// ============================================================================
+
+ScDBRangeBase::ScDBRangeBase(ScDocument* pDoc, RefType eType) :
+ mpDoc(pDoc), meType(eType)
+{
+}
+
+ScDBRangeBase::~ScDBRangeBase()
+{
+}
+
+ScDBRangeBase::RefType ScDBRangeBase::getType() const
+{
+ return meType;
+}
+
+bool ScDBRangeBase::fillQueryEntries(ScQueryParamBase* pParam, const ScDBRangeBase* pDBRef) const
+{
+ if (!pDBRef)
+ return false;
+
+ return lcl_fillQueryEntries(pParam, pDBRef, this);
+}
+
+void ScDBRangeBase::fillQueryOptions(ScQueryParamBase* pParam)
+{
+ pParam->bHasHeader = true;
+ pParam->bByRow = true;
+ pParam->bInplace = true;
+ pParam->bCaseSens = false;
+ pParam->bRegExp = false;
+ pParam->bDuplicate = true;
+ pParam->bMixedComparison = false;
+}
+
+ScDocument* ScDBRangeBase::getDoc() const
+{
+ return mpDoc;
+}
+
+// ============================================================================
+
+ScDBInternalRange::ScDBInternalRange(ScDocument* pDoc, const ScRange& rRange) :
+ ScDBRangeBase(pDoc, INTERNAL), maRange(rRange)
+{
+}
+
+ScDBInternalRange::~ScDBInternalRange()
+{
+}
+
+const ScRange& ScDBInternalRange::getRange() const
+{
+ return maRange;
+}
+
+SCCOL ScDBInternalRange::getColSize() const
+{
+ return maRange.aEnd.Col() - maRange.aStart.Col() + 1;
+}
+
+SCROW ScDBInternalRange::getRowSize() const
+{
+ return maRange.aEnd.Row() - maRange.aStart.Row() + 1;
+}
+
+SCSIZE ScDBInternalRange::getVisibleDataCellCount() const
+{
+ SCCOL nCols = getColSize();
+ SCROW nRows = getRowSize();
+ if (nRows <= 1)
+ return 0;
+
+ return (nRows-1)*nCols;
+}
+
+OUString ScDBInternalRange::getString(SCCOL nCol, SCROW nRow) const
+{
+ String aStr;
+ const ScAddress& s = maRange.aStart;
+ getDoc()->GetString(s.Col() + nCol, s.Row() + nRow, maRange.aStart.Tab(), aStr);
+ return aStr;
+}
+
+SCCOL ScDBInternalRange::getFirstFieldColumn() const
+{
+ return getRange().aStart.Col();
+}
+
+SCCOL ScDBInternalRange::findFieldColumn(SCCOL nIndex) const
+{
+ const ScRange& rRange = getRange();
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCCOL nDBCol1 = s.Col();
+ SCCOL nDBCol2 = e.Col();
+
+ if ( nIndex <= 0 || nIndex > (nDBCol2 - nDBCol1 + 1) )
+ return nDBCol1;
+
+ return Min(nDBCol2, static_cast<SCCOL>(nDBCol1 + nIndex - 1));
+}
+
+sal_uInt16 ScDBInternalRange::getCellString(OUString& rStr, ScBaseCell* pCell) const
+{
+ sal_uInt16 nErr = 0;
+ String aStr;
+ if (pCell)
+ {
+ SvNumberFormatter* pFormatter = getDoc()->GetFormatTable();
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_STRING:
+ ((ScStringCell*) pCell)->GetString(aStr);
+ break;
+ case CELLTYPE_EDIT:
+ ((ScEditCell*) pCell)->GetString(aStr);
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
+ nErr = pFCell->GetErrCode();
+ if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, aStr);
+ }
+ else
+ pFCell->GetString(aStr);
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = ((ScValueCell*) pCell)->GetValue();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, aStr);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ rStr = aStr;
+ return nErr;
+}
+
+SCCOL ScDBInternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
+{
+ const ScAddress& s = maRange.aStart;
+ const ScAddress& e = maRange.aEnd;
+ OUString aUpper = rStr;
+ lcl_toUpper(aUpper);
+
+ SCCOL nDBCol1 = s.Col();
+ SCROW nDBRow1 = s.Row();
+ SCTAB nDBTab1 = s.Tab();
+ SCCOL nDBCol2 = e.Col();
+
+ SCCOL nField = nDBCol1;
+ BOOL bFound = TRUE;
+
+ bFound = FALSE;
+ OUString aCellStr;
+ ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
+ while (!bFound && (aLook.Col() <= nDBCol2))
+ {
+ ScBaseCell* pCell = getDoc()->GetCell( aLook );
+ sal_uInt16 nErr = getCellString( aCellStr, pCell );
+ if (pErr)
+ *pErr = nErr;
+ lcl_toUpper(aCellStr);
+ bFound = ScGlobal::GetpTransliteration()->isEqual(aCellStr, aUpper);
+ if (!bFound)
+ aLook.IncCol();
+ }
+ nField = aLook.Col();
+
+ return bFound ? nField : -1;
+}
+
+ScDBQueryParamBase* ScDBInternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
+{
+ auto_ptr<ScDBQueryParamInternal> pParam(new ScDBQueryParamInternal);
+
+ // Set the database range first.
+ const ScAddress& s = maRange.aStart;
+ const ScAddress& e = maRange.aEnd;
+ pParam->nCol1 = s.Col();
+ pParam->nRow1 = s.Row();
+ pParam->nCol2 = e.Col();
+ pParam->nRow2 = e.Row();
+ pParam->nTab = s.Tab();
+
+ fillQueryOptions(pParam.get());
+
+ // Now construct the query entries from the query range.
+ if (!pQueryRef->fillQueryEntries(pParam.get(), this))
+ return NULL;
+
+ return pParam.release();
+}
+
+bool ScDBInternalRange::isRangeEqual(const ScRange& rRange) const
+{
+ return maRange == rRange;
+}
+
+// ============================================================================
+
+ScDBExternalRange::ScDBExternalRange(ScDocument* pDoc, const ScMatrixRef& pMat) :
+ ScDBRangeBase(pDoc, EXTERNAL), mpMatrix(pMat)
+{
+ SCSIZE nC, nR;
+ mpMatrix->GetDimensions(nC, nR);
+ mnCols = static_cast<SCCOL>(nC);
+ mnRows = static_cast<SCROW>(nR);
+}
+
+ScDBExternalRange::~ScDBExternalRange()
+{
+}
+
+SCCOL ScDBExternalRange::getColSize() const
+{
+ return mnCols;
+}
+
+SCROW ScDBExternalRange::getRowSize() const
+{
+ return mnRows;
+}
+
+SCSIZE ScDBExternalRange::getVisibleDataCellCount() const
+{
+ SCCOL nCols = getColSize();
+ SCROW nRows = getRowSize();
+ if (nRows <= 1)
+ return 0;
+
+ return (nRows-1)*nCols;
+}
+
+OUString ScDBExternalRange::getString(SCCOL nCol, SCROW nRow) const
+{
+ if (nCol >= mnCols || nRow >= mnRows)
+ return OUString();
+
+ return mpMatrix->GetString(nCol, nRow);
+}
+
+SCCOL ScDBExternalRange::getFirstFieldColumn() const
+{
+ return 0;
+}
+
+SCCOL ScDBExternalRange::findFieldColumn(SCCOL nIndex) const
+{
+ if (nIndex < 1)
+ // 1st field
+ return 0;
+
+ if (nIndex > mnCols)
+ // last field
+ return mnCols - 1;
+
+ return nIndex - 1;
+}
+
+SCCOL ScDBExternalRange::findFieldColumn(const OUString& rStr, sal_uInt16* pErr) const
+{
+ if (pErr)
+ pErr = 0;
+
+ OUString aUpper = rStr;
+ lcl_toUpper(aUpper);
+ for (SCCOL i = 0; i < mnCols; ++i)
+ {
+ OUString aUpperVal = mpMatrix->GetString(i, 0);
+ lcl_toUpper(aUpperVal);
+ if (aUpper.equals(aUpperVal))
+ return i;
+ }
+ return -1;
+}
+
+ScDBQueryParamBase* ScDBExternalRange::createQueryParam(const ScDBRangeBase* pQueryRef) const
+{
+ auto_ptr<ScDBQueryParamMatrix> pParam(new ScDBQueryParamMatrix);
+ pParam->mpMatrix = mpMatrix;
+ fillQueryOptions(pParam.get());
+
+ // Now construct the query entries from the query range.
+ if (!pQueryRef->fillQueryEntries(pParam.get(), this))
+ return NULL;
+
+ return pParam.release();
+}
+
+bool ScDBExternalRange::isRangeEqual(const ScRange& /*rRange*/) const
+{
+ return false;
+}
+
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 68fbcccfc..aee4743a0 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -68,11 +68,14 @@
#include <string.h>
#include <math.h>
#include <vector>
+#include <memory>
#include "cellkeytranslator.hxx"
#include "lookupcache.hxx"
#include "rangenam.hxx"
#include "compiler.hxx"
#include "externalrefmgr.hxx"
+#include "doubleref.hxx"
+#include "queryparam.hxx"
#define SC_DOUBLE_MAXVALUE 1.7e307
@@ -83,6 +86,8 @@ ScTokenStack* ScInterpreter::pGlobalStack = NULL;
BOOL ScInterpreter::bGlobalStackInUse = FALSE;
using namespace formula;
+using ::std::auto_ptr;
+
//-----------------------------------------------------------------------------
// Funktionen
//-----------------------------------------------------------------------------
@@ -5828,11 +5833,9 @@ void ScInterpreter::ScSubTotal()
#endif
-BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
- BOOL& rMissingField )
+ScDBQueryParamBase* ScInterpreter::GetDBParams( BOOL& rMissingField )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBParams" );
- BOOL bRet = FALSE;
BOOL bAllowMissingField = FALSE;
if ( rMissingField )
{
@@ -5841,14 +5844,10 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
}
if ( GetByte() == 3 )
{
-
- SCCOL nQCol1;
- SCROW nQRow1;
- SCTAB nQTab1;
- SCCOL nQCol2;
- SCROW nQRow2;
- SCTAB nQTab2;
- PopDoubleRef(nQCol1, nQRow1, nQTab1, nQCol2, nQRow2, nQTab2);
+ // First, get the query criteria range.
+ ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDoubleRef() );
+ if (!pQueryRef.get())
+ return NULL;
BOOL bByVal = TRUE;
double nVal = 0.0;
@@ -5904,116 +5903,85 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
SetError( errIllegalParameter );
}
- SCCOL nDBCol1;
- SCROW nDBRow1;
- SCTAB nDBTab1;
- SCCOL nDBCol2;
- SCROW nDBRow2;
- SCTAB nDBTab2;
- PopDoubleRef(nDBCol1, nDBRow1, nDBTab1, nDBCol2, nDBRow2, nDBTab2);
+ auto_ptr<ScDBRangeBase> pDBRef( PopDoubleRef() );
- if ( nGlobalError == 0 && bRangeFake )
+ if (nGlobalError || !pDBRef.get())
+ return NULL;
+
+ if ( bRangeFake )
{
// range parameter must match entire database range
- if ( aMissingRange == ScRange( nDBCol1, nDBRow1, nDBTab1, nDBCol2,
- nDBRow2, nDBTab2) )
+ if (pDBRef->isRangeEqual(aMissingRange))
rMissingField = TRUE;
else
SetError( errIllegalParameter );
}
- if (nGlobalError == 0)
+ if (nGlobalError)
+ return NULL;
+
+ SCCOL nField = pDBRef->getFirstFieldColumn();
+ if (rMissingField)
+ ; // special case
+ else if (bByVal)
+ nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
+ else
+ {
+ sal_uInt16 nErr = 0;
+ nField = pDBRef->findFieldColumn(aStr, &nErr);
+ SetError(nErr);
+ }
+
+ if (!ValidCol(nField))
+ return NULL;
+
+ auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
+
+ if (pParam.get())
{
- SCCOL nField = nDBCol1;
- BOOL bFound = TRUE;
+ // An allowed missing field parameter sets the result field
+ // to any of the query fields, just to be able to return
+ // some cell from the iterator.
if ( rMissingField )
- ; // special case
- else if ( bByVal )
- {
- if ( nVal <= 0 || nVal > (nDBCol2 - nDBCol1 + 1) )
- bFound = FALSE;
- else
- nField = Min(nDBCol2, (SCCOL)(nDBCol1 + (SCCOL)nVal - 1));
- }
- else
+ nField = static_cast<SCCOL>(pParam->GetEntry(0).nField);
+ pParam->mnField = nField;
+
+ SCSIZE nCount = pParam->GetEntryCount();
+ for ( SCSIZE i=0; i < nCount; i++ )
{
- bFound = FALSE;
- String aCellStr;
- ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
- while (!bFound && (aLook.Col() <= nDBCol2))
- {
- ScBaseCell* pCell = GetCell( aLook );
- GetCellString( aCellStr, pCell );
- bFound = ScGlobal::GetpTransliteration()->isEqual( aCellStr, aStr );
- if (!bFound)
- aLook.IncCol();
- }
- nField = aLook.Col();
- }
- if (bFound)
- {
- rParam.nCol1 = nDBCol1;
- rParam.nRow1 = nDBRow1;
- rParam.nCol2 = nDBCol2;
- rParam.nRow2 = nDBRow2;
- rParam.nTab = nDBTab1;
- rParam.bHasHeader = TRUE;
- rParam.bByRow = TRUE;
- rParam.bInplace = TRUE;
- rParam.bCaseSens = FALSE;
- rParam.bRegExp = FALSE;
- rParam.bDuplicate = TRUE;
- if (pDok->CreateQueryParam(nQCol1, nQRow1, nQCol2, nQRow2, nQTab1, rParam))
- {
- // An allowed missing field parameter sets the result field
- // to any of the query fields, just to be able to return
- // some cell from the iterator.
- if ( rMissingField )
- nField = static_cast<SCCOL>(rParam.GetEntry(0).nField);
-
- rParam.nCol1 = nField;
- rParam.nCol2 = nField;
- rTab = nDBTab1;
- bRet = TRUE;
- SCSIZE nCount = rParam.GetEntryCount();
- for ( SCSIZE i=0; i < nCount; i++ )
- {
- ScQueryEntry& rEntry = rParam.GetEntry(i);
- if ( rEntry.bDoQuery )
- {
- sal_uInt32 nIndex = 0;
- rEntry.bQueryByString = !pFormatter->IsNumberFormat(
- *rEntry.pStr, nIndex, rEntry.nVal );
- if ( rEntry.bQueryByString && !rParam.bRegExp )
- rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
- }
- else
- break; // for
- }
+ ScQueryEntry& rEntry = pParam->GetEntry(i);
+ if ( rEntry.bDoQuery )
+ {
+ sal_uInt32 nIndex = 0;
+ rEntry.bQueryByString = !pFormatter->IsNumberFormat(
+ *rEntry.pStr, nIndex, rEntry.nVal );
+ if ( rEntry.bQueryByString && !pParam->bRegExp )
+ pParam->bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
}
+ else
+ break; // for
}
+ return pParam.release();
}
}
- return bRet;
+ return false;
}
void ScInterpreter::DBIterator( ScIterFunc eFunc )
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
- SCTAB nTab1;
double nErg = 0.0;
double fMem = 0.0;
BOOL bNull = TRUE;
ULONG nCount = 0;
- ScQueryParam aQueryParam;
BOOL bMissingField = FALSE;
- if ( GetDBParams( nTab1, aQueryParam, bMissingField) )
+ auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
+ if (pQueryParam.get())
{
- double nVal;
- USHORT nErr;
- ScQueryValueIterator aValIter(pDok, nTab1, aQueryParam);
- if ( aValIter.GetFirst(nVal, nErr) && !nErr )
+ ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
+ ScDBQueryDataIterator::Value aValue;
+ if ( aValIter.GetFirst(aValue) && !aValue.mnError )
{
switch( eFunc )
{
@@ -6029,24 +5997,24 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
{
case ifAVERAGE:
case ifSUM:
- if ( bNull && nVal != 0.0 )
+ if ( bNull && aValue.mfValue != 0.0 )
{
bNull = FALSE;
- fMem = nVal;
+ fMem = aValue.mfValue;
}
else
- nErg += nVal;
+ nErg += aValue.mfValue;
break;
- case ifSUMSQ: nErg += nVal * nVal; break;
- case ifPRODUCT: nErg *= nVal; break;
- case ifMAX: if( nVal > nErg ) nErg = nVal; break;
- case ifMIN: if( nVal < nErg ) nErg = nVal; break;
+ case ifSUMSQ: nErg += aValue.mfValue * aValue.mfValue; break;
+ case ifPRODUCT: nErg *= aValue.mfValue; break;
+ case ifMAX: if( aValue.mfValue > nErg ) nErg = aValue.mfValue; break;
+ case ifMIN: if( aValue.mfValue < nErg ) nErg = aValue.mfValue; break;
default: ; // nothing
}
}
- while ( aValIter.GetNext(nVal, nErr) && !nErr );
+ while ( aValIter.GetNext(aValue) && !aValue.mnError );
}
- SetError(nErr);
+ SetError(aValue.mnError);
}
else
SetError( errIllegalParameter);
@@ -6071,13 +6039,12 @@ void ScInterpreter::ScDBSum()
void ScInterpreter::ScDBCount()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount" );
- SCTAB nTab;
- ScQueryParam aQueryParam;
BOOL bMissingField = TRUE;
- if ( GetDBParams( nTab, aQueryParam, bMissingField) )
+ auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
+ if (pQueryParam.get())
{
ULONG nCount = 0;
- if ( bMissingField )
+ if ( bMissingField && pQueryParam->GetType() == ScDBQueryParamBase::INTERNAL )
{ // count all matching records
// TODO: currently the QueryIterators only return cell pointers of
// existing cells, so if a query matches an empty cell there's
@@ -6087,7 +6054,9 @@ void ScInterpreter::ScDBCount()
// have to live with it until we reimplement the iterators to also
// return empty cells, which would mean to adapt all callers of
// iterators.
- ScQueryCellIterator aCellIter( pDok, nTab, aQueryParam);
+ ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pQueryParam.get());
+ SCTAB nTab = p->nTab;
+ ScQueryCellIterator aCellIter( pDok, nTab, *p);
if ( aCellIter.GetFirst() )
{
do
@@ -6098,17 +6067,17 @@ void ScInterpreter::ScDBCount()
}
else
{ // count only matching records with a value in the "result" field
- double nVal;
- USHORT nErr = 0;
- ScQueryValueIterator aValIter( pDok, nTab, aQueryParam);
- if ( aValIter.GetFirst( nVal, nErr) && !nErr )
+ ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
+ ScDBQueryDataIterator::Value aValue;
+ if ( aValIter.GetFirst(aValue) && !aValue.mnError )
{
do
{
nCount++;
- } while ( aValIter.GetNext( nVal, nErr) && !nErr );
+ }
+ while ( aValIter.GetNext(aValue) && !aValue.mnError );
}
- SetError( nErr );
+ SetError(aValue.mnError);
}
PushDouble( nCount );
}
@@ -6120,21 +6089,24 @@ void ScInterpreter::ScDBCount()
void ScInterpreter::ScDBCount2()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount2" );
- SCTAB nTab;
- ScQueryParam aQueryParam;
BOOL bMissingField = TRUE;
- if (GetDBParams( nTab, aQueryParam, bMissingField))
+ auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
+ if (pQueryParam.get())
{
ULONG nCount = 0;
- ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
- if ( aCellIter.GetFirst() )
+ pQueryParam->mbSkipString = false;
+ ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
+ ScDBQueryDataIterator::Value aValue;
+ if ( aValIter.GetFirst(aValue) && !aValue.mnError )
{
do
{
nCount++;
- } while ( aCellIter.GetNext() );
+ }
+ while ( aValIter.GetNext(aValue) && !aValue.mnError );
}
- PushDouble(nCount);
+ SetError(aValue.mnError);
+ PushDouble( nCount );
}
else
PushIllegalParameter();
@@ -6178,25 +6150,23 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
rValCount = 0.0;
double fSum = 0.0;
- SCTAB nTab;
- ScQueryParam aQueryParam;
BOOL bMissingField = FALSE;
- if (GetDBParams( nTab, aQueryParam, bMissingField))
+ auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
+ if (pQueryParam.get())
{
- double fVal;
- USHORT nErr;
- ScQueryValueIterator aValIter(pDok, nTab, aQueryParam);
- if (aValIter.GetFirst(fVal, nErr) && !nErr)
+ ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
+ ScDBQueryDataIterator::Value aValue;
+ if (aValIter.GetFirst(aValue) && !aValue.mnError)
{
do
{
rValCount++;
- values.push_back(fVal);
- fSum += fVal;
+ values.push_back(aValue.mfValue);
+ fSum += aValue.mfValue;
}
- while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
+ while ((aValue.mnError == 0) && aValIter.GetNext(aValue));
}
- SetError(nErr);
+ SetError(aValue.mnError);
}
else
SetError( errIllegalParameter);
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 594e234c1..909ba0413 100755
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -68,15 +68,18 @@
#include "jumpmatrix.hxx"
#include "parclass.hxx"
#include "externalrefmgr.hxx"
+#include "doubleref.hxx"
#include <math.h>
#include <float.h>
#include <map>
#include <algorithm>
#include <functional>
+#include <memory>
using namespace com::sun::star;
using namespace formula;
+using ::std::auto_ptr;
#define ADDIN_MAXSTRLEN 256
@@ -1222,6 +1225,42 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
}
}
+ScDBRangeBase* ScInterpreter::PopDoubleRef()
+{
+ if (!sp)
+ {
+ SetError(errUnknownStackVariable);
+ return NULL;
+ }
+
+ --sp;
+ FormulaToken* p = pStack[sp];
+ switch (p->GetType())
+ {
+ case svError:
+ nGlobalError = p->GetError();
+ break;
+ case svDoubleRef:
+ {
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+ SCTAB nTab1, nTab2;
+ DoubleRefToVars(static_cast<ScToken*>(p),
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
+
+ return new ScDBInternalRange(pDok,
+ ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
+ }
+ case svMatrix:
+ {
+ ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
+ return new ScDBExternalRange(pDok, pMat);
+ }
+ default:
+ SetError( errIllegalParameter);
+ }
+ return NULL;
+}
void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
@@ -2055,78 +2094,37 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
void ScInterpreter::ScDBGet()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBGet" );
- SCTAB nTab;
- ScQueryParam aQueryParam;
BOOL bMissingField = FALSE;
- if (GetDBParams( nTab, aQueryParam, bMissingField))
+ auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
+ if (!pQueryParam.get())
{
- ScBaseCell* pCell;
- ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
- if ( (pCell = aCellIter.GetFirst()) != NULL )
- {
- if (aCellIter.GetNext())
- PushIllegalArgument();
- else
- {
- switch (pCell->GetCellType())
- {
- case CELLTYPE_VALUE:
- {
- double rValue = ((ScValueCell*)pCell)->GetValue();
- if ( bCalcAsShown )
- {
- ULONG nFormat;
- nFormat = aCellIter.GetNumberFormat();
- rValue = pDok->RoundValueAsShown( rValue, nFormat );
- }
- PushDouble(rValue);
- }
- break;
- case CELLTYPE_STRING:
- {
- String rString;
- ((ScStringCell*)pCell)->GetString(rString);
- PushString(rString);
- }
- break;
- case CELLTYPE_EDIT:
- {
- String rString;
- ((ScEditCell*)pCell)->GetString(rString);
- PushString(rString);
- }
- break;
- case CELLTYPE_FORMULA:
- {
- USHORT rErr = ((ScFormulaCell*)pCell)->GetErrCode();
- if (rErr)
- PushError(rErr);
- else if (((ScFormulaCell*)pCell)->IsValue())
- {
- double rValue = ((ScFormulaCell*)pCell)->GetValue();
- PushDouble(rValue);
- }
- else
- {
- String rString;
- ((ScFormulaCell*)pCell)->GetString(rString);
- PushString(rString);
- }
- }
- break;
- case CELLTYPE_NONE:
- case CELLTYPE_NOTE:
- default:
- PushIllegalArgument();
- break;
- }
- }
- }
- else
- PushNoValue();
+ // Failed to create query param.
+ PushIllegalParameter();
+ return;
}
+
+ pQueryParam->mbSkipString = false;
+ ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
+ ScDBQueryDataIterator::Value aValue;
+ if (!aValIter.GetFirst(aValue) || aValue.mnError)
+ {
+ // No match found.
+ PushNoValue();
+ return;
+ }
+
+ ScDBQueryDataIterator::Value aValNext;
+ if (aValIter.GetNext(aValNext) && !aValNext.mnError)
+ {
+ // There should be only one unique match.
+ PushIllegalArgument();
+ return;
+ }
+
+ if (aValue.mbIsNumber)
+ PushDouble(aValue.mfValue);
else
- PushIllegalParameter();
+ PushString(aValue.maString);
}
diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk
index 52d9bad7c..f3fe479e3 100644
--- a/sc/source/core/tool/makefile.mk
+++ b/sc/source/core/tool/makefile.mk
@@ -76,6 +76,7 @@ SLOFILES = \
$(SLO)$/detdata.obj \
$(SLO)$/detfunc.obj \
$(SLO)$/docoptio.obj \
+ $(SLO)$/doubleref.obj \
$(SLO)$/editutil.obj \
$(SLO)$/filtopt.obj \
$(SLO)$/formulaparserpool.obj \
@@ -95,6 +96,7 @@ SLOFILES = \
$(SLO)$/printopt.obj \
$(SLO)$/prnsave.obj \
$(SLO)$/progress.obj \
+ $(SLO)$/queryparam.obj \
$(SLO)$/rangelst.obj \
$(SLO)$/rangenam.obj \
$(SLO)$/rangeseq.obj \
@@ -122,6 +124,7 @@ EXCEPTIONSFILES= \
$(SLO)$/chartlock.obj \
$(SLO)$/chgtrack.obj \
$(SLO)$/compiler.obj \
+ $(SLO)$/doubleref.obj \
$(SLO)$/formulaparserpool.obj \
$(SLO)$/interpr1.obj \
$(SLO)$/interpr2.obj \
@@ -130,6 +133,7 @@ EXCEPTIONSFILES= \
$(SLO)$/interpr5.obj \
$(SLO)$/lookupcache.obj \
$(SLO)$/prnsave.obj \
+ $(SLO)$/queryparam.obj \
$(SLO)$/reftokenhelper.obj \
$(SLO)$/token.obj
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
new file mode 100644
index 000000000..b97558df1
--- /dev/null
+++ b/sc/source/core/tool/queryparam.cxx
@@ -0,0 +1,365 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interpr4.cxx,v $
+ * $Revision: 1.57.92.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "queryparam.hxx"
+
+using ::std::vector;
+
+// ============================================================================
+
+ScQueryParamBase::ScQueryParamBase()
+{
+ Resize( MAXQUERY );
+ for (USHORT i=0; i<MAXQUERY; i++)
+ maEntries[i].Clear();
+}
+
+ScQueryParamBase::ScQueryParamBase(const ScQueryParamBase& r) :
+ bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
+ bRegExp(r.bRegExp), bDuplicate(r.bDuplicate), bMixedComparison(r.bMixedComparison),
+ maEntries(r.maEntries)
+{
+}
+
+ScQueryParamBase::~ScQueryParamBase()
+{
+}
+
+SCSIZE ScQueryParamBase::GetEntryCount() const
+{
+ return maEntries.size();
+}
+
+ScQueryEntry& ScQueryParamBase::GetEntry(SCSIZE n) const
+{
+ return maEntries[n];
+}
+
+void ScQueryParamBase::Resize(SCSIZE nNew)
+{
+ if ( nNew < MAXQUERY )
+ nNew = MAXQUERY; // nie weniger als MAXQUERY
+
+ vector<ScQueryEntry> aNewEntries(nNew);
+ SCSIZE nCopy = ::std::min(maEntries.size(), nNew);
+ for (SCSIZE i=0; i<nCopy; i++)
+ aNewEntries[i] = maEntries[i];
+
+ maEntries.swap(aNewEntries);
+}
+
+void ScQueryParamBase::DeleteQuery( SCSIZE nPos )
+{
+ if (nPos >= maEntries.size())
+ return;
+
+ size_t n = maEntries.size();
+ vector<ScQueryEntry> aNewEntries;
+ aNewEntries.reserve(n);
+ for (size_t i = 0; i < n; ++i)
+ if (i != nPos)
+ aNewEntries.push_back(maEntries[i]);
+
+ // Don't forget to append an empty entry to make up for the removed one.
+ // The size of the entries is not supposed to change.
+ aNewEntries.push_back(ScQueryEntry());
+
+ maEntries.swap(aNewEntries);
+}
+
+void ScQueryParamBase::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
+{
+ if (aCellStr.Len() > 0)
+ {
+ if ( nIndex >= maEntries.size() )
+ Resize( nIndex+1 );
+
+ ScQueryEntry& rEntry = GetEntry(nIndex);
+
+ rEntry.bDoQuery = TRUE;
+ // Operatoren herausfiltern
+ if (aCellStr.GetChar(0) == '<')
+ {
+ if (aCellStr.GetChar(1) == '>')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_NOT_EQUAL;
+ }
+ else if (aCellStr.GetChar(1) == '=')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_LESS_EQUAL;
+ }
+ else
+ {
+ *rEntry.pStr = aCellStr.Copy(1);
+ rEntry.eOp = SC_LESS;
+ }
+ }
+ else if (aCellStr.GetChar(0) == '>')
+ {
+ if (aCellStr.GetChar(1) == '=')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_GREATER_EQUAL;
+ }
+ else
+ {
+ *rEntry.pStr = aCellStr.Copy(1);
+ rEntry.eOp = SC_GREATER;
+ }
+ }
+ else
+ {
+ if (aCellStr.GetChar(0) == '=')
+ *rEntry.pStr = aCellStr.Copy(1);
+ else
+ *rEntry.pStr = aCellStr;
+ rEntry.eOp = SC_EQUAL;
+ }
+ }
+}
+
+// ============================================================================
+
+ScQueryParamTable::ScQueryParamTable()
+{
+}
+
+ScQueryParamTable::ScQueryParamTable(const ScQueryParamTable& r) :
+ nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab)
+{
+}
+
+ScQueryParamTable::~ScQueryParamTable()
+{
+}
+
+// ============================================================================
+
+ScQueryParam::ScQueryParam() :
+ ScQueryParamBase(),
+ ScQueryParamTable()
+{
+ Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
+ ScQueryParamBase(r),
+ ScQueryParamTable(r),
+ bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
+{
+}
+
+ScQueryParam::ScQueryParam( const ScDBQueryParamInternal& r ) :
+ ScQueryParamBase(r),
+ ScQueryParamTable(r),
+ bDestPers(true),
+ nDestTab(0),
+ nDestCol(0),
+ nDestRow(0)
+{
+}
+
+
+//------------------------------------------------------------------------
+
+ScQueryParam::~ScQueryParam()
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::Clear()
+{
+ nCol1=nCol2 = 0;
+ nRow1=nRow2 = 0;
+ nTab = SCTAB_MAX;
+ bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
+ bInplace = bByRow = bDuplicate = TRUE;
+
+ Resize( MAXQUERY );
+ for (USHORT i=0; i<MAXQUERY; i++)
+ maEntries[i].Clear();
+
+ ClearDestParams();
+}
+
+void ScQueryParam::ClearDestParams()
+{
+ bDestPers = true;
+ nDestTab = 0;
+ nDestCol = 0;
+ nDestRow = 0;
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
+{
+ nCol1 = r.nCol1;
+ nRow1 = r.nRow1;
+ nCol2 = r.nCol2;
+ nRow2 = r.nRow2;
+ nTab = r.nTab;
+ nDestTab = r.nDestTab;
+ nDestCol = r.nDestCol;
+ nDestRow = r.nDestRow;
+ bHasHeader = r.bHasHeader;
+ bInplace = r.bInplace;
+ bCaseSens = r.bCaseSens;
+ bRegExp = r.bRegExp;
+ bMixedComparison = r.bMixedComparison;
+ bDuplicate = r.bDuplicate;
+ bByRow = r.bByRow;
+ bDestPers = r.bDestPers;
+
+ maEntries = r.maEntries;
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
+{
+ BOOL bEqual = FALSE;
+
+ // Anzahl der Queries gleich?
+ SCSIZE nUsed = 0;
+ SCSIZE nOtherUsed = 0;
+ SCSIZE nEntryCount = GetEntryCount();
+ SCSIZE nOtherEntryCount = rOther.GetEntryCount();
+
+ while ( nUsed<nEntryCount && maEntries[nUsed].bDoQuery ) ++nUsed;
+ while ( nOtherUsed<nOtherEntryCount && rOther.maEntries[nOtherUsed].bDoQuery )
+ ++nOtherUsed;
+
+ if ( (nUsed == nOtherUsed)
+ && (nCol1 == rOther.nCol1)
+ && (nRow1 == rOther.nRow1)
+ && (nCol2 == rOther.nCol2)
+ && (nRow2 == rOther.nRow2)
+ && (nTab == rOther.nTab)
+ && (bHasHeader == rOther.bHasHeader)
+ && (bByRow == rOther.bByRow)
+ && (bInplace == rOther.bInplace)
+ && (bCaseSens == rOther.bCaseSens)
+ && (bRegExp == rOther.bRegExp)
+ && (bMixedComparison == rOther.bMixedComparison)
+ && (bDuplicate == rOther.bDuplicate)
+ && (bDestPers == rOther.bDestPers)
+ && (nDestTab == rOther.nDestTab)
+ && (nDestCol == rOther.nDestCol)
+ && (nDestRow == rOther.nDestRow) )
+ {
+ bEqual = TRUE;
+ for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
+ bEqual = maEntries[i] == rOther.maEntries[i];
+ }
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::MoveToDest()
+{
+ if (!bInplace)
+ {
+ SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
+ SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
+ SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
+
+ nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
+ nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
+ nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
+ nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
+ nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
+ size_t n = maEntries.size();
+ for (size_t i=0; i<n; i++)
+ maEntries[i].nField += nDifX;
+
+ bInplace = TRUE;
+ }
+ else
+ {
+ DBG_ERROR("MoveToDest, bInplace == TRUE");
+ }
+}
+
+// ============================================================================
+
+ScDBQueryParamBase::ScDBQueryParamBase(DataType eType) :
+ ScQueryParamBase(),
+ mnField(-1),
+ mbSkipString(true),
+ meType(eType)
+{
+}
+
+ScDBQueryParamBase::~ScDBQueryParamBase()
+{
+}
+
+ScDBQueryParamBase::DataType ScDBQueryParamBase::GetType() const
+{
+ return meType;
+}
+
+// ============================================================================
+
+ScDBQueryParamInternal::ScDBQueryParamInternal() :
+ ScDBQueryParamBase(ScDBQueryParamBase::INTERNAL),
+ ScQueryParamTable()
+{
+}
+
+ScDBQueryParamInternal::~ScDBQueryParamInternal()
+{
+}
+
+// ============================================================================
+
+ScDBQueryParamMatrix::ScDBQueryParamMatrix() :
+ ScDBQueryParamBase(ScDBQueryParamBase::MATRIX)
+{
+}
+
+ScDBQueryParamMatrix::~ScDBQueryParamMatrix()
+{
+}
+
diff --git a/sc/source/filter/excel/colrowst.cxx b/sc/source/filter/excel/colrowst.cxx
index 174ab2032..199dad8f7 100644
--- a/sc/source/filter/excel/colrowst.cxx
+++ b/sc/source/filter/excel/colrowst.cxx
@@ -43,6 +43,7 @@
#include "xltable.hxx"
#include "xistream.hxx"
#include "xistyle.hxx"
+#include "queryparam.hxx"
// for filter manager
#include "excimp8.hxx"
diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx
index 2b8a9433e..83287b0ae 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -235,7 +235,7 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList )
Add( new XclExpFilePass( GetRoot() ) );
Add( new XclExpInterfaceHdr( nCodePage ) );
Add( new XclExpUInt16Record( EXC_ID_MMS, 0 ) );
- Add( new XclExpEmptyRecord( EXC_ID_INTERFACEEND ) );
+ Add( new XclExpInterfaceEnd );
Add( new XclExpWriteAccess );
}
diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx
index e5c97d1a9..3767582c8 100644
--- a/sc/source/filter/excel/xecontent.cxx
+++ b/sc/source/filter/excel/xecontent.cxx
@@ -748,19 +748,19 @@ void XclExpCFImpl::WriteBody( XclExpStream& rStrm )
// font used flag for underline -> 0 = used, 1 = default
sal_uInt32 nFontFlags3 = mbUnderlUsed ? 0 : EXC_CF_FONT_UNDERL;
- rStrm.WriteZeroBytes( 64 );
+ rStrm.WriteZeroBytesToRecord( 64 );
rStrm << nHeight
<< nStyle
<< maFontData.mnWeight
<< EXC_FONTESC_NONE
<< maFontData.mnUnderline;
- rStrm.WriteZeroBytes( 3 );
+ rStrm.WriteZeroBytesToRecord( 3 );
rStrm << nColor
<< sal_uInt32( 0 )
<< nFontFlags1
<< EXC_CF_FONT_ESCAPEM // escapement never used -> set the flag
<< nFontFlags3;
- rStrm.WriteZeroBytes( 16 );
+ rStrm.WriteZeroBytesToRecord( 16 );
rStrm << sal_uInt16( 1 ); // must be 1
}
diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index 1dd1bbc74..6f5b0eb4a 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -259,6 +259,17 @@ void XclExpStream::WriteZeroBytes( sal_Size nBytes )
WriteRawZeroBytes( nBytes );
}
+void XclExpStream::WriteZeroBytesToRecord( sal_Size nBytes )
+{
+ if (!mbInRec)
+ // not in record.
+ return;
+
+ sal_uInt8 nZero = 0;
+ for (sal_Size i = 0; i < nBytes; ++i)
+ *this << nZero;
+}
+
sal_Size XclExpStream::CopyFromStream( SvStream& rInStrm, sal_Size nBytes )
{
sal_Size nStrmPos = rInStrm.Tell();
diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx
index dc542a1c1..7030bb568 100644
--- a/sc/source/filter/excel/xichart.cxx
+++ b/sc/source/filter/excel/xichart.cxx
@@ -34,6 +34,7 @@
#include "xichart.hxx"
#include <algorithm>
+#include <memory>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/drawing/Direction3D.hpp>
@@ -72,6 +73,8 @@
#include "tokenarray.hxx"
#include "token.hxx"
#include "compiler.hxx"
+#include "reftokenhelper.hxx"
+#include "chartlis.hxx"
#include "fprogressbar.hxx"
#include "xltracer.hxx"
#include "xistream.hxx"
@@ -123,6 +126,8 @@ using ::com::sun::star::chart2::data::XDataSequence;
using ::formula::FormulaToken;
using ::formula::StackVar;
+using ::std::vector;
+
// Helpers ====================================================================
namespace {
@@ -791,6 +796,22 @@ Sequence< Reference< XFormattedString > > XclImpChSourceLink::CreateStringSequen
return ScfApiHelper::VectorToSequence( aStringVec );
}
+void XclImpChSourceLink::FillSourceLink(vector<ScSharedTokenRef>& rTokens) const
+{
+ if (!mxTokenArray.is())
+ // no links to fill.
+ return;
+
+ mxTokenArray->Reset();
+ for (FormulaToken* p = mxTokenArray->First(); p; p = mxTokenArray->Next())
+ {
+ ScSharedTokenRef pToken(static_cast<ScToken*>(p->Clone()));
+ if (ScRefTokenHelper::isRef(pToken))
+ // This is a reference token. Store it.
+ ScRefTokenHelper::join(rTokens, pToken);
+ }
+}
+
// Text =======================================================================
XclImpChFontBase::~XclImpChFontBase()
@@ -1837,6 +1858,18 @@ Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
return xDataSeries;
}
+void XclImpChSeries::FillAllSourceLinks(vector<ScSharedTokenRef>& rTokens) const
+{
+ if (mxValueLink.is())
+ mxValueLink->FillSourceLink(rTokens);
+ if (mxCategLink.is())
+ mxCategLink->FillSourceLink(rTokens);
+ if (mxTitleLink.is())
+ mxTitleLink->FillSourceLink(rTokens);
+ if (mxBubbleLink.is())
+ mxBubbleLink->FillSourceLink(rTokens);
+}
+
void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
{
XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
@@ -3483,7 +3516,7 @@ XclImpChTextRef XclImpChChart::GetDefaultText( XclChTextType eTextType ) const
return maDefTexts.get( nDefTextId );
}
-void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress ) const
+void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressBar& rProgress, const OUString& rObjName ) const
{
// initialize conversion (locks the model to suppress any internal updates)
InitConversion( xChartDoc );
@@ -3526,6 +3559,28 @@ void XclImpChChart::Convert( Reference< XChartDocument > xChartDoc, ScfProgressB
// unlock the model
FinishConversion( rProgress );
+
+ ScDocument* pDoc = &GetRoot().GetDoc();
+ ScChartListenerCollection* pChartCollection = pDoc->GetChartListenerCollection();
+ if (pChartCollection)
+ {
+ // Now, start listening to this chart.
+ ::std::auto_ptr< vector<ScSharedTokenRef> > pRefTokens(new vector<ScSharedTokenRef>);
+ for (XclImpChSeriesVec::const_iterator itr = maSeries.begin(), itrEnd = maSeries.end(); itr != itrEnd; ++itr)
+ {
+ const XclImpChSeriesRef& rSeries = *itr;
+ rSeries->FillAllSourceLinks(*pRefTokens);
+ }
+ if (!pRefTokens->empty())
+ {
+ ::std::auto_ptr<ScChartListener> pListener(
+ new ScChartListener(rObjName, pDoc, pRefTokens.release()));
+ pListener->SetUsed(true);
+ pListener->StartListeningTo();
+ pChartCollection->Insert(pListener.release());
+
+ }
+ }
}
void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
@@ -3751,11 +3806,11 @@ sal_Size XclImpChart::GetProgressSize() const
return mxChartData.is() ? mxChartData->GetProgressSize() : 0;
}
-void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress ) const
+void XclImpChart::Convert( Reference< XModel > xModel, ScfProgressBar& rProgress, const OUString& rObjName ) const
{
Reference< XChartDocument > xChartDoc( xModel, UNO_QUERY );
if( mxChartData.is() && xChartDoc.is() )
- mxChartData->Convert( xChartDoc, rProgress );
+ mxChartData->Convert( xChartDoc, rProgress, rObjName );
}
void XclImpChart::ReadChChart( XclImpStream& rStrm )
diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx
index 5f1e8c547..57269a318 100644
--- a/sc/source/filter/excel/xiescher.cxx
+++ b/sc/source/filter/excel/xiescher.cxx
@@ -105,6 +105,7 @@
#include "convuno.hxx"
#include "postit.hxx"
#include "globstr.hrc"
+#include "chartlis.hxx"
#include "fprogressbar.hxx"
#include "xltracer.hxx"
@@ -1662,7 +1663,7 @@ SdrObject* XclImpChartObj::DoCreateSdrObj( const Rectangle& rAnchorRect, ScfProg
if( svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) )
{
Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY );
- mxChart->Convert( xModel, rProgress );
+ mxChart->Convert( xModel, rProgress, aEmbObjName );
Reference< XEmbedPersist > xPers( xEmbObj, UNO_QUERY );
if( xPers.is() )
@@ -3838,6 +3839,9 @@ void XclImpObjectManager::ConvertObjects()
rDffManager.ProcessDrawing( maDffStrm, *aPIt );
}
}
+ ScChartListenerCollection* pChartListeners = GetDoc().GetChartListenerCollection();
+ if (pChartListeners && pChartListeners->GetCount())
+ pChartListeners->SetDirty();
}
String XclImpObjectManager::GetDefaultObjName( const XclImpDrawObjBase& rDrawObj ) const
diff --git a/sc/source/filter/inc/excimp8.hxx b/sc/source/filter/inc/excimp8.hxx
index c3b369365..3bc83b9cc 100644
--- a/sc/source/filter/inc/excimp8.hxx
+++ b/sc/source/filter/inc/excimp8.hxx
@@ -37,6 +37,7 @@
#include "excscen.hxx"
#include "excdefs.hxx"
#include "ftools.hxx"
+#include "queryparam.hxx"
class SotStorage;
diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx
index b94d26124..f6a73ba2a 100644
--- a/sc/source/filter/inc/xcl97rec.hxx
+++ b/sc/source/filter/inc/xcl97rec.hxx
@@ -570,6 +570,19 @@ private:
// ============================================================================
+/** End of User Interface Records */
+class XclExpInterfaceEnd : public XclExpRecord
+{
+public:
+ explicit XclExpInterfaceEnd();
+ virtual ~XclExpInterfaceEnd();
+
+private:
+ virtual void WriteBody( XclExpStream& rStrm );
+};
+
+// ============================================================================
+
/** Write Access User Name - This record contains the user name, which is
the name you type when you install Excel. */
class XclExpWriteAccess : public XclExpRecord
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index 95d172baf..e7a2da370 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -126,6 +126,9 @@ public:
sal_Size Write( const void* pData, sal_Size nBytes );
/** Writes a sequence of nBytes zero bytes (respects slice setting). */
void WriteZeroBytes( sal_Size nBytes );
+
+ void WriteZeroBytesToRecord( sal_Size nBytes );
+
/** Copies nBytes bytes from current position of the stream rInStrm.
@descr Omitting the second parameter means: read to end of stream. */
sal_Size CopyFromStream( SvStream& rInStrm, sal_Size nBytes = STREAM_SEEK_TO_END );
diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx
index e09530083..34536a0da 100644
--- a/sc/source/filter/inc/xichart.hxx
+++ b/sc/source/filter/inc/xichart.hxx
@@ -39,6 +39,7 @@
#include <svl/itemset.hxx>
#include "rangelst.hxx"
+#include "token.hxx"
#include "xlchart.hxx"
#include "xlstyle.hxx"
#include "xistring.hxx"
@@ -403,6 +404,8 @@ public:
XFormattedStringSeq CreateStringSequence( const XclImpChRoot& rRoot,
sal_uInt16 nLeadFontIdx, const Color& rLeadFontColor ) const;
+ void FillSourceLink(::std::vector<ScSharedTokenRef>& rTokens) const;
+
private:
XclChSourceLink maData; /// Contents of the CHSOURCELINK record.
XclImpStringRef mxString; /// Text data (CHSTRING record).
@@ -811,6 +814,8 @@ public:
/** Creates a data series object with initialized source links. */
XDataSeriesRef CreateDataSeries() const;
+ void FillAllSourceLinks(::std::vector<ScSharedTokenRef>& rTokens) const;
+
private:
/** Reads a CHSOURCELINK record. */
void ReadChSourceLink( XclImpStream& rStrm );
@@ -1353,7 +1358,7 @@ public:
inline sal_Size GetProgressSize() const { return 2 * EXC_CHART_PROGRESS_SIZE; }
/** Converts and writes all properties to the passed chart. */
- void Convert( XChartDocRef xChartDoc, ScfProgressBar& rProgress ) const;
+ void Convert( XChartDocRef xChartDoc, ScfProgressBar& rProgress, const ::rtl::OUString& rObjName ) const;
private:
/** Reads a CHSERIES group (data series source and formatting). */
@@ -1421,7 +1426,7 @@ public:
inline bool IsPivotChart() const { return mbIsPivotChart; }
/** Creates the chart object in the passed component. */
- void Convert( XModelRef xModel, ScfProgressBar& rProgress ) const;
+ void Convert( XModelRef xModel, ScfProgressBar& rProgress, const ::rtl::OUString& rObjName ) const;
private:
/** Reads the CHCHART group (entire chart data). */
diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx
index f15ef9667..722881266 100644
--- a/sc/source/filter/xcl97/xcl97rec.cxx
+++ b/sc/source/filter/xcl97/xcl97rec.cxx
@@ -1459,6 +1459,19 @@ void XclExpInterfaceHdr::WriteBody( XclExpStream& rStrm )
// ============================================================================
+XclExpInterfaceEnd::XclExpInterfaceEnd() :
+ XclExpRecord(0x00E2, 0) {}
+
+XclExpInterfaceEnd::~XclExpInterfaceEnd() {}
+
+void XclExpInterfaceEnd::WriteBody( XclExpStream& rStrm )
+{
+ // Don't forget to re-enable encryption.
+ rStrm.EnableEncryption();
+}
+
+// ============================================================================
+
XclExpWriteAccess::XclExpWriteAccess() :
XclExpRecord(0x005C, 112)
{
diff --git a/sc/source/filter/xml/XMLExportDataPilot.hxx b/sc/source/filter/xml/XMLExportDataPilot.hxx
index a3f6cf8d7..46a2bb0b0 100644
--- a/sc/source/filter/xml/XMLExportDataPilot.hxx
+++ b/sc/source/filter/xml/XMLExportDataPilot.hxx
@@ -44,6 +44,7 @@ class ScDPDimensionSaveData;
class ScDPSaveGroupDimension;
class ScDPSaveNumGroupDimension;
struct ScDPNumGroupInfo;
+struct ScQueryParam;
class ScXMLExportDataPilot
{
diff --git a/sc/source/filter/xml/xmldpimp.hxx b/sc/source/filter/xml/xmldpimp.hxx
index 6d3bc6236..665fe80bd 100644
--- a/sc/source/filter/xml/xmldpimp.hxx
+++ b/sc/source/filter/xml/xmldpimp.hxx
@@ -40,6 +40,7 @@
#include "global.hxx"
#include "dpobject.hxx"
#include "dpsave.hxx"
+#include "queryparam.hxx"
#include <hash_set>
diff --git a/sc/source/ui/dbgui/foptmgr.cxx b/sc/source/ui/dbgui/foptmgr.cxx
index ee5f03954..a425836e7 100644
--- a/sc/source/ui/dbgui/foptmgr.cxx
+++ b/sc/source/ui/dbgui/foptmgr.cxx
@@ -45,6 +45,7 @@
#include "dbcolect.hxx"
#include "viewdata.hxx"
#include "document.hxx"
+#include "queryparam.hxx"
#define _FOPTMGR_CXX
#include "foptmgr.hxx"
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 8573ef309..6d82bb000 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -1061,8 +1061,11 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
else
{
// The source document has changed.
+ ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell();
+ ScDocShellModificator aMod(*pDocShell);
pMgr->switchSrcFile(mnFileId, aFile, aFilter);
maFilterName = aFilter;
+ aMod.SetDocumentModified();
}
}
diff --git a/sc/source/ui/inc/pfiltdlg.hxx b/sc/source/ui/inc/pfiltdlg.hxx
index a9ba0d10a..b3831737c 100644
--- a/sc/source/ui/inc/pfiltdlg.hxx
+++ b/sc/source/ui/inc/pfiltdlg.hxx
@@ -53,8 +53,8 @@
#ifndef _COMBOBOX_HXX //autogen
#include <vcl/combobox.hxx>
#endif
-#include "global.hxx" // -> ScQueryParam
#include "address.hxx"
+#include "queryparam.hxx"
//------------------------------------------------------------------
diff --git a/sc/source/ui/inc/uiitems.hxx b/sc/source/ui/inc/uiitems.hxx
index 3a9cb91c6..1e73bb235 100644
--- a/sc/source/ui/inc/uiitems.hxx
+++ b/sc/source/ui/inc/uiitems.hxx
@@ -34,6 +34,7 @@
#include "scdllapi.h"
#include "conditio.hxx"
#include "sortparam.hxx"
+#include "queryparam.hxx"
#include "paramisc.hxx"
#include <svl/poolitem.hxx>
diff --git a/sc/source/ui/inc/undodat.hxx b/sc/source/ui/inc/undodat.hxx
index fb42d818a..ad46cb7f3 100644
--- a/sc/source/ui/inc/undodat.hxx
+++ b/sc/source/ui/inc/undodat.hxx
@@ -36,6 +36,7 @@
#include "rangelst.hxx" // ScRangeListRef
#include "markdata.hxx"
#include "sortparam.hxx"
+#include "queryparam.hxx"
#include "pivot.hxx"
class ScDocShell;
diff --git a/sc/source/ui/undo/undobase.cxx b/sc/source/ui/undo/undobase.cxx
index f20abdb07..8b59f801b 100644
--- a/sc/source/ui/undo/undobase.cxx
+++ b/sc/source/ui/undo/undobase.cxx
@@ -45,6 +45,7 @@
#include "undodraw.hxx"
#include "dbcolect.hxx"
#include "attrib.hxx"
+#include "queryparam.hxx"
#include "globstr.hrc"
// STATIC DATA -----------------------------------------------------------
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx
index 51f7b806f..6435a71f8 100644
--- a/sc/source/ui/unoobj/chart2uno.cxx
+++ b/sc/source/ui/unoobj/chart2uno.cxx
@@ -2935,6 +2935,9 @@ void ScChart2DataSequence::BuildDataCache()
::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
for (;itr != itrEnd; ++itr, ++pArr)
*pArr = *itr;
+
+ // Clear the data series cache when the array is re-built.
+ m_aMixedDataCache.realloc(0);
}
void ScChart2DataSequence::RebuildDataCache()
@@ -3127,7 +3130,6 @@ void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint
if ( m_bGotDataChangedHint && m_pDocument )
{
m_aDataArray.clear();
- m_aDataArray.clear();
lang::EventObject aEvent;
aEvent.Source.set((cppu::OWeakObject*)this);
@@ -3302,19 +3304,24 @@ uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
throw uno::RuntimeException();
BuildDataCache();
- sal_Int32 nCount = m_aDataArray.size();
- uno::Sequence<uno::Any> aSeq(nCount);
- uno::Any* pArr = aSeq.getArray();
- ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
- for (; itr != itrEnd; ++itr, ++pArr)
+
+ if (!m_aMixedDataCache.getLength())
{
- if (itr->mbIsValue)
- *pArr <<= itr->mfValue;
- else
- *pArr <<= itr->maString;
- }
+ // Build a cache for the 1st time...
- return aSeq;
+ sal_Int32 nCount = m_aDataArray.size();
+ m_aMixedDataCache.realloc(nCount);
+ uno::Any* pArr = m_aMixedDataCache.getArray();
+ ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
+ for (; itr != itrEnd; ++itr, ++pArr)
+ {
+ if (itr->mbIsValue)
+ *pArr <<= itr->mfValue;
+ else
+ *pArr <<= itr->maString;
+ }
+ }
+ return m_aMixedDataCache;
}
// XNumericalDataSequence --------------------------------------------------
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 5cf7c27ff..cf7779ead 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -74,6 +74,7 @@
#include "inputopt.hxx"
#include "fillinfo.hxx"
#include "dpcontrol.hxx"
+#include "queryparam.hxx"
#include "sc.hrc"
#include <vcl/virdev.hxx>