[ooo-build-commit] patches/dev300

Kohei Yoshida kohei at kemper.freedesktop.org
Thu Sep 17 06:31:59 PDT 2009


 patches/dev300/apply                          |    5 
 patches/dev300/cws-kohei03-sc-m57.diff        | 3426 ++++++++++++++++++++++++++
 patches/dev300/cws-kohei03-sc.diff            |    2 
 patches/dev300/sc-dbrange-dynamic-resize.diff |  995 -------
 4 files changed, 3531 insertions(+), 897 deletions(-)

New commits:
commit e0dbbed42627ae2fbadaae712db79d1ad39c49e0
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Thu Sep 17 09:24:48 2009 -0400

    Patch massaging for dev300-m58.
    
    * patches/dev300/apply:
    * patches/dev300/cws-kohei03-sc-m57.diff:
    * patches/dev300/cws-kohei03-sc.diff: branched this patch
      for dev300-m58.
    
    * patches/dev300/sc-dbrange-dynamic-resize.diff: somehow I had
      managed to screw this patch in my previous commit.  Hopefully
      fixed this.

diff --git a/patches/dev300/apply b/patches/dev300/apply
index dd16720..44a16b7 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -193,8 +193,13 @@ cws-koheicsvimport-sc.diff,        kohei
 
 # kohei03 cws
 cws-kohei03-chart2.diff, kohei
+
+[ CWSBackports >= dev300-m58 ]
 cws-kohei03-sc.diff,     kohei
 
+[ CWSBackports < dev300-m58 ]
+cws-kohei03-sc-m57.diff, kohei
+
 [ LinuxOnly ]
 # Don't stat tons of config files we don't need to read on startup
 speed-configmgr.diff, i#56783, michael
diff --git a/patches/dev300/cws-kohei03-sc-m57.diff b/patches/dev300/cws-kohei03-sc-m57.diff
new file mode 100644
index 0000000..b008d67
--- /dev/null
+++ b/patches/dev300/cws-kohei03-sc-m57.diff
@@ -0,0 +1,3426 @@
+diff --git sc/inc/chart2uno.hxx sc/inc/chart2uno.hxx
+index 93afe64..46b7ff0 100644
+--- sc/inc/chart2uno.hxx
++++ 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 sc/inc/chartlis.hxx sc/inc/chartlis.hxx
+index a8a97d3..51ac644 100644
+--- sc/inc/chartlis.hxx
++++ 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
+diff --git sc/inc/column.hxx sc/inc/column.hxx
+index e4c7ed4..983ca1f 100644
+--- sc/inc/column.hxx
++++ 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 sc/inc/datauno.hxx sc/inc/datauno.hxx
+index 3103875..44e0336 100644
+--- sc/inc/datauno.hxx
++++ sc/inc/datauno.hxx
+@@ -32,6 +32,8 @@
+ #define SC_DATAUNO_HXX
+ 
+ #include "global.hxx"
++#include "queryparam.hxx"
++
+ #include <svtools/itemprop.hxx>
+ #include <svtools/lstner.hxx>
+ #include <com/sun/star/sheet/TableFilterField.hpp>
+diff --git sc/inc/dociter.hxx sc/inc/dociter.hxx
+index d5d4235..350c611 100644
+--- sc/inc/dociter.hxx
++++ 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,91 @@ 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;
++    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 sc/inc/document.hxx sc/inc/document.hxx
+index 240765d..d01ee71 100644
+--- sc/inc/document.hxx
++++ sc/inc/document.hxx
+@@ -227,7 +227,7 @@ class ScDocument
+ {
+ friend class ScDocumentIterator;
+ friend class ScValueIterator;
+-friend class ScQueryValueIterator;
++friend class ScDBQueryDataIterator;
+ friend class ScCellIterator;
+ friend class ScQueryCellIterator;
+ friend class ScHorizontalCellIterator;
+diff --git sc/inc/dpcachetable.hxx sc/inc/dpcachetable.hxx
+index 7a60535..0a22fb0 100644
+--- sc/inc/dpcachetable.hxx
++++ sc/inc/dpcachetable.hxx
+@@ -60,6 +60,7 @@ class ScDPDimension;
+ class ScDPCollection;
+ struct ScDPCacheCell;
+ struct ScDPItemData;
++struct ScQueryParam;
+ class Date;
+ 
+ // ----------------------------------------------------------------------------
+diff --git sc/inc/dpshttab.hxx sc/inc/dpshttab.hxx
+index ede4933..8483ca2 100644
+--- sc/inc/dpshttab.hxx
++++ sc/inc/dpshttab.hxx
+@@ -35,6 +35,7 @@
+ #include "global.hxx"
+ #include "address.hxx"
+ #include "scdllapi.h"
++#include "queryparam.hxx"
+ 
+ #include <vector>
+ 
+diff --git sc/inc/global.hxx sc/inc/global.hxx
+index 57a6ff1..b401cb9 100644
+--- sc/inc/global.hxx
++++ 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 sc/inc/queryparam.hxx sc/inc/queryparam.hxx
+new file mode 100644
+index 0000000..bc50237
+--- /dev/null
++++ 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 sc/inc/reftokenhelper.hxx sc/inc/reftokenhelper.hxx
+index d7b335f..99a5998 100644
+--- sc/inc/reftokenhelper.hxx
++++ 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 sc/inc/table.hxx sc/inc/table.hxx
+index 8194e25..589d73f 100644
+--- sc/inc/table.hxx
++++ sc/inc/table.hxx
+@@ -161,7 +161,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;
+diff --git sc/source/core/data/autonamecache.cxx sc/source/core/data/autonamecache.cxx
+index ea41e3e..329e7f4 100644
+--- sc/source/core/data/autonamecache.cxx
++++ sc/source/core/data/autonamecache.cxx
+@@ -40,6 +40,7 @@
+ #include "autonamecache.hxx"
+ #include "dociter.hxx"
+ #include "cell.hxx"
++#include "queryparam.hxx"
+ 
+ // -----------------------------------------------------------------------
+ 
+diff --git sc/source/core/data/cell.cxx sc/source/core/data/cell.cxx
+index 2ae9972..09da3d6 100644
+--- sc/source/core/data/cell.cxx
++++ sc/source/core/data/cell.cxx
+@@ -1851,8 +1851,7 @@ void ScFormulaCell::SetDirty()
+ 
+ void ScFormulaCell::SetDirtyAfterLoad()
+ {
+-    bDirty = TRUE;
+-    if ( !pDocument->GetHardRecalcState() )
++    if ( bDirty && !pDocument->GetHardRecalcState() )
+         pDocument->PutInFormulaTree( this );
+ }
+ 
+diff --git sc/source/core/data/dociter.cxx sc/source/core/data/dociter.cxx
+index f7f836e..031b70a 100644
+--- sc/source/core/data/dociter.cxx
++++ 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, rStr.getLength());
++}
++
++}
++
+ ScDocumentIterator::ScDocumentIterator( ScDocument* pDocument,
+                             SCTAB nStartTable, SCTAB nEndTable ) :
+     pDoc( pDocument ),
+@@ -482,83 +496,85 @@ 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()
++{
++}
++
++// ----------------------------------------------------------------------------
++
++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)
++{
++	ScColumn* pCol = &(mpDoc->pTab[nTab])->aCol[nCol];
++    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++;
+ 
+-        if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= aParam.nRow2 )
++		if ( nColRow < pCol->nCount && pCol->pItems[nColRow].nRow <= mpParam->nRow2 )
+         {
+             nRow = pCol->pItems[nColRow].nRow;
+             ScBaseCell* pCell = pCol->pItems[nColRow].pCell;
+-            if ( (pDoc->pTab[nTab])->ValidQuery( nRow, aParam, NULL,
++            if ( (mpDoc->pTab[nTab])->ValidQuery( nRow, *mpParam, NULL,
+                     (nCol == static_cast<SCCOL>(nFirstQueryField) ? pCell : NULL) ) )
+             {
+                 switch (pCell->GetCellType())
+                 {
+                     case CELLTYPE_VALUE:
+                         {
+-                            rValue = ((ScValueCell*)pCell)->GetValue();
++                            rValue.mfValue = ((ScValueCell*)pCell)->GetValue();
++                            rValue.mbIsNumber = true;
+                             if ( bCalcAsShown )
+                             {
+                                 lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
+-                                    nAttrEndRow, pCol->pAttrArray, nRow, pDoc );
+-                                rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
++									nAttrEndRow, pCol->pAttrArray, 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 +582,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 +616,309 @@ BOOL ScQueryValueIterator::GetThis(double& rValue, USHORT& rErr)
+                 nRow++;
+         }
+         else
+-            nRow = aParam.nRow2 + 1; // Naechste Spalte
++			nRow = mpParam->nRow2 + 1; // Naechste Spalte
+     }
+-//    return FALSE;
++    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];
++//  nColRow = 0;
++    ScColumn* pCol = &(mpDoc->pTab[nTab])->aCol[nCol];
+     pCol->Search( nRow, nColRow );
+-    return GetThis(rValue, rErr);
++    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::pCaseCollator : *ScGlobal::pCollator;
++
++    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 sc/source/core/data/dpcachetable.cxx sc/source/core/data/dpcachetable.cxx
+index 015c651..fd81c26 100644
+--- sc/source/core/data/dpcachetable.cxx
++++ 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>
+diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
+index f71b842..181c634 100644
+--- sc/source/core/data/global2.cxx
++++ 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 sc/source/core/data/sortparam.cxx sc/source/core/data/sortparam.cxx
+index 9531c71..dfab465 100644
+--- sc/source/core/data/sortparam.cxx
++++ 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 sc/source/core/data/table3.cxx sc/source/core/data/table3.cxx
+index ca196ea..2d8f0d3 100644
+--- sc/source/core/data/table3.cxx
++++ sc/source/core/data/table3.cxx
+@@ -60,6 +60,7 @@
+ #include "progress.hxx"
+ #include "cellform.hxx"
+ #include "postit.hxx"
++#include "queryparam.hxx"
+ 
+ #include <vector>
+ 
+diff --git sc/source/core/inc/doubleref.hxx sc/source/core/inc/doubleref.hxx
+new file mode 100644
+index 0000000..0aa577b
+--- /dev/null
++++ 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;
++class ScDBQueryParamBase;
++class 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 sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
+index ca21e19..e385a9c 100644
+--- sc/source/core/inc/interpre.hxx
++++ 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
+ {
+@@ -301,6 +304,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 );
+@@ -488,7 +492,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 sc/source/core/tool/dbcolect.cxx sc/source/core/tool/dbcolect.cxx
+index e1e3870..a47a669 100644
+--- sc/source/core/tool/dbcolect.cxx
++++ 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 sc/source/core/tool/doubleref.cxx sc/source/core/tool/doubleref.cxx
+new file mode 100644
+index 0000000..bb67aad
+--- /dev/null
++++ 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, 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::pTransliteration->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 = nC;
++    mnRows = 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 sc/source/core/tool/interpr1.cxx sc/source/core/tool/interpr1.cxx
+index 29a6884..eff5ea3 100644
+--- sc/source/core/tool/interpr1.cxx
++++ sc/source/core/tool/interpr1.cxx
+@@ -67,11 +67,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
+ 
+@@ -82,6 +85,8 @@ ScTokenStack* ScInterpreter::pGlobalStack = NULL;
+ BOOL ScInterpreter::bGlobalStackInUse = FALSE;
+ 
+ using namespace formula;
++using ::std::auto_ptr;
++
+ //-----------------------------------------------------------------------------
+ // Funktionen
+ //-----------------------------------------------------------------------------
+@@ -5619,11 +5624,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", "Eike.Rathke at sun.com", "ScInterpreter::GetDBParams" );
+-    BOOL bRet = FALSE;
+     BOOL bAllowMissingField = FALSE;
+     if ( rMissingField )
+     {
+@@ -5632,14 +5635,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;
+@@ -5695,116 +5694,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
+         {
+-            SCCOL   nField = nDBCol1;
+-            BOOL    bFound = TRUE;
++            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())
++        {
++            // 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", "Eike.Rathke at sun.com", "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 )
+             {
+@@ -5820,24 +5788,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);
+@@ -5862,13 +5830,12 @@ void ScInterpreter::ScDBSum()
+ void ScInterpreter::ScDBCount()
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "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
+@@ -5878,7 +5845,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
+@@ -5889,17 +5858,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 );
+     }
+@@ -5911,21 +5880,24 @@ void ScInterpreter::ScDBCount()
+ void ScInterpreter::ScDBCount2()
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "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();
+@@ -5969,25 +5941,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 sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
+index cf8dc7e..a301200 100644
+--- sc/source/core/tool/interpr4.cxx
++++ 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
+ 
+@@ -1021,6 +1024,44 @@ 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));
++        }
++        break;
++        case svMatrix:
++        {
++            ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
++            return new ScDBExternalRange(pDok, pMat);
++        }
++        break;
++        default:
++            SetError( errIllegalParameter);
++    }
++    return NULL;
++}
+ 
+ void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
+                                  SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
+@@ -1860,78 +1901,37 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
+ void ScInterpreter::ScDBGet()
+ {
+     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke at sun.com", "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 sc/source/core/tool/makefile.mk sc/source/core/tool/makefile.mk
+index b0f8f03..041d2c8 100644
+--- sc/source/core/tool/makefile.mk
++++ 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 \
+@@ -123,6 +125,7 @@ EXCEPTIONSFILES= \
+         $(SLO)$/chartlock.obj \
+         $(SLO)$/chgtrack.obj \
+         $(SLO)$/compiler.obj \
++		$(SLO)$/doubleref.obj \
+         $(SLO)$/formulaparserpool.obj \
+         $(SLO)$/interpr1.obj \
+         $(SLO)$/interpr2.obj \
+@@ -131,6 +134,7 @@ EXCEPTIONSFILES= \
+         $(SLO)$/interpr5.obj \
+         $(SLO)$/lookupcache.obj \
+         $(SLO)$/prnsave.obj \
++		$(SLO)$/queryparam.obj \
+         $(SLO)$/reftokenhelper.obj \
+ 		$(SLO)$/stringutil.obj \
+         $(SLO)$/token.obj
+diff --git sc/source/core/tool/queryparam.cxx sc/source/core/tool/queryparam.cxx
+new file mode 100644
+index 0000000..d9d477d
+--- /dev/null
++++ sc/source/core/tool/queryparam.cxx
+@@ -0,0 +1,361 @@
++/*************************************************************************
++ *
++ * 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-1);
++    for (size_t i = 0; i < n; ++i)
++        if (i != nPos)
++            aNewEntries.push_back(maEntries[i]);
++
++    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 sc/source/filter/excel/colrowst.cxx sc/source/filter/excel/colrowst.cxx
+index 174ab20..199dad8 100644
+--- sc/source/filter/excel/colrowst.cxx
++++ 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 sc/source/filter/excel/xichart.cxx sc/source/filter/excel/xichart.cxx
+index 2d920b0..69ead7f 100644
+--- sc/source/filter/excel/xichart.cxx
++++ 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,14 @@ Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const
+     return xDataSeries;
+ }
+ 
++void XclImpChSeries::FillAllSourceLinks(vector<ScSharedTokenRef>& rTokens) const
++{
++    mxValueLink->FillSourceLink(rTokens);
++    mxCategLink->FillSourceLink(rTokens);
++    mxTitleLink->FillSourceLink(rTokens);
++    mxBubbleLink->FillSourceLink(rTokens);
++}
++
+ void XclImpChSeries::ReadChSourceLink( XclImpStream& rStrm )
+ {
+     XclImpChSourceLinkRef xSrcLink( new XclImpChSourceLink( GetChRoot() ) );
+@@ -3481,7 +3510,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 );
+@@ -3524,6 +3553,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->SetDirty(true);
++            pListener->StartListeningTo();
++            pChartCollection->Insert(pListener.release());
++
++        }
++    }
+ }
+ 
+ void XclImpChChart::ReadChSeries( XclImpStream& rStrm )
+@@ -3749,11 +3800,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 sc/source/filter/excel/xiescher.cxx sc/source/filter/excel/xiescher.cxx
+index 599b33f..48406eb 100644
+--- sc/source/filter/excel/xiescher.cxx
++++ sc/source/filter/excel/xiescher.cxx
+@@ -1579,7 +1579,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() )
+diff --git sc/source/filter/inc/excimp8.hxx sc/source/filter/inc/excimp8.hxx
+index fadad41..43e630d 100644
+--- sc/source/filter/inc/excimp8.hxx
++++ 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 sc/source/filter/inc/xichart.hxx sc/source/filter/inc/xichart.hxx
+index 1798242..e923ee1 100644
+--- sc/source/filter/inc/xichart.hxx
++++ sc/source/filter/inc/xichart.hxx
+@@ -39,6 +39,7 @@
+ #include <svtools/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 sc/source/filter/xml/XMLExportDataPilot.hxx sc/source/filter/xml/XMLExportDataPilot.hxx
+index a3f6cf8..46a2bb0 100644
+--- sc/source/filter/xml/XMLExportDataPilot.hxx
++++ sc/source/filter/xml/XMLExportDataPilot.hxx
+@@ -44,6 +44,7 @@ class ScDPDimensionSaveData;
+ class ScDPSaveGroupDimension;
+ class ScDPSaveNumGroupDimension;
+ struct ScDPNumGroupInfo;
++struct ScQueryParam;
+ 
+ class ScXMLExportDataPilot
+ {
+diff --git sc/source/filter/xml/xmldpimp.hxx sc/source/filter/xml/xmldpimp.hxx
+index b4df6b1..705dbac 100644
+--- sc/source/filter/xml/xmldpimp.hxx
++++ 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 sc/source/ui/dbgui/foptmgr.cxx sc/source/ui/dbgui/foptmgr.cxx
+index ee5f039..a425836 100644
+--- sc/source/ui/dbgui/foptmgr.cxx
++++ 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 sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
+index 1f77d2c..f1587bc 100644
+--- sc/source/ui/docshell/externalrefmgr.cxx
++++ sc/source/ui/docshell/externalrefmgr.cxx
+@@ -1045,8 +1045,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);
+         maFilterName = aFilter;
++        aMod.SetDocumentModified();
+     }
+ }
+ 
+diff --git sc/source/ui/inc/pfiltdlg.hxx sc/source/ui/inc/pfiltdlg.hxx
+index a9ba0d1..b383173 100644
+--- sc/source/ui/inc/pfiltdlg.hxx
++++ 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 sc/source/ui/inc/uiitems.hxx sc/source/ui/inc/uiitems.hxx
+index 6581436..4cd4e58 100644
+--- sc/source/ui/inc/uiitems.hxx
++++ 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 <svtools/poolitem.hxx>
+ 
+diff --git sc/source/ui/inc/undodat.hxx sc/source/ui/inc/undodat.hxx
+index fb42d81..ad46cb7 100644
+--- sc/source/ui/inc/undodat.hxx
++++ 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 sc/source/ui/undo/undobase.cxx sc/source/ui/undo/undobase.cxx
+index f20abdb..8b59f80 100644
+--- sc/source/ui/undo/undobase.cxx
++++ 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 sc/source/ui/unoobj/chart2uno.cxx sc/source/ui/unoobj/chart2uno.cxx
+index 6e8ae0a..877e244 100644
+--- sc/source/ui/unoobj/chart2uno.cxx
++++ sc/source/ui/unoobj/chart2uno.cxx
+@@ -2919,6 +2919,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()
+@@ -3111,7 +3114,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);
+ 
+@@ -3286,19 +3288,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 sc/source/ui/view/gridwin4.cxx sc/source/ui/view/gridwin4.cxx
+index 1cd54a2..5428aa1 100644
+--- sc/source/ui/view/gridwin4.cxx
++++ 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>
+ 
diff --git a/patches/dev300/cws-kohei03-sc.diff b/patches/dev300/cws-kohei03-sc.diff
index b008d67..491a270 100644
--- a/patches/dev300/cws-kohei03-sc.diff
+++ b/patches/dev300/cws-kohei03-sc.diff
@@ -805,7 +805,7 @@ index f7f836e..031b70a 100644
 +    aResults.reserve(nEntryCount);
 +
 +    const CollatorWrapper& rCollator = 
-+        mpParam->bCaseSens ? *ScGlobal::pCaseCollator : *ScGlobal::pCollator;
++        mpParam->bCaseSens ? *ScGlobal::GetCaseCollator() : *ScGlobal::GetCollator();
 +
 +    for (SCSIZE i = 0; i < nEntryCount; ++i)
 +    {
diff --git a/patches/dev300/sc-dbrange-dynamic-resize.diff b/patches/dev300/sc-dbrange-dynamic-resize.diff
index 0d1235e..3236a74 100644
--- a/patches/dev300/sc-dbrange-dynamic-resize.diff
+++ b/patches/dev300/sc-dbrange-dynamic-resize.diff
@@ -1,27 +1,8 @@
-diff --git sc/inc/column.hxx sc/inc/column.hxx
-index d49f85b..355f30d 100644
---- sc/inc/column.hxx
-+++ sc/inc/column.hxx
-@@ -378,7 +378,7 @@ public:
-                 /// Including current, may return -1
-     SCsROW		GetNextUnprotected( SCROW nRow, BOOL bUp ) const;
- 
--    void		GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings);
-+    void		GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings, bool& rHasDates);
-     BOOL		GetDataEntries(SCROW nRow, TypedScStrCollection& rStrings, BOOL bLimit);
- 
- //UNUSED2008-05  SCROW		NoteCount( SCROW nMaxRow = MAXROW ) const;
 diff --git sc/inc/dbcolect.hxx sc/inc/dbcolect.hxx
-index 48d314e..00ea53b 100644
+index eea9076..00ea53b 100644
 --- sc/inc/dbcolect.hxx
 +++ sc/inc/dbcolect.hxx
-@@ -88,11 +88,13 @@ private:
-     SCCOLROW		nQueryField[MAXQUERY];
-     ScQueryOp		eQueryOp[MAXQUERY];
-     BOOL			bQueryByString[MAXQUERY];
-+    bool            bQueryByDate[MAXQUERY];
-     String*			pQueryStr[MAXQUERY];
-     double			nQueryVal[MAXQUERY];
+@@ -94,6 +94,7 @@ private:
      ScQueryConnect  eQueryConnect[MAXQUERY];
      BOOL			bIsAdvanced;		// TRUE if created by advanced filter
      ScRange			aAdvSource;			// source range
@@ -29,7 +10,7 @@ index 48d314e..00ea53b 100644
      // SubTotalParam
      BOOL			bSubRemoveOnly;
      BOOL			bSubReplace;
-@@ -140,9 +142,10 @@ public:
+@@ -141,9 +142,10 @@ public:
              const String& GetName() const				{ return aName; }
              void		GetName(String& rName) const	{ rName = aName; }
              void		SetName(const String& rName)	{ aName = rName; }
@@ -43,7 +24,7 @@ index 48d314e..00ea53b 100644
              BOOL		IsByRow() const 				{ return bByRow; }
              void		SetByRow(BOOL bByR) 			{ bByRow = bByR; }
 diff --git sc/inc/document.hxx sc/inc/document.hxx
-index 3a38dde..daeb91e 100644
+index a92545f..daeb91e 100644
 --- sc/inc/document.hxx
 +++ sc/inc/document.hxx
 @@ -873,7 +873,7 @@ public:
@@ -55,7 +36,7 @@ index 3a38dde..daeb91e 100644
      SC_DLLPUBLIC BOOL			GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const;
      SC_DLLPUBLIC BOOL			GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const;
      SC_DLLPUBLIC BOOL			GetPrintArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow,
-@@ -1392,10 +1392,13 @@ public:
+@@ -1392,6 +1392,9 @@ public:
                                          SCTAB nTab, ScQueryParam& rQueryParam );
      void 			GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr);
  
@@ -63,44 +44,23 @@ index 3a38dde..daeb91e 100644
 +    void            UpdateDynamicEndRow(ScDBData& rDBData) const;
 +
      BOOL			GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
--                                TypedScStrCollection& rStrings, bool bFilter = false );
-+                                bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates);
+                                 bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates);
      SC_DLLPUBLIC BOOL			GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
--                                SCTAB nTab, TypedScStrCollection& rStrings );
-+                                SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates );
-     BOOL			GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
-                                 TypedScStrCollection& rStrings, BOOL bLimit = FALSE );
-     BOOL			GetFormulaEntries( TypedScStrCollection& rStrings );
-diff --git sc/inc/global.hxx sc/inc/global.hxx
-index b401cb9..64cf3b8 100644
---- sc/inc/global.hxx
-+++ sc/inc/global.hxx
-@@ -797,6 +797,7 @@ struct ScQueryEntry
- {
-     BOOL			bDoQuery;
-     BOOL			bQueryByString;
-+    bool            bQueryByDate;
-     SCCOLROW		nField;
-     ScQueryOp		eOp;
-     ScQueryConnect  eConnect;
-diff --git sc/inc/rangeutl.hxx sc/inc/rangeutl.hxx
-index 1e8d5da..1dc463d 100644
---- sc/inc/rangeutl.hxx
-+++ sc/inc/rangeutl.hxx
-@@ -38,6 +38,11 @@
- #include <com/sun/star/table/CellRangeAddress.hpp>
- #include <com/sun/star/uno/Sequence.hxx>
- 
-+// Chart always stores cell range addresses using CONV_OOO convention. But
-+// if parsing with CONV_OOO fails, try parsing it using the current address
-+// convention.
-+#define CHART_ADDRESS_CONV_WORKAROUND 1
-+
- //------------------------------------------------------------------------
+diff --git sc/inc/queryparam.hxx sc/inc/queryparam.hxx
+index bc50237..01ddffb 100644
+--- sc/inc/queryparam.hxx
++++ sc/inc/queryparam.hxx
+@@ -86,6 +86,8 @@ struct SC_DLLPUBLIC ScQueryParam : public ScQueryParamBase, public ScQueryParamT
+     SCTAB           nDestTab;
+     SCCOL           nDestCol;
+     SCROW           nDestRow;
++    SCROW           nDynamicEndRow;
++    bool            bUseDynamicRange;
  
- class SvStream;
+     ScQueryParam();
+     ScQueryParam( const ScQueryParam& r );
 diff --git sc/inc/table.hxx sc/inc/table.hxx
-index 481cb8c..89f505e 100644
+index 3659381..89f505e 100644
 --- sc/inc/table.hxx
 +++ sc/inc/table.hxx
 @@ -379,7 +379,7 @@ public:
@@ -112,93 +72,11 @@ index 481cb8c..89f505e 100644
  
      SCSIZE	    GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow,
                                          SCCOL nEndCol, SCROW nEndRow, ScDirection eDir );
-@@ -643,8 +643,8 @@ public:
-     SCSIZE		Query(ScQueryParam& rQueryParam, BOOL bKeepSub);
-     BOOL		CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam);
- 
--    void		GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings);
--    void        GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings );
-+    void        GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates);
-+    void        GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates );
-     BOOL		GetDataEntries(SCCOL nCol, SCROW nRow, TypedScStrCollection& rStrings, BOOL bLimit);
- 
-     BOOL		HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow );
-diff --git sc/inc/tabprotection.hxx sc/inc/tabprotection.hxx
-index fc38a1b..99fec7b 100644
---- sc/inc/tabprotection.hxx
-+++ sc/inc/tabprotection.hxx
-@@ -38,7 +38,7 @@
- #include <vector>
- #include <boost/shared_ptr.hpp>
- 
--#define ENABLE_SHEET_PROTECTION 0
-+#define ENABLE_SHEET_PROTECTION 1
- 
- class ScDocument;
- class ScTableProtectionImpl;
-diff --git sc/source/core/data/column2.cxx sc/source/core/data/column2.cxx
-index 9fc2ea5..2291859 100644
---- sc/source/core/data/column2.cxx
-+++ sc/source/core/data/column2.cxx
-@@ -1319,6 +1319,10 @@ BOOL ScColumn::IsEmpty() const
- 
- BOOL ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow, bool bIgnoreNotes) const
- {
-+	Rectangle aRect;
-+	if (pAttrArray->HasLines(nStartRow, nEndRow, aRect, TRUE, TRUE))
-+		return FALSE;
-+
-     if ( nCount == 0 || !pItems )
-         return TRUE;
- 
-diff --git sc/source/core/data/column3.cxx sc/source/core/data/column3.cxx
-index 242c5c0..560801d 100644
---- sc/source/core/data/column3.cxx
-+++ sc/source/core/data/column3.cxx
-@@ -1470,8 +1470,9 @@ BOOL ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString,
- }
- 
- 
--void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings)
-+void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollection& rStrings, bool& rHasDates)
- {
-+    bool bHasDates = false;
-     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
-     String aString;
-     SCROW nRow = 0;
-@@ -1507,6 +1508,18 @@ void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollec
-                     nValue = 0.0;
-             }
- 
-+            if (pFormatter)
-+            {
-+                short nType = pFormatter->GetType(nFormat);
-+                if ((nType & NUMBERFORMAT_DATE) && !(nType & NUMBERFORMAT_TIME))
-+                {    
-+                    // special case for date values.  Disregard the time
-+                    // element if the number format is of date type.
-+                    nValue = ::rtl::math::approxFloor(nValue);
-+                    bHasDates = true;
-+                }
-+            }
-+
-             pData = new TypedStrData( aString, nValue, SC_STRTYPE_VALUE );
-         }
- #if 0 // DR
-@@ -1525,6 +1538,8 @@ void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, TypedScStrCollec
- 
-         ++nIndex;
-     }
-+
-+    rHasDates = bHasDates;
- }
- 
- //
 diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
-index f0806eb..396d54c 100644
+index caeb5b1..396d54c 100644
 --- sc/source/core/data/documen3.cxx
 +++ sc/source/core/data/documen3.cxx
-@@ -1255,17 +1255,31 @@ BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol,
+@@ -1255,6 +1255,18 @@ BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol,
      //return FALSE;
  }
  
@@ -217,13 +95,7 @@ index f0806eb..396d54c 100644
  //
  //	GetFilterEntries - Eintraege fuer AutoFilter-Listbox
  //
- 
--BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScStrCollection& rStrings, bool bFilter )
-+BOOL ScDocument::GetFilterEntries(
-+    SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates)
- {
-     if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
-     {
+@@ -1267,6 +1279,7 @@ BOOL ScDocument::GetFilterEntries(
          ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE);	//!??
          if (pDBData)
          {
@@ -231,7 +103,7 @@ index f0806eb..396d54c 100644
              SCTAB nAreaTab;
              SCCOL nStartCol;
              SCROW nStartRow;
-@@ -1277,6 +1291,7 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt
+@@ -1278,6 +1291,7 @@ BOOL ScDocument::GetFilterEntries(
  
              ScQueryParam aParam;
              pDBData->GetQueryParam( aParam );
@@ -239,34 +111,6 @@ index f0806eb..396d54c 100644
              rStrings.SetCaseSensitive( aParam.bCaseSens );
  
              // return all filter entries, if a filter condition is connected with a boolean OR
-@@ -1296,11 +1311,11 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt
- 
-             if ( bFilter )
-             {
--                pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings );
-+                pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
-             }
-             else
-             {
--                pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
-+                pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
-             }
- 
-             return TRUE;
-@@ -1315,11 +1330,11 @@ BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScSt
- //
- 
- BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
--                                        SCTAB nTab, TypedScStrCollection& rStrings )
-+                                        SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates )
- {
-     if ( ValidTab(nTab) && pTab[nTab] )
-     {
--        pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
-+        pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
-         return TRUE;
-     }
- 
 diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
 index 3d61f28..187199f 100644
 --- sc/source/core/data/document.cxx
@@ -280,90 +124,6 @@ index 3d61f28..187199f 100644
  {
      if (VALIDTAB(nTab))
          if (pTab[nTab])
-diff --git sc/source/core/data/global2.cxx sc/source/core/data/global2.cxx
-index 181c634..6f3c424 100644
---- sc/source/core/data/global2.cxx
-+++ sc/source/core/data/global2.cxx
-@@ -145,30 +145,32 @@ BOOL ScImportParam::operator==( const ScImportParam& rOther ) const
- //------------------------------------------------------------------------
- // struct ScQueryParam:
- 
--ScQueryEntry::ScQueryEntry()
-+ScQueryEntry::ScQueryEntry() :
-+    bDoQuery(FALSE),
-+    bQueryByString(FALSE),
-+    bQueryByDate(false),
-+    nField(0),
-+    eOp(SC_EQUAL),
-+    eConnect(SC_AND),
-+    pStr(new String),
-+    nVal(0.0),
-+    pSearchParam(NULL),
-+    pSearchText(NULL)
-+{
-+}
-+
-+ScQueryEntry::ScQueryEntry(const ScQueryEntry& r) :
-+    bDoQuery(r.bDoQuery),
-+    bQueryByString(r.bQueryByString),
-+    bQueryByDate(r.bQueryByDate),
-+    nField(r.nField),
-+    eOp(r.eOp),
-+    eConnect(r.eConnect),
-+    pStr(new String(*r.pStr)),
-+    nVal(r.nVal),
-+    pSearchParam(NULL),
-+    pSearchText(NULL)
- {
--    bDoQuery		= FALSE;
--    bQueryByString	= FALSE;
--    eOp				= SC_EQUAL;
--    eConnect		= SC_AND;
--    nField			= 0;
--    nVal			= 0.0;
--    pStr			= new String;
--    pSearchParam	= NULL;
--    pSearchText		= NULL;
--}
--
--ScQueryEntry::ScQueryEntry(const ScQueryEntry& r)
--{
--    bDoQuery		= r.bDoQuery;
--    bQueryByString	= r.bQueryByString;
--    eOp				= r.eOp;
--    eConnect		= r.eConnect;
--    nField			= r.nField;
--    nVal			= r.nVal;
--    pStr			= new String(*r.pStr);
--    pSearchParam	= NULL;
--    pSearchText		= NULL;
- }
- 
- ScQueryEntry::~ScQueryEntry()
-@@ -185,6 +187,7 @@ ScQueryEntry& ScQueryEntry::operator=( const ScQueryEntry& r )
- {
-     bDoQuery		= r.bDoQuery;
-     bQueryByString	= r.bQueryByString;
-+    bQueryByDate    = r.bQueryByDate;
-     eOp				= r.eOp;
-     eConnect		= r.eConnect;
-     nField			= r.nField;
-@@ -205,6 +208,7 @@ void ScQueryEntry::Clear()
- {
-     bDoQuery		= FALSE;
-     bQueryByString	= FALSE;
-+    bQueryByDate    = false;
-     eOp				= SC_EQUAL;
-     eConnect		= SC_AND;
-     nField			= 0;
-@@ -223,6 +227,7 @@ BOOL ScQueryEntry::operator==( const ScQueryEntry& r ) const
- {
-     return bDoQuery			== r.bDoQuery
-         && bQueryByString	== r.bQueryByString
-+        && bQueryByDate     == r.bQueryByDate
-         && eOp				== r.eOp
-         && eConnect			== r.eConnect
-         && nField			== r.nField
 diff --git sc/source/core/data/table1.cxx sc/source/core/data/table1.cxx
 index 15db733..10b8cda 100644
 --- sc/source/core/data/table1.cxx
@@ -378,39 +138,10 @@ index 15db733..10b8cda 100644
      BOOL bLeft       = FALSE;
      BOOL bRight  = FALSE;
 diff --git sc/source/core/data/table3.cxx sc/source/core/data/table3.cxx
-index 390f6b1..2ecc8c1 100644
+index 986755a..2ecc8c1 100644
 --- sc/source/core/data/table3.cxx
 +++ sc/source/core/data/table3.cxx
-@@ -61,6 +61,7 @@
- #include "cellform.hxx"
- #include "postit.hxx"
- #include "queryparam.hxx"
-+#include "svtools/zformat.hxx"
- 
- #include <vector>
- 
-@@ -1144,6 +1145,20 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam,
-             }
-             else
-                 nCellVal = GetValue( static_cast<SCCOL>(rEntry.nField), nRow );
-+
-+            if (rEntry.bQueryByDate)
-+            {
-+                sal_uInt32 nNumFmt = GetNumberFormat(static_cast<SCCOL>(rEntry.nField), nRow);
-+                const SvNumberformat* pEntry = pDocument->GetFormatTable()->GetEntry(nNumFmt);
-+                if (pEntry)
-+                {
-+                    short nNumFmtType = pEntry->GetType();
-+                    if ((nNumFmtType & NUMBERFORMAT_DATE) && !(nNumFmtType & NUMBERFORMAT_TIME))
-+                        // The format is of date type.  Strip off the time element.
-+                        nCellVal = ::rtl::math::approxFloor(nCellVal);
-+                }
-+            }
-+
-             switch (rEntry.eOp)
-             {
-                 case SC_EQUAL :
-@@ -1602,6 +1617,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
+@@ -1617,6 +1617,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
      BOOL* pSpecial = new BOOL[nEntryCount];
      lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
  
@@ -418,7 +149,7 @@ index 390f6b1..2ecc8c1 100644
      if (!aParam.bInplace)
      {
          nOutRow = aParam.nDestRow + nHeader;
-@@ -1610,7 +1626,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
+@@ -1625,7 +1626,7 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, BOOL bKeepSub)
                              aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
      }
  
@@ -427,65 +158,11 @@ index 390f6b1..2ecc8c1 100644
      {
          BOOL bResult;									// Filterergebnis
          BOOL bValid = ValidQuery(j, aParam, pSpecial);
-@@ -1931,12 +1947,13 @@ BOOL ScTable::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL /* nEndCol *
-     return TRUE;
- }
- 
--void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings)
-+void ScTable::GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, TypedScStrCollection& rStrings, bool& rHasDates)
- {
--    aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings );
-+    aCol[nCol].GetFilterEntries( nRow1, nRow2, rStrings, rHasDates );
- }
- 
--void ScTable::GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings )
-+void ScTable::GetFilteredFilterEntries(
-+    SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, TypedScStrCollection& rStrings, bool& rHasDates )
- {
-     // remove the entry for this column from the query parameter
-     ScQueryParam aParam( rParam );
-@@ -1954,15 +1971,18 @@ void ScTable::GetFilteredFilterEntries( SCCOL nCol, SCROW nRow1, SCROW nRow2, co
- 
-     BOOL* pSpecial = new BOOL[nEntryCount];
-     lcl_PrepareQuery( pDocument, this, aParam, pSpecial );
--
-+    bool bHasDates = false;
-     for ( SCROW j = nRow1; j <= nRow2; ++j )
-     {
-         if ( ValidQuery( j, aParam, pSpecial ) )
-         {
--            aCol[nCol].GetFilterEntries( j, j, rStrings );
-+            bool bThisHasDates = false;
-+            aCol[nCol].GetFilterEntries( j, j, rStrings, bThisHasDates );
-+            bHasDates |= bThisHasDates;
-         }
-     }
- 
-+    rHasDates = bHasDates;
-     delete[] pSpecial;
- }
- 
 diff --git sc/source/core/tool/dbcolect.cxx sc/source/core/tool/dbcolect.cxx
-index 22642f4..5fae4bd 100644
+index 4f0e755..5fae4bd 100644
 --- sc/source/core/tool/dbcolect.cxx
 +++ sc/source/core/tool/dbcolect.cxx
-@@ -159,6 +159,7 @@ ScDBData::ScDBData( const ScDBData& rData ) :
-         nQueryField[i]		= rData.nQueryField[i];
-         eQueryOp[i]			= rData.eQueryOp[i];
-         bQueryByString[i]	= rData.bQueryByString[i];
-+        bQueryByDate[i]     = rData.bQueryByDate[i];
-         pQueryStr[i]		= new String( *(rData.pQueryStr[i]) );
-         nQueryVal[i]		= rData.nQueryVal[i];
-         eQueryConnect[i]	= rData.eQueryConnect[i];
-@@ -249,6 +250,7 @@ ScDBData& ScDBData::operator= (const ScDBData& rData)
-         nQueryField[i]		= rData.nQueryField[i];
-         eQueryOp[i]			= rData.eQueryOp[i];
-         bQueryByString[i]	= rData.bQueryByString[i];
-+        bQueryByDate[i]     = rData.bQueryByDate[i];
-         *pQueryStr[i]		= *rData.pQueryStr[i];
-         nQueryVal[i]		= rData.nQueryVal[i];
-         eQueryConnect[i]	= rData.eQueryConnect[i];
-@@ -379,18 +381,20 @@ String ScDBData::GetOperations() const
+@@ -381,18 +381,20 @@ String ScDBData::GetOperations() const
      return aVal;
  }
  
@@ -510,7 +187,7 @@ index 22642f4..5fae4bd 100644
  }
  
  void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
-@@ -402,6 +406,11 @@ void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW
+@@ -404,6 +406,11 @@ void ScDBData::SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW
      nEndRow   = nRow2;
  }
  
@@ -522,7 +199,7 @@ index 22642f4..5fae4bd 100644
  void ScDBData::MoveTo(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
  {
      USHORT i;
-@@ -509,6 +518,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
+@@ -511,6 +518,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
      rQueryParam.nDestTab = nQueryDestTab;
      rQueryParam.nDestCol = nQueryDestCol;
      rQueryParam.nDestRow = nQueryDestRow;
@@ -530,236 +207,83 @@ index 22642f4..5fae4bd 100644
  
      rQueryParam.Resize( MAXQUERY );
      for (SCSIZE i=0; i<MAXQUERY; i++)
-@@ -519,6 +529,7 @@ void ScDBData::GetQueryParam( ScQueryParam& rQueryParam ) const
-         rEntry.nField = nQueryField[i];
-         rEntry.eOp = eQueryOp[i];
-         rEntry.bQueryByString = bQueryByString[i];
-+        rEntry.bQueryByDate = bQueryByDate[i];
-         *rEntry.pStr = *pQueryStr[i];
-         rEntry.nVal = nQueryVal[i];
-         rEntry.eConnect = eQueryConnect[i];
-@@ -550,6 +561,7 @@ void ScDBData::SetQueryParam(const ScQueryParam& rQueryParam)
-         nQueryField[i] = rEntry.nField;
-         eQueryOp[i] = rEntry.eOp;
-         bQueryByString[i] = rEntry.bQueryByString;
-+        bQueryByDate[i] = rEntry.bQueryByDate;
-         *pQueryStr[i] = *rEntry.pStr;
-         nQueryVal[i] = rEntry.nVal;
-         eQueryConnect[i] = rEntry.eConnect;
-diff --git sc/source/core/tool/rangeutl.cxx sc/source/core/tool/rangeutl.cxx
-index 62474c3..b5bdfda 100644
---- sc/source/core/tool/rangeutl.cxx
-+++ sc/source/core/tool/rangeutl.cxx
-@@ -479,6 +479,11 @@ sal_Bool ScRangeStringConverter::GetAddressFromString(
-     {
-         if ((rAddress.Parse( sToken, const_cast<ScDocument*>(pDocument), eConv ) & SCA_VALID) == SCA_VALID)
-             return true;
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+        ::formula::FormulaGrammar::AddressConvention eConvUI = pDocument->GetAddressConvention();
-+        if (eConv != eConvUI)
-+            return ((rAddress.Parse(sToken, const_cast<ScDocument*>(pDocument), eConvUI) & SCA_VALID) == SCA_VALID);
-+#endif
-     }
-     return sal_False;
- }
-@@ -505,6 +510,11 @@ sal_Bool ScRangeStringConverter::GetRangeFromString(
-             if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
-                 aUIString.Erase( 0, 1 );
-             bResult = ((rRange.aStart.Parse( aUIString, const_cast<ScDocument*> (pDocument), eConv) & SCA_VALID) == SCA_VALID);
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+            if (!bResult && eConv != eConv)
-+                bResult = ((rRange.aStart.Parse(
-+                    aUIString, const_cast<ScDocument*>(pDocument), eConv) & SCA_VALID) == SCA_VALID);
-+#endif
-             rRange.aEnd = rRange.aStart;
-         }
-         else
-@@ -529,6 +539,15 @@ sal_Bool ScRangeStringConverter::GetRangeFromString(
-                                 eConv) & SCA_VALID) == SCA_VALID) &&
-                           ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument),
-                                 eConv) & SCA_VALID) == SCA_VALID);
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+                if (!bResult && eConv != eConv)
-+                {
-+                    bResult = ((rRange.aStart.Parse( aUIString.Copy(0, (xub_StrLen)nIndex), const_cast<ScDocument*>(pDocument),
-+                                    eConv) & SCA_VALID) == SCA_VALID) &&
-+                              ((rRange.aEnd.Parse( aUIString.Copy((xub_StrLen)nIndex+1), const_cast<ScDocument*>(pDocument),
-+                                    eConv) & SCA_VALID) == SCA_VALID);
-+                }
-+#endif
-             }
-         }
-     }
-@@ -863,6 +882,8 @@ static void lcl_appendCellRangeAddress(
- 
- void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, const OUString& rXMLRange, ScDocument* pDoc )
+diff --git sc/source/core/tool/queryparam.cxx sc/source/core/tool/queryparam.cxx
+index d9d477d..0593534 100644
+--- sc/source/core/tool/queryparam.cxx
++++ sc/source/core/tool/queryparam.cxx
+@@ -177,7 +177,8 @@ ScQueryParam::ScQueryParam() :
+ ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
+     ScQueryParamBase(r),
+     ScQueryParamTable(r),
+-    bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
++    bDestPers(r.bDestPers), nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow),
++    nDynamicEndRow(r.nDynamicEndRow), bUseDynamicRange(r.bUseDynamicRange)
  {
-+    FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
-+    const OUString aRangeSep = GetScCompilerNativeSymbol(ocSep);
-     const sal_Unicode cSep = ' ';
-     const sal_Unicode cQuote = '\'';
- 
-@@ -915,13 +936,37 @@ void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, con
-             rtl::OUString aBuf;
-             USHORT nRet = aCell1.Parse(aBeginCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo1);
-             if ((nRet & SCA_VALID) != SCA_VALID)
-+            {    
-                 // first cell is invalid.
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+                if (eConv == FormulaGrammar::CONV_OOO)
-+                    continue;
-+
-+                nRet = aCell1.Parse(aBeginCell, pDoc, eConv, &aExtInfo1);
-+                if ((nRet & SCA_VALID) != SCA_VALID)
-+                    // first cell is really invalid.
-+                    continue;
-+#else
-                 continue;
-+#endif
-+            }
- 
-             nRet = aCell2.Parse(aEndCell, pDoc, FormulaGrammar::CONV_OOO, &aExtInfo2);
-             if ((nRet & SCA_VALID) != SCA_VALID)
-+            {    
-                 // second cell is invalid.
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+                if (eConv == FormulaGrammar::CONV_OOO)
-+                    continue;
-+
-+                nRet = aCell2.Parse(aEndCell, pDoc, eConv, &aExtInfo2);
-+                if ((nRet & SCA_VALID) != SCA_VALID)
-+                    // second cell is really invalid.
-+                    continue;
-+#else
-                 continue;
-+#endif
-+            }
- 
-             if (aExtInfo1.mnFileId != aExtInfo2.mnFileId || aExtInfo1.mbExternal != aExtInfo2.mbExternal)
-                 // external info inconsistency.
-@@ -932,7 +977,7 @@ void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, con
-             if (bFirst)
-                 bFirst = false;
-             else
--                aRetStr.appendAscii(";");
-+                aRetStr.append(aRangeSep);
- 
-             lcl_appendCellRangeAddress(aRetStr, pDoc, aCell1, aCell2, aExtInfo1, aExtInfo2);
-         }
-@@ -943,14 +988,22 @@ void ScRangeStringConverter::GetStringFromXMLRangeString( OUString& rString, con
-             ScAddress aCell;
-             USHORT nRet = aCell.Parse(aToken, pDoc, ::formula::FormulaGrammar::CONV_OOO, &aExtInfo);
-             if ((nRet & SCA_VALID) != SCA_VALID)
-+            {
-+#if CHART_ADDRESS_CONV_WORKAROUND
-+                nRet = aCell.Parse(aToken, pDoc, eConv, &aExtInfo);
-+                if ((nRet & SCA_VALID) != SCA_VALID)
-+                    continue;
-+#else
-                 continue;
-+#endif
-+            }
- 
-             // Looks good!
- 
-             if (bFirst)
-                 bFirst = false;
-             else
--                aRetStr.appendAscii(";");
-+                aRetStr.append(aRangeSep);
- 
-             lcl_appendCellAddress(aRetStr, pDoc, aCell, aExtInfo);
-         }
-diff --git sc/source/ui/app/inputhdl.cxx sc/source/ui/app/inputhdl.cxx
-index 98aac39..6ac26bc 100644
---- sc/source/ui/app/inputhdl.cxx
-+++ sc/source/ui/app/inputhdl.cxx
-@@ -2055,6 +2055,7 @@ IMPL_LINK( ScInputHandler, ModifyHdl, void *, EMPTYARG )
+ }
  
- BOOL ScInputHandler::DataChanging( sal_Unicode cTyped, BOOL bFromCommand )		// return TRUE = new view created
+@@ -187,7 +188,9 @@ ScQueryParam::ScQueryParam( const ScDBQueryParamInternal& r ) :
+     bDestPers(true),
+     nDestTab(0),
+     nDestCol(0),
+-    nDestRow(0)
++    nDestRow(0),
++    nDynamicEndRow(0),
++    bUseDynamicRange(false)
  {
-+    pActiveViewSh->GetViewData()->SetPasteMode( SC_PASTE_NONE );
-     bInOwnChange = TRUE;				// disable ModifyHdl (reset in DataChanged)
+ }
+     
+@@ -221,6 +224,8 @@ void ScQueryParam::ClearDestParams()
+     nDestTab = 0;
+     nDestCol = 0;
+     nDestRow = 0;
++    nDynamicEndRow = 0;
++    bUseDynamicRange = false;
+ }
  
-     if ( eMode == SC_INPUT_NONE )
+ //------------------------------------------------------------------------
+@@ -243,6 +248,8 @@ ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
+     bDuplicate  = r.bDuplicate;
+     bByRow      = r.bByRow;
+     bDestPers   = r.bDestPers;
++    nDynamicEndRow = r.nDynamicEndRow;
++    bUseDynamicRange = r.bUseDynamicRange;
+ 
+     maEntries = r.maEntries;
+ 
+@@ -281,7 +288,9 @@ BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
+         && (bDestPers   == rOther.bDestPers)
+         && (nDestTab    == rOther.nDestTab)
+         && (nDestCol    == rOther.nDestCol)
+-        && (nDestRow    == rOther.nDestRow) )
++        && (nDestRow    == rOther.nDestRow)
++        && (nDynamicEndRow == rOther.nDynamicEndRow)
++        && (bUseDynamicRange == rOther.bUseDynamicRange) )
+     {
+         bEqual = TRUE;
+         for ( SCSIZE i=0; i<nUsed && bEqual; i++ )
+@@ -305,6 +314,7 @@ void ScQueryParam::MoveToDest()
+         nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
+         nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
+         nTab  = sal::static_int_cast<SCTAB>( nTab  + nDifZ );
++        nDynamicEndRow = sal::static_int_cast<SCROW>( nDynamicEndRow + nDifY );
+         size_t n = maEntries.size();
+         for (size_t i=0; i<n; i++)
+             maEntries[i].nField += nDifX;
 diff --git sc/source/ui/dbgui/filtdlg.cxx sc/source/ui/dbgui/filtdlg.cxx
-index 4a2d4d4..3491024 100644
+index 4f56adb..51fe845 100644
 --- sc/source/ui/dbgui/filtdlg.cxx
 +++ sc/source/ui/dbgui/filtdlg.cxx
-@@ -451,24 +451,27 @@ void ScFilterDlg::UpdateValueList( USHORT nList )
-             SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
-             if (!pEntryLists[nColumn])
-             {
-+                USHORT nOffset = GetSliderPos();
+@@ -454,7 +454,7 @@ void ScFilterDlg::UpdateValueList( USHORT nList )
+                 USHORT nOffset = GetSliderPos();
                  SCTAB nTab		 = nSrcTab;
                  SCROW nFirstRow = theQueryData.nRow1;
 -                SCROW nLastRow	 = theQueryData.nRow2;
-+                SCROW nLastRow = theQueryData.bUseDynamicRange ? theQueryData.nDynamicEndRow : theQueryData.nRow2;
-+                mbHasDates[nOffset+nList-1] = false;
++                SCROW nLastRow   = theQueryData.bUseDynamicRange ? theQueryData.nDynamicEndRow : theQueryData.nRow2;
+                 mbHasDates[nOffset+nList-1] = false;
  
                  //	erstmal ohne die erste Zeile
- 
-                 pEntryLists[nColumn] = new TypedScStrCollection( 128, 128 );
-                 pEntryLists[nColumn]->SetCaseSensitive( aBtnCase.IsChecked() );
-                 pDoc->GetFilterEntriesArea( nColumn, nFirstRow+1, nLastRow,
--                                            nTab, *pEntryLists[nColumn] );
-+                                            nTab, *pEntryLists[nColumn], mbHasDates[nOffset+nList-1] );
- 
-                 //	Eintrag fuer die erste Zeile
-                 //!	Eintrag (pHdrEntry) ohne Collection erzeugen?
- 
-                 nHeaderPos[nColumn] = USHRT_MAX;
-                 TypedScStrCollection aHdrColl( 1, 1 );
-+                bool bDummy = false;
-                 pDoc->GetFilterEntriesArea( nColumn, nFirstRow, nFirstRow,
--                                            nTab, aHdrColl );
-+                                            nTab, aHdrColl, bDummy );
-                 TypedStrData* pHdrEntry = aHdrColl[0];
-                 if ( pHdrEntry )
-                 {
-@@ -1064,7 +1067,8 @@ IMPL_LINK( ScFilterDlg, ValModifyHdl, ComboBox*, pEd )
-                 static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0);
-            
-             ScQueryOp eOp  = (ScQueryOp)pLbCond->GetSelectEntryPos();
--           rEntry.eOp	  = eOp;
-+            rEntry.eOp	   = eOp;
-+            rEntry.bQueryByDate = mbHasDates[nQE];
- 
-         }
-     }		
-diff --git sc/source/ui/dbgui/pfiltdlg.cxx sc/source/ui/dbgui/pfiltdlg.cxx
-index 35bfc35..42c2c26 100644
---- sc/source/ui/dbgui/pfiltdlg.cxx
-+++ sc/source/ui/dbgui/pfiltdlg.cxx
-@@ -352,11 +352,12 @@ void ScPivotFilterDlg::UpdateValueList( USHORT nList )
-                 SCROW	nFirstRow	= theQueryData.nRow1;
-                 SCROW	nLastRow	= theQueryData.nRow2;
-                 nFirstRow++;
-+                bool bHasDates = false;
- 
-                 pEntryLists[nColumn] = new TypedScStrCollection( 128, 128 );
-                 pEntryLists[nColumn]->SetCaseSensitive( aBtnCase.IsChecked() );
-                 pDoc->GetFilterEntriesArea( nColumn, nFirstRow, nLastRow,
--                                            nTab, *pEntryLists[nColumn] );
-+                                            nTab, *pEntryLists[nColumn], bHasDates );
-             }
- 
-             TypedScStrCollection* pColl = pEntryLists[nColumn];
-diff --git sc/source/ui/docshell/docsh.cxx sc/source/ui/docshell/docsh.cxx
-index 2e9ad98..e884d14 100644
---- sc/source/ui/docshell/docsh.cxx
-+++ sc/source/ui/docshell/docsh.cxx
-@@ -1924,7 +1924,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
-             bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL);
-             if (bNeedRetypePassDlg && !pViewShell->ExecuteRetypePassDlg(PASSHASH_XL))
-             {
--                SetError( ERRCODE_ABORT );
-+                SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
-                 return false;
-             }
- #else
 diff --git sc/source/ui/inc/dbfunc.hxx sc/source/ui/inc/dbfunc.hxx
-index 91834e1..f9a76a0 100644
+index 91834e1..097202b 100644
 --- sc/source/ui/inc/dbfunc.hxx
 +++ sc/source/ui/inc/dbfunc.hxx
 @@ -80,7 +80,7 @@ public:
@@ -767,115 +291,12 @@ index 91834e1..f9a76a0 100644
  
                      // DB-Bereich vom Cursor
 -	ScDBData* 		GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bShrinkToData = false );
-+	ScDBData* 		GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bExpandRows = false, bool bShrinkToData = false );
++	ScDBData* 		GetDBData( BOOL bMarkArea = TRUE, ScGetDBMode eMode = SC_DB_MAKE, bool bShrinkToData = false, bool bExpandRows = false );
  
      void			NotifyCloseDbNameDlg( const ScDBCollection& rNewColl, const List& rDelAreaList );
  
-diff --git sc/source/ui/inc/filtdlg.hxx sc/source/ui/inc/filtdlg.hxx
-index c418e82..7409b5a 100644
---- sc/source/ui/inc/filtdlg.hxx
-+++ sc/source/ui/inc/filtdlg.hxx
-@@ -167,6 +167,7 @@ private:
-     ListBox*			aFieldLbArr[4];
-     ListBox*			aCondLbArr[4];
-     ListBox*			aConnLbArr[4];
-+    bool                mbHasDates[MAXQUERY];
-     BOOL                bRefreshExceptQuery[MAXQUERY];
-     USHORT				nFieldCount;
-     BOOL				bRefInputMode;
-diff --git sc/source/ui/inc/gridwin.hxx sc/source/ui/inc/gridwin.hxx
-index 4013e1a..aae0353 100644
---- sc/source/ui/inc/gridwin.hxx
-+++ sc/source/ui/inc/gridwin.hxx
-@@ -218,7 +218,7 @@ private:
- 
-     BOOL 			IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab );
-     void			ExecFilter( ULONG nSel, SCCOL nCol, SCROW nRow,
--                                const String& aValue );
-+                                const String& aValue, bool bCheckForDates );
-     void			FilterSelect( ULONG nSel );
- 
-     void			ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr );
-diff --git sc/source/ui/inc/preview.hxx sc/source/ui/inc/preview.hxx
-index 2449554..848f22e 100644
---- sc/source/ui/inc/preview.hxx
-+++ sc/source/ui/inc/preview.hxx
-@@ -66,6 +66,8 @@ private:
-     ScPreviewLocationData* pLocationData;	// stores table layout for accessibility API
-     FmFormView*		pDrawView;
- 
-+    SCTAB           nCurTab;
-+
-                                         // intern:
-     BOOL			bInPaint;
-     BOOL			bInGetState;
-diff --git sc/source/ui/inc/viewdata.hxx sc/source/ui/inc/viewdata.hxx
-index 6f0d986..19583a8 100644
---- sc/source/ui/inc/viewdata.hxx
-+++ sc/source/ui/inc/viewdata.hxx
-@@ -89,6 +89,13 @@ enum ScMarkType
- #endif
- };
- 
-+enum ScPasteFlags
-+{
-+    SC_PASTE_NONE   = 0,    // No flags specified
-+    SC_PASTE_MODE   = 1,    // Enable paste-mode
-+    SC_PASTE_BORDER = 2,    // Show a border around the source cells
-+};
-+
- class ScDocShell;
- class ScDocument;
- class ScDBFunc;
-@@ -210,6 +217,8 @@ private:
-     SCCOL				nTabStartCol;				// fuer Enter nach Tab
-     ScRange				aDelRange;					// fuer AutoFill-Loeschen
- 
-+    ScPasteFlags        nPasteFlags;
-+
-     ScSplitPos          eEditActivePart;            // the part that was active when edit mode was started
-     BOOL				bEditActive[4];				// aktiv?
-     BOOL				bActive;					// aktives Fenster ?
-@@ -295,6 +304,8 @@ public:
-     SCCOL			GetFixPosX() const						{ return pThisTab->nFixPosX; }
-     SCROW			GetFixPosY() const						{ return pThisTab->nFixPosY; }
-     BOOL			IsPagebreakMode() const					{ return bPagebreak; }
-+    BOOL            IsPasteMode() const                     { return nPasteFlags & SC_PASTE_MODE; }
-+    BOOL            ShowPasteSource() const                 { return nPasteFlags & SC_PASTE_BORDER; }
- 
-     void			SetPosX( ScHSplitPos eWhich, SCCOL nNewPosX );
-     void			SetPosY( ScVSplitPos eWhich, SCROW nNewPosY );
-@@ -309,6 +320,7 @@ public:
-     void			SetFixPosX( SCCOL nPos )						{ pThisTab->nFixPosX = nPos; }
-     void			SetFixPosY( SCROW nPos )						{ pThisTab->nFixPosY = nPos; }
-     void			SetPagebreakMode( BOOL bSet );
-+    void            SetPasteMode ( ScPasteFlags nFlags )            { nPasteFlags = nFlags; }
- 
-     void            SetZoomType( SvxZoomType eNew, BOOL bAll );
-     void            SetZoom( const Fraction& rNewX, const Fraction& rNewY, BOOL bAll );
-diff --git sc/source/ui/view/cellsh1.cxx sc/source/ui/view/cellsh1.cxx
-index d87d081..19ee659 100644
---- sc/source/ui/view/cellsh1.cxx
-+++ sc/source/ui/view/cellsh1.cxx
-@@ -1170,6 +1170,8 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
-                 WaitObject aWait( GetViewData()->GetDialogParent() );
-                 pTabViewShell->CopyToClip( NULL, FALSE, FALSE, TRUE );
-                 rReq.Done();
-+                GetViewData()->SetPasteMode( (ScPasteFlags) (SC_PASTE_MODE | SC_PASTE_BORDER) );
-+                pTabViewShell->ShowCursor();
-             }
-             break;
- 
-@@ -1178,6 +1180,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
-                 WaitObject aWait( GetViewData()->GetDialogParent() );
-                 pTabViewShell->CutToClip( NULL, TRUE );
-                 rReq.Done();
-+                GetViewData()->SetPasteMode( SC_PASTE_MODE );
-             }
-             break;
- 
 diff --git sc/source/ui/view/dbfunc.cxx sc/source/ui/view/dbfunc.cxx
-index 05dce54..fa05fa6 100644
+index 05dce54..e78581a 100644
 --- sc/source/ui/view/dbfunc.cxx
 +++ sc/source/ui/view/dbfunc.cxx
 @@ -107,7 +107,7 @@ void ScDBFunc::GotoDBArea( const String& rDBName )
@@ -883,7 +304,7 @@ index 05dce54..fa05fa6 100644
  //	aktuellen Datenbereich fuer Sortieren / Filtern suchen
  
 -ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bShrinkToData )
-+ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bExpandRows, bool bShrinkToData )
++ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, bool bShrinkToData, bool bExpandRows )
  {
      ScDocShell* pDocSh = GetViewData()->GetDocShell();
      ScDBData* pData = NULL;
@@ -911,80 +332,10 @@ index 05dce54..fa05fa6 100644
      }
      return pData;
 diff --git sc/source/ui/view/gridwin.cxx sc/source/ui/view/gridwin.cxx
-index b547e2c..57f1996 100644
+index 6e0280a..57f1996 100644
 --- sc/source/ui/view/gridwin.cxx
 +++ sc/source/ui/view/gridwin.cxx
-@@ -118,6 +118,7 @@
- #include "userdat.hxx"
- #include "drwlayer.hxx"
- #include "attrib.hxx"
-+#include "cellsh.hxx"
- #include "validat.hxx"
- #include "tabprotection.hxx"
- #include "postit.hxx"
-@@ -170,6 +171,7 @@ private:
-     BOOL			bInit;
-     BOOL			bCancelled;
-     BOOL            bInSelect;
-+    bool            mbListHasDates;
-     ULONG			nSel;
-     ScFilterBoxMode	eMode;
- 
-@@ -193,6 +195,8 @@ public:
-     BOOL            IsInInit() const        { return bInit; }
-     void			SetCancelled()			{ bCancelled = TRUE; }
-     BOOL            IsInSelect() const      { return bInSelect; }
-+    void            SetListHasDates(bool b) { mbListHasDates = b; }
-+    bool            HasDates() const        { return mbListHasDates; }
- };
- 
- //-------------------------------------------------------------------
-@@ -208,6 +212,7 @@ ScFilterListBox::ScFilterListBox( Window* pParent, ScGridWindow* pGrid,
-     bInit( TRUE ),
-     bCancelled( FALSE ),
-     bInSelect( FALSE ),
-+    mbListHasDates(false),
-     nSel( 0 ),
-     eMode( eNewMode )
- {
-@@ -912,7 +917,9 @@ void ScGridWindow::DoAutoFilterMenue( SCCOL nCol, SCROW nRow, BOOL bDataSelect )
-         pFilterBox->SetSeparatorPos( nDefCount - 1 );
- 
-         //	get list entries
--        pDoc->GetFilterEntries( nCol, nRow, nTab, aStrings, true );
-+        bool bHasDates = false;
-+        pDoc->GetFilterEntries( nCol, nRow, nTab, true, aStrings, bHasDates);
-+        pFilterBox->SetListHasDates(bHasDates);
- 
-         //	check widths of numerical entries (string entries are not included)
-         //	so all numbers are completely visible
-@@ -1122,7 +1129,7 @@ void ScGridWindow::FilterSelect( ULONG nSel )
-             ExecDataSelect( nCol, nRow, aString );
-             break;
-         case SC_FILTERBOX_FILTER:
--            ExecFilter( nSel, nCol, nRow, aString );
-+            ExecFilter( nSel, nCol, nRow, aString, pFilterBox->HasDates() );
-             break;
-         case SC_FILTERBOX_SCENARIO:
-             pViewData->GetView()->UseScenario( aString );
-@@ -1155,7 +1162,7 @@ void ScGridWindow::ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr )
- 
- void ScGridWindow::ExecFilter( ULONG nSel,
-                                SCCOL nCol, SCROW nRow,
--                               const String& aValue )
-+                               const String& aValue, bool bCheckForDates )
- {
-     SCTAB nTab = pViewData->GetTabNo();
-     ScDocument* pDoc = pViewData->GetDocument();
-@@ -1227,6 +1234,7 @@ void ScGridWindow::ExecFilter( ULONG nSel,
-                     rNewEntry.bDoQuery		 = TRUE;
-                     rNewEntry.bQueryByString = TRUE;
-                     rNewEntry.nField		 = nCol;
-+                    rNewEntry.bQueryByDate   = bCheckForDates;
-                     if ( nSel == SC_AUTOFILTER_TOP10 )
-                     {
-                         rNewEntry.eOp	= SC_TOPVAL;
-@@ -1268,6 +1276,7 @@ void ScGridWindow::ExecFilter( ULONG nSel,
+@@ -1276,6 +1276,7 @@ void ScGridWindow::ExecFilter( ULONG nSel,
                      pViewData->GetViewShell()->UpdateInputHandler();
                  }
  
@@ -992,122 +343,6 @@ index b547e2c..57f1996 100644
                  pViewData->GetView()->Query( aParam, NULL, TRUE );
                  pDBData->SetQueryParam( aParam );							// speichern
              }
-@@ -2962,12 +2971,30 @@ void ScGridWindow::SelectForContextMenu( const Point& rPosPixel )
-     }
- }
- 
-+static void ClearSingleSelection( ScViewData* pViewData )
-+{
-+    SCCOL nX;
-+    SCROW nY;
-+    ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( 
-+        pViewData->GetActiveWin() );
-+    if (!pTransObj)
-+        return;
-+
-+    ScDocument* pClipDoc = pTransObj->GetDocument();
-+    pClipDoc->GetClipArea( nX, nY, TRUE );
-+    if (nX == 0 && nY == 0)
-+    {
-+        ScTabView* pView = pViewData->GetView();
-+        pView->Unmark();
-+    }
-+}
-+
- void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
- {
-     // #96965# Cursor control for ref input dialog
-+    const KeyCode& rKeyCode = rKEvt.GetKeyCode();
-     if( SC_MOD()->IsRefDialogOpen() )
-     {
--        const KeyCode& rKeyCode = rKEvt.GetKeyCode();
-         if( !rKeyCode.GetModifier() && (rKeyCode.GetCode() == KEY_F2) )
-         {
-             SC_MOD()->EndReference();
-@@ -2982,9 +3009,35 @@ void __EXPORT ScGridWindow::KeyInput(const KeyEvent& rKEvt)
-             return;
-         }
-     }
-+    else if( rKeyCode.GetCode() == KEY_RETURN && pViewData->IsPasteMode() )
-+    {
-+        ScTabViewShell* pTabViewShell = pViewData->GetViewShell();
-+
-+        ScCellShell::PasteFromClipboard( pViewData, pTabViewShell, FALSE );
-+        ClearSingleSelection( pViewData );
-+
-+        uno::Reference<datatransfer::clipboard::XClipboard> xSystemClipboard = 
-+            TransferableHelper::GetSystemClipboard();
-+        if (xSystemClipboard.is())
-+        {
-+            xSystemClipboard->setContents(
-+                    uno::Reference<datatransfer::XTransferable>(),
-+                    uno::Reference<datatransfer::clipboard::XClipboardOwner>());
-+        }
-+
-+        // hide the border around the copy source
-+        pViewData->SetPasteMode( SC_PASTE_NONE );
-+        UpdateCursorOverlay();
-+        return;
-+    }
-     // wenn semi-Modeless-SfxChildWindow-Dialog oben, keine KeyInputs:
-     else if( !pViewData->IsAnyFillMode() )
-     {
-+        if (rKeyCode.GetCode() == KEY_ESCAPE)
-+        {
-+            pViewData->SetPasteMode( SC_PASTE_NONE );
-+            UpdateCursorOverlay();
-+        }
-         //	query for existing note marker before calling ViewShell's keyboard handling
-         //	which may remove the marker
-         BOOL bHadKeyMarker = ( pNoteMarker && pNoteMarker->IsByKeyboard() );
-diff --git sc/source/ui/view/preview.cxx sc/source/ui/view/preview.cxx
-index d1e59ca..0756c8f 100644
---- sc/source/ui/view/preview.cxx
-+++ sc/source/ui/view/preview.cxx
-@@ -112,6 +112,7 @@ ScPreview::ScPreview( Window* pParent, ScDocShell* pDocSh, ScPreviewShell* pView
-     bLocationValid( FALSE ),
-     pLocationData( NULL ),
-     pDrawView( NULL ),
-+    nCurTab ( ScDocShell::GetCurTab() ),
-     bInPaint( FALSE ),
-     bInGetState( FALSE ),
-     pDocShell( pDocSh ),
-@@ -252,8 +253,17 @@ void ScPreview::CalcPages( SCTAB /*nToWhichTab*/ )
-     //	but always all sheets are used (there is no selected sheet)
-     ScPrintOptions aOptions = SC_MOD()->GetPrintOptions();
- 
-+	ScMarkData aMarkData;
-+	aMarkData.SelectTable( nCurTab, TRUE );
-+
-     for (SCTAB i=nStart; i<nAnz; i++)
-     {
-+		if (!aOptions.GetAllSheets() && !aMarkData.GetTableSelect( i )) {
-+			nPages[i] = 0;
-+			nFirstAttr[i] = 0;
-+			continue;
-+		}
-+
-         long nAttrPage = i > 0 ? nFirstAttr[i-1] : 1;
- 
-         long nThisStart = nTotalPages;
-diff --git sc/source/ui/view/tabvwsh4.cxx sc/source/ui/view/tabvwsh4.cxx
-index 46e25c1..a7ba066 100644
---- sc/source/ui/view/tabvwsh4.cxx
-+++ sc/source/ui/view/tabvwsh4.cxx
-@@ -1194,8 +1194,13 @@ PrintDialog* __EXPORT ScTabViewShell::CreatePrintDialog( Window *pParent )
-     // instead of a separate progress for each sheet from ScPrintFunc
-     pDocShell->UpdatePendingRowHeights( MAXTAB, true );
- 
-+	ScMarkData aMarkData;
-+	aMarkData.SelectTable( GetViewData()->GetTabNo(), TRUE );
-+
-     for ( SCTAB i=0; i<nTabCount; i++ )
-     {
-+		if ( !bAllTabs && !aMarkData.GetTableSelect( i ) )
-+			continue;
-         ScPrintFunc aPrintFunc( pDocShell, pPrinter, i );
-         nDocPageMax += aPrintFunc.GetTotalPages();
-     }
 diff --git sc/source/ui/view/tabvwshc.cxx sc/source/ui/view/tabvwshc.cxx
 index 968984d..499c2a0 100644
 --- sc/source/ui/view/tabvwshc.cxx
@@ -1134,35 +369,3 @@ index 968984d..499c2a0 100644
  
              aArgSet.Put( ScQueryItem( SCITEM_QUERYDATA,
                                        GetViewData(),
-diff --git sc/source/ui/view/viewdata.cxx sc/source/ui/view/viewdata.cxx
-index df48982..e75b864 100644
---- sc/source/ui/view/viewdata.cxx
-+++ sc/source/ui/view/viewdata.cxx
-@@ -306,6 +306,7 @@ ScViewData::ScViewData( ScDocShell* pDocSh, ScTabViewShell* pViewSh )
-         eRefType	( SC_REFTYPE_NONE ),
-         nTabNo		( 0 ),
-         nRefTabNo	( 0 ),
-+        nPasteFlags ( SC_PASTE_NONE ),
-         eEditActivePart( SC_SPLIT_BOTTOMLEFT ),
-         bActive		( TRUE ),					//! wie initialisieren?
-         bIsRefMode	( FALSE ),
-@@ -432,6 +433,7 @@ void ScViewData::InitData( ScDocument* pDocument )
- //UNUSED2008-05      aDefPageZoomX = pRef->aDefPageZoomX;
- //UNUSED2008-05      aDefPageZoomY = pRef->aDefPageZoomY;
- //UNUSED2008-05      bPagebreak  = pRef->bPagebreak;
-+//UNUSED2008-05 	nPasteFlags = pRef->nPasteFlags;
- //UNUSED2008-05      aLogicMode  = pRef->aLogicMode;
- //UNUSED2008-05  
- //UNUSED2008-05      SetGridMode     ( pRef->IsGridMode() );
-diff --git sc/source/ui/view/viewfunc.cxx sc/source/ui/view/viewfunc.cxx
-index 8155a80..61670e7 100644
---- sc/source/ui/view/viewfunc.cxx
-+++ sc/source/ui/view/viewfunc.cxx
-@@ -1910,6 +1910,7 @@ void ScViewFunc::DeleteMulti( BOOL bRows, BOOL bRecord )
- 
- void ScViewFunc::DeleteContents( USHORT nFlags, BOOL bRecord )
- {
-+    GetViewData()->SetPasteMode( SC_PASTE_NONE );
-     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
-     BOOL bOnlyNotBecauseOfMatrix;
-     BOOL bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );


More information about the ooo-build-commit mailing list