ooo-build r11273 - in trunk: . patches/src680



Author: kyoshida
Date: Tue Jan 15 18:18:49 2008
New Revision: 11273
URL: http://svn.gnome.org/viewvc/ooo-build?rev=11273&view=rev

Log:
2008-01-15  Kohei Yoshida  <kyoshida novell com>

	* patches/src680/offapi-calc-datapilot-drilldown.diff:
	* patches/src680/sc-calc-datapilot-drilldown.diff: added cache table 
	implementation to Calc's DataPilot for source data caching.  also 
	refactored Calc's DataPilot code to make full use of the cache table.
	Several new UNO API's have been added to expose more of DataPilot's 
	functionality & attributes.  This is a backport of koheidatapilot01 CWS.
	
	* patches/src680/apply: apply the above patches.  They are under the new
	section labeled [ CalcDataPilotDrillDown ].


Added:
   trunk/patches/src680/offapi-calc-datapilot-drilldown.diff
   trunk/patches/src680/sc-calc-datapilot-drilldown.diff
Modified:
   trunk/ChangeLog
   trunk/patches/src680/apply

Modified: trunk/patches/src680/apply
==============================================================================
--- trunk/patches/src680/apply	(original)
+++ trunk/patches/src680/apply	Tue Jan 15 18:18:49 2008
@@ -35,7 +35,8 @@
 Localize  : 
 # Novell
 NovellBase : LinuxCommon, NovellOnly, NovellOnlyUnix, \
-	     NotDebian, Lockdown, CalcSolver, Split, Shrink
+	     NotDebian, Lockdown, CalcSolver, Split, Shrink, \
+	     CalcDataPilotDrillDown
 SUSE-9.1  : NovellBase
 SUSE-9.2  : NovellBase
 SUSE-9.3  : NovellBase
@@ -1647,6 +1648,12 @@
 # allow internal libsvg, hic sunt (still always) leones, HACK!!!
 libsvg-module.diff, fridrich
 
+[ CalcDataPilotDrillDown ]
+# Implements DataPilot cache table, result drill-down, and some extra UNO API.
+SectionOwner => kohei
+SectionIssue => i#57030, i#83250, i#84349
+sc-calc-datapilot-drilldown.diff
+offapi-calc-datapilot-drilldown.diff
 
 [ SharedWorksheets ]
 SectionOwner => jholesov

Added: trunk/patches/src680/offapi-calc-datapilot-drilldown.diff
==============================================================================
--- (empty file)
+++ trunk/patches/src680/offapi-calc-datapilot-drilldown.diff	Tue Jan 15 18:18:49 2008
@@ -0,0 +1,823 @@
+Index: offapi/com/sun/star/sheet/DataPilotFieldFilter.idl
+===================================================================
+RCS file: /cvs/api/offapi/com/sun/star/sheet/DataPilotFieldFilter.idl,v
+retrieving revision 1.2
+retrieving revision 1.1.2.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.2 -r1.1.2.3
+--- offapi/com/sun/star/sheet/DataPilotFieldFilter.idl	26 Nov 2007 15:22:52 -0000	1.2
++++ offapi/com/sun/star/sheet/DataPilotFieldFilter.idl	7 Dec 2007 05:39:58 -0000	1.1.2.3
+@@ -42,12 +42,34 @@
+ 
+ //=============================================================================
+ 
++/** A single filtering condition used when constructing a drill-down sheet.
++
++   <p>Each instance of <type>DataPilotFieldFilter</type> represents a filtering 
++   condition.  It is used when evaluating a row in a data source whether or not 
++   to include it in a filtered subset of the original data.  For example, for 
++   a given row to be included in the output of a drill-down data table, the row 
++   must match every single instance of <type>DataPilotFieldFilter</type> to be 
++   qualified.  If the field specified by the value of <member>FieldName</member>
++   is not found, then that filter condition will not be evaluated.</p>
++
++   <p>Note that this struct is typically used in a sequence and is not normally 
++   used as a single instance.</p>
++
++   @see <method>XDrillDownDataSupplier::getDrillDownData</method>
++   @see <type>DataPilotTableResultData</type>
++
++   @since OOo 3.0.0
++ */
+ struct DataPilotFieldFilter
+ {
+-    /** Field name. */
++    /** Field name.
++
++        @see <type>DataPilotField</type>
++     */
+     string FieldName;
+ 
+-    /** String value that needs to match against. */
++    /** String value to match against.
++     */
+     string MatchValue;
+ };
+ 
+Index: offapi/com/sun/star/sheet/DataPilotOutputRangeType.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/DataPilotOutputRangeType.idl
+diff -N offapi/com/sun/star/sheet/DataPilotOutputRangeType.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/DataPilotOutputRangeType.idl	7 Dec 2007 05:29:36 -0000	1.1.2.3
+@@ -0,0 +1,80 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: DataPilotOutputRangeType.idl,v $
++ *
++ *  $Revision: 1.1.2.3 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 05:29:36 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_DataPilotOutputRangeType_idl__
++#define __com_sun_star_sheet_DataPilotOutputRangeType_idl__
++
++module com { module sun { module star { module sheet {
++
++//============================================================================
++
++/** specifies region type of DataPilot table range
++
++    <p>This constant set is used to indicate the type of output range desired when
++    <method>XDataPilotTable2::getOutputRangeByType</method> is called, which 
++    returns a different cell range depending upon the value passed to it as the argument.</p>
++
++    @see com::sun::star::sheet::XDataPilotTable2
++
++    @since OOo 3.0.0
++ */
++constants DataPilotOutputRangeType
++{
++    //------------------------------------------------------------------------
++
++    /** whole DataPilot output range including the header area above the table
++        where the filter and page field buttons are located. */
++    const long WHOLE = 0;
++
++    //------------------------------------------------------------------------
++
++    /** whole table but without the header area where the filter and page field 
++        buttons are located. */
++    const long TABLE = 1;
++
++    //------------------------------------------------------------------------
++
++    /** result area where the result values are displayed.  This also includes
++        the column and row subtotal areas when they are displayed. */
++    const long RESULT = 2;
++};
++
++//============================================================================
++
++}; }; }; };
++
++
++
++#endif
+Index: offapi/com/sun/star/sheet/DataPilotSource.idl
+===================================================================
+RCS file: /cvs/api/offapi/com/sun/star/sheet/DataPilotSource.idl,v
+retrieving revision 1.6
+retrieving revision 1.6.404.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.6 -r1.6.404.3
+--- offapi/com/sun/star/sheet/DataPilotSource.idl	8 Sep 2005 04:34:04 -0000	1.6
++++ offapi/com/sun/star/sheet/DataPilotSource.idl	6 Dec 2007 22:19:05 -0000	1.6.404.3
+@@ -104,6 +104,29 @@
+ 	 */
+ 	[property] boolean RowGrand;
+ 
++    //-------------------------------------------------------------------------
++
++    /** specifies the number of row fields.
++
++        @since OOo 3.0.0
++     */
++    [readonly, property, optional] long RowFieldCount;
++
++    //-------------------------------------------------------------------------
++
++    /** specifies the number of column fields. 
++
++        @since OOo 3.0.0
++     */
++    [readonly, property, optional] long ColumnFieldCount;
++
++    //-------------------------------------------------------------------------
++
++    /** specifies the number of data fields. 
++
++        @since OOo 3.0.0
++     */
++    [readonly, property, optional] long DataFieldCount;
+ };
+ 
+ //=============================================================================
+Index: offapi/com/sun/star/sheet/DataPilotTableHeaderData.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/DataPilotTableHeaderData.idl
+diff -N offapi/com/sun/star/sheet/DataPilotTableHeaderData.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/DataPilotTableHeaderData.idl	7 Dec 2007 05:29:36 -0000	1.1.2.3
+@@ -0,0 +1,87 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: DataPilotTableHeaderData.idl,v $
++ *
++ *  $Revision: 1.1.2.3 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 05:29:36 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_DataPilotTableHeaderData_idl__
++#define __com_sun_star_sheet_DataPilotTableHeaderData_idl__
++
++#include <com/sun/star/sheet/DataPilotFieldFilter.idl>
++#include <com/sun/star/sheet/DataResult.idl>
++
++//=============================================================================
++
++module com {  module sun {  module star {  module sheet {
++
++//=============================================================================
++
++/** information about a cell within the column or row header area of a DataPilot table.
++
++    This struct contains information about a particular cell located within the 
++    column or row header area of a DataPilot table.  This is the type that is
++    contained in <member>DataPilotTablePositionData::PositionData</member> when 
++    the value of <member>DataPilotTablePositionData::PositionType</member> is
++    either <const>DataPilotTablePositionType::ROW_HEADER</const> or 
++    <const>DataPilotTablePositionType::COLUMN_HEADER</const>.
++
++    @see com::sun::star::sheet::DataPilotTablePositionData
++    @see com::sun::star::sheet::DataPilotTablePositionType
++    @see com::sun::star::sheet::DataPilotFieldFilter
++    @see com::sun::star::sheet::DataResult
++
++    @since OOo 3.0.0
++ */
++struct DataPilotTableHeaderData
++{
++    /** number of dimensions */
++    long    Dimension;
++
++    /** hierarchy */
++    long    Hierarchy;
++
++    /** level */
++    long    Level;
++
++    /** flag */
++    long    Flags;
++
++    /** member name */
++    string  MemberName;
++};
++
++//=============================================================================
++
++}; }; }; };
++
++#endif
++
+Index: offapi/com/sun/star/sheet/DataPilotTablePositionData.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/DataPilotTablePositionData.idl
+diff -N offapi/com/sun/star/sheet/DataPilotTablePositionData.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/DataPilotTablePositionData.idl	7 Dec 2007 05:29:36 -0000	1.1.2.5
+@@ -0,0 +1,98 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: DataPilotTablePositionData.idl,v $
++ *
++ *  $Revision: 1.1.2.5 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 05:29:36 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_DataPilotTablePositionData_idl__
++#define __com_sun_star_sheet_DataPilotTablePositionData_idl__
++
++#include <com/sun/star/sheet/DataPilotFieldFilter.idl>
++
++//=============================================================================
++
++module com {  module sun {  module star {  module sheet {
++
++//=============================================================================
++
++/** This structure contains information on a cell within a DataPilot table.
++
++    <p>This structure contains information on a particular cell within a DataPilot
++    table, and is used to retrieve its metadata.  The <member>PositionType</member>
++    member specifies in which sub-area of the table the cell is positioned, which
++    in turn determines the type of metadata contained in the <member>PositionData</member>
++    member.</p>
++
++    @see com::sun::star::sheet::DataPilotTablePositionType
++    @see com::sun::star::sheet::DataPiotTableResultData
++    @see com::sun::star::sheet::DataPiotTableHeaderData
++
++    @since OOo 3.0.0
++ */
++struct DataPilotTablePositionData
++{
++	//-------------------------------------------------------------------------
++
++    /** This parameter specifies which sub-area of a DataPilot table a given 
++        cell is positioned.  See <type>DataPilotTablePositionType</type>
++        for how to interpret the value of this parameter.
++
++        @see com::sun::star::sheet::DataPilotTablePositionType
++     */
++    long    PositionType;
++
++	//-------------------------------------------------------------------------
++
++    /** <p>This member contains a structure of different types depending on the 
++        position type specified in <member>PositionType</member> member.</p>
++
++        <p>When the value of <member>PositionType</member> is 
++        <const>DataPilotTablePositionType::RESULT</const>, <member>DataPilotTablePositionData::PositionData</member> 
++        contains an instance of type <type>DataPilotTableResultData</type>, 
++        whereas when the value of <member>DataPilotTablePositionData::PositionType</member>
++        is either <const>DataPilotTablePositionType::ROW_HEADER</const> 
++        or <const>DataPilotTablePositionType::COLUMN_HEADER</const>, then the 
++        <member>PositionData</member> member contains an instance of type <type>
++        DataPilotTableHeaderData</type>.</p>
++
++        @see com::sun::star::sheet::DataPiotTableResultData
++        @see com::sun::star::sheet::DataPiotTableHeaderData
++     */
++    any     PositionData;
++};
++
++//=============================================================================
++
++}; }; }; };
++
++#endif
++
+Index: offapi/com/sun/star/sheet/DataPilotTablePositionType.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/DataPilotTablePositionType.idl
+diff -N offapi/com/sun/star/sheet/DataPilotTablePositionType.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/DataPilotTablePositionType.idl	7 Dec 2007 05:29:36 -0000	1.1.2.6
+@@ -0,0 +1,82 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: DataPilotTablePositionType.idl,v $
++ *
++ *  $Revision: 1.1.2.6 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 05:29:36 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_DataPilotTablePositionType_idl__
++#define __com_sun_star_sheet_DataPilotTablePositionType_idl__
++
++module com { module sun { module star { module sheet {
++
++//============================================================================
++
++/** specifies in which sub-area a cell is positioned within a DataPilot table.
++
++    @see com::sun::star::sheet::DataPilotTablePositionData
++    @see com::sun::star::sheet::DataPilotTableResultData
++    @see com::sun::star::sheet::DataPilotTableHeaderData
++
++    @since OOo 3.0.0
++ */
++constants DataPilotTablePositionType
++{
++    //------------------------------------------------------------------------
++
++    /** indicates that the specified cell is not in the DataPilot table. */
++    const long NOT_IN_TABLE = 0;
++
++    //------------------------------------------------------------------------
++
++    /** indicates that the specified cell is within the result area. */
++    const long RESULT = 1;
++
++    //------------------------------------------------------------------------
++
++    /** indicates that the specified cell is within the row header area. */
++    const long ROW_HEADER = 2;
++
++    //------------------------------------------------------------------------
++
++    /** indicates that the specified cell is within the column header area. */
++    const long COLUMN_HEADER = 3;
++
++    //------------------------------------------------------------------------
++};
++
++//============================================================================
++
++}; }; }; };
++
++
++
++#endif
+Index: offapi/com/sun/star/sheet/DataPilotTableResultData.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/DataPilotTableResultData.idl
+diff -N offapi/com/sun/star/sheet/DataPilotTableResultData.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/DataPilotTableResultData.idl	7 Dec 2007 05:29:36 -0000	1.1.2.5
+@@ -0,0 +1,94 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: DataPilotTableResultData.idl,v $
++ *
++ *  $Revision: 1.1.2.5 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 05:29:36 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_DataPilotTableResultData_idl__
++#define __com_sun_star_sheet_DataPilotTableResultData_idl__
++
++#include <com/sun/star/sheet/DataPilotFieldFilter.idl>
++#include <com/sun/star/sheet/DataResult.idl>
++
++//=============================================================================
++
++module com {  module sun {  module star {  module sheet {
++
++//=============================================================================
++
++/** information about a cell positioned within the result area of a DataPilot table.
++
++    <p><type>DataPilotTableResultData</type> contains information about a 
++    particular cell positioned within the result area of a DataPilot table.</p>
++
++    @see com::sun::star::sheet::DataPilotTablePositionData
++    @see com::sun::star::sheet::DataPilotTablePositionType
++    @see com::sun::star::sheet::DataPilotFieldFilter
++    @see com::sun::star::sheet::DataResult
++
++    @since OOo 3.0.0
++ */
++struct DataPilotTableResultData
++{
++    //------------------------------------------------------------------------
++
++    /** This is a set of filter criteria that can be used to re-create those
++        data rows that contribute to the value shown in the cell.
++
++        @see com::sun::star::sheet::DataPilotFieldFilter
++     */
++    sequence< DataPilotFieldFilter >    FieldFilters;
++
++    //------------------------------------------------------------------------
++
++    /** This is a 0-based index that specifies which data field the data displayed
++        in the cell is for; the value of 0 means the cell is for the first data
++        field, 1 for the second, and so on.
++     */
++    long                                DataFieldIndex;
++
++    //------------------------------------------------------------------------
++
++    /** more information about the result contained in the 
++        <type>DataResult</type> type.
++
++        @see com::sun::star::sheet::DataResult
++     */
++    DataResult                          Result;
++};
++
++//=============================================================================
++
++}; }; }; };
++
++#endif
++
+Index: offapi/com/sun/star/sheet/XDataPilotTable2.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/XDataPilotTable2.idl
+diff -N offapi/com/sun/star/sheet/XDataPilotTable2.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/XDataPilotTable2.idl	7 Dec 2007 05:29:36 -0000	1.1.2.6
+@@ -0,0 +1,137 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: XDataPilotTable2.idl,v $
++ *
++ *  $Revision: 1.1.2.6 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 05:29:36 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_XDataPilotTable2_idl__
++#define __com_sun_star_sheet_XDataPilotTable2_idl__
++
++#ifndef __com_sun_star_uno_XInterface_idl__
++#include <com/sun/star/uno/XInterface.idl>
++#endif
++
++#ifndef __com_sun_star_table_CellAddress_idl__
++#include <com/sun/star/table/CellAddress.idl>
++#endif
++
++#ifndef __com_sun_star_table_CellRangeAddress_idl__
++#include <com/sun/star/table/CellRangeAddress.idl>
++#endif
++
++#ifndef __com_sun_star_sheet_XDataPilotTable_idl__
++#include <com/sun/star/sheet/XDataPilotTable.idl>
++#endif
++
++#ifndef __com_sun_star_sheet_DataPilotOutputRangeType_idl__
++#include <com/sun/star/sheet/DataPilotOutputRangeType.idl>
++#endif
++
++#ifndef __com_sun_star_sheet_DataPilotFieldFilter_idl__
++#include <com/sun/star/sheet/DataPilotFieldFilter.idl>
++#endif
++
++#include <com/sun/star/sheet/DataPilotTablePositionData.idl>
++
++module com {  module sun {  module star {  module sheet {
++
++/** additional methods to extend <type scope="com::sun::star::sheet">XDataPilotTable</type>. 
++
++   <type scope="com::sun::star::sheet">XDataPilotTable2</type> extends the old 
++   <type scope="com::sun::star::sheet">XDataPilotTable</type> interface with 
++   additional methods.
++
++   @see com::sun::star::sheet::XDataPilotTable
++
++   @since OOo 3.0.0
++ */
++interface XDataPilotTable2: com::sun::star::sheet::XDataPilotTable
++{
++    /** When the address of a cell within the result area is given, 
++        <method>XDataPilotTable2::getDrillDownData</method> returns its drill-down 
++        output table that includes only those rows that contribute to the value of
++        that cell.
++
++        @param aAddr cell address within the result area of a DataPilot table.
++
++        @returns drill-down output as 2-dimensional sequence, including the header row.
++
++        @see <method>XDataPilotTable2::insertDrillDownSheet</method>
++     */
++    sequence< sequence< any > > getDrillDownData( [in] com::sun::star::table::CellAddress aAddr );
++
++    /** Given a cell address, it returns the information about that cell.  The 
++        type of information returned depends upon whether the cell is within 
++        the result area or column/row header area.
++
++        @param aAddr address of the cell whose information is to be returned.
++
++        @returns <type>DataPilotTablePositionData</type> which contains the 
++        position type and the information for that cell position.
++
++        @see com::sun::star::sheet::DataPilotTablePositionData
++        @see com::sun::star::sheet::DataPilotTableHeaderData
++        @see com::sun::star::sheet::DataPilotTableResultData
++     */
++    DataPilotTablePositionData getPositionData( [in] com::sun::star::table::CellAddress aAddr );
++
++    /** <p>This method inserts a new sheet to display the drill-down data for a 
++        specified result cell.  A drill-down data for a result cell consists 
++        of a subset of rows from the original data source that contribute to 
++        the value displayed in that cell.</p>
++
++        <p>The new sheet is always inserted to the immediate left of the current
++        sheet where the DataPilot table is.  Note that when the drill-down data
++        is empty, no new sheet is inserted.</p>
++
++        @param aAddr address of a result cell
++
++        @returns <void/>
++     */
++    void insertDrillDownSheet( [in] com::sun::star::table::CellAddress aAddr );
++
++    /** <p>This method returns a different output range of a DataPilot table 
++        per specified output range type.</p>
++
++        @returns <type scope="com::sun::star::table">CellRangeAddress</type> depicting
++        the range specified.  See <type>DataPilotOutputRangeType</type> for a set
++        of possible output range types.
++
++        @see com::sun::star::sheet::DataPilotOutputRangeType
++     */
++    com::sun::star::table::CellRangeAddress getOutputRangeByType( [in] long nType );
++};
++
++}; }; }; };
++
++#endif
++
+Index: offapi/com/sun/star/sheet/XDrillDownDataSupplier.idl
+===================================================================
+RCS file: offapi/com/sun/star/sheet/XDrillDownDataSupplier.idl
+diff -N offapi/com/sun/star/sheet/XDrillDownDataSupplier.idl
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ offapi/com/sun/star/sheet/XDrillDownDataSupplier.idl	7 Dec 2007 18:37:34 -0000	1.1.2.2
+@@ -0,0 +1,95 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: XDrillDownDataSupplier.idl,v $
++ *
++ *  $Revision: 1.1.2.2 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/12/07 18:37:34 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef __com_sun_star_sheet_XDrillDownDataSupplier_idl__
++#define __com_sun_star_sheet_XDrillDownDataSupplier_idl__
++
++#ifndef __com_sun_star_uno_XInterface_idl__
++#include <com/sun/star/uno/XInterface.idl>
++#endif
++
++#ifndef __com_sun_star_sheet_DataPilotFieldFilter_idl__
++#include <com/sun/star/sheet/DataPilotFieldFilter.idl>
++#endif
++
++#ifndef __com_sun_star_table_CellAddress_idl__
++#include <com/sun/star/table/CellAddress.idl>
++#endif
++
++//=============================================================================
++
++module com {  module sun {  module star {  module sheet {
++
++//=============================================================================
++
++/** supplies a filtered subset of the original data source based on filtering criteria.
++
++    A service that acts as a DataPilot data source can optionally implement this
++    interface to allow drill-down of result data.  The method this interface provides
++    is used internally when calling <method>XDataPilotTable2::getDrillDownData</method>
++    or <method>XDataPilotTable2::insertDrillDownSheet</method>.  If the data source
++    service does not implement this interface, then the aformentioned two methods
++    will have no effect.
++
++    @see com::sun::star::sheet::DataPilotSource
++
++    @since OOo 3.0.0
++ */
++interface XDrillDownDataSupplier: com::sun::star::uno::XInterface
++{
++    /** This method returns filtered subset of the original source data based on 
++        a given set of filtering criteria.
++
++        @param aFilters filtering criteria
++
++        @returns a filtered subset of the origintal source data as 2-dimensional
++        sequences of <type scope="com::sun::star::uno">Any</any>.  The first row
++        must be the header row.  Each <type scope="com::sun::star::uno">Any</type>
++        instance must contain either <type>double</type> value for a numeric cell, or 
++        a <type>string</type> value for a string cell.
++
++        @see com::sun::star::sheet::DataPilotFieldFilter
++        @see com::sun::star::sheet::XDataPilotTable2
++     */
++    sequence< sequence< any > > getDrillDownData( 
++        [in] sequence< com::sun::star::sheet::DataPilotFieldFilter > aFilters );
++};
++
++//=============================================================================
++
++}; }; }; };
++
++#endif
++
+--- offapi/com/sun/star/sheet/makefile.mk.orig	2008-01-15 11:37:11.000000000 -0500
++++ offapi/com/sun/star/sheet/makefile.mk	2008-01-15 11:40:44.000000000 -0500
+@@ -315,7 +315,14 @@
+ 	XViewPanesSupplier.idl\
+ 	XViewSplitable.idl\
+ 	XVolatileResult.idl\
+-	_NamedRange.idl
++	_NamedRange.idl\
++	DataPilotTablePositionData.idl\
++	DataPilotTablePositionType.idl\
++	DataPilotOutputRangeType.idl\
++	DataPilotTableHeaderData.idl\
++	DataPilotTableResultData.idl\
++	XDataPilotTable2.idl\
++	XDrillDownDataSupplier.idl
+ 
+ # ------------------------------------------------------------------
+ 

Added: trunk/patches/src680/sc-calc-datapilot-drilldown.diff
==============================================================================
--- (empty file)
+++ trunk/patches/src680/sc-calc-datapilot-drilldown.diff	Tue Jan 15 18:18:49 2008
@@ -0,0 +1,5142 @@
+Index: sc/inc/dapiuno.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dapiuno.hxx,v
+retrieving revision 1.9
+retrieving revision 1.9.508.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.9 -r1.9.508.4
+--- sc/inc/dapiuno.hxx	13 Jan 2006 16:51:24 -0000	1.9
++++ sc/inc/dapiuno.hxx	30 Nov 2007 00:13:25 -0000	1.9.508.4
+@@ -56,9 +56,7 @@
+ #include <svtools/itemprop.hxx>
+ #endif
+ 
+-#ifndef _COM_SUN_STAR_SHEET_XDATAPILOTTABLE_HPP_
+-#include <com/sun/star/sheet/XDataPilotTable.hpp>
+-#endif
++#include <com/sun/star/sheet/XDataPilotTable2.hpp>
+ #ifndef _COM_SUN_STAR_SHEET_XDATAPILOTTABLES_HPP_
+ #include <com/sun/star/sheet/XDataPilotTables.hpp>
+ #endif
+@@ -124,6 +122,11 @@
+ #include <memory> 
+ #include <vector>
+ 
++namespace com { namespace sun { namespace star { namespace sheet {
++    struct DataPilotFieldFilter;
++    struct DataPilotTablePositionData;
++}}}}
++
+ class ScDocShell;
+ class ScPivot;
+ class ScDPSaveDimension;
+@@ -360,7 +363,7 @@
+ 
+ 
+ class ScDataPilotTableObj : public ScDataPilotDescriptorBase,
+-							public com::sun::star::sheet::XDataPilotTable
++							public com::sun::star::sheet::XDataPilotTable2
+ {
+ private:
+ 	SCTAB					nTab;
+@@ -392,6 +395,21 @@
+ 								throw(::com::sun::star::uno::RuntimeException);
+ 	virtual void SAL_CALL	refresh() throw(::com::sun::star::uno::RuntimeException);
+ 
++                            // XDataPilotTable2
++    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > > 
++        SAL_CALL getDrillDownData(const ::com::sun::star::table::CellAddress& aAddr)
++                                throw(::com::sun::star::uno::RuntimeException);
++
++    virtual ::com::sun::star::sheet::DataPilotTablePositionData
++        SAL_CALL getPositionData(const ::com::sun::star::table::CellAddress& aAddr)
++                                throw(::com::sun::star::uno::RuntimeException);
++
++    virtual void SAL_CALL insertDrillDownSheet(const ::com::sun::star::table::CellAddress& aAddr)
++                                throw(::com::sun::star::uno::RuntimeException);
++
++    virtual ::com::sun::star::table::CellRangeAddress SAL_CALL getOutputRangeByType( sal_Int32 nType )
++                                throw(::com::sun::star::uno::RuntimeException);
++
+ 							// XTypeProvider (overloaded)
+ 	virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes()
+ 								throw(::com::sun::star::uno::RuntimeException);
+Index: sc/inc/dpcachetable.hxx
+===================================================================
+RCS file: sc/inc/dpcachetable.hxx
+diff -N sc/inc/dpcachetable.hxx
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ sc/inc/dpcachetable.hxx	29 Oct 2007 17:44:39 -0000	1.1.2.1
+@@ -0,0 +1,189 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: dpcachetable.hxx,v $
++ *
++ *  $Revision: 1.1.2.1 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/10/29 17:44:39 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#ifndef SC_DPCACHETABLE_HXX
++#define SC_DPCACHETABLE_HXX
++
++#include "sal/types.h"
++#include "osl/mutex.hxx"
++#include "global.hxx"
++#include "collect.hxx"
++#include "dptabdat.hxx"
++
++#include <vector>
++#include <set>
++#include <hash_map>
++#include <boost/shared_ptr.hpp>
++#include <com/sun/star/uno/Reference.hxx>
++
++namespace com { namespace sun { namespace star {
++    namespace sdbc {
++        class XRowSet;
++    }
++    namespace sheet {
++        struct DataPilotFieldFilter;
++    }
++}}}
++
++class Date;
++
++class ScDocument;
++class ScRange;
++class ScDPDimension;
++
++class ScSharedStringTable
++{
++public:
++    static const sal_Int32 EMPTY = 0;
++
++    sal_Int32 insertString(const String& aStr);
++    sal_Int32 getStringId(const String& aStr);
++    const String* getString(sal_Int32 nId) const;
++
++    ScSharedStringTable();
++    ~ScSharedStringTable();
++
++private:
++    typedef ::std::hash_map< String, sal_Int32, ScStringHashCode, ::std::equal_to< String > > SharedStrMap;
++
++    ::std::vector<String> maSharedStrings;
++    SharedStrMap maSharedStringIds;
++    sal_Int32 mnStrCount;
++};
++
++// ----------------------------------------------------------------------------
++
++class ScDPCacheTable
++{
++public:
++    /** individual cell within table. */
++    struct Cell
++    {
++        sal_Int32   mnStrId;
++        double      mfValue;
++        bool        mbNumeric;
++        sal_uInt8   mnType;
++
++        Cell();
++    };
++
++    /** filtering criteria */
++    struct Filter
++    {
++        sal_Int32   mnFieldIndex;
++        sal_Int32   mnMatchStrId;
++
++        Filter();
++    };
++
++    ScDPCacheTable();
++    ~ScDPCacheTable();
++
++    sal_Int32 getHeaderSize() const;
++    sal_Int32 getRowSize() const;
++    sal_Int32 getColSize() const;
++
++    /** Fill the internal table from the cell range provided.  This function
++        assumes that the first row is the column header. */
++    void fillTable(ScDocument* pDoc, const ScRange& rRange, const ScQueryParam& rQuery, BOOL* pSpecial);
++
++    /** Fill the internal table from database connection object.  This function
++        assumes that the first row is the column header. */
++    void fillTable(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet >& xRowSet,
++                   const Date& rNullDate);
++
++    /** Check whether a specified row is active or not.  When a row is active,
++        it is used in calculation of the results data.  A row becomes inactive
++        when it is filtered out by page field. */
++    bool isRowActive(sal_Int32 nRow) const;
++
++    /** Set filter on/off flag to each row to control visibility.  The caller
++        must ensure that the table is filled before calling this function. */
++    void filterByPageDimension(const ::std::vector<ScDPDimension*>& rPageDims);
++
++    /** Get the cell instance at specified location within the data grid. Note
++        that the data grid doesn't include the header row.  Don't delete the
++        returned object! */
++    const ::ScDPCacheTable::Cell* getCell(SCCOL nCol, SCROW nRow) const;
++
++    const String* getFieldName(sal_Int32 nIndex) const;
++
++    /** Get the field index (i.e. column ID in the original data source) based
++        on the string value that corresponds with the column title.  It returns
++        -1 if no field matching the string value exists. */
++    sal_Int32 getFieldIndex(const String& rStr) const;
++
++    /** Get the unique entries for a field specified by index.  The caller must
++        make sure that the table is filled before calling function, or it will
++        get an empty collection. */
++    const TypedStrCollection& getFieldEntries(sal_Int32 nIndex) const;
++
++    void filterTable(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters,
++                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rTabData);
++
++    void clear();
++    void swap(ScDPCacheTable& rOther);
++    bool empty() const;
++
++    static const String* getString(sal_Int32 nId);
++    static sal_Int32 getStringId(const String& aStr);
++
++private:
++    void getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell& rCell);
++    ScDPCacheTable::Cell getSelectedDimension(ScDPDimension* pDim) const;
++
++private:
++    typedef ::boost::shared_ptr<TypedStrCollection> TypedStrCollectionPtr;
++
++    /** main data table. */
++    ::std::vector< ::std::vector< ::ScDPCacheTable::Cell > > maTable;
++
++    /** header string IDs */
++    ::std::vector<sal_Int32> maHeader;
++
++    /** unique field entires for each field (column). */
++    ::std::vector<TypedStrCollectionPtr> maFieldEntries;
++
++    /** used to track visibility of rows.  The first row below the header row
++        has the index of 0. */
++    ::std::vector<bool> maRowsVisible;
++
++    static sal_Int32 insertString(const String& aStr);
++    static ::osl::Mutex maStrMutex;
++    static ScSharedStringTable maStringTable;
++};
++
++
++#endif
+Index: sc/inc/dpgroup.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dpgroup.hxx,v
+retrieving revision 1.4
+retrieving revision 1.4.570.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.4 -r1.4.570.2
+--- sc/inc/dpgroup.hxx	8 Sep 2005 17:34:35 -0000	1.4
++++ sc/inc/dpgroup.hxx	6 Dec 2007 07:06:14 -0000	1.4.570.2
+@@ -37,6 +37,7 @@
+ #define SC_DPGROUP_HXX
+ 
+ #include <vector>
++#include <hash_set>
+ 
+ #ifndef SC_DPTABDAT_HXX
+ #include "dptabdat.hxx"
+@@ -180,13 +181,17 @@
+ 
+ class ScDPGroupTableData : public ScDPTableData
+ {
++    typedef ::std::hash_set< ::rtl::OUString, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > StringHashSet;
++
+     ScDPTableData*          pSourceData;
+     long                    nSourceCount;
+     ScDPGroupDimensionVec   aGroups;
+     ScDPNumGroupDimension*  pNumGroups;     // array[nSourceCount]
+     ScDocument*             pDoc;
++    StringHashSet           aGroupNames;
+ 
+     void        FillGroupValues( ScDPItemData* pItemData, long nCount, const long* pDims );
++    void        CopyFields(const ::std::vector<long>& rFieldDims, ::std::vector<long>& rNewFieldDims);
+     long*       CopyFields( const long* pSourceDims, long nCount );
+ 
+     bool        IsNumGroupDimension( long nDimension ) const;
+@@ -213,8 +218,12 @@
+     virtual void                    DisposeData();
+     virtual void                    SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty );
+ 
+-    virtual void                    ResetIterator();
+-    virtual BOOL                    GetNextRow( const ScDPTableIteratorParam& rParam );
++    virtual void                    CreateCacheTable();
++    virtual void                    FilterCacheTable(const ::std::vector<ScDPDimension*>& rPageDims);
++    virtual void                    GetDrillDownData(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters,
++                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rTabData);
++    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow);
++    virtual const ScDPCacheTable&   GetCacheTable() const;
+ 
+     virtual BOOL                    IsBaseForGroup(long nDim) const;
+     virtual long                    GetGroupBase(long nGroupDim) const;
+Index: sc/inc/dpobject.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dpobject.hxx,v
+retrieving revision 1.13
+retrieving revision 1.12.112.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.13 -r1.12.112.6
+--- sc/inc/dpobject.hxx	26 Nov 2007 15:18:35 -0000	1.13
++++ sc/inc/dpobject.hxx	4 Dec 2007 16:51:09 -0000	1.12.112.6
+@@ -62,6 +62,12 @@
+ 
+ //------------------------------------------------------------------
+ 
++namespace com { namespace sun { namespace star { namespace sheet {
++
++    struct DataPilotTablePositionData;
++    struct DataPilotTableHeaderData;
++
++}}}}
+ 
+ namespace com { namespace sun { namespace star { namespace sheet {
+     struct DataPilotFieldFilter;
+@@ -71,7 +77,6 @@
+ class SvStream;
+ class ScDPSaveData;
+ class ScDPOutput;
+-struct ScDPPositionData;
+ class ScMultipleReadHeader;
+ class ScMultipleWriteHeader;
+ class ScPivot;
+@@ -82,7 +87,7 @@
+ class StrCollection;
+ class TypedStrCollection;
+ struct PivotField;
+-
++class ScDPCacheTable;
+ 
+ struct ScDPServiceDesc
+ {
+@@ -146,6 +151,7 @@
+ 
+ 	void				Output();
+ 	ScRange				GetNewOutputRange( BOOL& rOverflow );
++    const ScRange       GetOutputRangeByType( sal_Int32 nType );
+ 
+ 	void				SetSaveData(const ScDPSaveData& rData);
+ 	ScDPSaveData*		GetSaveData() const		{ return pSaveData; }
+@@ -179,7 +185,7 @@
+ 	String				GetDimName( long nDim, BOOL& rIsDataLayout );
+     BOOL                IsDuplicated( long nDim );
+     long                GetDimCount();
+-	void				GetPositionData( ScDPPositionData& rData, const ScAddress& rPos );
++    void                GetHeaderPositionData(const ScAddress& rPos, ::com::sun::star::sheet::DataPilotTableHeaderData& rData);
+ 	long				GetHeaderDim( const ScAddress& rPos, USHORT& rOrient );
+ 	BOOL				GetHeaderDrag( const ScAddress& rPos, BOOL bMouseLeft, BOOL bMouseTop,
+ 										long nDragDim,
+@@ -196,7 +202,7 @@
+ 
+ 	void				FillPageList( TypedStrCollection& rStrings, long nField );
+ 
+-	void				ToggleDetails( ScDPPositionData& rElemDesc, ScDPObject* pDestObj );
++    void                ToggleDetails(const ::com::sun::star::sheet::DataPilotTableHeaderData& rElemDesc, ScDPObject* pDestObj);
+ 
+ 	BOOL				StoreOld(SvStream& rStream, ScMultipleWriteHeader& rHdr ) const;
+ 	BOOL				StoreNew(SvStream& rStream, ScMultipleWriteHeader& rHdr ) const;
+@@ -227,9 +233,16 @@
+ 	BOOL				RefsEqual( const ScDPObject& r ) const;
+ 	void				WriteRefsTo( ScDPObject& r ) const;
+ 
+-    bool                GetDataFieldPositionData(
+-                            ::std::vector< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters,
+-                            const ScAddress& rPos);
++    void                GetPositionData(const ScAddress& rPos, ::com::sun::star::sheet::DataPilotTablePositionData& rPosData);
++
++    bool                GetDataFieldPositionData(const ScAddress& rPos, 
++                                                 ::com::sun::star::uno::Sequence< 
++                                                    ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters);
++
++    void                GetDrillDownData(const ScAddress& rPos, 
++                                         ::com::sun::star::uno::Sequence< 
++                                            ::com::sun::star::uno::Sequence< 
++                                                ::com::sun::star::uno::Any > >& rTableData);
+ 
+ 	// apply drop-down attribute, initialize nHeaderRows, without accessing the source
+ 	// (button attribute must be present)
+Index: sc/inc/dpoutput.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dpoutput.hxx,v
+retrieving revision 1.9
+retrieving revision 1.8.112.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.9 -r1.8.112.6
+--- sc/inc/dpoutput.hxx	26 Nov 2007 15:18:57 -0000	1.9
++++ sc/inc/dpoutput.hxx	4 Dec 2007 06:06:26 -0000	1.8.112.6
+@@ -52,6 +52,8 @@
+ #include <com/sun/star/sheet/GeneralFunction.hpp>
+ #endif
+ 
++#include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
++
+ #ifndef SC_SCGLOB_HXX
+ #include "global.hxx"
+ #endif
+@@ -60,10 +62,12 @@
+ #include "address.hxx"
+ #endif
+ 
++#include "dpcachetable.hxx"
+ #include <vector>
+ 
+ namespace com { namespace sun { namespace star { namespace sheet {
+     struct DataPilotFieldFilter;
++    struct DataPilotTablePositionData;
+ }}}}
+ 
+ class Rectangle;
+@@ -74,19 +78,6 @@
+ struct ScDPOutLevelData;
+ 
+ 
+-
+-
+-struct ScDPPositionData
+-{
+-	long	nDimension;
+-	long	nHierarchy;
+-	long	nLevel;
+-	long	nFlags;
+-	String	aMemberName;
+-
+-	ScDPPositionData() { nDimension = nHierarchy = nLevel = -1; nFlags = 0; }	// invalid
+-};
+-
+ struct ScDPGetPivotDataField
+ {
+     String maFieldName;
+@@ -126,12 +117,15 @@
+ 			com::sun::star::sheet::DataResult> > aData;
+ 	BOOL					bResultsError;
+ 	String					aDataDescription;
++
++    // Number format related parameters
+ 	UINT32*					pColNumFmt;
+ 	UINT32*					pRowNumFmt;
+ 	long					nColFmtCount;
+ 	long					nRowFmtCount;
+     UINT32                  nSingleNumFmt;
+ 
++    // Output geometry related parameters
+ 	BOOL					bSizesValid;
+ 	BOOL					bSizeOverflow;
+ 	long					nColCount;
+@@ -155,6 +149,11 @@
+ 								BOOL bFrame = TRUE );
+ 	void			CalcSizes();
+ 
++    /** Query which sub-area of the table the cell is in. See
++        css.sheet.DataPilotTablePositionType for the interpretation of the
++        return value. */
++    sal_Int32       GetPositionType(const ScAddress& rPos);
++
+ public:
+ 					ScDPOutput( ScDocument* pD,
+ 								const com::sun::star::uno::Reference<
+@@ -165,15 +164,15 @@
+ 	void			SetPosition( const ScAddress& rPos );
+ 
+ 	void			Output();			//! Refresh?
+-	ScRange			GetOutputRange();
++    ScRange			GetOutputRange( sal_Int32 nRegionType = ::com::sun::star::sheet::DataPilotOutputRangeType::WHOLE );
+ 	long			GetHeaderRows();
+ 	BOOL			HasError();			// range overflow or exception from source
+ 
+-	void			GetPositionData( ScDPPositionData& rData, const ScAddress& rPos );
++    void            GetPositionData(const ScAddress& rPos, ::com::sun::star::sheet::DataPilotTablePositionData& rPosData);
+ 
+     /** Get filtering criteria based on the position of the cell within data
+         field region. */
+-    bool            GetDataFieldPositionData(::std::vector< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters, const ScAddress& rPos);
++    bool            GetDataResultPositionData(::std::vector< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters, const ScAddress& rPos);
+ 
+     BOOL            GetPivotData( ScDPGetPivotDataField& rTarget, /* returns result */
+                                   const std::vector< ScDPGetPivotDataField >& rFilters );
+Index: sc/inc/dpsdbtab.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dpsdbtab.hxx,v
+retrieving revision 1.3
+retrieving revision 1.3.570.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.3 -r1.3.570.2
+--- sc/inc/dpsdbtab.hxx	8 Sep 2005 17:35:48 -0000	1.3
++++ sc/inc/dpsdbtab.hxx	6 Dec 2007 07:06:15 -0000	1.3.570.2
+@@ -50,6 +50,11 @@
+ #include "dptabdat.hxx"
+ #endif
+ 
++#include <vector>
++#include <set>
++
++class ScDPCacheTable;
++
+ // --------------------------------------------------------------------
+ //
+ //	implementation of ScDPTableData with database data
+@@ -77,7 +82,6 @@
+ 	ScDatabaseDPData_Impl* pImpl;
+ 
+ 	BOOL			OpenDatabase();
+-	void			InitAllColumnEntries();
+ 
+ public:
+ 					ScDatabaseDPData(
+@@ -94,8 +98,12 @@
+ 	virtual void					DisposeData();
+ 	virtual void					SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty );
+ 
+-	virtual void					ResetIterator();
+-	virtual BOOL					GetNextRow( const ScDPTableIteratorParam& rParam );
++    virtual void                    CreateCacheTable();
++    virtual void                    FilterCacheTable(const ::std::vector<ScDPDimension*>& rPageDims);
++    virtual void                    GetDrillDownData(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters,
++                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rTabData);
++    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow);
++    virtual const ScDPCacheTable&   GetCacheTable() const;
+ };
+ 
+ 
+Index: sc/inc/dpshttab.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dpshttab.hxx,v
+retrieving revision 1.4
+retrieving revision 1.4.570.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.4 -r1.4.570.2
+--- sc/inc/dpshttab.hxx	8 Sep 2005 17:36:03 -0000	1.4
++++ sc/inc/dpshttab.hxx	6 Dec 2007 07:06:15 -0000	1.4.570.2
+@@ -48,6 +48,14 @@
+ #include "address.hxx"
+ #endif
+ 
++#include <vector>
++
++namespace com { namespace sun { namespace star { namespace sheet {
++    struct DataPilotFieldFilter;
++}}}}
++
++class ScDPDimension;
++class ScDPItemData;
+ 
+ // --------------------------------------------------------------------
+ //
+@@ -70,7 +78,6 @@
+ {
+ private:
+ 	ScSheetDPData_Impl* pImpl;
+-    BOOL* pSpecial;
+ 
+ public:
+ 					ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc );
+@@ -85,8 +92,12 @@
+ 	virtual void					DisposeData();
+ 	virtual void					SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty );
+ 
+-	virtual void					ResetIterator();
+-	virtual BOOL					GetNextRow( const ScDPTableIteratorParam& rParam );
++    virtual void                    CreateCacheTable();
++    virtual void                    FilterCacheTable(const ::std::vector<ScDPDimension*>& rPageDims);
++    virtual void                    GetDrillDownData(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters,
++                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rData);
++    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow);
++    virtual const ScDPCacheTable&   GetCacheTable() const;
+ };
+ 
+ 
+Index: sc/inc/dptabdat.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dptabdat.hxx,v
+retrieving revision 1.6
+retrieving revision 1.6.216.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.6 -r1.6.216.2
+--- sc/inc/dptabdat.hxx	25 Jan 2007 11:03:15 -0000	1.6
++++ sc/inc/dptabdat.hxx	6 Dec 2007 07:06:15 -0000	1.6.216.2
+@@ -40,11 +40,21 @@
+ #include "address.hxx"
+ #endif
+ 
++#include "dpoutput.hxx"
++
+ #ifndef _STRING_HXX
+ #include <tools/string.hxx>
+ #endif
+ 
++#include <vector>
++#include <set>
++
++namespace com { namespace sun { namespace star { namespace sheet {
++    struct DataPilotFieldFilter;
++}}}}
++
+ class TypedStrCollection;
++class ScDPDimension;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -65,6 +75,7 @@
+ #define SC_DAPI_LEVEL_WEEK		1
+ #define SC_DAPI_LEVEL_WEEKDAY	2
+ 
++
+ // --------------------------------------------------------------------
+ //
+ //	base class ScDPTableData to allow implementation with tabular data
+@@ -105,29 +116,12 @@
+ 	void	Set( double fV, BYTE nT ) { fValue = fV; nType = nT; }
+ };
+ 
+-
+-struct ScDPTableIteratorParam
+-{
+-	//	all pointers are just copied
+-
+-	SCSIZE			nColCount;
+-	const long*		pCols;
+-	ScDPItemData*	pColData;
+-	SCSIZE			nRowCount;
+-	const long*		pRows;
+-	ScDPItemData*	pRowData;
+-	SCSIZE			nPageCount;
+-	const long*		pPages;
+-	ScDPItemData*	pPageData;
+-	SCSIZE			nDatCount;
+-	const long*		pDats;
+-	ScDPValueData*	pValues;
+-
+-	ScDPTableIteratorParam( long nCCount, const long* pC, ScDPItemData* pCDat,
+-							long nRCount, const long* pR, ScDPItemData* pRDat,
+-							long nPCount, const long* pP, ScDPItemData* pPDat,
+-							long nDCount, const long* pD, ScDPValueData* pV );
+-};
++class ScDPResultMember;
++class ScDPDimension;
++class ScDPLevel;
++class ScDPInitState;
++class ScDPCacheTable;
++class ScDPResultMember;
+ 
+ class ScDPTableData
+ {
+@@ -138,6 +132,25 @@
+ 	long 	nLastRet;
+ 
+ public:
++    /** This structure stores dimension information used when calculating
++        results.  These data are read only during result calculation, so it
++        should be passed as a const instance. */
++    struct CalcInfo
++    {
++        ::std::vector<long>             aColLevelDims;
++        ::std::vector<ScDPDimension*>   aColDims;
++        ::std::vector<ScDPLevel*>       aColLevels;
++        ::std::vector<long>             aRowLevelDims;
++        ::std::vector<ScDPDimension*>   aRowDims;
++        ::std::vector<ScDPLevel*>       aRowLevels;
++        ::std::vector<long>             aPageDims;
++        ::std::vector<long>             aDataSrcCols;
++
++        ScDPInitState*                  pInitState;
++        ScDPResultMember*               pColRoot;
++        ScDPResultMember*               pRowRoot;
++    };
++
+ 				ScDPTableData();
+ 	virtual		~ScDPTableData();
+ 
+@@ -155,8 +168,12 @@
+ 	virtual void					DisposeData() = 0;
+ 	virtual void					SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty ) = 0;
+ 
+-	virtual void					ResetIterator() = 0;
+-	virtual BOOL					GetNextRow( const ScDPTableIteratorParam& rParam ) = 0;
++    virtual void                    CreateCacheTable();
++    virtual void                    FilterCacheTable(const ::std::vector<ScDPDimension*>& rPageDims);
++    virtual void                    GetDrillDownData(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::DataPilotFieldFilter >& aFilters,
++                                                     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >& rTabData);
++    virtual void                    CalcResults(CalcInfo& rInfo, bool bAutoShow);
++    virtual const ScDPCacheTable&   GetCacheTable() const = 0;
+ 
+                                     // overloaded in ScDPGroupTableData:
+     virtual BOOL                    IsBaseForGroup(long nDim) const;
+@@ -166,6 +183,25 @@
+                                                const ScDPItemData& rBaseData, long nBaseIndex ) const;
+     virtual BOOL                    HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex,
+                                                       const ScDPItemData& rSecondData, long nSecondIndex ) const;
++
++protected:
++    /** This structure stores vector arrays that hold intermediate data for
++        each row during cache table iteration. */
++    struct CalcRowData
++    {
++        ::std::vector<ScDPItemData>  aColData;
++        ::std::vector<ScDPItemData>  aRowData;
++        ::std::vector<ScDPItemData>  aPageData;
++        ::std::vector<ScDPValueData> aValues;
++    };
++
++    void            FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable, const CalcInfo& rInfo, CalcRowData& rData);
++    void            ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow);
++    void            CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, CalcInfo& rInfo, bool bAutoShow);
++
++private:
++    void            GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow, 
++                                const ::std::vector<long>& rDims, ::std::vector<ScDPItemData>& rItemData);
+ };
+ 
+ 
+Index: sc/inc/dptabres.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dptabres.hxx,v
+retrieving revision 1.7
+retrieving revision 1.7.202.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.7 -r1.7.202.6
+--- sc/inc/dptabres.hxx	27 Feb 2007 11:55:52 -0000	1.7
++++ sc/inc/dptabres.hxx	6 Dec 2007 07:06:15 -0000	1.7.202.6
+@@ -302,15 +302,17 @@
+                                     const ScDPItemData& rBaseData, long nBaseIndex ) const;
+     BOOL                HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex,
+                                           const ScDPItemData& rSecondData, long nSecondIndex ) const;
++
++    void                Debug() const;
+ };
+ 
+ 
+ class ScDPResultMember
+ {
+ private:
+-	ScDPResultData*			pResultData;
+-	ScDPDimension*			pParentDim;				//! Ref
+-	ScDPLevel*				pParentLevel;			//! Ref
++    const ScDPResultData*   pResultData;
++    const ScDPDimension*    pParentDim;             //! Ref
++    const ScDPLevel*        pParentLevel;           //! Ref
+ 	const ScDPMember*		pMemberDesc;			//! Ref
+ 	ScDPResultDimension*	pChildDimension;
+ 	ScDPDataMember*			pDataRoot;
+@@ -322,15 +324,20 @@
+ 	ScDPAggData				aColTotal;				// to store column totals
+ 
+ public:
+-						ScDPResultMember( ScDPResultData* pData, ScDPDimension* pDim,
+-											ScDPLevel* pLev, ScDPMember* pDesc,
++                        ScDPResultMember( const ScDPResultData* pData, const ScDPDimension* pDim,
++                                          const ScDPLevel* pLev, const ScDPMember* pDesc,
+ 											BOOL bForceSub );	//! Ref
+ 						~ScDPResultMember();
+ 
+-	void				InitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPInitState& rInitState );
+-	void				LateInitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPItemData* pItemData,
++    void                InitFrom( const ::std::vector<ScDPDimension*>& ppDim, 
++                                  const ::std::vector<ScDPLevel*>& ppLev,
++                                  size_t nPos,
++                                  ScDPInitState& rInitState );
++    void                LateInitFrom( const ::std::vector<ScDPDimension*>& ppDim, 
++                                      const ::std::vector<ScDPLevel*>& ppLev, 
++                                      const ::std::vector<ScDPItemData>& pItemData,
++                                      size_t nPos,
+                                         ScDPInitState& rInitState );
+-
+ 	String				GetName() const;
+     void                FillItemData( ScDPItemData& rData ) const;
+ 	BOOL				IsValid() const;
+@@ -343,15 +350,15 @@
+ 	long				GetSubTotalCount( long* pUserSubStart = NULL ) const;
+ 
+ 	BOOL				IsNamedItem( const ScDPItemData& r ) const;
+-	BOOL				IsValidEntry( const ScDPItemData* pMembers ) const;
++    bool                IsValidEntry( const ::std::vector<ScDPItemData>& aMembers ) const;
+ 
+ 	void				SetHasElements()	{ bHasElements = TRUE; }
+ 	void                SetAutoHidden()     { bAutoHidden = TRUE; }
+ 
+-	void				ProcessData( const ScDPItemData* pChildMembers,
+-										ScDPResultDimension* pDataDim,
+-										const ScDPItemData* pDataMembers,
+-										const ScDPValueData* pValues );
++    void                ProcessData( const ::std::vector<ScDPItemData>& aChildMembers,
++                                     const ScDPResultDimension* pDataDim,
++                                     const ::std::vector<ScDPItemData>& aDataMembers,
++                                     const ::std::vector<ScDPValueData>& aValues );
+ 
+ 	void				FillMemberResults( com::sun::star::uno::Sequence<
+ 												com::sun::star::sheet::MemberResult>* pSequences,
+@@ -391,15 +398,15 @@
+ class ScDPDataMember
+ {
+ private:
+-	ScDPResultData*			pResultData;
++    const ScDPResultData*       pResultData;
+ 	const ScDPResultMember*		pResultMember;			//! Ref?
+ 	ScDPDataDimension*		pChildDimension;
+ 	ScDPAggData				aAggregate;
+ 
+-	void				UpdateValues( const ScDPValueData* pValues, const ScDPSubTotalState& rSubState );
++    void                UpdateValues( const ::std::vector<ScDPValueData>& aValues, const ScDPSubTotalState& rSubState );
+ 
+ public:
+-						ScDPDataMember( ScDPResultData* pData, const ScDPResultMember* pRes );
++                        ScDPDataMember( const ScDPResultData* pData, const ScDPResultMember* pRes );
+ 						~ScDPDataMember();
+ 
+ 	void				InitFrom( const ScDPResultDimension* pDim );
+@@ -412,7 +419,7 @@
+ 
+ 	BOOL				HasHiddenDetails() const;
+ 
+-	void				ProcessData( const ScDPItemData* pChildMembers, const ScDPValueData* pValues,
++    void                ProcessData( const ::std::vector<ScDPItemData>& aChildMembers, const ::std::vector<ScDPValueData>& aValues,
+ 									const ScDPSubTotalState& rSubState );
+ 
+ 	BOOL				HasError( long nMeasure, const ScDPSubTotalState& rSubState ) const;
+@@ -462,7 +469,7 @@
+ 	typedef	std::hash_map <ScDPItemData, ScDPResultMember *, MemberHashFunc>	MemberHash;
+ 
+ private:
+-	ScDPResultData*			pResultData;
++    const ScDPResultData*   pResultData;
+ 	MemberArray				maMemberArray;
+ 	MemberHash				maMemberHash;
+ 	BOOL                    bInitialized;
+@@ -479,23 +486,28 @@
+ 
+ 	ScDPResultMember* 		FindMember( const ScDPItemData& rData ) const;
+ public:
+-						ScDPResultDimension( ScDPResultData* pData );
++                        ScDPResultDimension( const ScDPResultData* pData );
+ 						~ScDPResultDimension();
+ 
+ 						//	allocates new members
+-	void				InitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPInitState& rInitState );
+-	void				LateInitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPItemData* pItemData,
++    void                InitFrom( const ::std::vector<ScDPDimension*>& ppDim, 
++                                  const ::std::vector<ScDPLevel*>& ppLev,
++                                  size_t nPos,
++                                  ScDPInitState& rInitState );
++    void                LateInitFrom( const ::std::vector<ScDPDimension*>& ppDim, 
++                                      const ::std::vector<ScDPLevel*>& ppLev, 
++                                      const ::std::vector<ScDPItemData>& pItemData,
++                                      size_t nPos,
+                                         ScDPInitState& rInitState );
+ 
+ 	long				GetSize(long nMeasure) const;
+ 
+-	BOOL				IsValidEntry( const ScDPItemData* pMembers ) const;
+-
++    bool                IsValidEntry( const ::std::vector<ScDPItemData>& aMembers ) const;
+ 						//	modifies existing members, allocates data dimensions
+-	void				ProcessData( const ScDPItemData* pMembers,
+-										ScDPResultDimension* pDataDim,
+-										const ScDPItemData* pDataMembers,
+-										const ScDPValueData* pValues );	//! Test
++	void				ProcessData( const ::std::vector<ScDPItemData>& aMembers,
++                                     const ScDPResultDimension* pDataDim,
++                                     const ::std::vector<ScDPItemData>& aDataMembers,
++                                     const ::std::vector<ScDPValueData>& aValues ) const;	//! Test
+ 
+ 	void				FillMemberResults( com::sun::star::uno::Sequence<
+ 												com::sun::star::sheet::MemberResult>* pSequences,
+@@ -554,17 +566,17 @@
+ class ScDPDataDimension
+ {
+ private:
+-	ScDPResultData*		pResultData;
++    const ScDPResultData*		pResultData;
+ 	const ScDPResultDimension* pResultDimension;  // column
+ 	ScDPDataMembers		aMembers;
+ 	BOOL				bIsDataLayout;		//! or ptr to IntDimension?
+ 
+ public:
+-						ScDPDataDimension( ScDPResultData* pData );
++                        ScDPDataDimension( const ScDPResultData* pData );
+ 						~ScDPDataDimension();
+ 
+ 	void				InitFrom( const ScDPResultDimension* pDim );		// recursive
+-	void				ProcessData( const ScDPItemData* pDataMembers, const ScDPValueData* pValues,
++    void                ProcessData( const ::std::vector<ScDPItemData>& aDataMembers, const ::std::vector<ScDPValueData>& aValues,
+ 									const ScDPSubTotalState& rSubState );
+ 
+ 	void				FillDataRow( const ScDPResultDimension* pRefDim,
+Index: sc/inc/dptabsrc.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/dptabsrc.hxx,v
+retrieving revision 1.10
+retrieving revision 1.8.216.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.10 -r1.8.216.4
+--- sc/inc/dptabsrc.hxx	26 Nov 2007 15:19:15 -0000	1.10
++++ sc/inc/dptabsrc.hxx	6 Dec 2007 06:41:12 -0000	1.8.216.4
+@@ -93,6 +93,7 @@
+ #ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_
+ #include <com/sun/star/util/XRefreshable.hpp>
+ #endif
++#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
+ #ifndef _COM_SUN_STAR_UTIL_XCLONEABLE_HPP_
+ #include <com/sun/star/util/XCloneable.hpp>
+ #endif
+@@ -115,14 +116,20 @@
+ #ifndef _CPPUHELPER_IMPLBASE5_HXX_
+ #include <cppuhelper/implbase5.hxx>
+ #endif
++#include <cppuhelper/implbase6.hxx>
+ 
+ #ifndef SC_DPTABDAT_HXX
+ #include "dptabdat.hxx"
+ #endif
+ 
+-namespace com { namespace sun { namespace star { namespace sheet {
++namespace com { namespace sun { namespace star { 
++    namespace sheet {
+     struct DataPilotFieldFilter;
+-}}}}
++    }
++    namespace table {
++        struct CellAddress;
++    }
++}}}
+ 
+ class ScDPResultMember;
+ class ScDPResultData;
+@@ -152,14 +159,18 @@
+ class ScDPMember;
+ 
+ 
+-class ScDPSource : public cppu::WeakImplHelper5<
++class ScDPSource : public cppu::WeakImplHelper6<
+ 							com::sun::star::sheet::XDimensionsSupplier,
+ 							com::sun::star::sheet::XDataPilotResults,
+ 							com::sun::star::util::XRefreshable,
++                            com::sun::star::sheet::XDrillDownDataSupplier,
+ 							com::sun::star::beans::XPropertySet,
+ 							com::sun::star::lang::XServiceInfo >
+ {
+ private:
++    void FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &bHasAutoShow);
++
++private:
+ 	ScDPTableData*			pData;				// data source
+ 	ScDPDimensions*			pDimensions;		// api objects
+ 												// settings:
+@@ -186,7 +197,6 @@
+ 	com::sun::star::uno::Sequence<com::sun::star::sheet::MemberResult>* pRowResults;
+ 	List					aColLevelList;
+ 	List					aRowLevelList;
+-	ScSubTotalFunc			eDataFunctions[SC_DAPI_MAXFIELDS];
+ 	BOOL					bResultOverflow;
+ 
+ 	void					CreateRes_Impl();
+@@ -227,9 +237,6 @@
+ 
+ 	void					DumpState( ScDocument* pDoc, const ScAddress& rPos );
+ 
+-    void                    WriteDrillDownData( ScDocument* pDoc, const ScAddress& rPos,
+-                                    const ::std::vector< ::com::sun::star::sheet::DataPilotFieldFilter > rFilters );
+-
+ 							// XDimensionsSupplier
+ 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >
+ 							SAL_CALL getDimensions(  )
+@@ -249,6 +256,12 @@
+ 									::com::sun::star::util::XRefreshListener >& l )
+ 								throw(::com::sun::star::uno::RuntimeException);
+ 
++                            // XDrillDownDataSupplier
++    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > > 
++        SAL_CALL getDrillDownData(const ::com::sun::star::uno::Sequence< 
++                                      ::com::sun::star::sheet::DataPilotFieldFilter >& aFilters )
++                                throw(::com::sun::star::uno::RuntimeException);
++
+ 							// XPropertySet
+ 	virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo >
+ 							SAL_CALL getPropertySetInfo(  )
+@@ -365,7 +378,7 @@
+ {
+ private:
+ 	ScDPSource*			pSource;
+-	long				nDim;
++	long				nDim;               // dimension index (== column ID)
+ 	ScDPHierarchies*	pHierarchies;
+ 	long				nUsedHier;
+ 	USHORT				nFunction;			// enum GeneralFunction
+Index: sc/inc/unonames.hxx
+===================================================================
+RCS file: /cvs/sc/sc/inc/unonames.hxx,v
+retrieving revision 1.74
+retrieving revision 1.74.106.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.74 -r1.74.106.1
+--- sc/inc/unonames.hxx	6 Jul 2007 12:31:28 -0000	1.74
++++ sc/inc/unonames.hxx	6 Dec 2007 16:40:33 -0000	1.74.106.1
+@@ -542,6 +542,10 @@
+ #define SC_UNO_REPEATIF				"RepeatIfEmpty"
+ #define SC_UNO_DATADESC				"DataDescription"
+ #define SC_UNO_NUMBERFO				"NumberFormat"
++#define SC_UNO_ROWFIELDCOUNT        "RowFieldCount"
++#define SC_UNO_COLUMNFIELDCOUNT     "ColumnFieldCount"
++#define SC_UNO_DATAFIELDCOUNT       "DataFieldCount"
++
+ //  (preliminary:)
+ #define SC_UNO_REFVALUE				"ReferenceValue"
+ #define SC_UNO_SORTING				"Sorting"
+Index: sc/source/core/data/dpcachetable.cxx
+===================================================================
+RCS file: sc/source/core/data/dpcachetable.cxx
+diff -N sc/source/core/data/dpcachetable.cxx
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ sc/source/core/data/dpcachetable.cxx	31 Oct 2007 19:58:43 -0000	1.1.2.4
+@@ -0,0 +1,657 @@
++/*************************************************************************
++ *
++ *  OpenOffice.org - a multi-platform office productivity suite
++ *
++ *  $RCSfile: dpcachetable.cxx,v $
++ *
++ *  $Revision: 1.1.2.4 $
++ *
++ *  last change: $Author: kohei $ $Date: 2007/10/31 19:58:43 $
++ *
++ *  The Contents of this file are made available subject to
++ *  the terms of GNU Lesser General Public License Version 2.1.
++ *
++ *
++ *    GNU Lesser General Public License Version 2.1
++ *    =============================================
++ *    Copyright 2005 by Sun Microsystems, Inc.
++ *    901 San Antonio Road, Palo Alto, CA 94303, USA
++ *
++ *    This library is free software; you can redistribute it and/or
++ *    modify it under the terms of the GNU Lesser General Public
++ *    License version 2.1, as published by the Free Software Foundation.
++ *
++ *    This library 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 for more details.
++ *
++ *    You should have received a copy of the GNU Lesser General Public
++ *    License along with this library; if not, write to the Free Software
++ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ *    MA  02111-1307  USA
++ *
++ ************************************************************************/
++
++#include "dpcachetable.hxx"
++#include "document.hxx"
++#include "address.hxx"
++#include "cell.hxx"
++#include "dptabdat.hxx"
++#include "dptabsrc.hxx"
++
++#include <stdio.h>
++
++#include <com/sun/star/sdbc/DataType.hpp>
++#include <com/sun/star/sdbc/XRow.hpp>
++#include <com/sun/star/sdbc/XRowSet.hpp>
++#include <com/sun/star/sdbc/XResultSetMetaData.hpp>
++#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
++#include <com/sun/star/util/Date.hpp>
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
++
++using namespace ::com::sun::star;
++
++using ::rtl::OUString;
++using ::std::vector;
++using ::std::set;
++using ::com::sun::star::uno::Exception;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Any;
++using ::com::sun::star::uno::UNO_QUERY;
++using ::com::sun::star::uno::UNO_QUERY_THROW;
++using ::com::sun::star::sheet::DataPilotFieldFilter;
++
++static BOOL lcl_HasQueryEntry( const ScQueryParam& rParam )
++{
++    return rParam.GetEntryCount() > 0 &&
++            rParam.GetEntry(0).bDoQuery;
++}
++
++ScSharedStringTable::ScSharedStringTable() :
++    mnStrCount(0)
++{
++    // empty string (ID = 0)
++    maSharedStrings.push_back(String());
++    maSharedStringIds.insert( SharedStrMap::value_type(String(), mnStrCount++) );
++}
++
++ScSharedStringTable::~ScSharedStringTable()
++{
++}
++
++sal_Int32 ScSharedStringTable::insertString(const String& aStr)
++{
++    SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr), 
++        itrEnd = maSharedStringIds.end();
++
++    if (itr == itrEnd)
++    {
++        // new string.
++        maSharedStrings.push_back(aStr);
++        maSharedStringIds.insert( SharedStrMap::value_type(aStr, mnStrCount) );
++        return mnStrCount++;
++    }
++
++    // existing string.
++    return itr->second;
++}
++
++sal_Int32 ScSharedStringTable::getStringId(const String& aStr)
++{
++    SharedStrMap::const_iterator itr = maSharedStringIds.find(aStr), 
++        itrEnd = maSharedStringIds.end();
++    if (itr == itrEnd)
++    {
++        // string not found.
++        return insertString(aStr);
++    }
++    return itr->second;
++}
++
++const String* ScSharedStringTable::getString(sal_Int32 nId) const
++{
++    if (nId >= mnStrCount)
++        return NULL;
++
++    return &maSharedStrings[nId];
++}
++
++// ----------------------------------------------------------------------------
++
++ScDPCacheTable::Cell::Cell() :
++    mfValue(0.0),
++    mbNumeric(false),
++    mnType(SC_VALTYPE_EMPTY)
++{
++}
++
++ScDPCacheTable::Filter::Filter()
++{
++}
++
++::osl::Mutex ScDPCacheTable::maStrMutex;
++ScSharedStringTable ScDPCacheTable::maStringTable;
++
++ScDPCacheTable::ScDPCacheTable()
++{
++}
++
++ScDPCacheTable::~ScDPCacheTable()
++{
++}
++
++sal_Int32 ScDPCacheTable::getHeaderSize() const
++{
++    return maHeader.size();
++}
++
++sal_Int32 ScDPCacheTable::getRowSize() const
++{
++    return maTable.size();
++}
++
++sal_Int32 ScDPCacheTable::getColSize() const
++{
++    return maTable.empty() ? 0 : maTable[0].size();
++}
++
++void ScDPCacheTable::fillTable(ScDocument* pDoc, const ScRange& rRange, const ScQueryParam& rQuery, BOOL* pSpecial)
++{
++    SCTAB nTab = rRange.aStart.Tab();
++    SCCOL nStartCol = rRange.aStart.Col();
++    SCROW nStartRow = rRange.aStart.Row();
++    SCCOL nColCount = rRange.aEnd.Col() - rRange.aStart.Col() + 1;
++    SCROW nRowCount = rRange.aEnd.Row() - rRange.aStart.Row() + 1;
++
++    if (nRowCount <= 1 || nColCount <= 0)
++        return;
++
++    maTable.clear();
++    maTable.reserve(nRowCount);
++    maHeader.clear();
++    maHeader.reserve(nColCount);
++    maRowsVisible.clear();
++    maRowsVisible.reserve(nRowCount);
++
++    // Header row
++    for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
++    {
++        String aStr;
++        pDoc->GetString(nCol + nStartCol, nStartRow, nTab, aStr);
++        sal_Int32 nStrId = maStringTable.insertString(aStr);
++        maHeader.push_back(nStrId);
++    }
++
++    // Initialize field entries container.
++    maFieldEntries.clear();
++    maFieldEntries.reserve(nColCount);
++    for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
++    {
++        TypedStrCollectionPtr p(new TypedStrCollection);
++        maFieldEntries.push_back(p);
++    }
++
++    // Data rows
++    for (SCROW nRow = 1; nRow < nRowCount; ++nRow)
++    {
++        if ( lcl_HasQueryEntry(rQuery) && !pDoc->ValidQuery(nRow + nStartRow, nTab, rQuery, pSpecial) )
++            // filtered out by standard filter.
++            continue;
++
++        // Insert a new row into cache table.
++        maRowsVisible.push_back(true);
++        maTable.push_back( vector<Cell>() );
++        maTable.back().reserve(nColCount);
++
++        for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
++        {
++            maTable.back().push_back( ScDPCacheTable::Cell() );
++            Cell& rCell = maTable.back().back();
++                
++            String aStr;
++            pDoc->GetString(nStartCol + nCol, nStartRow + nRow, nTab, aStr);
++            rCell.mnStrId = maStringTable.insertString(aStr);
++            rCell.mnType = SC_VALTYPE_STRING;
++            rCell.mbNumeric = false;
++            ScAddress aPos(nStartCol + nCol, nStartRow + nRow, nTab);
++            getValueData(pDoc, aPos, rCell);
++
++            TypedStrData* pNew;
++            if (rCell.mbNumeric)
++                pNew = new TypedStrData(aStr, rCell.mfValue, SC_STRTYPE_VALUE);
++            else
++                pNew = new TypedStrData(aStr);
++
++            if (!maFieldEntries[nCol]->Insert(pNew))
++                delete pNew;
++        }
++    }
++}
++
++void lcl_GetCellValue(const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol,
++             const Date& rNullDate, ScDPCacheTable::Cell& rCell, String& rStr)
++{
++    short nNumType = NUMBERFORMAT_NUMBER;
++    BOOL bEmptyFlag = FALSE;
++    try
++    {
++        rStr = xRow->getString(nCol);
++        rCell.mnStrId = ScDPCacheTable::getStringId(rStr);
++        rCell.mnType = SC_VALTYPE_STRING;
++
++        switch (nType)
++        {
++            case sdbc::DataType::BIT:
++            case sdbc::DataType::BOOLEAN:
++            {
++                nNumType = NUMBERFORMAT_LOGICAL;
++                rCell.mfValue = xRow->getBoolean(nCol) ? 1 : 0;    
++                bEmptyFlag = (rCell.mfValue == 0.0 && xRow->wasNull());
++                rCell.mbNumeric = true;
++                rCell.mnType = SC_VALTYPE_VALUE;
++            }
++            break;
++
++            case sdbc::DataType::TINYINT:
++            case sdbc::DataType::SMALLINT:
++            case sdbc::DataType::INTEGER:
++            case sdbc::DataType::BIGINT:
++            case sdbc::DataType::FLOAT:
++            case sdbc::DataType::REAL:
++            case sdbc::DataType::DOUBLE:
++            case sdbc::DataType::NUMERIC:
++            case sdbc::DataType::DECIMAL:
++            {
++                //! do the conversion here?
++                rCell.mfValue = xRow->getDouble(nCol);
++                bEmptyFlag = (rCell.mfValue == 0.0 && xRow->wasNull());
++                rCell.mbNumeric = true;
++                rCell.mnType = SC_VALTYPE_VALUE;
++            }
++            break;
++
++            case sdbc::DataType::CHAR:
++            case sdbc::DataType::VARCHAR:
++            case sdbc::DataType::LONGVARCHAR:
++                bEmptyFlag = (rStr.Len() == 0 && xRow->wasNull());
++            break;
++
++            case sdbc::DataType::DATE:
++            {
++                nNumType = NUMBERFORMAT_DATE;
++
++                util::Date aDate = xRow->getDate(nCol);
++                rCell.mfValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate;
++                bEmptyFlag = xRow->wasNull();
++                rCell.mbNumeric = true;
++                rCell.mnType = SC_VALTYPE_VALUE;
++            }
++            break;
++
++                //! case sdbc::DataType::TIME:
++                //! case sdbc::DataType::TIMESTAMP:
++
++            case sdbc::DataType::SQLNULL:
++            case sdbc::DataType::BINARY:
++            case sdbc::DataType::VARBINARY:
++            case sdbc::DataType::LONGVARBINARY:
++            default:
++            break;
++        }
++    }
++    catch (uno::Exception&)
++    {
++    }
++}
++
++void ScDPCacheTable::fillTable(const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate)
++{
++    if (!xRowSet.is())
++        // Dont' even waste time to go any further.
++        return;
++
++    try
++    {
++        Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW);
++        Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData();
++        if (!xMeta.is())
++            return;
++
++        sal_Int32 nColCount = xMeta->getColumnCount();
++
++        // Get column titles and types.
++        vector<sal_Int32> aColTypes(nColCount);
++        maHeader.clear();
++        maHeader.reserve(nColCount);
++        for (sal_Int32 nCol = 0; nCol < nColCount; ++nCol)
++        {
++            String aColTitle = xMeta->getColumnLabel(nCol+1);
++            aColTypes[nCol]  = xMeta->getColumnType(nCol+1);
++            maHeader.push_back( ScDPCacheTable::getStringId(aColTitle) );
++        }
++
++        // Initialize field entries container.
++        maFieldEntries.clear();
++        maFieldEntries.reserve(nColCount);
++        for (SCCOL nCol = 0; nCol < nColCount; ++nCol)
++        {
++            TypedStrCollectionPtr p(new TypedStrCollection);
++            maFieldEntries.push_back(p);
++        }
++
++        // Now get the data rows.
++        Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW);
++        xRowSet->first();
++        maTable.clear();
++        maRowsVisible.clear();
++        do
++        {
++            maRowsVisible.push_back(true);
++            maTable.push_back( vector<Cell>() );
++            maTable.back().reserve(nColCount);
++            for (sal_Int32 nCol = 0; nCol < nColCount; ++nCol)
++            {
++                maTable.back().push_back( Cell() );
++                Cell& rCell = maTable.back().back();
++                String aStr;
++                lcl_GetCellValue(xRow, aColTypes[nCol], nCol+1, rNullDate, rCell, aStr);
++
++                TypedStrData* pNew;
++                if (rCell.mbNumeric)
++                    pNew = new TypedStrData(aStr, rCell.mfValue, SC_STRTYPE_VALUE);
++                else
++                    pNew = new TypedStrData(aStr);
++
++                if (!maFieldEntries[nCol]->Insert(pNew))
++                    delete pNew;
++            }
++        }
++        while (xRowSet->next());
++
++        xRowSet->beforeFirst();
++    }
++    catch (const Exception&)
++    {
++    }
++}
++
++bool ScDPCacheTable::isRowActive(sal_Int32 nRow) const
++{
++    if (nRow < 0 || nRow >= maRowsVisible.size())
++        // row index out of bound
++        return false;
++
++    return maRowsVisible[nRow];
++}
++
++void ScDPCacheTable::filterByPageDimension(const vector<ScDPDimension*>& rPageDims)
++{
++    sal_Int32 nRowSize = getRowSize();
++
++    if (nRowSize != static_cast<sal_Int32>(maRowsVisible.size()))
++    {
++        fprintf(stdout, "ScDPCacheTable::filterByPageDimension: the sizes of the two tables differ.\n");fflush(stdout);
++        return;
++    }
++
++    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
++    {
++        maRowsVisible[nRow] = true;
++        const vector<Cell>& rRow = maTable[nRow];
++        vector<ScDPDimension*>::const_iterator itr = rPageDims.begin(), itrEnd = rPageDims.end();
++        for (; itr != itrEnd; ++itr)
++        {
++            ScDPDimension* pDim = *itr;
++            ScDPCacheTable::Cell aDimCell = getSelectedDimension(pDim);
++            
++            sal_Int32 nCol = pDim->GetDimension();
++            const Cell& rCell = rRow[nCol];
++            if (aDimCell.mnStrId != ScSharedStringTable::EMPTY && aDimCell.mnStrId != rCell.mnStrId)
++            {
++                // Selected page dimension value does not match the current value.  Skip it 
++                // (note: when the selected page dimension value is empty, '- all -' is 
++                // selected.
++                maRowsVisible[nRow] = false;
++                break;
++            }
++        }
++    }
++}
++
++const ::ScDPCacheTable::Cell* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow) const
++{
++    if ( nRow >= static_cast<SCROW>(maTable.size()) )
++        return NULL;
++
++    const vector<Cell>& rRow = maTable.at(nRow);
++    if ( nCol < 0 || static_cast<size_t>(nCol) >= rRow.size() )
++        return NULL;
++
++    return &rRow.at(nCol);
++}
++
++const String* ScDPCacheTable::getFieldName(sal_Int32 nIndex) const
++{
++    if (nIndex >= static_cast<sal_Int32>(maHeader.size()))
++        return NULL;
++
++    return getString(maHeader[nIndex]);
++}
++
++sal_Int32 ScDPCacheTable::getFieldIndex(const String& rStr) const
++{
++    sal_Int32 nStrId = getStringId(rStr);
++    if (nStrId < 0)
++        // string not found.
++        return nStrId;
++
++    sal_Int32 n = maHeader.size();
++    for (sal_Int32 i = 0; i < n; ++i)
++    {
++        if (maHeader[i] == nStrId)
++            return i;
++    }
++
++    return -1;
++}
++
++const TypedStrCollection& ScDPCacheTable::getFieldEntries(sal_Int32 nIndex) const
++{
++    if (nIndex < 0 || nIndex >= maFieldEntries.size())
++    {
++        fprintf(stdout, "ScDPCacheTable::getFieldEntries: OUT OF BOUND\n");fflush(stdout);
++        // index out of bound.  Hopefully this code will never be reached.
++        static const TypedStrCollection emptyCollection;
++        return emptyCollection;
++    }
++
++    return *maFieldEntries[nIndex].get();
++}
++
++void ScDPCacheTable::filterTable(const Sequence<DataPilotFieldFilter>& rFilters, 
++                                 Sequence< Sequence<Any> >& rTabData)
++{
++    sal_Int32 nRowSize = getRowSize();
++    sal_Int32 nColSize = getColSize();
++
++    if (!nRowSize)
++        // no data to filter.
++        return;
++
++    // Convert filters first.
++    vector<Filter> filters;
++    sal_Int32 nFilterSize = rFilters.getLength();
++    filters.reserve(nFilterSize);
++    for (sal_Int32 i = 0; i < nFilterSize; ++i)
++    {
++        Filter fil;
++        fil.mnFieldIndex = getFieldIndex(String(rFilters[i].FieldName));
++        fil.mnMatchStrId = getStringId(String(rFilters[i].MatchValue));
++        if (fil.mnFieldIndex >= 0)
++            filters.push_back(fil);
++    }
++    
++    // Row first, then column.
++    vector< Sequence<Any> > tableData;
++    tableData.reserve(nRowSize+1);
++
++    // Header first.
++    Sequence<Any> headerRow(nColSize);
++    for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol)
++    {
++        OUString str;
++        const String* pStr = getString(maHeader[nCol]);
++        if (pStr)
++            str = *pStr;
++
++        Any any;
++        any <<= str;
++        headerRow[nCol] = any;
++    }
++    tableData.push_back(headerRow);
++
++    // Data rows.
++    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
++    {
++        if (!maRowsVisible[nRow])
++            // This row is filtered out.
++            continue;
++
++        bool bRetainRow = true;
++        vector<Filter>::const_iterator itr, itrEnd = filters.end();
++        for (itr = filters.begin(); itr != itrEnd; ++itr)
++        {
++            if (itr->mnFieldIndex >= nColSize)
++            {
++                // specified field is outside the source data columns.
++                bRetainRow = false;
++                break;
++            }
++
++            if ( maTable[nRow][itr->mnFieldIndex].mnStrId != itr->mnMatchStrId )
++            {
++                // The string value does not match.
++                bRetainRow = false;
++                break;
++            }
++        }
++
++        if (bRetainRow)
++        {
++            Sequence<Any> row(nColSize);
++            for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol)
++            {
++                Any any;
++                const Cell& rCell = maTable[nRow][nCol];
++                if (rCell.mbNumeric)
++                    any <<= rCell.mfValue;
++                else
++                {
++                    OUString str;
++                    const String* pStr = getString(rCell.mnStrId);
++                    if (pStr)
++                        str = *pStr;
++                    any <<= str;
++                }
++                row[nCol] = any;
++            }
++            tableData.push_back(row);
++        }
++    }
++
++    // convert vector to Seqeunce
++    sal_Int32 nTabSize = static_cast<sal_Int32>(tableData.size());
++    rTabData.realloc(nTabSize);
++    for (sal_Int32 i = 0; i < nTabSize; ++i)
++        rTabData[i] = tableData[i];
++}
++
++void ScDPCacheTable::clear()
++{
++    maTable.clear();
++    maHeader.clear();
++    maFieldEntries.clear();
++    maRowsVisible.clear();
++}
++
++void ScDPCacheTable::swap(ScDPCacheTable& rOther)
++{
++    maTable.swap(rOther.maTable);
++    maHeader.swap(rOther.maHeader);
++    maFieldEntries.swap(rOther.maFieldEntries);
++    maRowsVisible.swap(rOther.maRowsVisible);
++}
++
++bool ScDPCacheTable::empty() const
++{
++    return maTable.empty();
++}
++
++void ScDPCacheTable::getValueData(ScDocument* pDoc, const ScAddress& rPos, Cell& rCell)
++{
++    ScBaseCell* pCell = pDoc->GetCell(rPos);
++    if (!pCell)
++    {
++        rCell.mnType = SC_VALTYPE_EMPTY;
++        return;
++    }
++
++    CellType eType = pCell->GetCellType();
++    if (eType == CELLTYPE_NOTE)
++    {
++        // note cell
++        rCell.mnType = SC_VALTYPE_EMPTY;
++        return;
++    }
++
++    if (eType == CELLTYPE_FORMULA && static_cast<ScFormulaCell*>(pCell)->GetErrCode())
++    {
++        // formula cell with error
++        rCell.mnType = SC_VALTYPE_ERROR;
++        return;
++    }
++
++    if ( pCell->HasValueData() )
++    {
++        if (eType == CELLTYPE_VALUE)
++            // value cell
++            rCell.mfValue = static_cast<ScValueCell*>(pCell)->GetValue();
++        else if (eType == CELLTYPE_FORMULA)
++            // formula cell
++            rCell.mfValue = static_cast<ScFormulaCell*>(pCell)->GetValue();
++
++        rCell.mbNumeric = true;
++        rCell.mnType = SC_VALTYPE_VALUE;
++    }
++}
++
++ScDPCacheTable::Cell ScDPCacheTable::getSelectedDimension(ScDPDimension* pDim) const
++{
++    const ScDPItemData& rData = pDim->GetSelectedData();
++    Cell aCell;
++    aCell.mfValue = rData.fValue;
++    aCell.mbNumeric = rData.bHasValue;
++    aCell.mnStrId = getStringId(rData.aString);
++    return aCell;
++}
++
++// static 
++sal_Int32 ScDPCacheTable::insertString(const String& aStr)
++{
++    ::osl::MutexGuard aGuard(maStrMutex);
++    return maStringTable.insertString(aStr);
++}
++
++const String* ScDPCacheTable::getString(sal_Int32 nId)
++{
++    ::osl::MutexGuard aGuard(maStrMutex);
++    return maStringTable.getString(nId);
++}
++
++sal_Int32 ScDPCacheTable::getStringId(const String& aStr)
++{
++    ::osl::MutexGuard aGuard(maStrMutex);
++    return maStringTable.getStringId(aStr);
++}
+Index: sc/source/core/data/dpgroup.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dpgroup.cxx,v
+retrieving revision 1.7
+retrieving revision 1.7.202.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.7 -r1.7.202.2
+--- sc/source/core/data/dpgroup.cxx	27 Feb 2007 12:03:31 -0000	1.7
++++ sc/source/core/data/dpgroup.cxx	6 Dec 2007 07:06:15 -0000	1.7.202.2
+@@ -36,7 +36,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
+-
++#include <stdio.h>
+ 
+ // INCLUDE ---------------------------------------------------------------
+ 
+@@ -51,10 +51,24 @@
+ #include "collect.hxx"
+ #include "global.hxx"
+ #include "document.hxx"
++#include "dpcachetable.hxx"
++#include "dptabsrc.hxx"
++#include "dptabres.hxx"
+ 
+-#ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDGROUPBY_HPP_
+ #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+-#endif
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
++
++#include <vector>
++
++using namespace ::com::sun::star;
++using ::com::sun::star::uno::Any;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::UNO_QUERY;
++using ::com::sun::star::uno::UNO_QUERY_THROW;
++using ::rtl::OUString;
++
++using ::std::vector;
+ 
+ #define D_TIMEFACTOR              86400.0
+ 
+@@ -840,6 +854,7 @@
+     ScDPGroupDimension aNewGroup( rGroup );
+     aNewGroup.SetGroupDim( GetColumnCount() );      // new dimension will be at the end
+     aGroups.push_back( aNewGroup );
++    aGroupNames.insert( OUString(aNewGroup.GetName()) );
+ }
+ 
+ void ScDPGroupTableData::SetNumGroupDimension( long nIndex, const ScDPNumGroupDimension& rGroup )
+@@ -972,9 +987,98 @@
+     pSourceData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
+ }
+ 
+-void ScDPGroupTableData::ResetIterator()
++void ScDPGroupTableData::CreateCacheTable()
+ {
+-    pSourceData->ResetIterator();
++    pSourceData->CreateCacheTable();
++}
++
++void ScDPGroupTableData::FilterCacheTable(const vector<ScDPDimension*>& rPageDims)
++{
++    pSourceData->FilterCacheTable(rPageDims);
++}
++
++void ScDPGroupTableData::GetDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters, Sequence< Sequence<Any> >& rTabData)
++{
++    // Go through the field names and skip group name(s) if any.
++    vector<sheet::DataPilotFieldFilter> filters;
++    sal_Int32 nOrigSize = aFilters.getLength();
++    filters.reserve(nOrigSize);
++    StringHashSet::const_iterator itrEnd = aGroupNames.end();
++    for (sal_Int32 i = 0; i < nOrigSize; ++i)
++    {
++        if (aGroupNames.find(aFilters[i].FieldName) == itrEnd)
++            filters.push_back(aFilters[i]);
++    }
++
++    // Convert vector to Sequence.
++    size_t nSize = filters.size();
++    Sequence<sheet::DataPilotFieldFilter> filters2(nSize);
++    for (size_t i = 0; i < nSize; ++i)
++        filters2[i] = filters[i];
++
++    pSourceData->GetDrillDownData(filters2, rTabData);
++}
++
++void ScDPGroupTableData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
++{
++    // This CalcInfo instance is used only to retrive data from the original
++    // data source.
++    CalcInfo aInfoSrc = rInfo;
++    CopyFields(rInfo.aColLevelDims, aInfoSrc.aColLevelDims);
++    CopyFields(rInfo.aRowLevelDims, aInfoSrc.aRowLevelDims);
++    CopyFields(rInfo.aPageDims,     aInfoSrc.aPageDims);
++    CopyFields(rInfo.aDataSrcCols,  aInfoSrc.aDataSrcCols);
++
++    const ScDPCacheTable& rCacheTable = pSourceData->GetCacheTable();
++    sal_Int32 nRowSize = rCacheTable.getRowSize();
++    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
++    {
++        if (!rCacheTable.isRowActive(nRow))
++            continue;
++
++        CalcRowData aData;
++        FillRowDataFromCacheTable(nRow, rCacheTable, aInfoSrc, aData);
++
++        FillGroupValues(&aData.aColData[0], rInfo.aColLevelDims.size(), &rInfo.aColLevelDims[0]);
++        FillGroupValues(&aData.aRowData[0], rInfo.aRowLevelDims.size(), &rInfo.aRowLevelDims[0]);
++        FillGroupValues(&aData.aPageData[0], rInfo.aPageDims.size(), &rInfo.aPageDims[0]);
++
++        ProcessRowData(rInfo, aData, bAutoShow);
++    }
++}
++
++const ScDPCacheTable& ScDPGroupTableData::GetCacheTable() const
++{
++    return pSourceData->GetCacheTable();
++}
++
++void ScDPGroupTableData::CopyFields(const vector<long>& rFieldDims, vector<long>& rNewFieldDims)
++{
++    size_t nCount = rFieldDims.size();
++    if (!nCount)
++        return;
++
++    long nGroupedColumns = aGroups.size();
++
++    rNewFieldDims.clear();
++    rNewFieldDims.reserve(nCount);
++    for (long i = 0; i < nCount; ++i)
++    {
++        if ( rFieldDims[i] >= nSourceCount )
++        {
++            if ( rFieldDims[i] == nSourceCount + nGroupedColumns )
++                // data layout in source
++                rNewFieldDims.push_back(nSourceCount);
++            else
++            {
++                // original dimension
++                long n = rFieldDims[i] - nSourceCount;
++                rNewFieldDims.push_back(aGroups[n].GetSourceDim());
++            }
++        }
++        else
++            rNewFieldDims.push_back(rFieldDims[i]);
++    }
+ }
+ 
+ long* ScDPGroupTableData::CopyFields( const long* pSourceDims, long nCount )
+@@ -1055,42 +1159,6 @@
+     }
+ }
+ 
+-BOOL ScDPGroupTableData::GetNextRow( const ScDPTableIteratorParam& rParam )
+-{
+-    //
+-    //  call source with a param containing only dimension numbers valid for source
+-    //
+-
+-    long* pSourceCols = CopyFields( rParam.pCols, rParam.nColCount );
+-    long* pSourceRows = CopyFields( rParam.pRows, rParam.nRowCount );
+-    long* pSourcePages = CopyFields( rParam.pPages, rParam.nPageCount );
+-    long* pSourceDats = CopyFields( rParam.pDats, rParam.nDatCount );
+-    //  data fields can't be groups
+-
+-    ScDPTableIteratorParam aSourceParam( rParam.nColCount, pSourceCols, rParam.pColData, 
+-                                         rParam.nRowCount, pSourceRows, rParam.pRowData,
+-                                         rParam.nPageCount, pSourcePages, rParam.pPageData,
+-                                         rParam.nDatCount, pSourceDats, rParam.pValues );
+-
+-    BOOL bRet = pSourceData->GetNextRow( aSourceParam );
+-
+-    delete pSourceCols;
+-    delete pSourceRows;
+-    delete pSourcePages;
+-    delete pSourceDats;
+-
+-    //
+-    //  fill values for groups
+-    //
+-
+-    FillGroupValues( rParam.pColData, rParam.nColCount, rParam.pCols );
+-    FillGroupValues( rParam.pRowData, rParam.nRowCount, rParam.pRows );
+-    FillGroupValues( rParam.pPageData, rParam.nPageCount, rParam.pPages );
+-    // data is left unchanged - useful only for count
+-
+-    return bRet;
+-}
+-
+ BOOL ScDPGroupTableData::IsBaseForGroup(long nDim) const
+ {
+     for ( ScDPGroupDimensionVec::const_iterator aIter(aGroups.begin()); aIter != aGroups.end(); aIter++ )
+Index: sc/source/core/data/dpobject.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dpobject.cxx,v
+retrieving revision 1.22
+retrieving revision 1.21.112.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.22 -r1.21.112.6
+--- sc/source/core/data/dpobject.cxx	26 Nov 2007 15:19:32 -0000	1.22
++++ sc/source/core/data/dpobject.cxx	4 Dec 2007 06:06:26 -0000	1.21.112.6
+@@ -62,18 +62,32 @@
+ #include "unonames.hxx"
+ 
+ #include <com/sun/star/sheet/GeneralFunction.hpp>
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
++#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
+ #include <com/sun/star/lang/XMultiServiceFactory.hpp>
+ #include <com/sun/star/lang/XSingleServiceFactory.hpp>
+ #include <com/sun/star/lang/XInitialization.hpp>
+ #include <com/sun/star/container/XContentEnumerationAccess.hpp>
++#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
+ 
+ #include <comphelper/processfactory.hxx>
+ #include <tools/debug.hxx>
+ #include <svtools/zforlist.hxx>		// IsNumberFormat
+ 
++#include <vector>
++
+ using namespace com::sun::star;
++using ::std::vector;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::uno::UNO_QUERY;
++using ::com::sun::star::uno::Any;
++using ::com::sun::star::sheet::DataPilotTableHeaderData;
++using ::com::sun::star::sheet::DataPilotTablePositionData;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -478,6 +492,16 @@
+ 	aOutRange = pOutput->GetOutputRange();
+ }
+ 
++const ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType )
++{
++    CreateOutput();
++
++    if (pOutput->HasError())
++        return ScRange(aOutRange.aStart);
++
++    return pOutput->GetOutputRange(nType);
++}
++
+ BOOL lcl_HasButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
+ {
+ 	return ((const ScMergeFlagAttr*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->HasButton();
+@@ -601,11 +625,42 @@
+ 		r.SetSheetDesc( *pSheetDesc );
+ }
+ 
+-bool ScDPObject::GetDataFieldPositionData( std::vector< sheet::DataPilotFieldFilter >& rFilters, const ScAddress& rPos )
++void ScDPObject::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData)
+ {
+-    CreateOutput();             // create xSource and pOutput if not already done
++    CreateOutput();
++    pOutput->GetPositionData(rPos, rPosData);
++}
++
++bool ScDPObject::GetDataFieldPositionData(
++    const ScAddress& rPos, Sequence<sheet::DataPilotFieldFilter>& rFilters)
++{
++    CreateOutput();
++
++    vector<sheet::DataPilotFieldFilter> aFilters;
++    if (!pOutput->GetDataResultPositionData(aFilters, rPos))
++        return false;
+ 
+-	return pOutput->GetDataFieldPositionData( rFilters, rPos );
++    sal_Int32 n = static_cast<sal_Int32>(aFilters.size());
++    rFilters.realloc(n);
++    for (sal_Int32 i = 0; i < n; ++i)
++        rFilters[i] = aFilters[i];
++
++    return true;
++}
++
++void ScDPObject::GetDrillDownData(const ScAddress& rPos, Sequence< Sequence<Any> >& rTableData)
++{
++    CreateOutput();
++
++    Reference<sheet::XDrillDownDataSupplier> xDrillDownData(xSource, UNO_QUERY);
++    if (!xDrillDownData.is())
++        return;
++
++    Sequence<sheet::DataPilotFieldFilter> filters;
++    if (!GetDataFieldPositionData(rPos, filters))
++        return;
++
++    rTableData = xDrillDownData->getDrillDownData(filters);
+ }
+ 
+ BOOL ScDPObject::IsDimNameInUse( const String& rName ) const
+@@ -803,11 +858,21 @@
+ 		delete pAllData;
+ }
+ 
+-void ScDPObject::GetPositionData( ScDPPositionData& rData, const ScAddress& rPos )
++void ScDPObject::GetHeaderPositionData(const ScAddress& rPos, DataPilotTableHeaderData& rData)
+ {
++    using namespace ::com::sun::star::sheet::DataPilotTablePositionType;
++
+ 	CreateOutput();				// create xSource and pOutput if not already done
+ 
+-	pOutput->GetPositionData( rData, rPos );
++    // Reset member values to invalid state.
++    rData.Dimension = rData.Hierarchy = rData.Level = -1;
++    rData.Flags = 0;
++
++    DataPilotTablePositionData aPosData;
++    pOutput->GetPositionData(rPos, aPosData);
++    const sal_Int32 nPosType = aPosData.PositionType;
++    if (nPosType == COLUMN_HEADER || nPosType == ROW_HEADER)
++        aPosData.PositionData >>= rData;
+ }
+ 
+ // Returns TRUE on success and stores the result in rTarget
+@@ -1285,7 +1350,7 @@
+     return bHasData && !bError;
+ }
+ 
+-void ScDPObject::ToggleDetails( ScDPPositionData& rElemDesc, ScDPObject* pDestObj )
++void ScDPObject::ToggleDetails(const DataPilotTableHeaderData& rElemDesc, ScDPObject* pDestObj)
+ {
+ 	CreateObjects();			// create xSource if not already done
+ 
+@@ -1295,10 +1360,10 @@
+ 	uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
+ 	uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
+ 	long nIntCount = xIntDims->getCount();
+-	if ( rElemDesc.nDimension < nIntCount )
++	if ( rElemDesc.Dimension < nIntCount )
+ 	{
+ 		uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface(
+-									xIntDims->getByIndex(rElemDesc.nDimension) );
++									xIntDims->getByIndex(rElemDesc.Dimension) );
+ 		xDim = uno::Reference<container::XNamed>( xIntDim, uno::UNO_QUERY );
+ 	}
+ 	DBG_ASSERT( xDim.is(), "dimension not found" );
+@@ -1327,8 +1392,8 @@
+ 		nHierCount = xHiers->getCount();
+ 	}
+ 	uno::Reference<uno::XInterface> xHier;
+-	if ( rElemDesc.nHierarchy < nHierCount )
+-		xHier = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(rElemDesc.nHierarchy) );
++	if ( rElemDesc.Hierarchy < nHierCount )
++		xHier = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(rElemDesc.Hierarchy) );
+ 	DBG_ASSERT( xHier.is(), "hierarchy not found" );
+ 	if ( !xHier.is() ) return;
+ 
+@@ -1342,8 +1407,8 @@
+ 		nLevCount = xLevels->getCount();
+ 	}
+ 	uno::Reference<uno::XInterface> xLevel;
+-	if ( rElemDesc.nLevel < nLevCount )
+-		xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(rElemDesc.nLevel) );
++	if ( rElemDesc.Level < nLevCount )
++		xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(rElemDesc.Level) );
+ 	DBG_ASSERT( xLevel.is(), "level not found" );
+ 	if ( !xLevel.is() ) return;
+ 
+@@ -1357,11 +1422,10 @@
+ 
+ 	if ( xMembers.is() )
+ 	{
+-		rtl::OUString aName = rElemDesc.aMemberName;
+-		if ( xMembers->hasByName( aName ) )
++		if ( xMembers->hasByName(rElemDesc.MemberName) )
+ 		{
+ 			uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface(
+-											xMembers->getByName( aName ) );
++											xMembers->getByName(rElemDesc.MemberName) );
+ 			uno::Reference<beans::XPropertySet> xMbrProp( xMemberInt, uno::UNO_QUERY );
+ 			if ( xMbrProp.is() )
+ 			{
+@@ -1382,8 +1446,9 @@
+ 	DBG_ASSERT( pModifyData, "no data?" );
+ 	if ( pModifyData )
+ 	{
++        const String aName = rElemDesc.MemberName;
+ 		pModifyData->GetDimensionByName(aDimName)->
+-			GetMemberByName(rElemDesc.aMemberName)->SetShowDetails( !bShowDetails );	// toggle
++			GetMemberByName(aName)->SetShowDetails( !bShowDetails );	// toggle
+ 
+ 		if ( pDestObj )
+ 			pDestObj->InvalidateData();		// re-init source from SaveData
+Index: sc/source/core/data/dpoutput.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dpoutput.cxx,v
+retrieving revision 1.16
+retrieving revision 1.15.112.9
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.16 -r1.15.112.9
+--- sc/source/core/data/dpoutput.cxx	26 Nov 2007 15:19:49 -0000	1.16
++++ sc/source/core/data/dpoutput.cxx	5 Dec 2007 00:25:14 -0000	1.15.112.9
+@@ -36,7 +36,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
+-
++#include <stdio.h>
+ 
+ // INCLUDE ---------------------------------------------------------------
+ 
+@@ -48,6 +48,8 @@
+ #include <unotools/transliterationwrapper.hxx>
+ 
+ #include "dpoutput.hxx"
++#include "dptabsrc.hxx"
++#include "dpcachetable.hxx"
+ #include "document.hxx"
+ #include "patattr.hxx"
+ #include "docpool.hxx"
+@@ -60,21 +62,37 @@
+ #include "stlsheet.hxx"
+ #include "collect.hxx"
+ #include "scresid.hxx"
++#include "unonames.hxx"
+ #include "sc.hrc"
+ 
+-#include <com/sun/star/sheet/XLevelsSupplier.hpp>
+-#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
+-#include <com/sun/star/sheet/XDataPilotResults.hpp>
+-#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
+-#include <com/sun/star/sheet/DataResultFlags.hpp>
+-#include <com/sun/star/sheet/MemberResultFlags.hpp>
++#include <com/sun/star/container/XNamed.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+-#include <com/sun/star/sheet/TableFilterField.hpp>
++#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
++#include <com/sun/star/sheet/DataPilotTableResultData.hpp>
++#include <com/sun/star/sheet/DataResultFlags.hpp>
+ #include <com/sun/star/sheet/GeneralFunction.hpp>
+-#include <com/sun/star/container/XNamed.hpp>
++#include <com/sun/star/sheet/MemberResultFlags.hpp>
++#include <com/sun/star/sheet/TableFilterField.hpp>
++#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
++#include <com/sun/star/sheet/XDataPilotResults.hpp>
++#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
++#include <com/sun/star/sheet/XLevelsSupplier.hpp>
++
++#include <vector>
+ 
+ using namespace com::sun::star;
++using ::std::vector;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::UNO_QUERY;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::sheet::DataPilotTablePositionData;
++using ::com::sun::star::sheet::DataPilotTableResultData;
++using ::com::sun::star::uno::makeAny;
++using ::com::sun::star::uno::Any;
++using ::rtl::OUString;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -702,6 +720,42 @@
+ 	}
+ }
+ 
++sal_Int32 ScDPOutput::GetPositionType(const ScAddress& rPos)
++{
++    using namespace ::com::sun::star::sheet;
++
++    SCCOL nCol = rPos.Col();
++    SCROW nRow = rPos.Row();
++    SCTAB nTab = rPos.Tab();
++    if ( nTab != aStartPos.Tab() )
++        return DataPilotTablePositionType::NOT_IN_TABLE;
++
++    CalcSizes();
++
++    // Make sure the cursor is within the table.
++    if (nCol < nTabStartCol || nRow < nTabStartRow || nCol > nTabEndCol || nRow > nTabEndRow)
++        return DataPilotTablePositionType::NOT_IN_TABLE;
++
++    // test for result data area.
++    if (nCol >= nDataStartCol && nCol <= nTabEndCol && nRow >= nDataStartRow && nRow <= nTabEndRow)
++        return DataPilotTablePositionType::RESULT;
++
++    bool bInColHeader = (nRow >= nMemberStartRow && nRow < nMemberStartRow + nColFieldCount);
++    bool bInRowHeader = (nCol >= nMemberStartCol && nCol < nMemberStartCol + nRowFieldCount);
++
++    if (bInColHeader && bInRowHeader)
++        // probably in that ugly little box at the upper-left corner of the table.
++        return DataPilotTablePositionType::NOT_IN_TABLE;
++
++    if (bInColHeader)
++        return DataPilotTablePositionType::COLUMN_HEADER;
++
++    if (bInRowHeader)
++        return DataPilotTablePositionType::ROW_HEADER;
++
++    return DataPilotTablePositionType::NOT_IN_TABLE;
++}
++
+ void ScDPOutput::Output()
+ {
+ 	long nField;
+@@ -862,12 +916,30 @@
+ 	lcl_SetFrame( pDoc,nTab, nTabStartCol,nTabStartRow, nTabEndCol,nTabEndRow, 40 );
+ }
+ 
+-ScRange ScDPOutput::GetOutputRange()
++ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType )
+ {
++    using namespace ::com::sun::star::sheet;
++
+ 	CalcSizes();
+ 
++//  fprintf(stdout, "ScDPOutput::GetOutputRange: aStartPos = (%ld, %d)\n", aStartPos.Row(), aStartPos.Col());fflush(stdout);
++//  fprintf(stdout, "ScDPOutput::GetOutputRange: nTabStart (Row = %ld, Col = %ld)\n", nTabStartRow, nTabStartCol);fflush(stdout);
++//  fprintf(stdout, "ScDPOutput::GetOutputRange: nMemberStart (Row = %ld, Col = %ld)\n", nMemberStartRow, nMemberStartCol);fflush(stdout);
++//  fprintf(stdout, "ScDPOutput::GetOutputRange: nDataStart (Row = %ld, Col = %ld)\n", nDataStartRow, nDataStartCol);fflush(stdout);
++//  fprintf(stdout, "ScDPOutput::GetOutputRange: nTabEnd (Row = %ld, Col = %ld)\n", nTabEndRow, nTabStartCol);fflush(stdout);
++
+ 	SCTAB nTab = aStartPos.Tab();
+-	return ScRange( aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
++    switch (nRegionType)
++    {
++        case DataPilotOutputRangeType::RESULT:
++            return ScRange(nDataStartCol, nDataStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
++        case DataPilotOutputRangeType::TABLE:
++            return ScRange(aStartPos.Col(), nTabStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
++        default:
++            DBG_ASSERT(nRegionType == DataPilotOutputRangeType::WHOLE, "ScDPOutput::GetOutputRange: unknown region type");
++        break;
++    }
++    return ScRange(aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
+ }
+ 
+ BOOL ScDPOutput::HasError()
+@@ -929,13 +1001,10 @@
+     }
+ }
+ 
+-//
+-//		Methods to find specific parts of the table
+-//
+ 
+-void ScDPOutput::GetPositionData( ScDPPositionData& rData, const ScAddress& rPos )
++void ScDPOutput::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData)
+ {
+-	//!	preset rData to "invalid" ?
++    using namespace ::com::sun::star::sheet;
+ 
+ 	SCCOL nCol = rPos.Col();
+ 	SCROW nRow = rPos.Row();
+@@ -947,56 +1016,88 @@
+ 
+ 	CalcSizes();
+ 
+-	//	test for column field
++    rPosData.PositionType = GetPositionType(rPos);
++    switch (rPosData.PositionType)
++    {
++        case DataPilotTablePositionType::RESULT:
++        {
++            vector<DataPilotFieldFilter> aFilters;
++            GetDataResultPositionData(aFilters, rPos);
++            sal_Int32 nSize = aFilters.size();
++    
++            DataPilotTableResultData aResData;
++            aResData.FieldFilters.realloc(nSize);
++            for (sal_Int32 i = 0; i < nSize; ++i)
++                aResData.FieldFilters[i] = aFilters[i];
++    
++            aResData.DataFieldIndex = 0;
++            Reference<beans::XPropertySet> xPropSet(xSource, UNO_QUERY);
++            if (xPropSet.is())
++            {
++                sal_Int32 nDataFieldCount;
++                Any any = xPropSet->getPropertyValue(rtl::OUString::createFromAscii("DataFieldCount"));
++                if (any >>= nDataFieldCount)
++                    aResData.DataFieldIndex = (nRow - nDataStartRow) % nDataFieldCount;
++            }
++
++            // Copy appropriate DataResult object from the cached sheet::DataResult table.
++            if (aData.getLength() > nRow - nDataStartRow && 
++                aData[nRow-nDataStartRow].getLength() > nCol-nDataStartCol)
++                aResData.Result = aData[nRow-nDataStartRow][nCol-nDataStartCol];
+ 
+-	if ( nRow >= nMemberStartRow && nRow < nMemberStartRow + nColFieldCount )
++            rPosData.PositionData = makeAny(aResData);
++            return;
++        }
++        case DataPilotTablePositionType::COLUMN_HEADER:
+ 	{
++            fprintf(stdout, "ScDPOutput::GetPositionData: column header\n");fflush(stdout);
+ 		long nField = nRow - nMemberStartRow;
+ 		const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nField].aResult;
+ 		const sheet::MemberResult* pArray = rSequence.getConstArray();
+ 		long nThisColCount = rSequence.getLength();
+ 
+-		if ( nCol >= nDataStartCol && nCol < nDataStartCol + nThisColCount )
+-		{
+ 			long nItem = nCol - nDataStartCol;
+ 			//	get origin of "continue" fields
+-			while ( nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE ) )
++            while (nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
+ 				--nItem;
+-			rData.aMemberName = String(pArray[nItem].Name);
+-			rData.nFlags	  = pArray[nItem].Flags;
+-			rData.nDimension  = pColFields[nField].nDim;
+-			rData.nHierarchy  = pColFields[nField].nHier;
+-			rData.nLevel      = pColFields[nField].nLevel;
+-			return;
+-		}
+-	}
+ 
+-	//	test for row field
++            DataPilotTableHeaderData aHeaderData;
++            aHeaderData.MemberName = OUString(pArray[nItem].Name);
++            aHeaderData.Flags = pArray[nItem].Flags;
++            aHeaderData.Dimension = static_cast<sal_Int32>(pColFields[nField].nDim);
++            aHeaderData.Hierarchy = static_cast<sal_Int32>(pColFields[nField].nHier);
++            aHeaderData.Level     = static_cast<sal_Int32>(pColFields[nField].nLevel);
+ 
+-	if ( nCol >= nMemberStartCol && nCol < nMemberStartCol + nRowFieldCount )
++            rPosData.PositionData = makeAny(aHeaderData);
++            return;
++        }
++        case DataPilotTablePositionType::ROW_HEADER:
+ 	{
++            fprintf(stdout, "ScDPOutput::GetPositionData: row header\n");fflush(stdout);
+ 		long nField = nCol - nMemberStartCol;
+ 		const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nField].aResult;
+ 		const sheet::MemberResult* pArray = rSequence.getConstArray();
+ 		long nThisRowCount = rSequence.getLength();
+ 
+-		if ( nRow >= nDataStartRow && nRow < nDataStartRow + nThisRowCount )
+-		{
+ 			long nItem = nRow - nDataStartRow;
+ 			//	get origin of "continue" fields
+-			while ( nItem > 0 && ( pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE ) )
++            while ( nItem > 0 && (pArray[nItem].Flags & sheet::MemberResultFlags::CONTINUE) )
+ 				--nItem;
+-			rData.aMemberName = String(pArray[nItem].Name);
+-			rData.nFlags	  = pArray[nItem].Flags;
+-			rData.nDimension  = pRowFields[nField].nDim;
+-			rData.nHierarchy  = pRowFields[nField].nHier;
+-			rData.nLevel      = pRowFields[nField].nLevel;
++
++            DataPilotTableHeaderData aHeaderData;
++            aHeaderData.MemberName = OUString(pArray[nItem].Name);
++            aHeaderData.Flags = pArray[nItem].Flags;
++            aHeaderData.Dimension = static_cast<sal_Int32>(pRowFields[nField].nDim);
++            aHeaderData.Hierarchy = static_cast<sal_Int32>(pRowFields[nField].nHier);
++            aHeaderData.Level     = static_cast<sal_Int32>(pRowFields[nField].nLevel);
++
++            rPosData.PositionData = makeAny(aHeaderData);
+ 			return;
+ 		}
+ 	}
+ }
+ 
+-bool ScDPOutput::GetDataFieldPositionData(std::vector<sheet::DataPilotFieldFilter>& rFilters, const ScAddress& rPos)
++bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>& rFilters, const ScAddress& rPos)
+ {
+     SCCOL nCol = rPos.Col();
+     SCROW nRow = rPos.Row();
+@@ -1013,8 +1114,6 @@
+         return false;
+     }
+ 
+-    rtl::OUString sTotal( ScGlobal::GetRscString(STR_PIVOT_TOTAL) );
+-
+     // column fields
+     for (SCCOL nColField = 0; nColField < nColFieldCount; ++nColField)
+     {
+@@ -1022,10 +1121,10 @@
+         filter.FieldName = pColFields[nColField].aCaption;
+ 
+         const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nColField].aResult;
++        long nThisColCount = rSequence.getLength();
+         const sheet::MemberResult* pArray = rSequence.getConstArray();
+ 
+-        DBG_ASSERT(nDataStartCol + rSequence.getLength() - 1 == nTabEndCol,
+-                    "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
++        DBG_ASSERT(nDataStartCol + nThisColCount - 1 == nTabEndCol, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
+ 
+         long nItem = nCol - nDataStartCol;
+                 //	get origin of "continue" fields
+@@ -1033,7 +1132,7 @@
+             --nItem;
+ 
+         filter.MatchValue = pArray[nItem].Name;
+-        if (pArray[nItem].Name.getLength() > 0 && pArray[nItem].Name != sTotal)
++        if (pArray[nItem].Name.getLength() > 0 && !pArray[nItem].Name.equalsAscii("Total"))
+             rFilters.push_back(filter);
+     }
+ 
+@@ -1044,10 +1143,10 @@
+         filter.FieldName = pRowFields[nRowField].aCaption;
+ 
+         const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nRowField].aResult;
++        long nThisRowCount = rSequence.getLength();
+         const sheet::MemberResult* pArray = rSequence.getConstArray();
+ 
+-        DBG_ASSERT(nDataStartRow + rSequence.getLength() - 1 == nTabEndRow,
+-                    "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
++        DBG_ASSERT(nDataStartRow + nThisRowCount - 1 == nTabEndRow, "ScDPOutput::GetDataFieldCellData: error in geometric assumption");
+ 
+         long nItem = nRow - nDataStartRow;
+ 			//	get origin of "continue" fields
+@@ -1055,7 +1154,7 @@
+             --nItem;
+ 
+         filter.MatchValue = pArray[nItem].Name;
+-        if (pArray[nItem].Name.getLength() > 0 && pArray[nItem].Name != sTotal)
++        if (pArray[nItem].Name.getLength() > 0 && !pArray[nItem].Name.equalsAscii("Total"))
+             rFilters.push_back(filter);
+     }
+ 
+Index: sc/source/core/data/dpsdbtab.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dpsdbtab.cxx,v
+retrieving revision 1.12
+retrieving revision 1.12.202.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.12 -r1.12.202.3
+--- sc/source/core/data/dpsdbtab.cxx	27 Feb 2007 12:04:37 -0000	1.12
++++ sc/source/core/data/dpsdbtab.cxx	6 Dec 2007 07:06:15 -0000	1.12.202.3
+@@ -36,7 +36,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
+-
++#include <stdio.h>
+ 
+ // INCLUDE --------------------------------------------------------------
+ 
+@@ -55,14 +55,24 @@
+ #include <com/sun/star/sdbc/XRowSet.hpp>
+ #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
+ #include <com/sun/star/lang/XMultiServiceFactory.hpp>
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ 
+ #include "dpsdbtab.hxx"
+ #include "collect.hxx"
+ #include "global.hxx"
+ #include "globstr.hrc"
++#include "dpcachetable.hxx"
++#include "dptabres.hxx"
+ 
+ using namespace com::sun::star;
+ 
++using ::std::vector;
++using ::std::set;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::uno::Any;
++using ::com::sun::star::uno::UNO_QUERY;
++
+ #define SC_SERVICE_ROWSET			"com.sun.star.sdb.RowSet"
+ #define SC_SERVICE_INTHANDLER		"com.sun.star.sdb.InteractionHandler"
+ 
+@@ -79,14 +89,12 @@
+ 	::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager;
+ 	ScImportSourceDesc	aDesc;
+ 	long				nColCount;
+-	BOOL				bValid;
+-	BOOL				bAtStart;
+-	String*				pTitles;
+-	TypedStrCollection** ppStrings;
+ 	uno::Reference<sdbc::XRowSet> xRowSet;
+ 	sal_Int32*			pTypes;
+ 	SvNumberFormatter*	pFormatter;
+ 
++    ScDPCacheTable      aCacheTable;
++
+ 	ScDatabaseDPData_Impl() {}
+ };
+ 
+@@ -100,14 +108,11 @@
+ 	pImpl->xServiceManager = xSMgr;
+ 	pImpl->aDesc = rImport;
+ 	pImpl->nColCount = 0;
+-	pImpl->bValid = FALSE;
+-	pImpl->bAtStart = FALSE;
+-	pImpl->pTitles = NULL;
+-	pImpl->ppStrings = NULL;
+ 	pImpl->pTypes = NULL;
+ 	pImpl->pFormatter = NULL;		// created on demand
+ 
+ 	OpenDatabase();
++    CreateCacheTable();
+ }
+ 
+ ScDatabaseDPData::~ScDatabaseDPData()
+@@ -115,13 +120,6 @@
+ 	::comphelper::disposeComponent( pImpl->xRowSet );
+ 
+ 	delete[] pImpl->pTypes;
+-	if ( pImpl->ppStrings )
+-	{
+-		for (long i=0; i<pImpl->nColCount; i++)
+-			delete pImpl->ppStrings[i];
+-		delete[] pImpl->ppStrings;
+-	}
+-	delete[] pImpl->pTitles;
+ 	delete pImpl->pFormatter;		// NumberFormatter is local for this object
+ 	delete pImpl;
+ }
+@@ -129,21 +127,7 @@
+ void ScDatabaseDPData::DisposeData()
+ {
+ 	//!	use OpenDatabase here?
+-
+-	//!	column titles ???
+-
+-	//	collections for column entries
+-	if ( pImpl->ppStrings )
+-	{
+-		for (long i=0; i<pImpl->nColCount; i++)
+-		{
+-			delete pImpl->ppStrings[i];
+-			pImpl->ppStrings[i] = NULL;
+-		}
+-	}
+-
+-	//!	init entries on demand!
+-	InitAllColumnEntries();				//! configurable ???
++    pImpl->aCacheTable.clear();
+ }
+ 
+ BOOL ScDatabaseDPData::OpenDatabase()
+@@ -199,8 +183,6 @@
+ 			else
+ 				pImpl->xRowSet->execute();
+ 
+-			pImpl->bAtStart = TRUE;
+-
+ 			//
+ 			//	get column descriptions
+ 			//
+@@ -216,22 +198,9 @@
+ 			uno::Reference<sdbc::XResultSet> xResSet( pImpl->xRowSet, uno::UNO_QUERY );
+ 			if ( pImpl->nColCount > 0 && xResSet.is() )
+ 			{
+-				//	get column titles
+-				pImpl->pTitles = new String[pImpl->nColCount];
+ 				pImpl->pTypes = new sal_Int32[pImpl->nColCount];
+ 				for (long nCol=0; nCol<pImpl->nColCount; nCol++)
+-				{
+-					pImpl->pTitles[nCol] = xMeta->getColumnLabel( nCol+1 );
+ 					pImpl->pTypes[nCol]  = xMeta->getColumnType( nCol+1 );
+-				}
+-
+-				//	collections for column entries
+-				pImpl->ppStrings = new TypedStrCollection*[pImpl->nColCount];
+-				for (long i=0; i<pImpl->nColCount; i++)
+-					pImpl->ppStrings[i] = NULL;
+-
+-				//!	init entries on demand!
+-				InitAllColumnEntries();				//! configurable ???
+ 
+ 				bSuccess = TRUE;
+ 			}
+@@ -252,7 +221,6 @@
+ 	if (!bSuccess)
+ 		::comphelper::disposeComponent( pImpl->xRowSet );
+ 
+-	pImpl->bValid = bSuccess;
+ 	return bSuccess;
+ }
+ 
+@@ -261,103 +229,6 @@
+ 	return pImpl->nColCount;
+ }
+ 
+-void lcl_FillItemData( ScDPItemData& rData,
+-						const uno::Reference<sdbc::XRow>& xRow, long nRowPos,
+-						long nType, BOOL bStringForVal, ScDatabaseDPData_Impl* pImpl )
+-{
+-	//!	merge with lcl_PutData in dbdocimp.cxx
+-
+-	rData.aString.Erase();
+-	rData.fValue = 0.0;
+-	rData.bHasValue = FALSE;
+-	short nNumType = NUMBERFORMAT_NUMBER;
+-	BOOL bEmptyFlag = FALSE;
+-
+-	if (!xRow.is())
+-		return;
+-
+-	try
+-	{
+-		switch ( nType )
+-		{
+-			case sdbc::DataType::BIT:
+-			case sdbc::DataType::BOOLEAN:
+-				nNumType = NUMBERFORMAT_LOGICAL;
+-				rData.fValue = (xRow->getBoolean(nRowPos) ? 1 : 0);
+-				bEmptyFlag = ( rData.fValue == 0.0 ) && xRow->wasNull();
+-				rData.bHasValue = TRUE;
+-				break;
+-
+-			case sdbc::DataType::TINYINT:
+-			case sdbc::DataType::SMALLINT:
+-			case sdbc::DataType::INTEGER:
+-			case sdbc::DataType::BIGINT:
+-			case sdbc::DataType::FLOAT:
+-			case sdbc::DataType::REAL:
+-			case sdbc::DataType::DOUBLE:
+-			case sdbc::DataType::NUMERIC:
+-			case sdbc::DataType::DECIMAL:
+-				//!	do the conversion here?
+-				rData.fValue = xRow->getDouble(nRowPos);
+-				bEmptyFlag = ( rData.fValue == 0.0 ) && xRow->wasNull();
+-				rData.bHasValue = TRUE;
+-				break;
+-
+-			case sdbc::DataType::CHAR:
+-			case sdbc::DataType::VARCHAR:
+-			case sdbc::DataType::LONGVARCHAR:
+-				rData.aString = xRow->getString(nRowPos);
+-				bEmptyFlag = ( rData.aString.Len() == 0 ) && xRow->wasNull();
+-				break;
+-
+-			case sdbc::DataType::DATE:
+-				{
+-					nNumType = NUMBERFORMAT_DATE;
+-
+-					if (!pImpl->pFormatter)
+-						pImpl->pFormatter = new SvNumberFormatter( pImpl->xServiceManager, ScGlobal::eLnge );
+-
+-					util::Date aDate = xRow->getDate(nRowPos);
+-					rData.fValue = Date( aDate.Day, aDate.Month, aDate.Year ) -
+-												*pImpl->pFormatter->GetNullDate();
+-					bEmptyFlag = xRow->wasNull();
+-					rData.bHasValue = TRUE;
+-				}
+-				break;
+-
+-			//! case sdbc::DataType::TIME:
+-			//! case sdbc::DataType::TIMESTAMP:
+-
+-			case sdbc::DataType::SQLNULL:
+-				//bEmptyFlag = TRUE;
+-				break;
+-
+-			case sdbc::DataType::BINARY:
+-			case sdbc::DataType::VARBINARY:
+-			case sdbc::DataType::LONGVARBINARY:
+-			default:
+-				//bError = TRUE;		// unknown type
+-				break;
+-		}
+-	}
+-	catch ( uno::Exception& )
+-	{
+-		//bError = TRUE;
+-	}
+-
+-	if ( bEmptyFlag )
+-		rData.bHasValue = FALSE;		// empty -> empty string
+-
+-	if ( rData.bHasValue && bStringForVal )
+-	{
+-		if (!pImpl->pFormatter)
+-			pImpl->pFormatter = new SvNumberFormatter( pImpl->xServiceManager, ScGlobal::eLnge );
+-
+-		ULONG nIndex = pImpl->pFormatter->GetStandardFormat( nNumType, ScGlobal::eLnge );
+-		pImpl->pFormatter->GetInputLineString( rData.fValue, nIndex, rData.aString );
+-	}
+-}
+-
+ void lcl_Reset( const uno::Reference<sdbc::XRowSet>& xRowSet )
+ 					throw(sdbc::SQLException, uno::RuntimeException)
+ {
+@@ -367,104 +238,10 @@
+ 	xRowSet->execute();		// restart
+ }
+ 
+-void ScDatabaseDPData::InitAllColumnEntries()
+-{
+-	DBG_ASSERT( pImpl->ppStrings, "GetColumnEntries: no entries" );
+-	long nCol;
+-	for ( nCol=0; nCol<pImpl->nColCount; nCol++ )
+-		if (!pImpl->ppStrings[nCol])
+-			pImpl->ppStrings[nCol] = new TypedStrCollection;
+-
+-//	Sound::Beep();		//! Test !!!
+-
+-	uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+-	uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+-	if ( xRow.is() )
+-	{
+-		ScDPItemData aItemData;
+-
+-		try
+-		{
+-			if ( !pImpl->bAtStart )
+-				lcl_Reset( xRowSet );
+-
+-			pImpl->bAtStart = FALSE;
+-			while ( xRowSet->next() )
+-			{
+-				for ( nCol=0; nCol<pImpl->nColCount; nCol++ )
+-				{
+-					//!	get string for value data only if value hasn't been inserted yet
+-					lcl_FillItemData( aItemData, xRow, nCol+1, pImpl->pTypes[nCol], TRUE, pImpl );
+-					TypedStrData* pNew = new TypedStrData(
+-							aItemData.aString, aItemData.fValue,
+-							aItemData.bHasValue ? SC_STRTYPE_VALUE : SC_STRTYPE_STANDARD );
+-					if (!pImpl->ppStrings[nCol]->Insert(pNew))
+-						delete pNew;
+-				}
+-			}
+-		}
+-		catch ( sdbc::SQLException& rError )
+-		{
+-			//!	store error message
+-			InfoBox aInfoBox( 0, String(rError.Message) );
+-			aInfoBox.Execute();
+-		}
+-		catch ( uno::Exception& )
+-		{
+-			DBG_ERROR("Unexpected exception in database");
+-		}
+-	}
+-}
+-
+ const TypedStrCollection& ScDatabaseDPData::GetColumnEntries(long nColumn)
+ {
+-	DBG_ASSERT( pImpl->ppStrings && nColumn < pImpl->nColCount, "GetColumnEntries: no entries" );
+-	if (!pImpl->ppStrings[nColumn])
+-	{
+-		TypedStrCollection* pColl = new TypedStrCollection;
+-
+-		//!	select distinct values directly from database
+-
+-//		Sound::Beep();		//! Test !!!
+-
+-		uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+-		uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+-		if ( xRow.is() )
+-		{
+-			ScDPItemData aItemData;
+-
+-			try
+-			{
+-				if ( !pImpl->bAtStart )
+-					lcl_Reset( xRowSet );
+-
+-				pImpl->bAtStart = FALSE;
+-				while ( xRowSet->next() )
+-				{
+-					//!	get string for value data only if value hasn't been inserted yet
+-					lcl_FillItemData( aItemData, xRow, nColumn+1, pImpl->pTypes[nColumn], TRUE, pImpl );
+-					TypedStrData* pNew = new TypedStrData(
+-							aItemData.aString, aItemData.fValue,
+-							aItemData.bHasValue ? SC_STRTYPE_VALUE : SC_STRTYPE_STANDARD );
+-					if (!pColl->Insert(pNew))
+-						delete pNew;
+-				}
+-			}
+-			catch ( sdbc::SQLException& rError )
+-			{
+-				//!	store error message
+-				InfoBox aInfoBox( 0, String(rError.Message) );
+-				aInfoBox.Execute();
+-			}
+-			catch ( uno::Exception& )
+-			{
+-				DBG_ERROR("Unexpected exception in database");
+-			}
+-		}
+-
+-		pImpl->ppStrings[nColumn] = pColl;
+-	}
+-	return *pImpl->ppStrings[nColumn];
++    CreateCacheTable();
++    return pImpl->aCacheTable.getFieldEntries(nColumn);
+ }
+ 
+ String ScDatabaseDPData::getDimensionName(long nColumn)
+@@ -475,10 +252,12 @@
+ 		//return "Data";
+ 		return ScGlobal::GetRscString(STR_PIVOT_DATA);
+ 	}
+-	else if ( pImpl->pTitles && nColumn < pImpl->nColCount )
+-	{
+-		return pImpl->pTitles[nColumn];
+-	}
++
++    CreateCacheTable();
++    const String* pStr = pImpl->aCacheTable.getFieldName(nColumn);
++    if (pStr)
++        return *pStr;
++
+ 	DBG_ERROR("getDimensionName: invalid dimension");
+ 	return String();
+ }
+@@ -500,106 +279,39 @@
+ 	//!	disable flags
+ }
+ 
+-void ScDatabaseDPData::ResetIterator()
++void ScDatabaseDPData::CreateCacheTable()
+ {
+-	try
+-	{
+-		uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+-		if ( xRowSet.is() && !pImpl->bAtStart )
+-		{
+-			lcl_Reset( xRowSet );
+-			pImpl->bAtStart = TRUE;
+-		}
+-	}
+-	catch ( sdbc::SQLException& rError )
+-	{
+-		//!	store error message
+-		InfoBox aInfoBox( 0, String(rError.Message) );
+-		aInfoBox.Execute();
+-	}
+-	catch ( uno::Exception& )
+-	{
+-		DBG_ERROR("Unexpected exception in database");
+-	}
++    if (!pImpl->aCacheTable.empty())
++        return;
++
++    // Get null date.
++    if (!pImpl->pFormatter)
++        pImpl->pFormatter = new SvNumberFormatter(pImpl->xServiceManager, ScGlobal::eLnge);
+ 
+-//	Sound::Beep();		//! Test !!!
++    pImpl->aCacheTable.fillTable(pImpl->xRowSet, *pImpl->pFormatter->GetNullDate());
+ }
+ 
+-BOOL ScDatabaseDPData::GetNextRow( const ScDPTableIteratorParam& rParam )
++void ScDatabaseDPData::FilterCacheTable(const vector<ScDPDimension*>& rPageDims)
+ {
+-	BOOL bSuccess = FALSE;
+-	uno::Reference<sdbc::XRowSet> xRowSet = pImpl->xRowSet;
+-	uno::Reference<sdbc::XRow> xRow( xRowSet, uno::UNO_QUERY );
+-
+-	try
+-	{
+-		pImpl->bAtStart = FALSE;
+-		if ( xRow.is() && xRowSet->next() )
+-		{
+-			SCSIZE i;
+-
+-			for (i=0; i<rParam.nColCount; i++)
+-			{
+-				long nDim = rParam.pCols[i];
+-				if ( getIsDataLayoutDimension(nDim) )
+-					rParam.pColData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+-				else
+-					lcl_FillItemData( rParam.pColData[i], xRow, nDim+1, pImpl->pTypes[nDim], FALSE, pImpl );
+-			}
+-
+-			for (i=0; i<rParam.nRowCount; i++)
+-			{
+-				long nDim = rParam.pRows[i];
+-				if ( getIsDataLayoutDimension(nDim) )
+-					rParam.pRowData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+-				else
+-					lcl_FillItemData( rParam.pRowData[i], xRow, nDim+1, pImpl->pTypes[nDim], FALSE, pImpl );
+-			}
+-
+-			for (i=0; i<rParam.nPageCount; i++)
+-			{
+-				long nDim = rParam.pPages[i];
+-				if ( getIsDataLayoutDimension(nDim) )
+-					rParam.pPageData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+-				else
+-					lcl_FillItemData( rParam.pPageData[i], xRow, nDim+1, pImpl->pTypes[nDim], FALSE, pImpl );
+-			}
+-
+-			for (i=0; i<rParam.nDatCount; i++)
+-			{
+-				//!	merge this with lcl_FillItemData, distinguish all SC_VALTYPE_... types
+-
+-				long nDim = rParam.pDats[i];
++    CreateCacheTable();
++    pImpl->aCacheTable.filterByPageDimension(rPageDims);
++}
+ 
+-				double fVal = 0.0;
+-				BYTE nType = SC_VALTYPE_EMPTY;
+-				try
+-				{
+-					fVal = xRow->getDouble( nDim+1 );
+-				}
+-				catch ( uno::Exception& )
+-				{
+-					//	anything that can't be converted to a number is a string
+-					nType = SC_VALTYPE_STRING;
+-				}
+-				rParam.pValues[i].Set( fVal, SC_VALTYPE_VALUE );
+-			}
++void ScDatabaseDPData::GetDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& rFilters, Sequence< Sequence<Any> >& rTabData)
++{
++    CreateCacheTable();
++    pImpl->aCacheTable.filterTable(rFilters, rTabData);
++}
+ 
+-			bSuccess = TRUE;
+-		}
+-	}
+-	catch ( sdbc::SQLException& rError )
+-	{
+-		//!	store error message
+-		InfoBox aInfoBox( 0, String(rError.Message) );
+-		aInfoBox.Execute();
+-	}
+-	catch ( uno::Exception& )
+-	{
+-		DBG_ERROR("Unexpected exception in database");
+-	}
++void ScDatabaseDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
++{
++    CreateCacheTable();
++    CalcResultsFromCacheTable(pImpl->aCacheTable, rInfo, bAutoShow);
++}
+ 
+-	return bSuccess;
++const ScDPCacheTable& ScDatabaseDPData::GetCacheTable() const
++{
++    return pImpl->aCacheTable;
+ }
+ 
+ // -----------------------------------------------------------------------
+Index: sc/source/core/data/dpshttab.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dpshttab.cxx,v
+retrieving revision 1.9
+retrieving revision 1.9.202.4
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.9 -r1.9.202.4
+--- sc/source/core/data/dpshttab.cxx	27 Feb 2007 12:04:49 -0000	1.9
++++ sc/source/core/data/dpshttab.cxx	6 Dec 2007 07:06:15 -0000	1.9.202.4
+@@ -44,11 +44,24 @@
+ #include <svtools/zforlist.hxx>
+ 
+ #include "dpshttab.hxx"
++#include "dptabres.hxx"
+ #include "document.hxx"
+ #include "collect.hxx"
+ #include "cell.hxx"
++#include "dpcachetable.hxx"
+ #include "globstr.hrc"
+ 
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
++
++#include <vector>
++#include <set>
++
++using namespace ::com::sun::star;
++using ::com::sun::star::uno::Any;
++using ::com::sun::star::uno::Sequence;
++using ::std::vector;
++using ::std::set;
++
+ // -----------------------------------------------------------------------
+ 
+ class ScSheetDPData_Impl
+@@ -57,49 +70,47 @@
+ 	ScDocument*		pDoc;
+ 	ScRange			aRange;
+ 	ScQueryParam	aQuery;
+-	long			nColCount;
++    BOOL*           pSpecial;           // to flag special handling of query parameters in ValidQuery.
+ 	BOOL			bIgnoreEmptyRows;
+ 	BOOL			bRepeatIfEmpty;
+-	TypedStrCollection**	ppStrings;
+ 	BOOL*			pDateDim;
+ 	SCROW			nNextRow;		// for iterator, within range
+ 
+-	ScSheetDPData_Impl() {}
++    ScDPCacheTable  aCacheTable;
++
++	ScSheetDPData_Impl() :
++        pSpecial(NULL)
++    {
++    }
+ };
+ 
+ // -----------------------------------------------------------------------
+ 
+ ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc )
+-    : pSpecial(NULL)
+ {
+-	long nCount = rDesc.aSourceRange.aEnd.Col() - rDesc.aSourceRange.aStart.Col() + 1;
+ 	pImpl = new ScSheetDPData_Impl;
+ 	pImpl->pDoc = pD;
+ 	pImpl->aRange = rDesc.aSourceRange;
+ 	pImpl->aQuery = rDesc.aQueryParam;
+ 	pImpl->bIgnoreEmptyRows = FALSE;
+ 	pImpl->bRepeatIfEmpty = FALSE;
+-	pImpl->nColCount = nCount;
+-	pImpl->ppStrings = new TypedStrCollection*[nCount];
+ 	pImpl->pDateDim = NULL;
+-	for (long i=0; i<nCount; i++)
+-		pImpl->ppStrings[i] = NULL;
+ 
+ 	pImpl->nNextRow = pImpl->aRange.aStart.Row() + 1;
+ 
+     SCSIZE nEntryCount(pImpl->aQuery.GetEntryCount());
+-    pSpecial = new BOOL[nEntryCount];
++    pImpl->pSpecial = new BOOL[nEntryCount];
+     for (SCSIZE j = 0; j < nEntryCount; ++j )
+     {
+         ScQueryEntry& rEntry = pImpl->aQuery.GetEntry(j);
+         if (rEntry.bDoQuery)
+         {
+-            pSpecial[j] = false;
++            pImpl->pSpecial[j] = false;
+             if (!rEntry.bQueryByString)
+             {
+                 if (*rEntry.pStr == EMPTY_STRING &&
+                    ((rEntry.nVal == SC_EMPTYFIELDS) || (rEntry.nVal == SC_NONEMPTYFIELDS)))
+-                    pSpecial[j] = true;
++                    pImpl->pSpecial[j] = true;
+             }
+             else
+             {
+@@ -110,30 +121,25 @@
+             }
+     	}
+     }
++    CreateCacheTable();
+ }
+ 
+ ScSheetDPData::~ScSheetDPData()
+ {
+-	for (long i=0; i<pImpl->nColCount; i++)
+-		delete pImpl->ppStrings[i];
+-	delete[] pImpl->ppStrings;
+ 	delete[] pImpl->pDateDim;
++    delete[] pImpl->pSpecial;
+ 	delete pImpl;
+-    delete[] pSpecial;
+ }
+ 
+ void ScSheetDPData::DisposeData()
+ {
+-	for (long i=0; i<pImpl->nColCount; i++)
+-	{
+-		delete pImpl->ppStrings[i];
+-		pImpl->ppStrings[i] = NULL;
+-	}
++    pImpl->aCacheTable.clear();
+ }
+ 
+ long ScSheetDPData::GetColumnCount()
+ {
+-	return pImpl->nColCount;
++    CreateCacheTable();
++    return pImpl->aCacheTable.getColSize();
+ }
+ 
+ BOOL lcl_HasQuery( const ScQueryParam& rParam )
+@@ -144,81 +150,31 @@
+ 
+ const TypedStrCollection& ScSheetDPData::GetColumnEntries(long nColumn)
+ {
+-	DBG_ASSERT(nColumn>=0 && nColumn<pImpl->nColCount, "ScSheetDPData: wrong column");
+-
+-	if (!pImpl->ppStrings[nColumn])
+-	{
+-		TypedStrCollection* pColl = new TypedStrCollection;
+-
+-		//!	document must have function to fill collection!!!
+-		String aDocStr;
+-		SCCOL nDocCol = (SCCOL)(pImpl->aRange.aStart.Col() + nColumn);
+-		SCTAB nDocTab = pImpl->aRange.aStart.Tab();
+-		SCROW nStartRow = pImpl->aRange.aStart.Row()+1;	// start of data
+-		SCROW nEndRow = pImpl->aRange.aEnd.Row();
+-		SCCOL nStartCol = pImpl->aRange.aStart.Col();
+-		SCCOL nEndCol = pImpl->aRange.aEnd.Col();
+-		for (SCROW nRow = nStartRow; nRow <= nEndRow; nRow++)
+-		{
+-			if ( pImpl->bIgnoreEmptyRows &&
+-					pImpl->pDoc->IsBlockEmpty( nDocTab, nStartCol, nRow, nEndCol, nRow ) )
+-			{
+-				//	ignore this (empty) row
+-				//!	count and skip empty rows?
+-			}
+-			else if ( pImpl->bRepeatIfEmpty && nRow > nStartRow &&
+-						!pImpl->pDoc->HasData( nDocCol, nRow, nDocTab ) )
+-			{
+-				//	ignore empty member (if it's not the first row)
+-			}
+-			else if ( lcl_HasQuery(pImpl->aQuery) &&
+-						!pImpl->pDoc->ValidQuery( nRow, nDocTab, pImpl->aQuery, pSpecial ) )
+-			{
+-				//	this row is filtered out
+-			}
+-			else
+-			{
+-				TypedStrData* pNew;
+-				pImpl->pDoc->GetString( nDocCol, nRow, nDocTab, aDocStr );
+-				if ( pImpl->pDoc->HasValueData( nDocCol, nRow, nDocTab ) )
+-				{
+-					double fVal = pImpl->pDoc->GetValue(ScAddress(nDocCol, nRow, nDocTab));
+-					pNew = new TypedStrData( aDocStr, fVal, SC_STRTYPE_VALUE );
+-				}
+-				else
+-					pNew = new TypedStrData( aDocStr );
+-
+-				if (!pColl->Insert(pNew))
+-					delete pNew;
+-			}
+-		}
+-
+-		pImpl->ppStrings[nColumn] = pColl;
+-	}
+-	return *pImpl->ppStrings[nColumn];
++    DBG_ASSERT(nColumn>=0 && nColumn < pImpl->aCacheTable.getColSize(), "ScSheetDPData: wrong column");
++    CreateCacheTable();
++    return pImpl->aCacheTable.getFieldEntries(nColumn);
+ }
+ 
+ String ScSheetDPData::getDimensionName(long nColumn)
+ {
++    CreateCacheTable();
+ 	if (getIsDataLayoutDimension(nColumn))
+ 	{
+ 		//!	different internal and display names?
+ 		//return "Data";
+ 		return ScGlobal::GetRscString(STR_PIVOT_DATA);
+ 	}
+-	else if ( nColumn >= pImpl->nColCount )
++    else if (nColumn >= pImpl->aCacheTable.getColSize())
+ 	{
+ 		DBG_ERROR("getDimensionName: invalid dimension");
+ 		return String();
+ 	}
+ 	else
+ 	{
+-		SCCOL nDocCol = (SCCOL)(pImpl->aRange.aStart.Col() + nColumn);
+-		SCROW nDocRow = pImpl->aRange.aStart.Row();
+-		SCTAB nDocTab = pImpl->aRange.aStart.Tab();
+-		String aDocStr;
+-		pImpl->pDoc->GetString( nDocCol, nDocRow, nDocTab, aDocStr );
+-		return aDocStr;
++        const String* pStr = pImpl->aCacheTable.getFieldName(nColumn);
++        if (pStr)
++            return *pStr;
++        else return String();
+ 	}
+ }
+ 
+@@ -235,11 +191,13 @@
+ 
+ BOOL ScSheetDPData::IsDateDimension(long nDim)
+ {
++    CreateCacheTable();
++    long nColCount = pImpl->aCacheTable.getColSize();
+ 	if (getIsDataLayoutDimension(nDim))
+ 	{
+ 		return FALSE;
+ 	}
+-	else if ( nDim >= pImpl->nColCount )
++    else if (nDim >= nColCount)
+ 	{
+ 		DBG_ERROR("IsDateDimension: invalid dimension");
+ 		return FALSE;
+@@ -248,9 +206,9 @@
+ 	{
+ 		if (!pImpl->pDateDim)
+ 		{
+-			pImpl->pDateDim = new BOOL[pImpl->nColCount];
++            pImpl->pDateDim = new BOOL[nColCount];
+ 			ScRange aTestRange = pImpl->aRange;
+-			for (long i=0; i<pImpl->nColCount; i++)
++			for (long i = 0; i < nColCount; ++i)
+ 			{
+ 				SCCOL nCol = (SCCOL)( pImpl->aRange.aStart.Col() + i );
+ 				aTestRange.aStart.SetCol(nCol);
+@@ -264,11 +222,12 @@
+ 
+ UINT32 ScSheetDPData::GetNumberFormat(long nDim)
+ {
++    CreateCacheTable();
+ 	if (getIsDataLayoutDimension(nDim))
+ 	{
+ 		return 0;
+ 	}
+-	else if ( nDim >= pImpl->nColCount )
++    else if (nDim >= pImpl->aCacheTable.getColSize())
+ 	{
+ 		DBG_ERROR("GetNumberFormat: invalid dimension");
+ 		return 0;
+@@ -286,7 +245,8 @@
+ 
+ BOOL ScSheetDPData::getIsDataLayoutDimension(long nColumn)
+ {
+-	return ( nColumn == pImpl->nColCount );
++    CreateCacheTable();
++    return (nColumn == pImpl->aCacheTable.getColSize());
+ }
+ 
+ void ScSheetDPData::SetEmptyFlags( BOOL bIgnoreEmptyRows, BOOL bRepeatIfEmpty )
+@@ -295,131 +255,41 @@
+ 	pImpl->bRepeatIfEmpty   = bRepeatIfEmpty;
+ }
+ 
+-void ScSheetDPData::ResetIterator()
++void ScSheetDPData::CreateCacheTable()
+ {
+-	pImpl->nNextRow = pImpl->aRange.aStart.Row() + 1;
++    // Scan and store the data from the source range.
++    if (!pImpl->aCacheTable.empty())
++        // already cached.
++        return;
++
++    pImpl->aCacheTable.fillTable(pImpl->pDoc, pImpl->aRange, pImpl->aQuery, pImpl->pSpecial);
+ }
+ 
+-void lcl_GetStringOrValue( ScDPItemData& rData, ScDocument* pDoc,
+-							SCCOL nCol, SCROW nRow, SCTAB nTab,
+-							BOOL bRepeatIfEmpty, SCROW nFirstDataRow )
++void ScSheetDPData::FilterCacheTable(const vector<ScDPDimension*>& rPageDims)
+ {
+-	if ( bRepeatIfEmpty )
+-	{
+-		//	use first non-empty entry
+-		//!	just keep old ItemData ????
+-		//!	otherwise count empty cells and subtract!
+-
+-		while ( !pDoc->HasData( nCol, nRow, nTab ) && nRow > nFirstDataRow )
+-			--nRow;
+-	}
+-
+-	BOOL bVal = pDoc->HasValueData( nCol, nRow, nTab );
+-	rData.bHasValue = bVal;
+-	if (bVal)
+-		rData.fValue = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
+-	else
+-		pDoc->GetString( nCol, nRow, nTab, rData.aString );
++    CreateCacheTable();
++    pImpl->aCacheTable.filterByPageDimension(rPageDims);
+ }
+ 
+-BOOL ScSheetDPData::GetNextRow( const ScDPTableIteratorParam& rParam )
++void ScSheetDPData::GetDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& rFilters, Sequence< Sequence<Any> >& rData)
+ {
+-	if ( pImpl->nNextRow > pImpl->aRange.aEnd.Row() )
+-		return FALSE;
+-
+-	SCSIZE i;
+-	long nStartCol = pImpl->aRange.aStart.Col();
+-	SCTAB nDocTab = pImpl->aRange.aStart.Tab();
+-	SCROW nFirstDataRow = pImpl->aRange.aStart.Row() + 1;
+-
+-	BOOL bFilteredOut;
+-	do
+-	{
+-		if ( pImpl->bIgnoreEmptyRows )
+-		{
+-			SCCOL nEndCol = pImpl->aRange.aEnd.Col();
+-			while ( pImpl->pDoc->IsBlockEmpty( nDocTab, (SCCOL)nStartCol, pImpl->nNextRow,
+-												nEndCol, pImpl->nNextRow ) )
+-			{
+-				++pImpl->nNextRow;
+-				if ( pImpl->nNextRow > pImpl->aRange.aEnd.Row() )
+-					return FALSE;
+-			}
+-		}
+-
+-		bFilteredOut = ( lcl_HasQuery(pImpl->aQuery) && 
+-				!pImpl->pDoc->ValidQuery( pImpl->nNextRow, nDocTab, pImpl->aQuery, pSpecial ) );
+-		if ( bFilteredOut )
+-		{
+-			++pImpl->nNextRow;
+-			if ( pImpl->nNextRow > pImpl->aRange.aEnd.Row() )
+-				return FALSE;
+-		}
+-	}
+-	while (bFilteredOut);
+-
+-	//!	use more efficient iterators
+-
+-	for (i=0; i<rParam.nColCount; i++)
+-	{
+-		long nDim = rParam.pCols[i];
+-		if ( getIsDataLayoutDimension(nDim) )
+-			rParam.pColData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+-		else
+-			lcl_GetStringOrValue( rParam.pColData[i], pImpl->pDoc,
+-									(SCCOL)(nStartCol+nDim), pImpl->nNextRow, nDocTab,
+-									pImpl->bRepeatIfEmpty, nFirstDataRow );
+-	}
++    CreateCacheTable();
++    sal_Int32 nRowSize = pImpl->aCacheTable.getRowSize();
++    if (!nRowSize)
++        return;
+ 
+-	for (i=0; i<rParam.nRowCount; i++)
+-	{
+-		long nDim = rParam.pRows[i];
+-		if ( getIsDataLayoutDimension(nDim) )
+-			rParam.pRowData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+-		else
+-			lcl_GetStringOrValue( rParam.pRowData[i], pImpl->pDoc,
+-									(SCCOL)(nStartCol+nDim), pImpl->nNextRow, nDocTab,
+-									pImpl->bRepeatIfEmpty, nFirstDataRow );
+-	}
++    pImpl->aCacheTable.filterTable(rFilters, rData);
++}
+ 
+-	for (i=0; i<rParam.nPageCount; i++)
+-	{
+-		long nDim = rParam.pPages[i];
+-		if ( getIsDataLayoutDimension(nDim) )
+-			rParam.pPageData[i].SetString( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")) );
+-		else
+-			lcl_GetStringOrValue( rParam.pPageData[i], pImpl->pDoc,
+-									(USHORT)(nStartCol+nDim), pImpl->nNextRow, nDocTab,
+-									pImpl->bRepeatIfEmpty, nFirstDataRow );
+-	}
+-
+-	for (i=0; i<rParam.nDatCount; i++)
+-	{
+-		long nDim = rParam.pDats[i];
+-		ScAddress aPos( (SCCOL)(nStartCol+nDim), pImpl->nNextRow, nDocTab );
+-		ScBaseCell* pCell = pImpl->pDoc->GetCell( aPos );
+-		if ( !pCell || pCell->GetCellType() == CELLTYPE_NOTE )
+-			rParam.pValues[i].Set( 0.0, SC_VALTYPE_EMPTY );
+-		else if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->GetErrCode() )
+-			rParam.pValues[i].Set( 0.0, SC_VALTYPE_ERROR );
+-		else if ( pCell->HasValueData() )
+-		{
+-			//!	GetValue method at BaseCell?
+-			DBG_ASSERT( pCell->GetCellType() == CELLTYPE_VALUE ||
+-						pCell->GetCellType() == CELLTYPE_FORMULA, "wrong cell type" );
+-			double fVal;
+-			if ( pCell->GetCellType() == CELLTYPE_VALUE )
+-				fVal = ((ScValueCell*)pCell)->GetValue();
+-			else
+-				fVal = ((ScFormulaCell*)pCell)->GetValue();
+-			rParam.pValues[i].Set( fVal, SC_VALTYPE_VALUE );
+-		}
+-		else
+-			rParam.pValues[i].Set( 0.0, SC_VALTYPE_STRING );
+-	}
++void ScSheetDPData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
++{
++    CreateCacheTable();
++    CalcResultsFromCacheTable(pImpl->aCacheTable, rInfo, bAutoShow);
++}
+ 
+-	pImpl->nNextRow++;
+-	return TRUE;
++const ScDPCacheTable& ScSheetDPData::GetCacheTable() const
++{
++    return pImpl->aCacheTable;
+ }
+ 
+ // -----------------------------------------------------------------------
+Index: sc/source/core/data/dptabdat.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dptabdat.cxx,v
+retrieving revision 1.12
+retrieving revision 1.12.202.5
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.12 -r1.12.202.5
+--- sc/source/core/data/dptabdat.cxx	27 Feb 2007 12:05:02 -0000	1.12
++++ sc/source/core/data/dptabdat.cxx	6 Dec 2007 07:06:15 -0000	1.12.202.5
+@@ -36,7 +36,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
+-
++#include <stdio.h>
+ 
+ // INCLUDE ---------------------------------------------------------------
+ 
+@@ -50,8 +50,18 @@
+ #include <unotools/collatorwrapper.hxx>
+ #endif
+ 
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
++
+ #include "dptabdat.hxx"
+ #include "global.hxx"
++#include "dpcachetable.hxx"
++#include "dptabres.hxx"
++
++using namespace ::com::sun::star;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Any;
++using ::std::vector;
++using ::std::set;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -113,29 +123,7 @@
+         return ScGlobal::pCollator->compareString( rA.aString, rB.aString );
+ }
+ 
+-// -----------------------------------------------------------------------
+-
+-ScDPTableIteratorParam::ScDPTableIteratorParam(
+-							long nCCount, const long* pC, ScDPItemData* pCDat,
+-							long nRCount, const long* pR, ScDPItemData* pRDat,
+-							long nPCount, const long* pP, ScDPItemData* pPDat,
+-							long nDCount, const long* pD, ScDPValueData* pV ) :
+-	nColCount( (SCSIZE)nCCount ),
+-	pCols	 ( pC ),
+-	pColData ( pCDat ),
+-	nRowCount( (SCSIZE)nRCount ),
+-	pRows	 ( pR ),
+-	pRowData ( pRDat ),
+-	nPageCount( (SCSIZE)nPCount ),
+-	pPages	 ( pP ),
+-	pPageData( pPDat ),
+-	nDatCount( (SCSIZE)nDCount ),
+-	pDats	 ( pD ),
+-	pValues	 ( pV )
+-{
+-}
+-
+-// -----------------------------------------------------------------------
++// ---------------------------------------------------------------------------
+ 
+ ScDPTableData::ScDPTableData()
+ {
+@@ -193,6 +181,26 @@
+ 	return nRet;
+ }
+ 
++void ScDPTableData::CreateCacheTable()
++{
++    fprintf(stdout, "ScDPTableData::CreateCacheTable: un-implemented...\n");fflush(stdout);
++}
++
++void ScDPTableData::FilterCacheTable(const vector<ScDPDimension*>& rPageDims)
++{
++    fprintf(stdout, "ScDPTableData::FilterCacheTable: un-implemented...\n");fflush(stdout);
++}
++
++void ScDPTableData::GetDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters, Sequence< Sequence<Any> >& rTabData)
++{
++    fprintf(stdout, "ScDPTableData::GetDrillDownData: un-implemented...\n");fflush(stdout);
++}
++
++void ScDPTableData::CalcResults(CalcInfo& rInfo, bool bAutoShow)
++{
++    fprintf(stdout, "ScDPTableData::CalcResults: un-implemented...\n");fflush(stdout);
++}
++
+ UINT32 ScDPTableData::GetNumberFormat(long)
+ {
+ 	return 0;			// default format
+@@ -227,6 +235,105 @@
+     return FALSE;
+ }
+ 
++void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable, 
++                                        const CalcInfo& rInfo, CalcRowData& rData)
++{
++    // column dimensions
++    GetItemData(rCacheTable, nRow, rInfo.aColLevelDims, rData.aColData);
++
++    // row dimensions
++    GetItemData(rCacheTable, nRow, rInfo.aRowLevelDims, rData.aRowData);
++
++    // page dimensions
++    GetItemData(rCacheTable, nRow, rInfo.aPageDims, rData.aPageData);
++
++    sal_Int32 n = rInfo.aDataSrcCols.size();
++    for (sal_Int32 i = 0; i < n; ++i)
++    {
++        long nDim = rInfo.aDataSrcCols[i];
++        rData.aValues.push_back( ScDPValueData() );
++        ScDPValueData& rVal = rData.aValues.back();
++        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(nDim, nRow);
++        if (pCell)
++        {
++            rVal.fValue = pCell->mbNumeric ? pCell->mfValue : 0.0;
++            rVal.nType = pCell->mnType;
++        }
++        else
++            rVal.Set(0.0, SC_VALTYPE_EMPTY);
++    }
++}
++
++void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow)
++{
++    if (!bAutoShow)
++    {
++        rInfo.pColRoot->LateInitFrom(rInfo.aColDims, rInfo.aColLevels, rData.aColData, 0, *rInfo.pInitState);
++        rInfo.pRowRoot->LateInitFrom(rInfo.aRowDims, rInfo.aRowLevels, rData.aRowData, 0, *rInfo.pInitState);
++    }
++
++    if ( ( !rInfo.pColRoot->GetChildDimension() || rInfo.pColRoot->GetChildDimension()->IsValidEntry(rData.aColData) ) &&
++         ( !rInfo.pRowRoot->GetChildDimension() || rInfo.pRowRoot->GetChildDimension()->IsValidEntry(rData.aRowData) ) )
++    {
++        //! single process method with ColMembers, RowMembers and data !!!
++        if (rInfo.pColRoot->GetChildDimension())
++        {
++            vector<ScDPItemData> aEmptyData;
++            rInfo.pColRoot->GetChildDimension()->ProcessData(rData.aColData, NULL, aEmptyData, rData.aValues);
++        }
++
++        rInfo.pRowRoot->ProcessData(rData.aRowData, rInfo.pColRoot->GetChildDimension(), 
++                                    rData.aColData, rData.aValues);
++    }
++}
++
++void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, CalcInfo& rInfo, bool bAutoShow)
++{
++    sal_Int32 nRowSize = rCacheTable.getRowSize();
++    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
++    {
++        if (!rCacheTable.isRowActive(nRow))
++            continue;
++
++        CalcRowData aData;
++        FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData);
++        ProcessRowData(rInfo, aData, bAutoShow);
++    }
++}
++
++void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow, 
++                                const vector<long>& rDims, vector<ScDPItemData>& rItemData)
++{
++    sal_Int32 nDimSize = rDims.size();
++    for (sal_Int32 i = 0; i < nDimSize; ++i)
++    {
++        long nDim = rDims[i];
++        rItemData.push_back( ScDPItemData() );
++        ScDPItemData& rData = rItemData.back();
++        if (getIsDataLayoutDimension(nDim))
++        {
++            rData.SetString(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")));
++            continue;
++        }
++
++        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(nDim, nRow);
++        if (!pCell)
++            continue;
++
++        const String* pString = ScDPCacheTable::getString(pCell->mnStrId);
++        if (!pString)
++            continue;
++
++        rData.aString = *pString;
++        rData.bHasValue = false;
++        if (pCell->mbNumeric)
++        {
++            rData.bHasValue = true;
++            rData.fValue = pCell->mfValue;
++        }
++    }
++}
++
+ // -----------------------------------------------------------------------
+ 
+ 
+Index: sc/source/core/data/dptabres.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dptabres.cxx,v
+retrieving revision 1.11
+retrieving revision 1.11.200.9
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.11 -r1.11.200.9
+--- sc/source/core/data/dptabres.cxx	27 Feb 2007 12:05:33 -0000	1.11
++++ sc/source/core/data/dptabres.cxx	6 Dec 2007 07:06:15 -0000	1.11.200.9
+@@ -36,7 +36,7 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
+-
++#include <stdio.h>
+ 
+ // INCLUDE ---------------------------------------------------------------
+ 
+@@ -66,6 +66,7 @@
+ #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
+ 
+ using namespace com::sun::star;
++using ::std::vector;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -563,6 +564,7 @@
+ 	if ( bEmpty || bError )
+ 		fResult = 0.0;		// default, in case the state is later modified
+ 
++//  fprintf(stdout, "ScDPAggData::Calculate: result = %g\n", fResult);fflush(stdout);
+ 	fVal = fResult;			// used directly from now on
+ 	fAux = 0.0;				// used for running total or original result of reference value
+ }
+@@ -894,11 +896,30 @@
+     return pSource->GetData()->HasCommonElement( rFirstData, nFirstIndex, rSecondData, nSecondIndex );
+ }
+ 
++void ScDPResultData::Debug() const
++{
++    fprintf(stdout, "------------------------------ ScDPResultData::Debug ------------------------------\n");
++    fprintf(stdout, "data at col (%d);  data at row (%d);  late init(%d)\n", bDataAtCol, bDataAtRow, bLateInit);
++    for (long i = 0; i < nMeasCount; ++i)
++    {
++        fprintf(stdout, "  measure id = %ld --------------------\n", i);
++        fprintf(stdout, "    measure function = %d\n", pMeasFuncs[i]);
++        fprintf(stdout, "    measure name = '%s'\n", 
++                OUStringToOString(rtl::OUString(pMeasNames[i]), RTL_TEXTENCODING_UTF8).getStr());
++        fprintf(stdout, "    measure ref orientation = %d\n", pMeasRefOrient[i]);
++        fprintf(stdout, "    measure ref type = %ld  field = '%s'  item type = %ld  item name = '%s'\n", 
++                pMeasRefs[i].ReferenceType, 
++                OUStringToOString(pMeasRefs[i].ReferenceField, RTL_TEXTENCODING_UTF8).getStr(),
++                pMeasRefs[i].ReferenceItemType,
++                OUStringToOString(pMeasRefs[i].ReferenceItemName, RTL_TEXTENCODING_UTF8).getStr());
++    }
++}
++
+ // -----------------------------------------------------------------------
+ 
+ 
+-ScDPResultMember::ScDPResultMember( ScDPResultData* pData, ScDPDimension* pDim,
+-									ScDPLevel* pLev, ScDPMember* pDesc,
++ScDPResultMember::ScDPResultMember( const ScDPResultData* pData, const ScDPDimension* pDim,
++									const ScDPLevel* pLev, const ScDPMember* pDesc,
+ 									BOOL bForceSub ) :
+ 	pResultData( pData ),
+ 	pParentDim( pDim ),
+@@ -945,19 +966,28 @@
+ 		return ((ScDPMember*)pMemberDesc)->IsNamedItem( r );
+ 	return FALSE;
+ }
+-BOOL ScDPResultMember::IsValidEntry( const ScDPItemData* pMembers ) const
++
++bool ScDPResultMember::IsValidEntry( const vector<ScDPItemData>& aMembers ) const
+ {
+ 	if ( !IsValid() )
+-		return FALSE;
++        return false;
+ 
+ 	const ScDPResultDimension* pChildDim = GetChildDimension();
+ 	if (pChildDim)
+-		return pChildDim->IsValidEntry( pMembers + 1 );
++    {
++        if (aMembers.size() < 2)
++            return false;
++
++        vector<ScDPItemData>::const_iterator itr = aMembers.begin();
++        vector<ScDPItemData> aChildMembers(++itr, aMembers.end());
++        return pChildDim->IsValidEntry(aChildMembers);
++    }
+ 	else
+-		return TRUE;
++        return true;
+ }
+ 
+-void ScDPResultMember::InitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPInitState& rInitState )
++void ScDPResultMember::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, 
++                                 size_t nPos, ScDPInitState& rInitState )
+ {
+ 	//	with LateInit, initialize only those members that have data
+ 	if ( pResultData->IsLateInit() )
+@@ -965,22 +995,22 @@
+ 
+ 	bInitialized = TRUE;
+ 
++    if (nPos >= ppDim.size())
++        return;
++
+ 	//	skip child dimension if details are not shown
+ 	if ( pMemberDesc && !pMemberDesc->getShowDetails() )
+ 	{
+-		if ( *ppDim )
+ 			bHasHiddenDetails = TRUE;	// only if there is a next dimension
+ 		return;
+ 	}
+ 
+-	if ( *ppDim )
+-	{
+ 		pChildDimension = new ScDPResultDimension( pResultData );
+-		pChildDimension->InitFrom( ppDim, ppLev, rInitState );
+-	}
++    pChildDimension->InitFrom( ppDim, ppLev, nPos, rInitState );
+ }
+ 
+-void ScDPResultMember::LateInitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPItemData* pItemData,
++void ScDPResultMember::LateInitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, 
++                                     const vector<ScDPItemData>& pItemData, size_t nPos,
+                                     ScDPInitState& rInitState )
+ {
+ 	//	without LateInit, everything has already been initialized
+@@ -989,21 +1019,22 @@
+ 
+ 	bInitialized = TRUE;
+ 
++    if (nPos >= ppDim.size())
++        // No next dimension.  Bail out.
++        return;
++
+ 	//	skip child dimension if details are not shown
+ 	if ( pMemberDesc && !pMemberDesc->getShowDetails() )
+ 	{
+-		if ( *ppDim )
+ 			bHasHiddenDetails = TRUE;	// only if there is a next dimension
+ 		return;
+ 	}
+ 
+-	if ( *ppDim )
+-	{
+ 		//	LateInitFrom is called several times...
+ 		if ( !pChildDimension )
+ 			pChildDimension = new ScDPResultDimension( pResultData );
+-		pChildDimension->LateInitFrom( ppDim, ppLev, pItemData, rInitState );
+-	}
++
++    pChildDimension->LateInitFrom( ppDim, ppLev, pItemData, nPos, rInitState );
+ }
+ 
+ BOOL ScDPResultMember::IsSubTotalInTitle(long nMeasure) const
+@@ -1123,16 +1154,14 @@
+ 		return 0;
+ }
+ 
+-void ScDPResultMember::ProcessData( const ScDPItemData* pChildMembers, ScDPResultDimension* pDataDim,
+-										const ScDPItemData* pDataMembers, const ScDPValueData* pValues )
++void ScDPResultMember::ProcessData( const vector<ScDPItemData>& aChildMembers, const ScDPResultDimension* pDataDim,
++                                    const vector<ScDPItemData>& aDataMembers, const vector<ScDPValueData>& aValues )
+ {
+ 	SetHasElements();
+ 
+ 	if (pChildDimension)
+-		pChildDimension->ProcessData( pChildMembers, pDataDim, pDataMembers, pValues );
++        pChildDimension->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues );
+ 
+-	if ( pDataMembers )
+-	{
+ 		if ( !pDataRoot )
+ 		{
+ 			pDataRoot = new ScDPDataMember( pResultData, NULL );
+@@ -1158,8 +1187,7 @@
+ 				aSubState.eRowForce = lcl_GetForceFunc( pParentLevel, nUserPos );
+ 			}
+ 
+-			pDataRoot->ProcessData( pDataMembers, pValues, aSubState );
+-		}
++        pDataRoot->ProcessData( aDataMembers, aValues, aSubState );
+ 	}
+ }
+ 
+@@ -1575,7 +1603,7 @@
+ 
+ // -----------------------------------------------------------------------
+ 
+-ScDPDataMember::ScDPDataMember( ScDPResultData* pData, const ScDPResultMember* pRes ) :
++ScDPDataMember::ScDPDataMember( const ScDPResultData* pData, const ScDPResultMember* pRes ) :
+ 	pResultData( pData ),
+ 	pResultMember( pRes ),
+ 	pChildDimension( NULL )
+@@ -1647,7 +1675,7 @@
+ 	return nRet;
+ }
+ 
+-void ScDPDataMember::UpdateValues( const ScDPValueData* pValues, const ScDPSubTotalState& rSubState )
++void ScDPDataMember::UpdateValues( const vector<ScDPValueData>& aValues, const ScDPSubTotalState& rSubState )
+ {
+ 	//!	find out how many and which subtotals are used
+ 
+@@ -1663,19 +1691,15 @@
+ 			pAgg = pAgg->GetChild();		// created if not there
+ 	}
+ 
+-	long nCount = pResultData->GetMeasureCount();
+-	for (long nPos=0; nPos<nCount; nPos++)
++    size_t nCount = aValues.size();
++    for (size_t nPos = 0; nPos < nCount; ++nPos)
+ 	{
+-		pAgg->Update( *pValues, pResultData->GetMeasureFunction(nPos), rSubState );
+-		if ( nPos+1 < nCount )
+-		{
+-			pAgg = pAgg->GetChild();		// created if not there
+-			++pValues;						// next value entry
+-		}
++        pAgg->Update(aValues[nPos], pResultData->GetMeasureFunction(nPos), rSubState);
++        pAgg = pAgg->GetChild();
+ 	}
+ }
+ 
+-void ScDPDataMember::ProcessData( const ScDPItemData* pChildMembers, const ScDPValueData* pValues,
++void ScDPDataMember::ProcessData( const vector<ScDPItemData>& aChildMembers, const vector<ScDPValueData>& aValues,
+ 									const ScDPSubTotalState& rSubState )
+ {
+ 	if ( pResultData->IsLateInit() && !pChildDimension && pResultMember && pResultMember->GetChildDimension() )
+@@ -1704,11 +1728,11 @@
+ 			aLocalSubState.eColForce = lcl_GetForceFunc( pForceLevel, nUserPos );
+ 		}
+ 
+-		UpdateValues( pValues, aLocalSubState );
++		UpdateValues( aValues, aLocalSubState );
+ 	}
+ 
+ 	if (pChildDimension)
+-		pChildDimension->ProcessData( pChildMembers, pValues, rSubState );		// with unmodified subtotal state
++		pChildDimension->ProcessData( aChildMembers, aValues, rSubState );		// with unmodified subtotal state
+ }
+ 
+ BOOL ScDPDataMember::HasData( long nMeasure, const ScDPSubTotalState& rSubState ) const
+@@ -2413,7 +2437,7 @@
+ class ScDPGroupCompare
+ {
+ private:
+-    ScDPResultData*      pResultData;
++    const ScDPResultData* pResultData;
+     const ScDPInitState& rInitState;
+     long                 nDimSource;
+     BOOL                 bIncludeAll;
+@@ -2422,14 +2446,14 @@
+     const ScDPItemData*  pBaseData;
+ 
+ public:
+-            ScDPGroupCompare( ScDPResultData* pData, const ScDPInitState& rState, long nDimension );
++            ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitState& rState, long nDimension );
+             ~ScDPGroupCompare() {}
+ 
+     BOOL    IsIncluded( const ScDPMember& rMember )     { return bIncludeAll || TestIncluded( rMember ); }
+     BOOL    TestIncluded( const ScDPMember& rMember );
+ };
+ 
+-ScDPGroupCompare::ScDPGroupCompare( ScDPResultData* pData, const ScDPInitState& rState, long nDimension ) :
++ScDPGroupCompare::ScDPGroupCompare( const ScDPResultData* pData, const ScDPInitState& rState, long nDimension ) :
+     pResultData( pData ),
+     rInitState( rState ),
+     nDimSource( nDimension ),
+@@ -2494,7 +2518,7 @@
+ 
+ // -----------------------------------------------------------------------
+ 
+-ScDPResultDimension::ScDPResultDimension( ScDPResultData* pData ) :
++ScDPResultDimension::ScDPResultDimension( const ScDPResultData* pData ) :
+ 	pResultData( pData ),
+ 	bInitialized( FALSE ),
+ 	bIsDataLayout( FALSE ),
+@@ -2538,18 +2562,28 @@
+ 	return NULL;
+ }
+ 
+-void ScDPResultDimension::InitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPInitState& rInitState )
++void ScDPResultDimension::InitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, 
++                                    size_t nPos, ScDPInitState& rInitState )
+ {
+-	ScDPDimension* pThisDim = *ppDim;
+-	ScDPLevel* pThisLevel = *ppLev;
+-	if (pThisDim && pThisLevel)
++    if (nPos >= ppDim.size() || nPos >= ppLev.size())
+ 	{
+-		ScDPDimension** ppChildDim = ppDim + 1;
+-		ScDPLevel** ppChildLev = ppLev + 1;
++        bInitialized = true;
++        return;
++    }
+ 
+-		bIsDataLayout = pThisDim->getIsDataLayoutDimension();
+-		aDimensionName = pThisDim->getName();
++	ScDPDimension* pThisDim = ppDim[nPos];
++	ScDPLevel* pThisLevel = ppLev[nPos];
+ 
++    if (!pThisDim || !pThisLevel)
++    {
++        bInitialized = true;
++        return;
++    }
++
++    bIsDataLayout = pThisDim->getIsDataLayoutDimension();   // member
++    aDimensionName = pThisDim->getName();                   // member 
++
++    // Check the autoshow setting.  If it's enabled, store the settings.
+     	const sheet::DataPilotFieldAutoShowInfo& rAutoInfo = pThisLevel->GetAutoShow();
+     	if ( rAutoInfo.IsEnabled )
+     	{
+@@ -2559,6 +2593,7 @@
+     	    nAutoCount    = rAutoInfo.ItemCount;
+     	}
+ 
++    // Check the sort info, and store the settings if appropriate.
+         const sheet::DataPilotFieldSortInfo& rSortInfo = pThisLevel->GetSortInfo();
+         if ( rSortInfo.Mode == sheet::DataPilotFieldSortMode::DATA )
+         {
+@@ -2573,6 +2608,7 @@
+         long nDimSource = pThisDim->GetDimension();     //! check GetSourceDim?
+         ScDPGroupCompare aCompare( pResultData, rInitState, nDimSource );
+ 
++    // Now, go through all members and initialize them.
+ 		ScDPMembers* pMembers = pThisLevel->GetMembersObject();
+ 		long nMembCount = pMembers->getCount();
+ 		for ( long i=0; i<nMembCount; i++ )
+@@ -2595,25 +2631,26 @@
+                     maMemberHash.insert( std::pair< const ScDPItemData, ScDPResultMember *>( aMemberData, pNew ) );
+ 
+                 rInitState.AddMember( nDimSource, aMemberData );
+-    			pNew->InitFrom( ppChildDim, ppChildLev, rInitState );
++            pNew->InitFrom( ppDim, ppLev, nPos+1, rInitState );
+     			rInitState.RemoveMember();
+             }
+ 		}
+-	}
+ 	bInitialized = TRUE;
+ }
+ 
+-void ScDPResultDimension::LateInitFrom( ScDPDimension** ppDim, ScDPLevel** ppLev, ScDPItemData* pItemData,
++void ScDPResultDimension::LateInitFrom( const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLev, 
++                                        const vector<ScDPItemData>& pItemData, size_t nPos,
+                                         ScDPInitState& rInitState )
+ {
+-	ScDPDimension* pThisDim = *ppDim;
+-	ScDPLevel* pThisLevel = *ppLev;
+-	ScDPItemData& rThisData = *pItemData;
+-	if (pThisDim && pThisLevel)
+-	{
+-		ScDPDimension** ppChildDim = ppDim + 1;
+-		ScDPLevel** ppChildLev = ppLev + 1;
+-		ScDPItemData* pChildData = pItemData + 1;
++    if (nPos >= ppDim.size() || nPos >= ppLev.size() || nPos >= pItemData.size())
++        return;
++
++	ScDPDimension* pThisDim = ppDim[nPos];
++	ScDPLevel* pThisLevel = ppLev[nPos];
++	const ScDPItemData& rThisData = pItemData[nPos];
++
++    if (!pThisDim || !pThisLevel)
++        return;
+ 
+         long nDimSource = pThisDim->GetDimension();     //! check GetSourceDim?
+ 
+@@ -2683,7 +2720,7 @@
+ 				ScDPItemData aMemberData;
+ 				pResultMember->FillItemData( aMemberData );
+ 				rInitState.AddMember( nDimSource, aMemberData );
+-				pResultMember->LateInitFrom( ppChildDim, ppChildLev, pChildData, rInitState );
++            pResultMember->LateInitFrom( ppDim, ppLev, pItemData, nPos+1, rInitState );
+ 				rInitState.RemoveMember();
+ 			}
+ 		}
+@@ -2695,11 +2732,10 @@
+                 ScDPItemData aMemberData;
+                 pResultMember->FillItemData( aMemberData );
+                 rInitState.AddMember( nDimSource, aMemberData );
+-				pResultMember->LateInitFrom( ppChildDim, ppChildLev, pChildData, rInitState );
++            pResultMember->LateInitFrom( ppDim, ppLev, pItemData, nPos+1, rInitState );
+     			rInitState.RemoveMember();
+ 			}
+ 		}
+-	}
+ }
+ 
+ long ScDPResultDimension::GetSize(long nMeasure) const
+@@ -2722,26 +2758,37 @@
+ 	return nTotal;
+ }
+ 
+-BOOL ScDPResultDimension::IsValidEntry( const ScDPItemData* pMembers ) const
++bool ScDPResultDimension::IsValidEntry( const vector<ScDPItemData>& aMembers ) const
+ {
+-    // the ScDPItemData array must contain enough entries for all dimensions - this isn't checked
+-	const ScDPResultMember* pMember = FindMember( *pMembers );
+-	if( NULL != pMember )
+-		return pMember->IsValidEntry( pMembers );
++    if (aMembers.empty())
++        return false;
++
++    const ScDPResultMember* pMember = FindMember( aMembers[0] );
++    if ( NULL != pMember )
++        return pMember->IsValidEntry( aMembers );
+ 
+ 	DBG_ERROR("IsValidEntry: Member not found");
+-	return FALSE;
++    return false;
+ }
+ 
+-void ScDPResultDimension::ProcessData( const ScDPItemData* pMembers,
+-							ScDPResultDimension* pDataDim, const ScDPItemData* pDataMembers,
+-							const ScDPValueData* pValues )
++void ScDPResultDimension::ProcessData( const vector<ScDPItemData>& aMembers,
++                                       const ScDPResultDimension* pDataDim, 
++                                       const vector<ScDPItemData>& aDataMembers,
++                                       const vector<ScDPValueData>& aValues ) const
+ {
+-    // the ScDPItemData array must contain enough entries for all dimensions - this isn't checked
+-	ScDPResultMember* pMember = FindMember( *pMembers );
+-	if( NULL != pMember )
++    if (aMembers.empty())
++        return;
++
++	ScDPResultMember* pMember = FindMember( aMembers[0] );
++	if ( NULL != pMember )
++	{
++        vector<ScDPItemData> aChildMembers;
++        if (aMembers.size() > 1)
+ 		{
+-			pMember->ProcessData( pMembers + 1, pDataDim, pDataMembers, pValues );
++            vector<ScDPItemData>::const_iterator itr = aMembers.begin();
++            aChildMembers.assign(++itr, aMembers.end());
++        }
++        pMember->ProcessData( aChildMembers, pDataDim, aDataMembers, aValues );
+ 			return;
+ 		}
+ 
+@@ -3210,7 +3257,7 @@
+ 
+ // -----------------------------------------------------------------------
+ 
+-ScDPDataDimension::ScDPDataDimension( ScDPResultData* pData ) :
++ScDPDataDimension::ScDPDataDimension( const ScDPResultData* pData ) :
+ 	pResultData( pData ),
+ 	pResultDimension( NULL ),
+ 	bIsDataLayout( FALSE )
+@@ -3229,6 +3276,8 @@
+     pResultDimension = pDim;
+ 	bIsDataLayout = pDim->IsDataLayout();
+ 
++    // Go through all result members under the given result dimension, and
++    // create a new data member instance for each result member.
+ 	long nCount = pDim->GetMemberCount();
+ 	for (long i=0; i<nCount; i++)
+ 	{
+@@ -3249,7 +3298,7 @@
+ 	}
+ }
+ 
+-void ScDPDataDimension::ProcessData( const ScDPItemData* pDataMembers, const ScDPValueData* pValues,
++void ScDPDataDimension::ProcessData( const vector<ScDPItemData>& aDataMembers, const vector<ScDPValueData>& aValues,
+ 									const ScDPSubTotalState& rSubState )
+ {
+     // the ScDPItemData array must contain enough entries for all dimensions - this isn't checked
+@@ -3260,9 +3309,15 @@
+ 		ScDPDataMember* pMember = aMembers[(USHORT)i];
+ 
+ 		// always first member for data layout dim
+-		if ( bIsDataLayout || pMember->IsNamedItem( *pDataMembers ) )
++        if ( bIsDataLayout || ( !aDataMembers.empty() && pMember->IsNamedItem(aDataMembers[0]) ) )
++        {
++            vector<ScDPItemData> aChildDataMembers;
++            if (aDataMembers.size() > 1)
+ 		{
+-			pMember->ProcessData( pDataMembers + 1, pValues, rSubState );
++                vector<ScDPItemData>::const_iterator itr = aDataMembers.begin();
++                aChildDataMembers.assign(++itr, aDataMembers.end());
++            }
++            pMember->ProcessData( aChildDataMembers, aValues, rSubState );
+ 			return;
+ 		}
+ 	}
+Index: sc/source/core/data/dptabsrc.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/dptabsrc.cxx,v
+retrieving revision 1.22
+retrieving revision 1.20.42.11
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.22 -r1.20.42.11
+--- sc/source/core/data/dptabsrc.cxx	26 Nov 2007 15:20:11 -0000	1.22
++++ sc/source/core/data/dptabsrc.cxx	6 Dec 2007 16:40:33 -0000	1.20.42.11
+@@ -36,11 +36,14 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+ 
++#include <stdio.h>
+ 
+ 
+ // INCLUDE ---------------------------------------------------------------
+ 
+ #include <algorithm>
++#include <vector>
++#include <set>
+ 
+ #include <tools/debug.hxx>
+ #include <rtl/math.hxx>
+@@ -65,8 +68,10 @@
+ #include <com/sun/star/beans/PropertyAttribute.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
++#include <com/sun/star/table/CellAddress.hpp>
+ 
+ #ifndef _UNOTOOLS_COLLATORWRAPPER_HXX
+ #include <unotools/collatorwrapper.hxx>
+@@ -79,6 +84,11 @@
+ #endif
+ 
+ using namespace com::sun::star;
++using ::std::vector;
++using ::std::set;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Any;
+ 
+ // -----------------------------------------------------------------------
+ 
+@@ -416,6 +426,14 @@
+ 	DBG_ERROR("not implemented");	//! exception?
+ }
+ 
++Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters)
++    throw (uno::RuntimeException)
++{
++    Sequence< Sequence<Any> > aTabData;
++    pData->GetDrillDownData(aFilters, aTabData);
++    return aTabData;
++}
++
+ String ScDPSource::getDataDescription()
+ {
+ 	CreateRes_Impl();		// create pResData
+@@ -507,7 +525,7 @@
+ 	bResultOverflow = FALSE;
+ }
+ 
+-long lcl_CountMinMembers( ScDPDimension** ppDim, ScDPLevel** ppLevel, long nLevels )
++long lcl_CountMinMembers(const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLevel, long nLevels )
+ {
+ 	//	Calculate the product of the member count for those consecutive levels that
+ 	//	have the "show all" flag, one following level, and the data layout dimension.
+@@ -579,6 +597,54 @@
+     return -1;  // not found
+ }
+ 
++void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &rHasAutoShow)
++{
++    long* nDims = bIsRow ? nRowDims : nColDims;
++    long nDimCount = bIsRow ? nRowDimCount : nColDimCount;
++
++    for (long i = 0; i < nDimCount; ++i)
++    {
++        ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nDims[i] );
++        long nHierarchy = pDim->getUsedHierarchy();
++        if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
++            nHierarchy = 0;
++        ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
++        long nCount = pLevels->getCount();
++
++        //!	Test
++        if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
++            nCount = 0;
++        //!	Test
++
++        for (long j = 0; j < nCount; ++j)
++        {
++            ScDPLevel* pLevel = pLevels->getByIndex(j);
++            pLevel->EvaluateSortOrder();
++
++            // no layout flags for column fields, only for row fields
++            pLevel->SetEnableLayout( bIsRow );           
++
++            if ( pLevel->GetAutoShow().IsEnabled )
++                rHasAutoShow = TRUE;
++
++            if (bIsRow)
++            {
++                rInfo.aRowLevelDims.push_back(nDims[i]);
++                rInfo.aRowDims.push_back(pDim);
++                rInfo.aRowLevels.push_back(pLevel);
++            }
++            else
++            {
++                rInfo.aColLevelDims.push_back(nDims[i]);
++                rInfo.aColDims.push_back(pDim);
++                rInfo.aColLevels.push_back(pLevel);
++            }
++
++            pLevel->GetMembersObject();                 // initialize for groups
++        }
++    }
++}
++
+ void ScDPSource::CreateRes_Impl()
+ {
+ 	if ( !pResData )
+@@ -592,24 +658,33 @@
+ 			nDataOrient = sheet::DataPilotFieldOrientation_ROW;
+ 		}
+ 
++        // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and 
++        // eDataFunctions into a structure and use vector instead of static 
++        // or pointer arrays.
+ 		String* pDataNames = NULL;
+ 		sheet::DataPilotFieldReference* pDataRefValues = NULL;
++        ScSubTotalFunc eDataFunctions[SC_DAPI_MAXFIELDS];
++		USHORT nDataRefOrient[SC_DAPI_MAXFIELDS];
+ 		if (nDataDimCount)
+ 		{
+ 			pDataNames = new String[nDataDimCount];
+ 			pDataRefValues = new sheet::DataPilotFieldReference[nDataDimCount];
+ 		}
+ 
+-		long nDataSrcCols[SC_DAPI_MAXFIELDS];
+-		USHORT nDataRefOrient[SC_DAPI_MAXFIELDS];
++        ScDPTableData::CalcInfo aInfo;
++
+ 
+ 		//	LateInit (initialize only those rows/children that are used) can be used unless
+ 		//	any data dimension needs reference values from column/row dimensions
+ 		BOOL bLateInit = TRUE;
+ 
++        // Go through all data dimensions (i.e. fields) and build their meta data
++        // so that they can be passed on to ScDPResultData instance later.
++        // TODO: aggregate all of data dimension info into a structure.
+ 		long i;
+ 		for (i=0; i<nDataDimCount; i++)
+ 		{
++            // Get function for each data field.
+ 			long nDimIndex = nDataDims[i];
+ 			ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
+ 			sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
+@@ -618,7 +693,11 @@
+ 				//!	test for numeric data
+ 				eUser = sheet::GeneralFunction_SUM;
+ 			}
++
++            // Map UNO's enum to internal enum ScSubTotalFunc.
+ 			eDataFunctions[i] = ScDataUnoConversion::GeneralToSubTotal( eUser );
++
++            // Get reference field/item information.
+ 			pDataRefValues[i] = pDim->GetReferenceValue();
+ 			nDataRefOrient[i] = sheet::DataPilotFieldOrientation_HIDDEN;	// default if not used
+ 			sal_Int32 eRefType = pDataRefValues[i].ReferenceType;
+@@ -652,10 +731,10 @@
+ 			//!	the complete name (function and field) must be stored at the dimension
+ 
+ 			long nSource = ((ScDPDimension*)pDim)->GetSourceDim();
+-			if ( nSource >= 0 )
+-				nDataSrcCols[i] = nSource;
++            if (nSource >= 0)
++                aInfo.aDataSrcCols.push_back(nSource);
+ 			else
+-				nDataSrcCols[i] = nDimIndex;
++                aInfo.aDataSrcCols.push_back(nDimIndex);
+ 		}
+ 
+ 		pResData = new ScDPResultData( this );
+@@ -666,7 +745,7 @@
+ 		delete[] pDataNames;
+ 		delete[] pDataRefValues;
+ 
+-        BOOL bHasAutoShow = FALSE;
++        bool bHasAutoShow = false;
+ 
+         ScDPInitState aInitState;
+ 
+@@ -684,86 +763,22 @@
+ 		pColResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bColumnGrand );
+ 		pRowResRoot = new ScDPResultMember( pResData, NULL, NULL, NULL, bRowGrand );
+ 
+-		ScDPDimension* ppColDim[SC_DAPI_MAXFIELDS];		//! Ref?
+-		ScDPLevel* ppColLevel[SC_DAPI_MAXFIELDS];		//! Ref?
+-		long nColLevelDims[SC_DAPI_MAXFIELDS];
+-		long nColLevelCount = 0;
+-		for (i=0; i<nColDimCount; i++)
+-		{
+-			ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nColDims[i] );
+-			long nHierarchy = pDim->getUsedHierarchy();
+-			if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
+-				nHierarchy = 0;
+-			ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
+-			long nCount = pLevels->getCount();
++        FillCalcInfo(false, aInfo, bHasAutoShow);
++        long nColLevelCount = aInfo.aColLevels.size();
+ 
+-			//!	Test
+-			if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
+-				nCount = 0;
+-			//!	Test
+-
+-			for (long j=0; j<nCount; j++)
+-			{
+-			    ScDPLevel* pLevel = pLevels->getByIndex(j);
+-			    pLevel->EvaluateSortOrder();
+-			    pLevel->SetEnableLayout( FALSE );           // no layout flags for column fields
+-			    if ( pLevel->GetAutoShow().IsEnabled )
+-    			    bHasAutoShow = TRUE;
+-				nColLevelDims[nColLevelCount] = nColDims[i];
+-				ppColDim[nColLevelCount] = pDim;
+-				ppColLevel[nColLevelCount] = pLevel;
+-                pLevel->GetMembersObject();                 // initialize for groups
+-				++nColLevelCount;
+-			}
+-		}
+-		ppColDim[nColLevelCount] = NULL;
+-		ppColLevel[nColLevelCount] = NULL;
+-
+-		pColResRoot->InitFrom( ppColDim, ppColLevel, aInitState );
++        pColResRoot->InitFrom( aInfo.aColDims, aInfo.aColLevels, 0, aInitState );
+ 		pColResRoot->SetHasElements();
+ 
+-		ScDPDimension* ppRowDim[SC_DAPI_MAXFIELDS];		//! Ref?
+-		ScDPLevel* ppRowLevel[SC_DAPI_MAXFIELDS];		//! Ref?
+-		long nRowLevelDims[SC_DAPI_MAXFIELDS];
+-		long nRowLevelCount = 0;
+-		for (i=0; i<nRowDimCount; i++)
+-		{
+-			ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nRowDims[i] );
+-			long nHierarchy = pDim->getUsedHierarchy();
+-			if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
+-				nHierarchy = 0;
+-			ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
+-			long nCount = pLevels->getCount();
+-
+-			//!	Test
+-			if ( pDim->getIsDataLayoutDimension() && nDataDimCount < 2 )
+-				nCount = 0;
+-			//!	Test
+-
+-			for (long j=0; j<nCount; j++)
+-			{
+-			    ScDPLevel* pLevel = pLevels->getByIndex(j);
+-			    pLevel->EvaluateSortOrder();
+-			    pLevel->SetEnableLayout( TRUE );            // enable layout flags for row fields
+-			    if ( pLevel->GetAutoShow().IsEnabled )
+-    			    bHasAutoShow = TRUE;
+-				nRowLevelDims[nRowLevelCount] = nRowDims[i];
+-				ppRowDim[nRowLevelCount] = pDim;
+-				ppRowLevel[nRowLevelCount] = pLevel;
+-                pLevel->GetMembersObject();                 // initialize for groups
+-				++nRowLevelCount;
+-			}
+-		}
+-		ppRowDim[nRowLevelCount] = NULL;
+-		ppRowLevel[nRowLevelCount] = NULL;
++        FillCalcInfo(true, aInfo, bHasAutoShow);
++        long nRowLevelCount = aInfo.aRowLevels.size();
+ 
+ 		if ( nRowLevelCount > 0 )
+ 		{
+ 		    // disable layout flags for the innermost row field (level)
+-		    ppRowLevel[nRowLevelCount-1]->SetEnableLayout( FALSE );
++            aInfo.aRowLevels[nRowLevelCount-1]->SetEnableLayout( FALSE );
+ 		}
+ 
+-		pRowResRoot->InitFrom( ppRowDim, ppRowLevel, aInitState );
++        pRowResRoot->InitFrom( aInfo.aRowDims, aInfo.aRowLevels, 0, aInitState );
+ 		pRowResRoot->SetHasElements();
+ 
+         // initialize members object also for all page dimensions (needed for numeric groups)
+@@ -773,6 +788,7 @@
+             long nHierarchy = pDim->getUsedHierarchy();
+             if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
+                 nHierarchy = 0;
++
+             ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
+             long nCount = pLevels->getCount();
+             for (long j=0; j<nCount; j++)
+@@ -782,8 +798,9 @@
+ 		//	pre-check: calculate minimum number of result columns / rows from
+ 		//	levels that have the "show all" flag set
+ 
+-		long nMinColMembers = lcl_CountMinMembers( ppColDim, ppColLevel, nColLevelCount );
+-		long nMinRowMembers = lcl_CountMinMembers( ppRowDim, ppRowLevel, nRowLevelCount );
++		long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount );
++		long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount );
++
+ 		if ( nMinColMembers > SC_MINCOUNT_LIMIT || nMinRowMembers > SC_MINCOUNT_LIMIT )
+ 		{
+ 			//	resulting table is too big -> abort before calculating
+@@ -793,49 +810,25 @@
+ 		}
+ 		else
+ 		{
+-			ScDPItemData aColData[SC_DAPI_MAXFIELDS];
+-			ScDPItemData aRowData[SC_DAPI_MAXFIELDS];
+-			ScDPItemData aPageData[SC_DAPI_MAXFIELDS];
+-			ScDPValueData aValues[SC_DAPI_MAXFIELDS];
+-
+-			ScDPTableIteratorParam aIterPar(
+-						nColLevelCount,  nColLevelDims,  aColData,
+-						nRowLevelCount,  nRowLevelDims,  aRowData,
+-						nPageDimCount,   nPageDims,      aPageData,
+-						nDataDimCount,   nDataSrcCols,   aValues );
+-
+-			pData->ResetIterator();
+-			while ( pData->GetNextRow( aIterPar ) )
+-			{
+-				// test page fields ----------------------------
+-				BOOL bValidPage = TRUE;
+-				for (i=0; i<nPageDimCount; i++)
+-				{
+-					ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nPageDims[i] );
+-					if ( !pDim->IsValidPage( aPageData[i] ) )
+-						bValidPage = FALSE;
+-				}
+-				// end of page fields --------------------------
+-
+-				if ( bValidPage )
+ 				{
+-				    //! move LateInit outside of bValidPage test?
+-					pColResRoot->LateInitFrom( ppColDim, ppColLevel, aColData, aInitState );
+-					pRowResRoot->LateInitFrom( ppRowDim, ppRowLevel, aRowData, aInitState );
+-
+-					//	test for filtered entries
+-					//!	test child dimensions for null !!!
+-					if ( ( !pColResRoot->GetChildDimension() || pColResRoot->GetChildDimension()->IsValidEntry( aColData ) ) &&
+-						 ( !pRowResRoot->GetChildDimension() || pRowResRoot->GetChildDimension()->IsValidEntry( aRowData ) ) )
++                vector<ScDPDimension*> aPageDims;
++                aPageDims.reserve(nPageDimCount);
++                for (i = 0; i < nPageDimCount; ++i)
+ 					{
+-						//!	single process method with ColMembers, RowMembers and data !!!
+-						if (pColResRoot->GetChildDimension())
+-							pColResRoot->GetChildDimension()->ProcessData( aColData, NULL, NULL, aValues );
+-
+-						pRowResRoot->ProcessData( aRowData, pColResRoot->GetChildDimension(), aColData, aValues );
+-					}
++                    ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nPageDims[i]);
++                    if (pDim)
++                        aPageDims.push_back(pDim);
+ 				}
++                pData->FilterCacheTable(aPageDims);
+ 			}
++            aInfo.aPageDims.reserve(nPageDimCount);
++            for (i = 0; i < nPageDimCount; ++i)
++                aInfo.aPageDims.push_back(nPageDims[i]);
++
++            aInfo.pInitState = &aInitState;
++            aInfo.pColRoot   = pColResRoot;
++            aInfo.pRowRoot   = pRowResRoot;
++            pData->CalcResults(aInfo, false);
+ 
+ 			// ----------------------------------------------------------------
+ 			//  With all data processed, calculate the final results:
+@@ -853,21 +846,7 @@
+     			//  desired members only.
+     			pColResRoot->ResetResults( TRUE );
+     			pRowResRoot->ResetResults( TRUE );
+-
+-    			//  Again loop over the source data.
+-    			//  LateInitFrom is not needed again.
+-    			pData->ResetIterator();
+-    			while ( pData->GetNextRow( aIterPar ) )
+-    			{
+-    				//	test for filtered entries
+-    				if ( ( !pColResRoot->GetChildDimension() || pColResRoot->GetChildDimension()->IsValidEntry( aColData ) ) &&
+-    					 ( !pRowResRoot->GetChildDimension() || pRowResRoot->GetChildDimension()->IsValidEntry( aRowData ) ) )
+-    				{
+-    					if (pColResRoot->GetChildDimension())
+-    						pColResRoot->GetChildDimension()->ProcessData( aColData, NULL, NULL, aValues );
+-    					pRowResRoot->ProcessData( aRowData, pColResRoot->GetChildDimension(), aColData, aValues );
+-    				}
+-    			}
++                pData->CalcResults(aInfo, true);
+ 
+     			//  Call UpdateDataResults again, with the new (limited) values.
+     			pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
+@@ -893,105 +872,6 @@
+ 	}
+ }
+ 
+-void ScDPSource::WriteDrillDownData( ScDocument* pDoc, const ScAddress& rPos,
+-                    const std::vector< sheet::DataPilotFieldFilter > rFilters )
+-{
+-    ScAddress aOutPos( rPos );
+-    long nCol;
+-    long nColumnCount = GetData()->GetColumnCount();
+-
+-    // count non-group columns (for output - still included in filtering)
+-    long nSourceCount = 0;
+-    while ( nSourceCount < nColumnCount && pData->GetGroupBase(nSourceCount) < 0 )
+-        ++nSourceCount;
+-
+-    // collect ScDPItemData for each filtered column
+-    std::vector<bool> aFilterFlags( nColumnCount, false );
+-    std::vector<ScDPItemData> aFilterValues( nColumnCount );
+-    for ( std::vector<sheet::DataPilotFieldFilter>::const_iterator aFilterIter = rFilters.begin();
+-          aFilterIter != rFilters.end(); ++aFilterIter )
+-    {
+-        String aFieldName( aFilterIter->FieldName );
+-        for (nCol=0; nCol<nColumnCount; ++nCol)
+-            if ( aFieldName == pData->getDimensionName( nCol ) )
+-            {
+-                ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
+-                ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
+-                                        GetLevelsObject()->getByIndex(0)->GetMembersObject();
+-                sal_Int32 nIndex = pMembers->GetIndexFromName( aFilterIter->MatchValue );
+-                if ( nIndex >= 0 )
+-                {
+-                    aFilterFlags[nCol] = true;
+-                    pMembers->getByIndex(nIndex)->FillItemData( aFilterValues[nCol] );
+-                }
+-            }
+-    }
+-
+-    // add filter conditions for page fields
+-    for (long nPagePos=0; nPagePos<nPageDimCount; ++nPagePos)
+-    {
+-        nCol = nPageDims[nPagePos];
+-        ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
+-        if ( pDim->HasSelectedPage() )
+-        {
+-            aFilterFlags[nCol] = true;
+-            aFilterValues[nCol] = pDim->GetSelectedData();
+-        }
+-    }
+-
+-    // output column headers
+-    for (nCol=0; nCol<nSourceCount; ++nCol)
+-    {
+-        pDoc->PutCell( aOutPos, new ScStringCell( pData->getDimensionName( nCol ) ) );
+-        aOutPos.SetCol( aOutPos.Col() + 1 );
+-    }
+-    aOutPos.SetRow( aOutPos.Row() + 1 );
+-
+-    // get all fields from source as column fields
+-    ScDPItemData aColData[SC_DAPI_MAXFIELDS];
+-    long nFields[SC_DAPI_MAXFIELDS];
+-    for (sal_Int32 i=0; i<nColumnCount; ++i)
+-        nFields[i] = i;
+-    ScDPTableIteratorParam aIterPar( nColumnCount, nFields, aColData,   // column fields
+-                                     0, NULL, NULL,                     // row fields
+-                                     0, NULL, NULL,                     // page fields
+-                                     0, NULL, NULL );                   // data fields
+-    pData->ResetIterator();
+-    while ( pData->GetNextRow( aIterPar ) )
+-    {
+-        bool bInclude = true;
+-        for (nCol=0; nCol<nColumnCount; ++nCol)
+-        {
+-            if ( aFilterFlags[nCol] && !aColData[nCol].IsCaseInsEqual( aFilterValues[nCol] ) )
+-                bInclude = false;
+-        }
+-
+-        if ( bInclude )         // output data row
+-        {
+-            aOutPos.SetCol( rPos.Col() );
+-            for (nCol=0; nCol<nSourceCount; ++nCol)
+-            {
+-                if ( aColData[nCol].bHasValue )
+-                    pDoc->SetValue( aOutPos.Col(), aOutPos.Row(), aOutPos.Tab(), aColData[nCol].fValue );
+-                else if ( aColData[nCol].aString.Len() )
+-                    pDoc->PutCell( aOutPos, new ScStringCell( aColData[nCol].aString ) );
+-                aOutPos.SetCol( aOutPos.Col() + 1 );
+-            }
+-            aOutPos.SetRow( aOutPos.Row() + 1 );
+-        }
+-    }
+-
+-    // set number format (important for dates)
+-    if ( aOutPos.Row() > rPos.Row() + 1 )
+-        for (nCol=0; nCol<nSourceCount; ++nCol)
+-        {
+-            ScPatternAttr aPattern( pDoc->GetPool() );
+-            aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALUE_FORMAT, pData->GetNumberFormat(nCol) ) );
+-            SCCOL nFmtCol = static_cast<SCCOL>( rPos.Col() + nCol );
+-            pDoc->ApplyPatternAreaTab( nFmtCol, rPos.Row() + 1, nFmtCol, aOutPos.Row() - 1, rPos.Tab(), aPattern );
+-        }
+-}
+-
+ void ScDPSource::DumpState( ScDocument* pDoc, const ScAddress& rPos )
+ {
+     CreateRes_Impl();
+@@ -1185,6 +1065,12 @@
+ 		lcl_SetBoolInAny( aRet, getRepeatIfEmpty() );
+ 	else if ( aNameStr.EqualsAscii( SC_UNO_DATADESC ) )				// read-only
+ 		aRet <<= rtl::OUString( getDataDescription() );
++    else if ( aNameStr.EqualsAscii( SC_UNO_ROWFIELDCOUNT ) )        // read-only
++        aRet <<= static_cast<sal_Int32>(nRowDimCount);
++    else if ( aNameStr.EqualsAscii( SC_UNO_COLUMNFIELDCOUNT ) )     // read-only
++        aRet <<= static_cast<sal_Int32>(nColDimCount);
++    else if ( aNameStr.EqualsAscii( SC_UNO_DATAFIELDCOUNT ) )       // read-only
++        aRet <<= static_cast<sal_Int32>(nDataDimCount);
+ 	else
+ 	{
+ 		DBG_ERROR("unknown property");
+Index: sc/source/core/data/makefile.mk
+===================================================================
+RCS file: /cvs/sc/sc/source/core/data/makefile.mk,v
+retrieving revision 1.21
+retrieving revision 1.21.202.1
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.21 -r1.21.202.1
+--- sc/source/core/data/makefile.mk	27 Feb 2007 12:06:42 -0000	1.21
++++ sc/source/core/data/makefile.mk	29 Oct 2007 17:44:40 -0000	1.21.202.1
+@@ -77,6 +77,7 @@
+ 	$(SLO)$/documen8.obj \
+ 	$(SLO)$/documen9.obj \
+ 	$(SLO)$/document.obj \
++        $(SLO)$/dpcachetable.obj \
+         $(SLO)$/dpdimsave.obj \
+         $(SLO)$/dpgroup.obj \
+ 	$(SLO)$/dpobject.obj \
+@@ -131,6 +132,7 @@
+ 	$(SLO)$/documen5.obj \
+ 	$(SLO)$/documen6.obj \
+ 	$(SLO)$/documen9.obj \
++        $(SLO)$/dpcachetable.obj \
+ 	$(SLO)$/dpsdbtab.obj \
+ 	$(SLO)$/dpobject.obj \
+ 	$(SLO)$/dpoutput.obj \
+Index: sc/source/ui/inc/dbfunc.hxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/inc/dbfunc.hxx,v
+retrieving revision 1.10
+retrieving revision 1.9.20.2
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.10 -r1.9.20.2
+--- sc/source/ui/inc/dbfunc.hxx	7 Dec 2007 10:42:00 -0000	1.10
++++ sc/source/ui/inc/dbfunc.hxx	4 Jan 2008 03:45:52 -0000	1.9.20.2
+@@ -110,7 +110,7 @@
+     void            SetDataPilotDetails( BOOL bShow, const String* pNewDimensionName = NULL );
+ 
+     void            ShowDataPilotSourceData( ScDPObject& rDPObj,
+-                        const ::std::vector< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters );
++                        const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters );
+ 
+ 	void			MakeOutline( BOOL bColumns, BOOL bRecord = TRUE );
+ 	void			RemoveOutline( BOOL bColumns, BOOL bRecord = TRUE );
+Index: sc/source/ui/unoobj/dapiuno.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/unoobj/dapiuno.cxx,v
+retrieving revision 1.20
+retrieving revision 1.19.202.7
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.20 -r1.19.202.7
+--- sc/source/ui/unoobj/dapiuno.cxx	20 Nov 2007 17:42:20 -0000	1.20
++++ sc/source/ui/unoobj/dapiuno.cxx	6 Dec 2007 01:51:27 -0000	1.19.202.7
+@@ -45,6 +45,7 @@
+ #include "datauno.hxx"
+ #include "miscuno.hxx"
+ #include "docsh.hxx"
++#include "tabvwsh.hxx"
+ #include "pivot.hxx"
+ #include "rangeutl.hxx"
+ #include "unoguard.hxx"
+@@ -76,12 +77,23 @@
+ #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+ #endif
+ 
++#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
++#include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
++
+ #ifndef _COMPHELPER_EXTRACT_HXX_
+ #include <comphelper/extract.hxx>
+ #endif
+ 
+ using namespace com::sun::star;
+ 
++using ::com::sun::star::sheet::DataPilotFieldFilter;
++using ::com::sun::star::sheet::DataPilotTablePositionData;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::table::CellAddress;
++using ::com::sun::star::table::CellRangeAddress;
++using ::com::sun::star::uno::RuntimeException;
++using ::com::sun::star::uno::Any;
+ 
+ //------------------------------------------------------------------------
+ 
+@@ -532,7 +544,7 @@
+ 									lang::WrappedTargetException, uno::RuntimeException)
+ {
+ 	ScUnoGuard aGuard;
+-	uno::Reference<sheet::XDataPilotTable> xTable(GetObjectByIndex_Impl(static_cast<SCSIZE>(nIndex)));
++    uno::Reference<sheet::XDataPilotTable2> xTable(GetObjectByIndex_Impl(static_cast<SCSIZE>(nIndex)));
+ 	if (xTable.is())
+         return uno::makeAny(xTable);
+ 	else
+@@ -543,7 +555,7 @@
+ uno::Type SAL_CALL ScDataPilotTablesObj::getElementType() throw(uno::RuntimeException)
+ {
+ 	ScUnoGuard aGuard;
+-	return getCppuType((uno::Reference<sheet::XDataPilotTable>*)0);
++    return getCppuType((uno::Reference<sheet::XDataPilotTable2>*)0);
+ }
+ 
+ sal_Bool SAL_CALL ScDataPilotTablesObj::hasElements() throw(uno::RuntimeException)
+@@ -559,7 +571,7 @@
+ 					lang::WrappedTargetException, uno::RuntimeException)
+ {
+ 	ScUnoGuard aGuard;
+-	uno::Reference<sheet::XDataPilotTable> xTable(GetObjectByName_Impl(aName));
++    uno::Reference<sheet::XDataPilotTable2> xTable(GetObjectByName_Impl(aName));
+ 	if (xTable.is())
+         return uno::makeAny(xTable);
+ 	else
+@@ -1014,7 +1026,7 @@
+ uno::Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType )
+ 												throw(uno::RuntimeException)
+ {
+-	SC_QUERYINTERFACE( sheet::XDataPilotTable )
++    SC_QUERYINTERFACE( sheet::XDataPilotTable2 )
+ 
+ 	return ScDataPilotDescriptorBase::queryInterface( rType );
+ }
+@@ -1041,7 +1053,7 @@
+ 
+ 		aTypes.realloc( nParentLen + 1 );
+ 		uno::Type* pPtr = aTypes.getArray();
+-		pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XDataPilotTable>*)0);
++        pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XDataPilotTable2>*)0);
+ 
+ 		for (long i=0; i<nParentLen; i++)
+ 			pPtr[i] = pParentPtr[i];				// parent types first
+@@ -1164,6 +1176,59 @@
+ 	}
+ }
+ 
++Sequence< Sequence<Any> > SAL_CALL ScDataPilotTableObj::getDrillDownData(const CellAddress& aAddr)
++    throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    Sequence< Sequence<Any> > aTabData;
++    ScAddress aAddr2(aAddr.Column, aAddr.Row, aAddr.Sheet);
++    GetDPObject()->GetDrillDownData(aAddr2, aTabData);
++    return aTabData;
++}
++
++DataPilotTablePositionData SAL_CALL ScDataPilotTableObj::getPositionData(const CellAddress& aAddr)
++    throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    DataPilotTablePositionData aPosData;
++    ScAddress aAddr2(aAddr.Column, aAddr.Row, aAddr.Sheet);
++    GetDPObject()->GetPositionData(aAddr2, aPosData);
++    return aPosData;
++}
++
++void SAL_CALL ScDataPilotTableObj::insertDrillDownSheet(const CellAddress& aAddr)
++    throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    ScDPObject* pDPObj = GetDPObject();
++    if (!pDPObj)
++        throw RuntimeException();
++
++    Sequence<DataPilotFieldFilter> aFilters;
++    pDPObj->GetDataFieldPositionData(
++        ScAddress(aAddr.Column, aAddr.Row, aAddr.Sheet), aFilters);
++    GetDocShell()->GetBestViewShell()->ShowDataPilotSourceData(*pDPObj, aFilters);
++}
++
++CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRangeByType( sal_Int32 nType )
++    throw (RuntimeException)
++{
++    ScUnoGuard aGuard;
++    table::CellRangeAddress aRet;
++    ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName);
++    if (!pDPObj)
++        return aRet;
++
++    const ScRange aRange = pDPObj->GetOutputRangeByType(nType);
++    aRet.Sheet       = aRange.aStart.Tab();
++    aRet.StartColumn = aRange.aStart.Col();
++    aRet.StartRow    = aRange.aStart.Row();
++    aRet.EndColumn   = aRange.aEnd.Col();
++    aRet.EndRow      = aRange.aEnd.Row();
++
++    return aRet;
++}
++
+ //------------------------------------------------------------------------
+ 
+ ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) :
+Index: sc/source/ui/view/cellsh1.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/cellsh1.cxx,v
+retrieving revision 1.48
+retrieving revision 1.46.172.3
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.48 -r1.46.172.3
+--- sc/source/ui/view/cellsh1.cxx	26 Nov 2007 15:20:42 -0000	1.48
++++ sc/source/ui/view/cellsh1.cxx	5 Dec 2007 00:25:15 -0000	1.46.172.3
+@@ -35,7 +35,7 @@
+ 
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+-
++#include <stdio.h>
+ 
+ //------------------------------------------------------------------
+ 
+@@ -973,7 +973,7 @@
+                                     GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
+                 if ( pDPObj )
+                 {
+-                    std::vector<sheet::DataPilotFieldFilter> aFilters;
++                    Sequence<sheet::DataPilotFieldFilter> aFilters;
+                     USHORT nOrientation;
+                     if ( pTabViewShell->HasSelectionForDrillDown( nOrientation ) )
+                     {
+@@ -990,9 +990,9 @@
+                         }
+                     }
+                     else if ( !pDPObj->IsServiceData() &&
+-                               pDPObj->GetDataFieldPositionData( aFilters,
+-                                        ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
+-                                                   GetViewData()->GetTabNo() ) ) )
++                               pDPObj->GetDataFieldPositionData( 
++                                   ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ),
++                                   aFilters ) )
+                         pTabViewShell->ShowDataPilotSourceData( *pDPObj, aFilters );
+                     else
+                         pTabViewShell->SetDataPilotDetails( TRUE );
+Index: sc/source/ui/view/dbfunc3.cxx
+===================================================================
+RCS file: /cvs/sc/sc/source/ui/view/dbfunc3.cxx,v
+retrieving revision 1.15
+retrieving revision 1.13.202.6
+diff -u -b -I $Revision.*$ -I $Author.*$ -r1.15 -r1.13.202.6
+--- sc/source/ui/view/dbfunc3.cxx	26 Nov 2007 15:21:00 -0000	1.15
++++ sc/source/ui/view/dbfunc3.cxx	6 Dec 2007 06:40:28 -0000	1.13.202.6
+@@ -40,6 +40,7 @@
+ 
+ // INCLUDE ---------------------------------------------------------------
+ 
++#include "dbfunc.hxx"
+ #include "scitems.hxx"
+ #include <sfx2/bindings.hxx>
+ #include <vcl/svapp.hxx>
+@@ -53,15 +54,15 @@
+ #include <com/sun/star/sheet/MemberResultFlags.hpp>
+ 
+ #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
++#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
+ #include <com/sun/star/sheet/MemberResultFlags.hpp>
+-#ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDGROUPBY_HPP_
+ #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
+-#endif
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
++#include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
++#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
++#include <com/sun/star/beans/XPropertySet.hpp>
++#include <com/sun/star/container/XNameAccess.hpp>
+ 
+-#include <hash_set>
+-
+-#include "dbfunc.hxx"
+ #include "global.hxx"
+ #include "globstr.hrc"
+ #include "sc.hrc"
+@@ -81,8 +82,21 @@
+ #include "dpoutput.hxx"
+ #include "dptabsrc.hxx"
+ #include "editable.hxx"
++#include "docpool.hxx"
++#include "patattr.hxx"
++#include "unonames.hxx"
++#include "cell.hxx"
++
++#include <hash_set>
++#include <memory>
+ 
+ using namespace com::sun::star;
++using ::com::sun::star::uno::Any;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Reference;
++using ::com::sun::star::uno::UNO_QUERY;
++using ::com::sun::star::beans::XPropertySet;
++using ::std::auto_ptr;
+ 
+ // STATIC DATA -----------------------------------------------------------
+ 
+@@ -718,22 +732,21 @@
+         for (SCROW nRow=nStartRow; nRow<=nEndRow && bContinue; nRow++)
+             for (SCCOL nCol=nStartCol; nCol<=nEndCol && bContinue; nCol++)
+             {
+-                ScDPPositionData aData;
+-                pDPObj->GetPositionData( aData, ScAddress( nCol, nRow, nTab ) );
+-
+-                if ( aData.nDimension < 0 )
++                sheet::DataPilotTableHeaderData aData;
++                pDPObj->GetHeaderPositionData(ScAddress(nCol, nRow, nTab), aData);
++                if ( aData.Dimension < 0 )
+                     bContinue = FALSE;              // not part of any dimension
+                 else
+                 {
+                     if ( nStartDimension < 0 )      // first member?
+                     {
+-                        nStartDimension = aData.nDimension;
+-                        nStartHierarchy = aData.nHierarchy;
+-                        nStartLevel     = aData.nLevel;
+-                    }
+-                    if ( aData.nDimension != nStartDimension ||
+-                         aData.nHierarchy != nStartHierarchy ||
+-                         aData.nLevel     != nStartLevel )
++                        nStartDimension = aData.Dimension;
++                        nStartHierarchy = aData.Hierarchy;
++                        nStartLevel     = aData.Level;
++                    }
++                    if ( aData.Dimension != nStartDimension ||
++                         aData.Hierarchy != nStartHierarchy ||
++                         aData.Level     != nStartLevel )
+                     {
+                         bContinue = FALSE;          // cannot mix dimensions
+                     }
+@@ -742,9 +755,9 @@
+                 {
+                     // accept any part of a member description, also subtotals,
+                     // but don't stop if empty parts are contained
+-                    if ( aData.nFlags & sheet::MemberResultFlags::HASMEMBER )
++                    if ( aData.Flags & sheet::MemberResultFlags::HASMEMBER )
+                     {
+-                        StrData* pNew = new StrData( aData.aMemberName );
++                        StrData* pNew = new StrData( aData.MemberName );
+                         if ( !rEntries.Insert( pNew ) )
+                             delete pNew;
+                     }
+@@ -1421,16 +1434,16 @@
+             // renaming a group (item)?
+             // allow only on the item name itself - not on empty cells, not on subtotals
+ 
+-            ScDPPositionData aPosData;
+-            pDPObj->GetPositionData( aPosData, rPos );
+-            if ( ( aPosData.nFlags & sheet::MemberResultFlags::HASMEMBER ) &&
+-                 ! ( aPosData.nFlags & sheet::MemberResultFlags::SUBTOTAL ) &&
++            sheet::DataPilotTableHeaderData aPosData;
++            pDPObj->GetHeaderPositionData(rPos, aPosData);
++            if ( ( aPosData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
++                 ! ( aPosData.Flags & sheet::MemberResultFlags::SUBTOTAL ) &&
+                  aOldText.Len() )
+             {
+                 if ( aData.GetExistingDimensionData() )
+                 {
+                     BOOL bIsDataLayout;
+-                    String aDimName = pDPObj->GetDimName( aPosData.nDimension, bIsDataLayout );
++                    String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
+ 
+                     ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
+                     ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
+@@ -1504,26 +1517,26 @@
+     ScDPObject* pDPObj = pDoc->GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() );
+     if ( pDPObj && pDPObj == pDoc->GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) )
+     {
+-        ScDPPositionData aDestData;
+-        pDPObj->GetPositionData( aDestData, rDest );
+-        bool bValid = ( aDestData.nDimension >= 0 );        // dropping onto a field
++        sheet::DataPilotTableHeaderData aDestData;
++        pDPObj->GetHeaderPositionData( rDest, aDestData );
++        bool bValid = ( aDestData.Dimension >= 0 );        // dropping onto a field
+ 
+         // look through the source range
+-        std::hash_set< String, ScStringHashCode, std::equal_to<String> > aMembersSet;   // for lookup
+-        std::vector<String> aMembersVector;         // members in original order, for inserting
++        std::hash_set< rtl::OUString, rtl::OUStringHash, std::equal_to<rtl::OUString> > aMembersSet;   // for lookup
++        std::vector< rtl::OUString > aMembersVector;  // members in original order, for inserting
+         aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ),
+                                           static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) );
+         for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow )
+             for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol )
+             {
+-                ScDPPositionData aSourceData;
+-                pDPObj->GetPositionData( aSourceData, ScAddress( nCol, nRow, rSource.aStart.Tab() ) );
+-                if ( aSourceData.nDimension == aDestData.nDimension && aSourceData.aMemberName.Len() )
++                sheet::DataPilotTableHeaderData aSourceData;
++                pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData );
++                if ( aSourceData.Dimension == aDestData.Dimension && aSourceData.MemberName.getLength() )
+                 {
+-                    if ( aMembersSet.find( aSourceData.aMemberName ) == aMembersSet.end() )
++                    if ( aMembersSet.find( aSourceData.MemberName ) == aMembersSet.end() )
+                     {
+-                        aMembersSet.insert( aSourceData.aMemberName );
+-                        aMembersVector.push_back( aSourceData.aMemberName );
++                        aMembersSet.insert( aSourceData.MemberName );
++                        aMembersVector.push_back( aSourceData.MemberName );
+                     }
+                     // duplicates are ignored
+                 }
+@@ -1534,7 +1547,7 @@
+         if ( bValid )
+         {
+             BOOL bIsDataLayout;
+-            String aDimName = pDPObj->GetDimName( aDestData.nDimension, bIsDataLayout );
++            String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
+             if ( !bIsDataLayout )
+             {
+                 ScDPSaveData aData( *pDPObj->GetSaveData() );
+@@ -1542,7 +1555,7 @@
+ 
+                 // get all member names in source order
+                 uno::Sequence<rtl::OUString> aMemberNames;
+-                pDPObj->GetMembers( aDestData.nDimension, aMemberNames );
++                pDPObj->GetMembers( aDestData.Dimension, aMemberNames );
+ 
+                 bool bInserted = false;
+ 
+@@ -1551,10 +1564,10 @@
+                 {
+                     String aMemberStr( aMemberNames[nMemberPos] );
+ 
+-                    if ( !bInserted && aMemberStr == aDestData.aMemberName )
++                    if ( !bInserted && aMemberNames[nMemberPos] == aDestData.MemberName )
+                     {
+                         // insert dragged items before this item
+-                        for ( std::vector<String>::const_iterator aIter = aMembersVector.begin();
++                        for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin();
+                               aIter != aMembersVector.end(); ++aIter )
+                             lcl_MoveToEnd( *pDim, *aIter );
+                         bInserted = true;
+@@ -1565,7 +1578,7 @@
+                 }
+                 // insert dragged item at end if dest wasn't found (for example, empty)
+                 if ( !bInserted )
+-                    for ( std::vector<String>::const_iterator aIter = aMembersVector.begin();
++                    for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin();
+                           aIter != aMembersVector.end(); ++aIter )
+                         lcl_MoveToEnd( *pDim, *aIter );
+ 
+@@ -1720,19 +1733,62 @@
+     }
+ }
+ 
+-void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const std::vector<sheet::DataPilotFieldFilter>& rFilters )
++void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters )
+ {
+-    uno::Reference<sheet::XDimensionsSupplier> xSource = rDPObj.GetSource();
+-    ScDPSource* pTabSource = dynamic_cast<ScDPSource*>(xSource.get());
+-    DBG_ASSERT( pTabSource, "can't get ScDPSource" );
+-    if ( pTabSource )
+-    {
+-        // output into clipboard document (for easy undo)
++    Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource();
++    Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions();
++    Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY);
++    if (!xDDSupplier.is())
++        return;
++
++    Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters);
++    sal_Int32 nRowSize = aTabData.getLength();
++    if (nRowSize <= 1)
++        // There is no data to show.  Bail out.
++        return;
++
++    sal_Int32 nColSize = aTabData[0].getLength();
++
+         ScDocument* pDoc = GetViewData()->GetDocument();
+         SCTAB nNewTab = GetViewData()->GetTabNo();
+-        ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP );
++
++    auto_ptr<ScDocument> pInsDoc(new ScDocument(SCDOCMODE_CLIP));
+         pInsDoc->ResetClip( pDoc, nNewTab );
+-        pTabSource->WriteDrillDownData( pInsDoc, ScAddress( 0, 0, nNewTab ), rFilters );
++    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
++    {
++        for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol)
++        {
++            const Any& rAny = aTabData[nRow][nCol];
++            rtl::OUString aStr;
++            double fVal;
++            if (rAny >>= aStr)
++                pInsDoc->PutCell( ScAddress(nCol, nRow, nNewTab), new ScStringCell(String(aStr)) );
++            else if (rAny >>= fVal)
++                pInsDoc->SetValue(nCol, nRow, nNewTab, fVal);
++        }
++    }
++
++    // set number format (important for dates)
++    for (sal_Int32 nCol = 0; nCol < nColSize; ++nCol)
++    {
++        rtl::OUString aStr;
++        if (!(aTabData[0][nCol] >>= aStr))
++            continue;
++
++        Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY);
++        if (!xPropSet.is())
++            continue;
++
++        Any any = xPropSet->getPropertyValue( rtl::OUString::createFromAscii(SC_UNO_NUMBERFO) );
++        sal_Int32 nNumFmt = 0;
++        if (!(any >>= nNumFmt))
++            continue;
++
++        ScPatternAttr aPattern( pInsDoc->GetPool() );
++        aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<UINT32>(nNumFmt)) );
++        pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern);
++    }
++
+         SCCOL nEndCol = 0;
+         SCROW nEndRow = 0;
+         pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow );
+@@ -1742,15 +1798,12 @@
+         String aUndo = ScGlobal::GetRscString( STR_UNDO_DOOUTLINE );
+         pMgr->EnterListAction( aUndo, aUndo );
+ 
+-        // insert new sheet and paste result
+         String aNewTabName;
+         pDoc->CreateValidTabName(aNewTabName);
+-        if ( InsertTable( aNewTabName, nNewTab ) )
+-            PasteFromClip( IDF_ALL, pInsDoc );
++    if ( InsertTable(aNewTabName, nNewTab) )
++        PasteFromClip( IDF_ALL, pInsDoc.get() );
+ 
+         pMgr->LeaveListAction();
+-        delete pInsDoc;
+-    }
+ }
+ 
+ //
+--- sc/source/ui/view/gridwin.cxx.orig	2008-01-15 11:54:09.000000000 -0500
++++ sc/source/ui/view/gridwin.cxx	2008-01-15 12:04:53.000000000 -0500
+@@ -93,6 +93,10 @@
+ 
+ #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+ #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
++#include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
++#include <com/sun/star/sheet/DataPilotTableResultData.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
++#include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
+ #include <com/sun/star/sheet/MemberResultFlags.hpp>
+ #include <com/sun/star/awt/KeyModifier.hpp>
+ #include <com/sun/star/awt/MouseButton.hpp>
+@@ -164,6 +168,8 @@
+ #endif
+ 
+ using namespace com::sun::star;
++using ::com::sun::star::uno::Sequence;
++using ::com::sun::star::uno::Any;
+ 
+ const BYTE SC_NESTEDBUTTON_NONE = 0;
+ const BYTE SC_NESTEDBUTTON_DOWN = 1;
+@@ -2046,11 +2052,13 @@
+ 		if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() )
+ 		{
+ 			ScAddress aCellPos( nPosX, nPosY, nTab );
+-			ScDPPositionData aData;
+-			pDPObj->GetPositionData( aData, aCellPos );
+ 
+-			if ( ( aData.nFlags & sheet::MemberResultFlags::HASMEMBER ) &&
+-				 ! ( aData.nFlags & sheet::MemberResultFlags::SUBTOTAL ) )
++            // Check for header drill-down first.
++            sheet::DataPilotTableHeaderData aData;
++            pDPObj->GetHeaderPositionData(aCellPos, aData);
++
++            if ( ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
++                 ! ( aData.Flags & sheet::MemberResultFlags::SUBTOTAL ) )
+ 			{
+                 USHORT nDummy;
+                 if ( pView->HasSelectionForDrillDown( nDummy ) )
+@@ -2072,8 +2080,8 @@
+             {
+                 // Check if the data area is double-clicked.
+ 
+-                std::vector<sheet::DataPilotFieldFilter> aFilters;
+-                if ( !pDPObj->IsServiceData() && pDPObj->GetDataFieldPositionData( aFilters, aCellPos ) )
++                Sequence<sheet::DataPilotFieldFilter> aFilters;
++                if ( pDPObj->GetDataFieldPositionData(aCellPos, aFilters) )
+                     pViewData->GetView()->ShowDataPilotSourceData( *pDPObj, aFilters );
+                 else
+                     Sound::Beep();  // nothing to expand/collapse/show
+@@ -3274,24 +3282,24 @@
+             bool bDPSort = false;
+             if ( pThisDoc->GetDPAtCursor( nSourceStartX, nSourceStartY, aSourceRange.aStart.Tab() ) == pDPObj )
+             {
+-                ScDPPositionData aDestData;
+-                pDPObj->GetPositionData( aDestData, ScAddress(nNewDragX, nNewDragY, nTab) );
+-                bool bValid = ( aDestData.nDimension >= 0 );        // dropping onto a field
++                sheet::DataPilotTableHeaderData aDestData;
++                pDPObj->GetHeaderPositionData( ScAddress(nNewDragX, nNewDragY, nTab), aDestData );
++                bool bValid = ( aDestData.Dimension >= 0 );        // dropping onto a field
+ 
+                 // look through the source range
+                 for (SCROW nRow = aSourceRange.aStart.Row(); bValid && nRow <= aSourceRange.aEnd.Row(); ++nRow )
+                     for (SCCOL nCol = aSourceRange.aStart.Col(); bValid && nCol <= aSourceRange.aEnd.Col(); ++nCol )
+                     {
+-                        ScDPPositionData aSourceData;
+-                        pDPObj->GetPositionData( aSourceData, ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ) );
+-                        if ( aSourceData.nDimension != aDestData.nDimension || !aSourceData.aMemberName.Len() )
++                        sheet::DataPilotTableHeaderData aSourceData;
++                        pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, aSourceRange.aStart.Tab() ), aSourceData );
++                        if ( aSourceData.Dimension != aDestData.Dimension || !aSourceData.MemberName.getLength() )
+                             bValid = false;     // empty (subtotal) or different field
+                     }
+ 
+                 if ( bValid )
+                 {
+                     BOOL bIsDataLayout;
+-                    String aDimName = pDPObj->GetDimName( aDestData.nDimension, bIsDataLayout );
++                    String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
+                     const ScDPSaveDimension* pDim = pDPObj->GetSaveData()->GetExistingDimensionByName( aDimName );
+                     if ( pDim )
+                     {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]