xref: /aoo41x/main/sc/source/ui/view/dbfunc3.cxx (revision b3f79822)
1*b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*b3f79822SAndrew Rist  * distributed with this work for additional information
6*b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9*b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*b3f79822SAndrew Rist  *
11*b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*b3f79822SAndrew Rist  *
13*b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15*b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17*b3f79822SAndrew Rist  * specific language governing permissions and limitations
18*b3f79822SAndrew Rist  * under the License.
19*b3f79822SAndrew Rist  *
20*b3f79822SAndrew Rist  *************************************************************/
21*b3f79822SAndrew Rist 
22*b3f79822SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir 
29cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include "dbfunc.hxx"
32cdf0e10cSrcweir #include "scitems.hxx"
33cdf0e10cSrcweir #include <sfx2/bindings.hxx>
34cdf0e10cSrcweir #include <vcl/svapp.hxx>
35cdf0e10cSrcweir #include <vcl/msgbox.hxx>
36cdf0e10cSrcweir #include <vcl/sound.hxx>
37cdf0e10cSrcweir #include <vcl/waitobj.hxx>
38cdf0e10cSrcweir #include <svl/zforlist.hxx>
39cdf0e10cSrcweir #include <sfx2/app.hxx>
40cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
41cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp>
42cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
43cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
44cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
45cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
46cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
47cdf0e10cSrcweir #include <com/sun/star/sheet/GeneralFunction.hpp>
48cdf0e10cSrcweir #include <com/sun/star/sheet/MemberResultFlags.hpp>
49cdf0e10cSrcweir #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
50cdf0e10cSrcweir #include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #include "global.hxx"
53cdf0e10cSrcweir #include "globstr.hrc"
54cdf0e10cSrcweir #include "sc.hrc"
55cdf0e10cSrcweir #include "undotab.hxx"
56cdf0e10cSrcweir #include "undodat.hxx"
57cdf0e10cSrcweir #include "dbcolect.hxx"
58cdf0e10cSrcweir #include "rangenam.hxx"
59cdf0e10cSrcweir #include "rangeutl.hxx"
60cdf0e10cSrcweir #include "docsh.hxx"
61cdf0e10cSrcweir #include "olinetab.hxx"
62cdf0e10cSrcweir #include "consoli.hxx"
63cdf0e10cSrcweir #include "olinefun.hxx"
64cdf0e10cSrcweir #include "dpobject.hxx"
65cdf0e10cSrcweir #include "dpsave.hxx"
66cdf0e10cSrcweir #include "dpdimsave.hxx"
67cdf0e10cSrcweir #include "dbdocfun.hxx"
68cdf0e10cSrcweir #include "dpoutput.hxx"
69cdf0e10cSrcweir #include "dptabsrc.hxx"
70cdf0e10cSrcweir #include "editable.hxx"
71cdf0e10cSrcweir #include "docpool.hxx"
72cdf0e10cSrcweir #include "patattr.hxx"
73cdf0e10cSrcweir #include "unonames.hxx"
74cdf0e10cSrcweir #include "cell.hxx"
75cdf0e10cSrcweir #include "userlist.hxx"
76cdf0e10cSrcweir 
77cdf0e10cSrcweir #include <hash_set>
78cdf0e10cSrcweir #include <hash_map>
79cdf0e10cSrcweir #include <memory>
80cdf0e10cSrcweir #include <list>
81cdf0e10cSrcweir #include <vector>
82cdf0e10cSrcweir 
83cdf0e10cSrcweir using namespace com::sun::star;
84cdf0e10cSrcweir using ::com::sun::star::uno::Any;
85cdf0e10cSrcweir using ::com::sun::star::uno::Sequence;
86cdf0e10cSrcweir using ::com::sun::star::uno::Reference;
87cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY;
88cdf0e10cSrcweir using ::com::sun::star::beans::XPropertySet;
89cdf0e10cSrcweir using ::com::sun::star::container::XNameAccess;
90cdf0e10cSrcweir using ::com::sun::star::sheet::XDimensionsSupplier;
91cdf0e10cSrcweir using ::rtl::OUString;
92cdf0e10cSrcweir using ::rtl::OUStringHash;
93cdf0e10cSrcweir using ::rtl::OUStringBuffer;
94cdf0e10cSrcweir using ::std::auto_ptr;
95cdf0e10cSrcweir using ::std::list;
96cdf0e10cSrcweir using ::std::vector;
97cdf0e10cSrcweir using ::std::hash_map;
98cdf0e10cSrcweir using ::std::hash_set;
99cdf0e10cSrcweir 
100cdf0e10cSrcweir // STATIC DATA -----------------------------------------------------------
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 
103cdf0e10cSrcweir //==================================================================
104cdf0e10cSrcweir 
105cdf0e10cSrcweir //
106cdf0e10cSrcweir //			Outliner
107cdf0e10cSrcweir //
108cdf0e10cSrcweir 
109cdf0e10cSrcweir //	Outline-Gruppierung erzeugen
110cdf0e10cSrcweir 
111cdf0e10cSrcweir void ScDBFunc::MakeOutline( sal_Bool bColumns, sal_Bool bRecord )
112cdf0e10cSrcweir {
113cdf0e10cSrcweir 	ScRange aRange;
114cdf0e10cSrcweir 	if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
115cdf0e10cSrcweir 	{
116cdf0e10cSrcweir 		ScDocShell* pDocSh = GetViewData()->GetDocShell();
117cdf0e10cSrcweir 		ScOutlineDocFunc aFunc(*pDocSh);
118cdf0e10cSrcweir 		aFunc.MakeOutline( aRange, bColumns, bRecord, sal_False );
119cdf0e10cSrcweir 	}
120cdf0e10cSrcweir 	else
121cdf0e10cSrcweir 		ErrorMessage(STR_NOMULTISELECT);
122cdf0e10cSrcweir }
123cdf0e10cSrcweir 
124cdf0e10cSrcweir //	Outline-Gruppierung loeschen
125cdf0e10cSrcweir 
126cdf0e10cSrcweir void ScDBFunc::RemoveOutline( sal_Bool bColumns, sal_Bool bRecord )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir 	ScRange aRange;
129cdf0e10cSrcweir 	if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
130cdf0e10cSrcweir 	{
131cdf0e10cSrcweir 		ScDocShell* pDocSh = GetViewData()->GetDocShell();
132cdf0e10cSrcweir 		ScOutlineDocFunc aFunc(*pDocSh);
133cdf0e10cSrcweir 		aFunc.RemoveOutline( aRange, bColumns, bRecord, sal_False );
134cdf0e10cSrcweir 	}
135cdf0e10cSrcweir 	else
136cdf0e10cSrcweir 		ErrorMessage(STR_NOMULTISELECT);
137cdf0e10cSrcweir }
138cdf0e10cSrcweir 
139cdf0e10cSrcweir //	Menue-Status: Outlines loeschen
140cdf0e10cSrcweir 
141cdf0e10cSrcweir void ScDBFunc::TestRemoveOutline( sal_Bool& rCol, sal_Bool& rRow )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir 	sal_Bool bColFound = sal_False;
144cdf0e10cSrcweir 	sal_Bool bRowFound = sal_False;
145cdf0e10cSrcweir 
146cdf0e10cSrcweir 	SCCOL nStartCol, nEndCol;
147cdf0e10cSrcweir 	SCROW nStartRow, nEndRow;
148cdf0e10cSrcweir 	SCTAB nStartTab, nEndTab;
149cdf0e10cSrcweir 	if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
150cdf0e10cSrcweir 	{
151cdf0e10cSrcweir 		SCTAB nTab = nStartTab;
152cdf0e10cSrcweir 		ScDocument* pDoc = GetViewData()->GetDocument();
153cdf0e10cSrcweir 		ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
154cdf0e10cSrcweir 		if (pTable)
155cdf0e10cSrcweir 		{
156cdf0e10cSrcweir 			ScOutlineArray* pArray;
157cdf0e10cSrcweir 			ScOutlineEntry* pEntry;
158cdf0e10cSrcweir 			SCCOLROW nStart;
159cdf0e10cSrcweir 			SCCOLROW nEnd;
160cdf0e10cSrcweir 			sal_Bool bColMarked = ( nStartRow == 0 && nEndRow == MAXROW );
161cdf0e10cSrcweir 			sal_Bool bRowMarked = ( nStartCol == 0 && nEndCol == MAXCOL );
162cdf0e10cSrcweir 
163cdf0e10cSrcweir 			//	Spalten
164cdf0e10cSrcweir 
165cdf0e10cSrcweir 			if ( !bRowMarked || bColMarked )		// nicht wenn ganze Zeilen markiert
166cdf0e10cSrcweir 			{
167cdf0e10cSrcweir 				pArray = pTable->GetColArray();
168cdf0e10cSrcweir 				ScSubOutlineIterator aColIter( pArray );
169cdf0e10cSrcweir 				while ((pEntry=aColIter.GetNext()) != NULL && !bColFound)
170cdf0e10cSrcweir 				{
171cdf0e10cSrcweir 					nStart = pEntry->GetStart();
172cdf0e10cSrcweir 					nEnd   = pEntry->GetEnd();
173cdf0e10cSrcweir 					if ( nStartCol<=static_cast<SCCOL>(nEnd) && nEndCol>=static_cast<SCCOL>(nStart) )
174cdf0e10cSrcweir 						bColFound = sal_True;
175cdf0e10cSrcweir 				}
176cdf0e10cSrcweir 			}
177cdf0e10cSrcweir 
178cdf0e10cSrcweir 			//	Zeilen
179cdf0e10cSrcweir 
180cdf0e10cSrcweir 			if ( !bColMarked || bRowMarked )		// nicht wenn ganze Spalten markiert
181cdf0e10cSrcweir 			{
182cdf0e10cSrcweir 				pArray = pTable->GetRowArray();
183cdf0e10cSrcweir 				ScSubOutlineIterator aRowIter( pArray );
184cdf0e10cSrcweir 				while ((pEntry=aRowIter.GetNext()) != NULL && !bRowFound)
185cdf0e10cSrcweir 				{
186cdf0e10cSrcweir 					nStart = pEntry->GetStart();
187cdf0e10cSrcweir 					nEnd   = pEntry->GetEnd();
188cdf0e10cSrcweir 					if ( nStartRow<=nEnd && nEndRow>=nStart )
189cdf0e10cSrcweir 						bRowFound = sal_True;
190cdf0e10cSrcweir 				}
191cdf0e10cSrcweir 			}
192cdf0e10cSrcweir 		}
193cdf0e10cSrcweir 	}
194cdf0e10cSrcweir 
195cdf0e10cSrcweir 	rCol = bColFound;
196cdf0e10cSrcweir 	rRow = bRowFound;
197cdf0e10cSrcweir }
198cdf0e10cSrcweir 
199cdf0e10cSrcweir void ScDBFunc::RemoveAllOutlines( sal_Bool bRecord )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
202cdf0e10cSrcweir 	ScDocShell* pDocSh = GetViewData()->GetDocShell();
203cdf0e10cSrcweir 	ScOutlineDocFunc aFunc(*pDocSh);
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 	HideCursor();
206cdf0e10cSrcweir 	sal_Bool bOk = aFunc.RemoveAllOutlines( nTab, bRecord, sal_False );
207cdf0e10cSrcweir 	ShowCursor();
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 	if (bOk)
210cdf0e10cSrcweir 		UpdateScrollBars();
211cdf0e10cSrcweir }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir //	Auto-Outlines
214cdf0e10cSrcweir 
215cdf0e10cSrcweir void ScDBFunc::AutoOutline( sal_Bool bRecord )
216cdf0e10cSrcweir {
217cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
218cdf0e10cSrcweir 	ScRange aRange( 0,0,nTab, MAXCOL,MAXROW,nTab );		// ganze Tabelle, wenn nichts markiert
219cdf0e10cSrcweir 	ScMarkData& rMark = GetViewData()->GetMarkData();
220cdf0e10cSrcweir 	if ( rMark.IsMarked() || rMark.IsMultiMarked() )
221cdf0e10cSrcweir 	{
222cdf0e10cSrcweir 		rMark.MarkToMulti();
223cdf0e10cSrcweir 		rMark.GetMultiMarkArea( aRange );
224cdf0e10cSrcweir 	}
225cdf0e10cSrcweir 
226cdf0e10cSrcweir 	ScDocShell* pDocSh = GetViewData()->GetDocShell();
227cdf0e10cSrcweir 	ScOutlineDocFunc aFunc(*pDocSh);
228cdf0e10cSrcweir 	aFunc.AutoOutline( aRange, bRecord, sal_False );
229cdf0e10cSrcweir }
230cdf0e10cSrcweir 
231cdf0e10cSrcweir //	Outline-Ebene auswaehlen
232cdf0e10cSrcweir 
233cdf0e10cSrcweir void ScDBFunc::SelectLevel( sal_Bool bColumns, sal_uInt16 nLevel, sal_Bool bRecord, sal_Bool bPaint )
234cdf0e10cSrcweir {
235cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
236cdf0e10cSrcweir 	ScDocShell* pDocSh = GetViewData()->GetDocShell();
237cdf0e10cSrcweir 	ScOutlineDocFunc aFunc(*pDocSh);
238cdf0e10cSrcweir 
239cdf0e10cSrcweir 	HideCursor();
240cdf0e10cSrcweir 	sal_Bool bOk = aFunc.SelectLevel( nTab, bColumns, nLevel, bRecord, bPaint, sal_False );
241cdf0e10cSrcweir 	ShowCursor();
242cdf0e10cSrcweir 
243cdf0e10cSrcweir 	if (bOk)
244cdf0e10cSrcweir 		UpdateScrollBars();
245cdf0e10cSrcweir }
246cdf0e10cSrcweir 
247cdf0e10cSrcweir //	einzelne Outline-Gruppe einblenden
248cdf0e10cSrcweir 
249cdf0e10cSrcweir void ScDBFunc::ShowOutline( sal_Bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bRecord, sal_Bool bPaint )
250cdf0e10cSrcweir {
251cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
252cdf0e10cSrcweir 	ScDocShell* pDocSh = GetViewData()->GetDocShell();
253cdf0e10cSrcweir 	ScOutlineDocFunc aFunc(*pDocSh);
254cdf0e10cSrcweir 
255cdf0e10cSrcweir 	HideCursor();
256cdf0e10cSrcweir 	sal_Bool bOk = aFunc.ShowOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint, sal_False );
257cdf0e10cSrcweir 	ShowCursor();
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 	if ( bOk && bPaint )
260cdf0e10cSrcweir 		UpdateScrollBars();
261cdf0e10cSrcweir }
262cdf0e10cSrcweir 
263cdf0e10cSrcweir //	einzelne Outline-Gruppe ausblenden
264cdf0e10cSrcweir 
265cdf0e10cSrcweir void ScDBFunc::HideOutline( sal_Bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bRecord, sal_Bool bPaint )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
268cdf0e10cSrcweir 	ScDocShell* pDocSh = GetViewData()->GetDocShell();
269cdf0e10cSrcweir 	ScOutlineDocFunc aFunc(*pDocSh);
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 	HideCursor();
272cdf0e10cSrcweir 	sal_Bool bOk = aFunc.HideOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint, sal_False );
273cdf0e10cSrcweir 	ShowCursor();
274cdf0e10cSrcweir 
275cdf0e10cSrcweir 	if ( bOk && bPaint )
276cdf0e10cSrcweir 		UpdateScrollBars();
277cdf0e10cSrcweir }
278cdf0e10cSrcweir 
279cdf0e10cSrcweir //	Menue-Status: markierten Bereich ein-/ausblenden
280cdf0e10cSrcweir 
281cdf0e10cSrcweir sal_Bool ScDBFunc::OutlinePossible(sal_Bool bHide)
282cdf0e10cSrcweir {
283cdf0e10cSrcweir 	sal_Bool bEnable = sal_False;
284cdf0e10cSrcweir 
285cdf0e10cSrcweir 	SCCOL nStartCol;
286cdf0e10cSrcweir 	SCROW nStartRow;
287cdf0e10cSrcweir 	SCTAB nStartTab;
288cdf0e10cSrcweir 	SCCOL nEndCol;
289cdf0e10cSrcweir 	SCROW nEndRow;
290cdf0e10cSrcweir 	SCTAB nEndTab;
291cdf0e10cSrcweir 
292cdf0e10cSrcweir 	if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
293cdf0e10cSrcweir 	{
294cdf0e10cSrcweir 		ScDocument* pDoc = GetViewData()->GetDocument();
295cdf0e10cSrcweir 		SCTAB nTab = GetViewData()->GetTabNo();
296cdf0e10cSrcweir 		ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
297cdf0e10cSrcweir 		if (pTable)
298cdf0e10cSrcweir 		{
299cdf0e10cSrcweir 			ScOutlineArray* pArray;
300cdf0e10cSrcweir 			ScOutlineEntry* pEntry;
301cdf0e10cSrcweir 			SCCOLROW nStart;
302cdf0e10cSrcweir 			SCCOLROW nEnd;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 			//	Spalten
305cdf0e10cSrcweir 
306cdf0e10cSrcweir 			pArray = pTable->GetColArray();
307cdf0e10cSrcweir 			ScSubOutlineIterator aColIter( pArray );
308cdf0e10cSrcweir 			while ((pEntry=aColIter.GetNext()) != NULL && !bEnable)
309cdf0e10cSrcweir 			{
310cdf0e10cSrcweir 				nStart = pEntry->GetStart();
311cdf0e10cSrcweir 				nEnd   = pEntry->GetEnd();
312cdf0e10cSrcweir 				if ( bHide )
313cdf0e10cSrcweir 				{
314cdf0e10cSrcweir 					if ( nStartCol<=static_cast<SCCOL>(nEnd) && nEndCol>=static_cast<SCCOL>(nStart) )
315cdf0e10cSrcweir 						if (!pEntry->IsHidden())
316cdf0e10cSrcweir 							bEnable = sal_True;
317cdf0e10cSrcweir 				}
318cdf0e10cSrcweir 				else
319cdf0e10cSrcweir 				{
320cdf0e10cSrcweir 					if ( nStart>=nStartCol && nEnd<=nEndCol )
321cdf0e10cSrcweir 						if (pEntry->IsHidden())
322cdf0e10cSrcweir 							bEnable = sal_True;
323cdf0e10cSrcweir 				}
324cdf0e10cSrcweir 			}
325cdf0e10cSrcweir 
326cdf0e10cSrcweir 			//	Zeilen
327cdf0e10cSrcweir 
328cdf0e10cSrcweir 			pArray = pTable->GetRowArray();
329cdf0e10cSrcweir 			ScSubOutlineIterator aRowIter( pArray );
330cdf0e10cSrcweir 			while ((pEntry=aRowIter.GetNext()) != NULL)
331cdf0e10cSrcweir 			{
332cdf0e10cSrcweir 				nStart = pEntry->GetStart();
333cdf0e10cSrcweir 				nEnd   = pEntry->GetEnd();
334cdf0e10cSrcweir 				if ( bHide )
335cdf0e10cSrcweir 				{
336cdf0e10cSrcweir 					if ( nStartRow<=nEnd && nEndRow>=nStart )
337cdf0e10cSrcweir 						if (!pEntry->IsHidden())
338cdf0e10cSrcweir 							bEnable = sal_True;
339cdf0e10cSrcweir 				}
340cdf0e10cSrcweir 				else
341cdf0e10cSrcweir 				{
342cdf0e10cSrcweir 					if ( nStart>=nStartRow && nEnd<=nEndRow )
343cdf0e10cSrcweir 						if (pEntry->IsHidden())
344cdf0e10cSrcweir 							bEnable = sal_True;
345cdf0e10cSrcweir 				}
346cdf0e10cSrcweir 			}
347cdf0e10cSrcweir 		}
348cdf0e10cSrcweir 	}
349cdf0e10cSrcweir 
350cdf0e10cSrcweir 	return bEnable;
351cdf0e10cSrcweir }
352cdf0e10cSrcweir 
353cdf0e10cSrcweir //	markierten Bereich einblenden
354cdf0e10cSrcweir 
355cdf0e10cSrcweir void ScDBFunc::ShowMarkedOutlines( sal_Bool bRecord )
356cdf0e10cSrcweir {
357cdf0e10cSrcweir 	ScRange aRange;
358cdf0e10cSrcweir 	if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
359cdf0e10cSrcweir 	{
360cdf0e10cSrcweir 		ScDocShell* pDocSh = GetViewData()->GetDocShell();
361cdf0e10cSrcweir 		ScOutlineDocFunc aFunc(*pDocSh);
362cdf0e10cSrcweir 		HideCursor();
363cdf0e10cSrcweir 		sal_Bool bDone = aFunc.ShowMarkedOutlines( aRange, bRecord, sal_False );
364cdf0e10cSrcweir 		ShowCursor();
365cdf0e10cSrcweir 		if (bDone)
366cdf0e10cSrcweir 			UpdateScrollBars();
367cdf0e10cSrcweir 	}
368cdf0e10cSrcweir 	else
369cdf0e10cSrcweir 		ErrorMessage(STR_NOMULTISELECT);
370cdf0e10cSrcweir }
371cdf0e10cSrcweir 
372cdf0e10cSrcweir //	markierten Bereich ausblenden
373cdf0e10cSrcweir 
374cdf0e10cSrcweir void ScDBFunc::HideMarkedOutlines( sal_Bool bRecord )
375cdf0e10cSrcweir {
376cdf0e10cSrcweir 	ScRange aRange;
377cdf0e10cSrcweir 	if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
378cdf0e10cSrcweir 	{
379cdf0e10cSrcweir 		ScDocShell* pDocSh = GetViewData()->GetDocShell();
380cdf0e10cSrcweir 		ScOutlineDocFunc aFunc(*pDocSh);
381cdf0e10cSrcweir 		HideCursor();
382cdf0e10cSrcweir 		sal_Bool bDone = aFunc.HideMarkedOutlines( aRange, bRecord, sal_False );
383cdf0e10cSrcweir 		ShowCursor();
384cdf0e10cSrcweir 		if (bDone)
385cdf0e10cSrcweir 			UpdateScrollBars();
386cdf0e10cSrcweir 	}
387cdf0e10cSrcweir 	else
388cdf0e10cSrcweir 		ErrorMessage(STR_NOMULTISELECT);
389cdf0e10cSrcweir }
390cdf0e10cSrcweir 
391cdf0e10cSrcweir //	--------------------------------------------------------------------------
392cdf0e10cSrcweir 
393cdf0e10cSrcweir //
394cdf0e10cSrcweir //			Teilergebnisse
395cdf0e10cSrcweir //
396cdf0e10cSrcweir 
397cdf0e10cSrcweir void ScDBFunc::DoSubTotals( const ScSubTotalParam& rParam, sal_Bool bRecord,
398cdf0e10cSrcweir 							const ScSortParam* pForceNewSort )
399cdf0e10cSrcweir {
400cdf0e10cSrcweir 	sal_Bool bDo = !rParam.bRemoveOnly;							// sal_False = nur loeschen
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 	ScDocShell* pDocSh = GetViewData()->GetDocShell();
403cdf0e10cSrcweir 	ScDocument* pDoc = pDocSh->GetDocument();
404cdf0e10cSrcweir 	ScMarkData& rMark = GetViewData()->GetMarkData();
405cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
406cdf0e10cSrcweir 	if (bRecord && !pDoc->IsUndoEnabled())
407cdf0e10cSrcweir 		bRecord = sal_False;
408cdf0e10cSrcweir 
409cdf0e10cSrcweir 	ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
410cdf0e10cSrcweir 												rParam.nCol2, rParam.nRow2 );
411cdf0e10cSrcweir 	if (!pDBData)
412cdf0e10cSrcweir 	{
413cdf0e10cSrcweir 		DBG_ERROR( "SubTotals: keine DBData" );
414cdf0e10cSrcweir 		return;
415cdf0e10cSrcweir 	}
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 	ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW );
418cdf0e10cSrcweir 	if (!aTester.IsEditable())
419cdf0e10cSrcweir 	{
420cdf0e10cSrcweir 		ErrorMessage(aTester.GetMessageId());
421cdf0e10cSrcweir 		return;
422cdf0e10cSrcweir 	}
423cdf0e10cSrcweir 
424cdf0e10cSrcweir 	if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
425cdf0e10cSrcweir 						 rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
426cdf0e10cSrcweir 	{
427cdf0e10cSrcweir 		ErrorMessage(STR_MSSG_INSERTCELLS_0);	// nicht in zusammengefasste einfuegen
428cdf0e10cSrcweir 		return;
429cdf0e10cSrcweir 	}
430cdf0e10cSrcweir 
431cdf0e10cSrcweir 	WaitObject aWait( GetViewData()->GetDialogParent() );
432cdf0e10cSrcweir 	sal_Bool bOk = sal_True;
433cdf0e10cSrcweir 	sal_Bool bDelete = sal_False;
434cdf0e10cSrcweir 	if (rParam.bReplace)
435cdf0e10cSrcweir 		if (pDoc->TestRemoveSubTotals( nTab, rParam ))
436cdf0e10cSrcweir 		{
437cdf0e10cSrcweir 			bDelete = sal_True;
438cdf0e10cSrcweir 			bOk = ( MessBox( GetViewData()->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
439cdf0e10cSrcweir 				// "StarCalc" "Daten loeschen?"
440cdf0e10cSrcweir 				ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
441cdf0e10cSrcweir 				ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute()
442cdf0e10cSrcweir 				== RET_YES );
443cdf0e10cSrcweir 		}
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 	if (bOk)
446cdf0e10cSrcweir 	{
447cdf0e10cSrcweir 		ScDocShellModificator aModificator( *pDocSh );
448cdf0e10cSrcweir 
449cdf0e10cSrcweir 		ScSubTotalParam aNewParam( rParam );		// Bereichsende wird veraendert
450cdf0e10cSrcweir 		ScDocument*		pUndoDoc = NULL;
451cdf0e10cSrcweir 		ScOutlineTable*	pUndoTab = NULL;
452cdf0e10cSrcweir 		ScRangeName*	pUndoRange = NULL;
453cdf0e10cSrcweir 		ScDBCollection* pUndoDB = NULL;
454cdf0e10cSrcweir 		SCTAB 			nTabCount = 0;				// fuer Referenz-Undo
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 		if (bRecord)										// alte Daten sichern
457cdf0e10cSrcweir 		{
458cdf0e10cSrcweir 			sal_Bool bOldFilter = bDo && rParam.bDoSort;
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 			nTabCount = pDoc->GetTableCount();
461cdf0e10cSrcweir 			pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
462cdf0e10cSrcweir 			ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
463cdf0e10cSrcweir 			if (pTable)
464cdf0e10cSrcweir 			{
465cdf0e10cSrcweir 				pUndoTab = new ScOutlineTable( *pTable );
466cdf0e10cSrcweir 
467cdf0e10cSrcweir 				SCCOLROW nOutStartCol;							// Zeilen/Spaltenstatus
468cdf0e10cSrcweir 				SCCOLROW nOutStartRow;
469cdf0e10cSrcweir 				SCCOLROW nOutEndCol;
470cdf0e10cSrcweir 				SCCOLROW nOutEndRow;
471cdf0e10cSrcweir 				pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
472cdf0e10cSrcweir 				pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
473cdf0e10cSrcweir 
474cdf0e10cSrcweir 				pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
475cdf0e10cSrcweir 				pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc );
476cdf0e10cSrcweir 				pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc );
477cdf0e10cSrcweir 			}
478cdf0e10cSrcweir 			else
479cdf0e10cSrcweir 				pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, bOldFilter );
480cdf0e10cSrcweir 
481cdf0e10cSrcweir 			//	Datenbereich sichern - incl. Filter-Ergebnis
482cdf0e10cSrcweir 			pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab,
483cdf0e10cSrcweir 									IDF_ALL, sal_False, pUndoDoc );
484cdf0e10cSrcweir 
485cdf0e10cSrcweir 			//	alle Formeln wegen Referenzen
486cdf0e10cSrcweir 			pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
487cdf0e10cSrcweir 										IDF_FORMULA, sal_False, pUndoDoc );
488cdf0e10cSrcweir 
489cdf0e10cSrcweir 			//	DB- und andere Bereiche
490cdf0e10cSrcweir 			ScRangeName* pDocRange = pDoc->GetRangeName();
491cdf0e10cSrcweir 			if (pDocRange->GetCount())
492cdf0e10cSrcweir 				pUndoRange = new ScRangeName( *pDocRange );
493cdf0e10cSrcweir 			ScDBCollection* pDocDB = pDoc->GetDBCollection();
494cdf0e10cSrcweir 			if (pDocDB->GetCount())
495cdf0e10cSrcweir 				pUndoDB = new ScDBCollection( *pDocDB );
496cdf0e10cSrcweir 		}
497cdf0e10cSrcweir 
498cdf0e10cSrcweir //		pDoc->SetOutlineTable( nTab, NULL );
499cdf0e10cSrcweir 		ScOutlineTable*	pOut = pDoc->GetOutlineTable( nTab );
500cdf0e10cSrcweir 		if (pOut)
501cdf0e10cSrcweir 			pOut->GetRowArray()->RemoveAll();		// nur Zeilen-Outlines loeschen
502cdf0e10cSrcweir 
503cdf0e10cSrcweir 		if (rParam.bReplace)
504cdf0e10cSrcweir 			pDoc->RemoveSubTotals( nTab, aNewParam );
505cdf0e10cSrcweir 		sal_Bool bSuccess = sal_True;
506cdf0e10cSrcweir 		if (bDo)
507cdf0e10cSrcweir 		{
508cdf0e10cSrcweir 			// Sortieren
509cdf0e10cSrcweir 			if ( rParam.bDoSort || pForceNewSort )
510cdf0e10cSrcweir 			{
511cdf0e10cSrcweir 				pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
512cdf0e10cSrcweir 
513cdf0e10cSrcweir 				//	Teilergebnis-Felder vor die Sortierung setzen
514cdf0e10cSrcweir 				//	(doppelte werden weggelassen, kann darum auch wieder aufgerufen werden)
515cdf0e10cSrcweir 
516cdf0e10cSrcweir 				ScSortParam aOldSort;
517cdf0e10cSrcweir 				pDBData->GetSortParam( aOldSort );
518cdf0e10cSrcweir 				ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort );
519cdf0e10cSrcweir 				Sort( aSortParam, sal_False, sal_False );
520cdf0e10cSrcweir 			}
521cdf0e10cSrcweir 
522cdf0e10cSrcweir 			bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
523cdf0e10cSrcweir 		}
524cdf0e10cSrcweir 		ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
525cdf0e10cSrcweir 			aNewParam.nCol2, aNewParam.nRow2, nTab );
526cdf0e10cSrcweir 		pDoc->SetDirty( aDirtyRange );
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 		if (bRecord)
529cdf0e10cSrcweir 		{
530cdf0e10cSrcweir //			ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
531cdf0e10cSrcweir 			pDocSh->GetUndoManager()->AddUndoAction(
532cdf0e10cSrcweir 				new ScUndoSubTotals( pDocSh, nTab,
533cdf0e10cSrcweir 										rParam, aNewParam.nRow2,
534cdf0e10cSrcweir 										pUndoDoc, pUndoTab, // pUndoDBData,
535cdf0e10cSrcweir 										pUndoRange, pUndoDB ) );
536cdf0e10cSrcweir 		}
537cdf0e10cSrcweir 
538cdf0e10cSrcweir 		if (!bSuccess)
539cdf0e10cSrcweir 		{
540cdf0e10cSrcweir 			// "Kann keine Zeilen einfuegen"
541cdf0e10cSrcweir 			ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
542cdf0e10cSrcweir 		}
543cdf0e10cSrcweir 
544cdf0e10cSrcweir 													// merken
545cdf0e10cSrcweir 		pDBData->SetSubTotalParam( aNewParam );
546cdf0e10cSrcweir 		pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
547cdf0e10cSrcweir 		pDoc->CompileDBFormula();
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 		DoneBlockMode();
550cdf0e10cSrcweir 		InitOwnBlockMode();
551cdf0e10cSrcweir 		rMark.SetMarkArea( ScRange( aNewParam.nCol1,aNewParam.nRow1,nTab,
552cdf0e10cSrcweir 									aNewParam.nCol2,aNewParam.nRow2,nTab ) );
553cdf0e10cSrcweir         MarkDataChanged();
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 		pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
556cdf0e10cSrcweir 												PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
557cdf0e10cSrcweir 
558cdf0e10cSrcweir 		aModificator.SetDocumentModified();
559cdf0e10cSrcweir 
560cdf0e10cSrcweir 		SelectionChanged();
561cdf0e10cSrcweir 	}
562cdf0e10cSrcweir }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir //
565cdf0e10cSrcweir //			Consolidate
566cdf0e10cSrcweir //
567cdf0e10cSrcweir 
568cdf0e10cSrcweir void ScDBFunc::Consolidate( const ScConsolidateParam& rParam, sal_Bool bRecord )
569cdf0e10cSrcweir {
570cdf0e10cSrcweir 	ScDocShell* pDocShell = GetViewData()->GetDocShell();
571cdf0e10cSrcweir 	pDocShell->DoConsolidate( rParam, bRecord );
572cdf0e10cSrcweir 	SetTabNo( rParam.nTab, sal_True );
573cdf0e10cSrcweir }
574cdf0e10cSrcweir 
575cdf0e10cSrcweir //
576cdf0e10cSrcweir //			Pivot
577cdf0e10cSrcweir //
578cdf0e10cSrcweir 
579cdf0e10cSrcweir String lcl_MakePivotTabName( const String& rPrefix, SCTAB nNumber )
580cdf0e10cSrcweir {
581cdf0e10cSrcweir 	String aName = rPrefix;
582cdf0e10cSrcweir 	aName += String::CreateFromInt32( nNumber );
583cdf0e10cSrcweir 	return aName;
584cdf0e10cSrcweir }
585cdf0e10cSrcweir 
586cdf0e10cSrcweir bool ScDBFunc::MakePivotTable( const ScDPSaveData& rData, const ScRange& rDest, sal_Bool bNewTable,
587cdf0e10cSrcweir 								const ScDPObject& rSource, sal_Bool bApi )
588cdf0e10cSrcweir {
589cdf0e10cSrcweir 	//	#70096# error message if no fields are set
590cdf0e10cSrcweir 	//	this must be removed when drag&drop of fields from a toolbox is available
591cdf0e10cSrcweir 
592cdf0e10cSrcweir 	if ( rData.IsEmpty() && !bApi )
593cdf0e10cSrcweir 	{
594cdf0e10cSrcweir 		ErrorMessage(STR_PIVOT_NODATA);
595cdf0e10cSrcweir 		return false;
596cdf0e10cSrcweir 	}
597cdf0e10cSrcweir 
598cdf0e10cSrcweir 	ScDocShell* pDocSh	= GetViewData()->GetDocShell();
599cdf0e10cSrcweir 	ScDocument* pDoc 	= GetViewData()->GetDocument();
600cdf0e10cSrcweir 	sal_Bool bUndo(pDoc->IsUndoEnabled());
601cdf0e10cSrcweir 
602cdf0e10cSrcweir 	ScRange aDestRange = rDest;
603cdf0e10cSrcweir 	if ( bNewTable )
604cdf0e10cSrcweir 	{
605cdf0e10cSrcweir 		SCTAB nSrcTab = GetViewData()->GetTabNo();
606cdf0e10cSrcweir 
607cdf0e10cSrcweir 		String aName( ScGlobal::GetRscString(STR_PIVOT_TABLE) );
608cdf0e10cSrcweir 		String aStr;
609cdf0e10cSrcweir 
610cdf0e10cSrcweir 		pDoc->GetName( nSrcTab, aStr );
611cdf0e10cSrcweir 		aName += '_';
612cdf0e10cSrcweir 		aName += aStr;
613cdf0e10cSrcweir 		aName += '_';
614cdf0e10cSrcweir 
615cdf0e10cSrcweir 		SCTAB nNewTab = nSrcTab+1;
616cdf0e10cSrcweir 
617cdf0e10cSrcweir 		SCTAB i=1;
618cdf0e10cSrcweir 		while ( !pDoc->InsertTab( nNewTab, lcl_MakePivotTabName( aName, i ) ) && i <= MAXTAB )
619cdf0e10cSrcweir 			i++;
620cdf0e10cSrcweir 
621cdf0e10cSrcweir 		sal_Bool bAppend = ( nNewTab+1 == pDoc->GetTableCount() );
622cdf0e10cSrcweir 		if (bUndo)
623cdf0e10cSrcweir 		{
624cdf0e10cSrcweir 			pDocSh->GetUndoManager()->AddUndoAction(
625cdf0e10cSrcweir 						new ScUndoInsertTab( pDocSh, nNewTab, bAppend, lcl_MakePivotTabName( aName, i ) ));
626cdf0e10cSrcweir 		}
627cdf0e10cSrcweir 
628cdf0e10cSrcweir 		GetViewData()->InsertTab( nNewTab );
629cdf0e10cSrcweir 		SetTabNo( nNewTab, sal_True );
630cdf0e10cSrcweir 
631cdf0e10cSrcweir 		aDestRange = ScRange( 0, 0, nNewTab );
632cdf0e10cSrcweir 	}
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 	ScDPObject* pDPObj = pDoc->GetDPAtCursor(
635cdf0e10cSrcweir 							aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aStart.Tab() );
636cdf0e10cSrcweir 
637cdf0e10cSrcweir 	ScDPObject aObj( rSource );
638cdf0e10cSrcweir 	aObj.SetOutRange( aDestRange );
639cdf0e10cSrcweir     if ( pDPObj && !rData.GetExistingDimensionData() )
640cdf0e10cSrcweir     {
641cdf0e10cSrcweir         // copy dimension data from old object - lost in the dialog
642cdf0e10cSrcweir         //! change the dialog to keep the dimension data
643cdf0e10cSrcweir 
644cdf0e10cSrcweir         ScDPSaveData aNewData( rData );
645cdf0e10cSrcweir         const ScDPSaveData* pOldData = pDPObj->GetSaveData();
646cdf0e10cSrcweir         if ( pOldData )
647cdf0e10cSrcweir         {
648cdf0e10cSrcweir             const ScDPDimensionSaveData* pDimSave = pOldData->GetExistingDimensionData();
649cdf0e10cSrcweir             aNewData.SetDimensionData( pDimSave );
650cdf0e10cSrcweir         }
651cdf0e10cSrcweir         aObj.SetSaveData( aNewData );
652cdf0e10cSrcweir     }
653cdf0e10cSrcweir     else
654cdf0e10cSrcweir         aObj.SetSaveData( rData );
655cdf0e10cSrcweir 
656cdf0e10cSrcweir 	sal_Bool bAllowMove = ( pDPObj != NULL );	// allow re-positioning when editing existing table
657cdf0e10cSrcweir 
658cdf0e10cSrcweir 	ScDBDocFunc aFunc( *pDocSh );
659cdf0e10cSrcweir 	bool bSuccess = aFunc.DataPilotUpdate( pDPObj, &aObj, sal_True, sal_False, bAllowMove );
660cdf0e10cSrcweir 
661cdf0e10cSrcweir 	CursorPosChanged();		// shells may be switched
662cdf0e10cSrcweir 
663cdf0e10cSrcweir 	if ( bNewTable )
664cdf0e10cSrcweir 	{
665cdf0e10cSrcweir 		pDocSh->PostPaintExtras();
666cdf0e10cSrcweir 		SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
667cdf0e10cSrcweir 	}
668cdf0e10cSrcweir 
669cdf0e10cSrcweir 	return bSuccess;
670cdf0e10cSrcweir }
671cdf0e10cSrcweir 
672cdf0e10cSrcweir void ScDBFunc::DeletePivotTable()
673cdf0e10cSrcweir {
674cdf0e10cSrcweir 	ScDocShell* pDocSh	  = GetViewData()->GetDocShell();
675cdf0e10cSrcweir 	ScDocument* pDoc	  = pDocSh->GetDocument();
676cdf0e10cSrcweir 	ScDPObject*	pDPObj    = pDoc->GetDPAtCursor( GetViewData()->GetCurX(),
677cdf0e10cSrcweir 												  GetViewData()->GetCurY(),
678cdf0e10cSrcweir 												  GetViewData()->GetTabNo() );
679cdf0e10cSrcweir 	if ( pDPObj )
680cdf0e10cSrcweir 	{
681cdf0e10cSrcweir 		ScDBDocFunc aFunc( *pDocSh );
682cdf0e10cSrcweir 		aFunc.DataPilotUpdate( pDPObj, NULL, sal_True, sal_False );
683cdf0e10cSrcweir 		CursorPosChanged();		// shells may be switched
684cdf0e10cSrcweir 	}
685cdf0e10cSrcweir 	else
686cdf0e10cSrcweir 		ErrorMessage(STR_PIVOT_NOTFOUND);
687cdf0e10cSrcweir }
688cdf0e10cSrcweir sal_uLong RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, sal_Bool bRecord, sal_Bool bApi )
689cdf0e10cSrcweir {
690cdf0e10cSrcweir 	if( !pDPObj )
691cdf0e10cSrcweir 		return STR_PIVOT_NOTFOUND;
692cdf0e10cSrcweir 
693cdf0e10cSrcweir     if ( pDocSh && !pDoc )
694cdf0e10cSrcweir         pDoc = pDocSh->GetDocument();
695cdf0e10cSrcweir 
696cdf0e10cSrcweir 	if( !pDoc  )
697cdf0e10cSrcweir         return static_cast<sal_uLong>(-1);
698cdf0e10cSrcweir 
699cdf0e10cSrcweir 	if( !pDocSh && ( pDocSh = PTR_CAST( ScDocShell, pDoc->GetDocumentShell() ) ) == NULL )
700cdf0e10cSrcweir         return static_cast<sal_uLong>(-1);
701cdf0e10cSrcweir 
702cdf0e10cSrcweir 	if( sal_uLong nErrId = pDPObj->RefreshCache() )
703cdf0e10cSrcweir 		return nErrId;
704cdf0e10cSrcweir 	else if ( nErrId == 0 )
705cdf0e10cSrcweir 	{
706cdf0e10cSrcweir 		//Refresh all dpobjects
707cdf0e10cSrcweir 		ScDPCollection* pDPCollection = pDoc->GetDPCollection();
708cdf0e10cSrcweir 		sal_uInt16 nCount = pDPCollection->GetCount();
709cdf0e10cSrcweir 		for (sal_uInt16 i=0; i<nCount; i++)
710cdf0e10cSrcweir 		{
711cdf0e10cSrcweir 			if ( (*pDPCollection)[i]->GetCacheId() == pDPObj->GetCacheId()  )
712cdf0e10cSrcweir 			{
713cdf0e10cSrcweir 				ScDBDocFunc aFunc( * pDocSh );
714cdf0e10cSrcweir 				if ( !aFunc.DataPilotUpdate( (*pDPCollection)[i], (*pDPCollection)[i], bRecord, bApi ) )
715cdf0e10cSrcweir 					break;
716cdf0e10cSrcweir 			}
717cdf0e10cSrcweir 		}
718cdf0e10cSrcweir 
719cdf0e10cSrcweir 		return nErrId;
720cdf0e10cSrcweir 	}
721cdf0e10cSrcweir 
722cdf0e10cSrcweir 	return 0U;
723cdf0e10cSrcweir }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir sal_uLong  ScDBFunc::RecalcPivotTable()
726cdf0e10cSrcweir {
727cdf0e10cSrcweir 	ScDocShell* pDocSh  = GetViewData()->GetDocShell();
728cdf0e10cSrcweir 	ScDocument* pDoc	= GetViewData()->GetDocument();
729cdf0e10cSrcweir 
730cdf0e10cSrcweir 	//	old pivot not used any more
731cdf0e10cSrcweir 
732cdf0e10cSrcweir 	ScDPObject*	pDPObj	= pDoc->GetDPAtCursor( GetViewData()->GetCurX(),
733cdf0e10cSrcweir 												  GetViewData()->GetCurY(),
734cdf0e10cSrcweir 												  GetViewData()->GetTabNo() );
735cdf0e10cSrcweir 	if ( pDPObj )
736cdf0e10cSrcweir 	{
737cdf0e10cSrcweir         // Wang Xu Ming -- 2009-6-17
738cdf0e10cSrcweir         // DataPilot Migration
739cdf0e10cSrcweir         //ScDBDocFunc aFunc( *pDocSh );
740cdf0e10cSrcweir         //aFunc.DataPilotUpdate( pDPObj, pDPObj, sal_True, sal_False );
741cdf0e10cSrcweir         //CursorPosChanged();      // shells may be switched
742cdf0e10cSrcweir         sal_uLong nErrId = RefreshDPObject( pDPObj, pDoc, pDocSh, sal_True, sal_False );//pDPObj->RefreshCache();
743cdf0e10cSrcweir         if ( nErrId == 0 )
744cdf0e10cSrcweir         {
745cdf0e10cSrcweir             // There is no undo for the refresh of the cache table, but the undo history for cell changes
746cdf0e10cSrcweir             // remains valid and should be preserved, so the history isn't cleared here.
747cdf0e10cSrcweir             //GetViewData()->GetDocShell()->GetUndoManager()->Clear();
748cdf0e10cSrcweir         }
749cdf0e10cSrcweir         else if (nErrId <= USHRT_MAX)
750cdf0e10cSrcweir             ErrorMessage(static_cast<sal_uInt16>(nErrId));
751cdf0e10cSrcweir       return nErrId;
752cdf0e10cSrcweir       // End Comments
753cdf0e10cSrcweir 	}
754cdf0e10cSrcweir 	else
755cdf0e10cSrcweir 		ErrorMessage(STR_PIVOT_NOTFOUND);
756cdf0e10cSrcweir     return STR_PIVOT_NOTFOUND;
757cdf0e10cSrcweir }
758cdf0e10cSrcweir 
759cdf0e10cSrcweir void ScDBFunc::GetSelectedMemberList( ScStrCollection& rEntries, long& rDimension )
760cdf0e10cSrcweir {
761cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
762cdf0e10cSrcweir             							GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
763cdf0e10cSrcweir     if ( !pDPObj )
764cdf0e10cSrcweir         return;
765cdf0e10cSrcweir 
766cdf0e10cSrcweir     long nStartDimension = -1;
767cdf0e10cSrcweir     long nStartHierarchy = -1;
768cdf0e10cSrcweir     long nStartLevel     = -1;
769cdf0e10cSrcweir 
770cdf0e10cSrcweir     ScRangeListRef xRanges;
771cdf0e10cSrcweir     GetViewData()->GetMultiArea( xRanges );         // incl. cursor if nothing is selected
772cdf0e10cSrcweir     sal_uLong nRangeCount = xRanges->Count();
773cdf0e10cSrcweir     sal_Bool bContinue = sal_True;
774cdf0e10cSrcweir 
775cdf0e10cSrcweir     for (sal_uLong nRangePos=0; nRangePos<nRangeCount && bContinue; nRangePos++)
776cdf0e10cSrcweir     {
777cdf0e10cSrcweir         ScRange aRange = *xRanges->GetObject(nRangePos);
778cdf0e10cSrcweir         SCCOL nStartCol = aRange.aStart.Col();
779cdf0e10cSrcweir         SCROW nStartRow = aRange.aStart.Row();
780cdf0e10cSrcweir         SCCOL nEndCol = aRange.aEnd.Col();
781cdf0e10cSrcweir         SCROW nEndRow = aRange.aEnd.Row();
782cdf0e10cSrcweir         SCTAB nTab = aRange.aStart.Tab();
783cdf0e10cSrcweir 
784cdf0e10cSrcweir         for (SCROW nRow=nStartRow; nRow<=nEndRow && bContinue; nRow++)
785cdf0e10cSrcweir             for (SCCOL nCol=nStartCol; nCol<=nEndCol && bContinue; nCol++)
786cdf0e10cSrcweir             {
787cdf0e10cSrcweir                 sheet::DataPilotTableHeaderData aData;
788cdf0e10cSrcweir                 pDPObj->GetHeaderPositionData(ScAddress(nCol, nRow, nTab), aData);
789cdf0e10cSrcweir                 if ( aData.Dimension < 0 )
790cdf0e10cSrcweir                     bContinue = sal_False;              // not part of any dimension
791cdf0e10cSrcweir                 else
792cdf0e10cSrcweir                 {
793cdf0e10cSrcweir                     if ( nStartDimension < 0 )      // first member?
794cdf0e10cSrcweir                     {
795cdf0e10cSrcweir                         nStartDimension = aData.Dimension;
796cdf0e10cSrcweir                         nStartHierarchy = aData.Hierarchy;
797cdf0e10cSrcweir                         nStartLevel     = aData.Level;
798cdf0e10cSrcweir                     }
799cdf0e10cSrcweir                     if ( aData.Dimension != nStartDimension ||
800cdf0e10cSrcweir                          aData.Hierarchy != nStartHierarchy ||
801cdf0e10cSrcweir                          aData.Level     != nStartLevel )
802cdf0e10cSrcweir                     {
803cdf0e10cSrcweir                         bContinue = sal_False;          // cannot mix dimensions
804cdf0e10cSrcweir                     }
805cdf0e10cSrcweir                 }
806cdf0e10cSrcweir                 if ( bContinue )
807cdf0e10cSrcweir                 {
808cdf0e10cSrcweir                     // accept any part of a member description, also subtotals,
809cdf0e10cSrcweir                     // but don't stop if empty parts are contained
810cdf0e10cSrcweir                     if ( aData.Flags & sheet::MemberResultFlags::HASMEMBER )
811cdf0e10cSrcweir                     {
812cdf0e10cSrcweir                         StrData* pNew = new StrData( aData.MemberName );
813cdf0e10cSrcweir                         if ( !rEntries.Insert( pNew ) )
814cdf0e10cSrcweir                             delete pNew;
815cdf0e10cSrcweir                     }
816cdf0e10cSrcweir                 }
817cdf0e10cSrcweir             }
818cdf0e10cSrcweir     }
819cdf0e10cSrcweir 
820cdf0e10cSrcweir     rDimension = nStartDimension;   // dimension from which the found members came
821cdf0e10cSrcweir     if (!bContinue)
822cdf0e10cSrcweir         rEntries.FreeAll();         // remove all if not valid
823cdf0e10cSrcweir }
824cdf0e10cSrcweir 
825cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForDateGroup( ScDPNumGroupInfo& rOldInfo, sal_Int32& rParts )
826cdf0e10cSrcweir {
827cdf0e10cSrcweir     // determine if the date group dialog has to be shown for the current selection
828cdf0e10cSrcweir 
829cdf0e10cSrcweir     sal_Bool bFound = sal_False;
830cdf0e10cSrcweir 
831cdf0e10cSrcweir     SCCOL nCurX = GetViewData()->GetCurX();
832cdf0e10cSrcweir     SCROW nCurY = GetViewData()->GetCurY();
833cdf0e10cSrcweir     SCTAB nTab = GetViewData()->GetTabNo();
834cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
835cdf0e10cSrcweir 
836cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab );
837cdf0e10cSrcweir     if ( pDPObj )
838cdf0e10cSrcweir     {
839cdf0e10cSrcweir         ScStrCollection aEntries;
840cdf0e10cSrcweir         long nSelectDimension = -1;
841cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
842cdf0e10cSrcweir 
843cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
844cdf0e10cSrcweir         {
845cdf0e10cSrcweir             sal_Bool bIsDataLayout;
846cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
847cdf0e10cSrcweir             String aBaseDimName( aDimName );
848cdf0e10cSrcweir 
849cdf0e10cSrcweir             sal_Bool bInGroupDim = sal_False;
850cdf0e10cSrcweir             sal_Bool bFoundParts = sal_False;
851cdf0e10cSrcweir 
852cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData =
853cdf0e10cSrcweir                 const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() );
854cdf0e10cSrcweir             if ( pDimData )
855cdf0e10cSrcweir             {
856cdf0e10cSrcweir                 const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName );
857cdf0e10cSrcweir                 const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( aDimName );
858cdf0e10cSrcweir                 if ( pNumGroupDim )
859cdf0e10cSrcweir                 {
860cdf0e10cSrcweir                     //  existing num group dimension
861cdf0e10cSrcweir 
862cdf0e10cSrcweir                     if ( pNumGroupDim->GetDatePart() != 0 )
863cdf0e10cSrcweir                     {
864cdf0e10cSrcweir                         //  dimension has date info -> edit settings of this dimension
865cdf0e10cSrcweir                         //  (parts are collected below)
866cdf0e10cSrcweir 
867cdf0e10cSrcweir                         rOldInfo = pNumGroupDim->GetDateInfo();
868cdf0e10cSrcweir                         bFound = sal_True;
869cdf0e10cSrcweir                     }
870cdf0e10cSrcweir                     else if ( pNumGroupDim->GetInfo().DateValues )
871cdf0e10cSrcweir                     {
872cdf0e10cSrcweir                         //  Numerical grouping with DateValues flag is used for grouping
873cdf0e10cSrcweir                         //  of days with a "Number of days" value.
874cdf0e10cSrcweir 
875cdf0e10cSrcweir                         rOldInfo = pNumGroupDim->GetInfo();
876cdf0e10cSrcweir                         rParts = com::sun::star::sheet::DataPilotFieldGroupBy::DAYS;               // not found in CollectDateParts
877cdf0e10cSrcweir                         bFoundParts = sal_True;
878cdf0e10cSrcweir                         bFound = sal_True;
879cdf0e10cSrcweir                     }
880cdf0e10cSrcweir                     bInGroupDim = sal_True;
881cdf0e10cSrcweir                 }
882cdf0e10cSrcweir                 else if ( pGroupDim )
883cdf0e10cSrcweir                 {
884cdf0e10cSrcweir                     //  existing additional group dimension
885cdf0e10cSrcweir 
886cdf0e10cSrcweir                     if ( pGroupDim->GetDatePart() != 0 )
887cdf0e10cSrcweir                     {
888cdf0e10cSrcweir                         //  dimension has date info -> edit settings of this dimension
889cdf0e10cSrcweir                         //  (parts are collected below)
890cdf0e10cSrcweir 
891cdf0e10cSrcweir                         rOldInfo = pGroupDim->GetDateInfo();
892cdf0e10cSrcweir                         aBaseDimName = pGroupDim->GetSourceDimName();
893cdf0e10cSrcweir                         bFound = sal_True;
894cdf0e10cSrcweir                     }
895cdf0e10cSrcweir                     bInGroupDim = sal_True;
896cdf0e10cSrcweir                 }
897cdf0e10cSrcweir             }
898cdf0e10cSrcweir             if ( bFound && !bFoundParts )
899cdf0e10cSrcweir             {
900cdf0e10cSrcweir                 // collect date parts from all group dimensions
901cdf0e10cSrcweir                 rParts = pDimData->CollectDateParts( aBaseDimName );
902cdf0e10cSrcweir             }
903cdf0e10cSrcweir             if ( !bFound && !bInGroupDim )
904cdf0e10cSrcweir             {
905cdf0e10cSrcweir                 // create new date group dimensions if the selection is a single cell
906cdf0e10cSrcweir                 // in a normal dimension with date content
907cdf0e10cSrcweir 
908cdf0e10cSrcweir                 ScRange aSelRange;
909cdf0e10cSrcweir                 if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) &&
910cdf0e10cSrcweir                         aSelRange.aStart == aSelRange.aEnd )
911cdf0e10cSrcweir                 {
912cdf0e10cSrcweir                     SCCOL nSelCol = aSelRange.aStart.Col();
913cdf0e10cSrcweir                     SCROW nSelRow = aSelRange.aStart.Row();
914cdf0e10cSrcweir                     SCTAB nSelTab = aSelRange.aStart.Tab();
915cdf0e10cSrcweir                     if ( pDoc->HasValueData( nSelCol, nSelRow, nSelTab ) )
916cdf0e10cSrcweir                     {
917cdf0e10cSrcweir                         sal_uLong nIndex = static_cast<const SfxUInt32Item*>(pDoc->GetAttr(
918cdf0e10cSrcweir                                         nSelCol, nSelRow, nSelTab, ATTR_VALUE_FORMAT))->GetValue();
919cdf0e10cSrcweir                         short nType = pDoc->GetFormatTable()->GetType(nIndex);
920cdf0e10cSrcweir                         if ( nType == NUMBERFORMAT_DATE || nType == NUMBERFORMAT_TIME || nType == NUMBERFORMAT_DATETIME )
921cdf0e10cSrcweir                         {
922cdf0e10cSrcweir                             bFound = sal_True;
923cdf0e10cSrcweir                             // use currently selected value for automatic limits
924cdf0e10cSrcweir                             if( rOldInfo.AutoStart )
925cdf0e10cSrcweir                                 rOldInfo.Start = pDoc->GetValue( aSelRange.aStart );
926cdf0e10cSrcweir                             if( rOldInfo.AutoEnd )
927cdf0e10cSrcweir                                 rOldInfo.End = pDoc->GetValue( aSelRange.aStart );
928cdf0e10cSrcweir                         }
929cdf0e10cSrcweir                     }
930cdf0e10cSrcweir                 }
931cdf0e10cSrcweir             }
932cdf0e10cSrcweir         }
933cdf0e10cSrcweir     }
934cdf0e10cSrcweir 
935cdf0e10cSrcweir     return bFound;
936cdf0e10cSrcweir }
937cdf0e10cSrcweir 
938cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForNumGroup( ScDPNumGroupInfo& rOldInfo )
939cdf0e10cSrcweir {
940cdf0e10cSrcweir     // determine if the numeric group dialog has to be shown for the current selection
941cdf0e10cSrcweir 
942cdf0e10cSrcweir     sal_Bool bFound = sal_False;
943cdf0e10cSrcweir 
944cdf0e10cSrcweir     SCCOL nCurX = GetViewData()->GetCurX();
945cdf0e10cSrcweir     SCROW nCurY = GetViewData()->GetCurY();
946cdf0e10cSrcweir     SCTAB nTab = GetViewData()->GetTabNo();
947cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
948cdf0e10cSrcweir 
949cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab );
950cdf0e10cSrcweir     if ( pDPObj )
951cdf0e10cSrcweir     {
952cdf0e10cSrcweir         ScStrCollection aEntries;
953cdf0e10cSrcweir         long nSelectDimension = -1;
954cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
955cdf0e10cSrcweir 
956cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
957cdf0e10cSrcweir         {
958cdf0e10cSrcweir             sal_Bool bIsDataLayout;
959cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
960cdf0e10cSrcweir 
961cdf0e10cSrcweir             sal_Bool bInGroupDim = sal_False;
962cdf0e10cSrcweir 
963cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData =
964cdf0e10cSrcweir                 const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() );
965cdf0e10cSrcweir             if ( pDimData )
966cdf0e10cSrcweir             {
967cdf0e10cSrcweir                 const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName );
968cdf0e10cSrcweir                 if ( pNumGroupDim )
969cdf0e10cSrcweir                 {
970cdf0e10cSrcweir                     //  existing num group dimension
971cdf0e10cSrcweir                     //  -> edit settings of this dimension
972cdf0e10cSrcweir 
973cdf0e10cSrcweir                     rOldInfo = pNumGroupDim->GetInfo();
974cdf0e10cSrcweir                     bFound = sal_True;
975cdf0e10cSrcweir                 }
976cdf0e10cSrcweir                 else if ( pDimData->GetNamedGroupDim( aDimName ) )
977cdf0e10cSrcweir                     bInGroupDim = sal_True;                                    // in a group dimension
978cdf0e10cSrcweir             }
979cdf0e10cSrcweir             if ( !bFound && !bInGroupDim )
980cdf0e10cSrcweir             {
981cdf0e10cSrcweir                 // create a new num group dimension if the selection is a single cell
982cdf0e10cSrcweir                 // in a normal dimension with numeric content
983cdf0e10cSrcweir 
984cdf0e10cSrcweir                 ScRange aSelRange;
985cdf0e10cSrcweir                 if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) &&
986cdf0e10cSrcweir                         aSelRange.aStart == aSelRange.aEnd )
987cdf0e10cSrcweir                 {
988cdf0e10cSrcweir                     if ( pDoc->HasValueData( aSelRange.aStart.Col(), aSelRange.aStart.Row(),
989cdf0e10cSrcweir                                              aSelRange.aStart.Tab() ) )
990cdf0e10cSrcweir                     {
991cdf0e10cSrcweir                         bFound = sal_True;
992cdf0e10cSrcweir                         // use currently selected value for automatic limits
993cdf0e10cSrcweir                         if( rOldInfo.AutoStart )
994cdf0e10cSrcweir                             rOldInfo.Start = pDoc->GetValue( aSelRange.aStart );
995cdf0e10cSrcweir                         if( rOldInfo.AutoEnd )
996cdf0e10cSrcweir                             rOldInfo.End = pDoc->GetValue( aSelRange.aStart );
997cdf0e10cSrcweir                     }
998cdf0e10cSrcweir                 }
999cdf0e10cSrcweir             }
1000cdf0e10cSrcweir         }
1001cdf0e10cSrcweir     }
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir     return bFound;
1004cdf0e10cSrcweir }
1005cdf0e10cSrcweir 
1006cdf0e10cSrcweir void ScDBFunc::DateGroupDataPilot( const ScDPNumGroupInfo& rInfo, sal_Int32 nParts )
1007cdf0e10cSrcweir {
1008cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1009cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1010cdf0e10cSrcweir     if ( pDPObj )
1011cdf0e10cSrcweir     {
1012cdf0e10cSrcweir         ScStrCollection aEntries;
1013cdf0e10cSrcweir         long nSelectDimension = -1;
1014cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1015cdf0e10cSrcweir 
1016cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1017cdf0e10cSrcweir         {
1018cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1019cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1022cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1023cdf0e10cSrcweir 
1024cdf0e10cSrcweir             // find original base
1025cdf0e10cSrcweir             String aBaseDimName = aDimName;
1026cdf0e10cSrcweir             if( const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ) )
1027cdf0e10cSrcweir                 aBaseDimName = pBaseGroupDim->GetSourceDimName();
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir             // remove all existing parts (the grouping is built completely new)
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir             /*  Remove numeric group dimension (exists once at most). No need
1032cdf0e10cSrcweir                 to delete anything in save data (grouping was done inplace in
1033cdf0e10cSrcweir                 an existing base dimension). */
1034cdf0e10cSrcweir             pDimData->RemoveNumGroupDimension( aBaseDimName );
1035cdf0e10cSrcweir 
1036cdf0e10cSrcweir             /*  Remove named group dimension(s). Collect deleted dimension
1037cdf0e10cSrcweir                 names which may be reused while recreating the groups.
1038cdf0e10cSrcweir                 Dimensions have to be removed from dimension save data and from
1039cdf0e10cSrcweir                 save data too. */
1040cdf0e10cSrcweir             std::vector< String > aDeletedNames;
1041cdf0e10cSrcweir             const ScDPSaveGroupDimension* pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName );
1042cdf0e10cSrcweir             while ( pExistingGroup )
1043cdf0e10cSrcweir             {
1044cdf0e10cSrcweir                 String aGroupDimName = pExistingGroup->GetGroupDimName();
1045cdf0e10cSrcweir                 pDimData->RemoveGroupDimension( aGroupDimName );     // pExistingGroup is deleted
1046cdf0e10cSrcweir 
1047cdf0e10cSrcweir                 // also remove SaveData settings for the dimension that no longer exists
1048cdf0e10cSrcweir                 aData.RemoveDimensionByName( aGroupDimName );
1049cdf0e10cSrcweir 
1050cdf0e10cSrcweir                 /*  The name can be used for the new group dimensions, although
1051cdf0e10cSrcweir                     it is still in use with the DataPilotSource. */
1052cdf0e10cSrcweir                 aDeletedNames.push_back( aGroupDimName );
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir                 // see if there are more group dimensions
1055cdf0e10cSrcweir                 pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName );
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir                 if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
1058cdf0e10cSrcweir                 {
1059cdf0e10cSrcweir                     // still get the same group dimension?
1060cdf0e10cSrcweir                     DBG_ERROR("couldn't remove group dimension");
1061cdf0e10cSrcweir                     pExistingGroup = NULL;      // avoid endless loop
1062cdf0e10cSrcweir                 }
1063cdf0e10cSrcweir             }
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir             if ( nParts )
1066cdf0e10cSrcweir             {
1067cdf0e10cSrcweir                 // create date group dimensions
1068cdf0e10cSrcweir 
1069cdf0e10cSrcweir                 ScDPNumGroupInfo aEmpty;
1070cdf0e10cSrcweir                 bool bFirst = true;
1071cdf0e10cSrcweir                 sal_Int32 nMask = 1;
1072cdf0e10cSrcweir                 for (sal_uInt16 nBit=0; nBit<32; nBit++)
1073cdf0e10cSrcweir                 {
1074cdf0e10cSrcweir                     if ( nParts & nMask )
1075cdf0e10cSrcweir                     {
1076cdf0e10cSrcweir                         if ( bFirst )
1077cdf0e10cSrcweir                         {
1078cdf0e10cSrcweir                             // innermost part: create NumGroupDimension (replacing original values)
1079cdf0e10cSrcweir                             // Dimension name is left unchanged
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir                             if ( (nParts == sheet::DataPilotFieldGroupBy::DAYS) && (rInfo.Step >= 1.0) )
1082cdf0e10cSrcweir                             {
1083cdf0e10cSrcweir                                 // only days, and a step value specified: use numerical grouping
1084cdf0e10cSrcweir                                 // with DateValues flag, not date grouping
1085cdf0e10cSrcweir 
1086cdf0e10cSrcweir                                 ScDPNumGroupInfo aNumInfo( rInfo );
1087cdf0e10cSrcweir                                 aNumInfo.DateValues = sal_True;
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir                                 ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, aNumInfo );
1090cdf0e10cSrcweir                                 pDimData->AddNumGroupDimension( aNumGroupDim );
1091cdf0e10cSrcweir                             }
1092cdf0e10cSrcweir                             else
1093cdf0e10cSrcweir                             {
1094cdf0e10cSrcweir                                 ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, rInfo, nMask );
1095cdf0e10cSrcweir                                 pDimData->AddNumGroupDimension( aNumGroupDim );
1096cdf0e10cSrcweir                             }
1097cdf0e10cSrcweir 
1098cdf0e10cSrcweir                             bFirst = false;
1099cdf0e10cSrcweir                         }
1100cdf0e10cSrcweir                         else
1101cdf0e10cSrcweir                         {
1102cdf0e10cSrcweir                             // additional parts: create GroupDimension (shown as additional dimensions)
1103cdf0e10cSrcweir                             String aGroupDimName = pDimData->CreateDateGroupDimName( nMask, *pDPObj, true, &aDeletedNames );
1104cdf0e10cSrcweir                             ScDPSaveGroupDimension aGroupDim( aBaseDimName, aGroupDimName );
1105cdf0e10cSrcweir                             aGroupDim.SetDateInfo( rInfo, nMask );
1106cdf0e10cSrcweir                             pDimData->AddGroupDimension( aGroupDim );
1107cdf0e10cSrcweir 
1108cdf0e10cSrcweir                             // set orientation
1109cdf0e10cSrcweir                             ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName );
1110cdf0e10cSrcweir                             if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN )
1111cdf0e10cSrcweir                             {
1112cdf0e10cSrcweir                                 ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aBaseDimName );
1113cdf0e10cSrcweir                                 pSaveDimension->SetOrientation( pOldDimension->GetOrientation() );
1114cdf0e10cSrcweir                                 long nPosition = 0;     //! before (immediate) base
1115cdf0e10cSrcweir                                 aData.SetPosition( pSaveDimension, nPosition );
1116cdf0e10cSrcweir                             }
1117cdf0e10cSrcweir                         }
1118cdf0e10cSrcweir                     }
1119cdf0e10cSrcweir                     nMask *= 2;
1120cdf0e10cSrcweir                 }
1121cdf0e10cSrcweir             }
1122cdf0e10cSrcweir 
1123cdf0e10cSrcweir             // apply changes
1124cdf0e10cSrcweir             ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1125cdf0e10cSrcweir             ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1126cdf0e10cSrcweir             pNewObj->SetSaveData( aData );
1127cdf0e10cSrcweir             aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1128cdf0e10cSrcweir             delete pNewObj;
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir             // unmark cell selection
1131cdf0e10cSrcweir             Unmark();
1132cdf0e10cSrcweir         }
1133cdf0e10cSrcweir     }
1134cdf0e10cSrcweir }
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir void ScDBFunc::NumGroupDataPilot( const ScDPNumGroupInfo& rInfo )
1137cdf0e10cSrcweir {
1138cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1139cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1140cdf0e10cSrcweir     if ( pDPObj )
1141cdf0e10cSrcweir     {
1142cdf0e10cSrcweir         ScStrCollection aEntries;
1143cdf0e10cSrcweir         long nSelectDimension = -1;
1144cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1147cdf0e10cSrcweir         {
1148cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1149cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1150cdf0e10cSrcweir 
1151cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1152cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1153cdf0e10cSrcweir 
1154cdf0e10cSrcweir             ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( aDimName );
1155cdf0e10cSrcweir             if ( pExisting )
1156cdf0e10cSrcweir             {
1157cdf0e10cSrcweir                 // modify existing group dimension
1158cdf0e10cSrcweir                 pExisting->SetGroupInfo( rInfo );
1159cdf0e10cSrcweir             }
1160cdf0e10cSrcweir             else
1161cdf0e10cSrcweir             {
1162cdf0e10cSrcweir                 // create new group dimension
1163cdf0e10cSrcweir                 ScDPSaveNumGroupDimension aNumGroupDim( aDimName, rInfo );
1164cdf0e10cSrcweir                 pDimData->AddNumGroupDimension( aNumGroupDim );
1165cdf0e10cSrcweir             }
1166cdf0e10cSrcweir 
1167cdf0e10cSrcweir             // apply changes
1168cdf0e10cSrcweir             ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1169cdf0e10cSrcweir             ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1170cdf0e10cSrcweir             pNewObj->SetSaveData( aData );
1171cdf0e10cSrcweir             aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1172cdf0e10cSrcweir             delete pNewObj;
1173cdf0e10cSrcweir 
1174cdf0e10cSrcweir             // unmark cell selection
1175cdf0e10cSrcweir             Unmark();
1176cdf0e10cSrcweir         }
1177cdf0e10cSrcweir     }
1178cdf0e10cSrcweir }
1179cdf0e10cSrcweir 
1180cdf0e10cSrcweir void ScDBFunc::GroupDataPilot()
1181cdf0e10cSrcweir {
1182cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1183cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1184cdf0e10cSrcweir     if ( pDPObj )
1185cdf0e10cSrcweir     {
1186cdf0e10cSrcweir         ScStrCollection aEntries;
1187cdf0e10cSrcweir         long nSelectDimension = -1;
1188cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1189cdf0e10cSrcweir 
1190cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1191cdf0e10cSrcweir         {
1192cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1193cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1194cdf0e10cSrcweir 
1195cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1196cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1197cdf0e10cSrcweir 
1198cdf0e10cSrcweir             // find original base
1199cdf0e10cSrcweir             String aBaseDimName( aDimName );
1200cdf0e10cSrcweir             const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName );
1201cdf0e10cSrcweir             if ( pBaseGroupDim )
1202cdf0e10cSrcweir             {
1203cdf0e10cSrcweir                 // any entry's SourceDimName is the original base
1204cdf0e10cSrcweir                 aBaseDimName = pBaseGroupDim->GetSourceDimName();
1205cdf0e10cSrcweir             }
1206cdf0e10cSrcweir 
1207cdf0e10cSrcweir             // find existing group dimension
1208cdf0e10cSrcweir             // (using the selected dim, can be intermediate group dim)
1209cdf0e10cSrcweir             ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName );
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir             // remove the selected items from their groups
1212cdf0e10cSrcweir             // (empty groups are removed, too)
1213cdf0e10cSrcweir             sal_uInt16 nEntryCount = aEntries.GetCount();
1214cdf0e10cSrcweir             sal_uInt16 nEntry;
1215cdf0e10cSrcweir             if ( pGroupDimension )
1216cdf0e10cSrcweir             {
1217cdf0e10cSrcweir                 for (nEntry=0; nEntry<nEntryCount; nEntry++)
1218cdf0e10cSrcweir                 {
1219cdf0e10cSrcweir                     String aEntryName = aEntries[nEntry]->GetString();
1220cdf0e10cSrcweir                     if ( pBaseGroupDim )
1221cdf0e10cSrcweir                     {
1222cdf0e10cSrcweir                         // for each selected (intermediate) group, remove all its items
1223cdf0e10cSrcweir                         // (same logic as for adding, below)
1224cdf0e10cSrcweir                         const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
1225cdf0e10cSrcweir                         if ( pBaseGroup )
1226cdf0e10cSrcweir                             pBaseGroup->RemoveElementsFromGroups( *pGroupDimension );   // remove all elements
1227cdf0e10cSrcweir                         else
1228cdf0e10cSrcweir                             pGroupDimension->RemoveFromGroups( aEntryName );
1229cdf0e10cSrcweir                     }
1230cdf0e10cSrcweir                     else
1231cdf0e10cSrcweir                         pGroupDimension->RemoveFromGroups( aEntryName );
1232cdf0e10cSrcweir                 }
1233cdf0e10cSrcweir             }
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir             ScDPSaveGroupDimension* pNewGroupDim = NULL;
1236cdf0e10cSrcweir             if ( !pGroupDimension )
1237cdf0e10cSrcweir             {
1238cdf0e10cSrcweir                 // create a new group dimension
1239cdf0e10cSrcweir                 String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL );
1240cdf0e10cSrcweir                 pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName );
1241cdf0e10cSrcweir 
1242cdf0e10cSrcweir                 pGroupDimension = pNewGroupDim;     // make changes to the new dim if none existed
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir                 if ( pBaseGroupDim )
1245cdf0e10cSrcweir                 {
1246cdf0e10cSrcweir                     // If it's a higher-order group dimension, pre-allocate groups for all
1247cdf0e10cSrcweir                     // non-selected original groups, so the individual base members aren't
1248cdf0e10cSrcweir                     // used for automatic groups (this would make the original groups hard
1249cdf0e10cSrcweir                     // to find).
1250cdf0e10cSrcweir                     //! Also do this when removing groups?
1251cdf0e10cSrcweir                     //! Handle this case dynamically with automatic groups?
1252cdf0e10cSrcweir 
1253cdf0e10cSrcweir                     long nGroupCount = pBaseGroupDim->GetGroupCount();
1254cdf0e10cSrcweir                     for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ )
1255cdf0e10cSrcweir                     {
1256cdf0e10cSrcweir                         const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup );
1257cdf0e10cSrcweir 
1258cdf0e10cSrcweir                         StrData aStrData( pBaseGroup->GetGroupName() );
1259cdf0e10cSrcweir                         sal_uInt16 nCollIndex;
1260cdf0e10cSrcweir                         if ( !aEntries.Search( &aStrData, nCollIndex ) )    //! ignore case?
1261cdf0e10cSrcweir                         {
1262cdf0e10cSrcweir                             // add an additional group for each item that is not in the selection
1263cdf0e10cSrcweir                             ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() );
1264cdf0e10cSrcweir                             aGroup.AddElementsFromGroup( *pBaseGroup );
1265cdf0e10cSrcweir                             pGroupDimension->AddGroupItem( aGroup );
1266cdf0e10cSrcweir                         }
1267cdf0e10cSrcweir                     }
1268cdf0e10cSrcweir                 }
1269cdf0e10cSrcweir             }
1270cdf0e10cSrcweir             String aGroupDimName = pGroupDimension->GetGroupDimName();
1271cdf0e10cSrcweir 
1272cdf0e10cSrcweir             //! localized prefix string
1273cdf0e10cSrcweir             String aGroupName = pGroupDimension->CreateGroupName( String::CreateFromAscii("Group") );
1274cdf0e10cSrcweir             ScDPSaveGroupItem aGroup( aGroupName );
1275cdf0e10cSrcweir             for (nEntry=0; nEntry<nEntryCount; nEntry++)
1276cdf0e10cSrcweir             {
1277cdf0e10cSrcweir                 String aEntryName = aEntries[nEntry]->GetString();
1278cdf0e10cSrcweir                 if ( pBaseGroupDim )
1279cdf0e10cSrcweir                 {
1280cdf0e10cSrcweir                     // for each selected (intermediate) group, add all its items
1281cdf0e10cSrcweir                     const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
1282cdf0e10cSrcweir                     if ( pBaseGroup )
1283cdf0e10cSrcweir                         aGroup.AddElementsFromGroup( *pBaseGroup );
1284cdf0e10cSrcweir                     else
1285cdf0e10cSrcweir                         aGroup.AddElement( aEntryName );    // no group found -> automatic group, add the item itself
1286cdf0e10cSrcweir                 }
1287cdf0e10cSrcweir                 else
1288cdf0e10cSrcweir                     aGroup.AddElement( aEntryName );        // no group dimension, add all items directly
1289cdf0e10cSrcweir             }
1290cdf0e10cSrcweir 
1291cdf0e10cSrcweir             pGroupDimension->AddGroupItem( aGroup );
1292cdf0e10cSrcweir 
1293cdf0e10cSrcweir             if ( pNewGroupDim )
1294cdf0e10cSrcweir             {
1295cdf0e10cSrcweir                 pDimData->AddGroupDimension( *pNewGroupDim );
1296cdf0e10cSrcweir                 delete pNewGroupDim;        // AddGroupDimension copies the object
1297cdf0e10cSrcweir                 // don't access pGroupDimension after here
1298cdf0e10cSrcweir             }
1299cdf0e10cSrcweir             pGroupDimension = pNewGroupDim = NULL;
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir             // set orientation
1302cdf0e10cSrcweir             ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName );
1303cdf0e10cSrcweir             if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN )
1304cdf0e10cSrcweir             {
1305cdf0e10cSrcweir                 ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aDimName );
1306cdf0e10cSrcweir                 pSaveDimension->SetOrientation( pOldDimension->GetOrientation() );
1307cdf0e10cSrcweir                 long nPosition = 0;     //! before (immediate) base
1308cdf0e10cSrcweir                 aData.SetPosition( pSaveDimension, nPosition );
1309cdf0e10cSrcweir             }
1310cdf0e10cSrcweir 
1311cdf0e10cSrcweir             // apply changes
1312cdf0e10cSrcweir             ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1313cdf0e10cSrcweir             ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1314cdf0e10cSrcweir             pNewObj->SetSaveData( aData );
1315cdf0e10cSrcweir             aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1316cdf0e10cSrcweir             delete pNewObj;
1317cdf0e10cSrcweir 
1318cdf0e10cSrcweir             // unmark cell selection
1319cdf0e10cSrcweir             Unmark();
1320cdf0e10cSrcweir         }
1321cdf0e10cSrcweir     }
1322cdf0e10cSrcweir }
1323cdf0e10cSrcweir 
1324cdf0e10cSrcweir void ScDBFunc::UngroupDataPilot()
1325cdf0e10cSrcweir {
1326cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1327cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1328cdf0e10cSrcweir     if ( pDPObj )
1329cdf0e10cSrcweir     {
1330cdf0e10cSrcweir         ScStrCollection aEntries;
1331cdf0e10cSrcweir         long nSelectDimension = -1;
1332cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1333cdf0e10cSrcweir 
1334cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1335cdf0e10cSrcweir         {
1336cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1337cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1338cdf0e10cSrcweir 
1339cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1340cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1341cdf0e10cSrcweir             //! test first if DimensionData exists?
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir             sal_Bool bApply = sal_False;
1344cdf0e10cSrcweir 
1345cdf0e10cSrcweir             ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
1346cdf0e10cSrcweir             const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName );
1347cdf0e10cSrcweir             if ( ( pGroupDim && pGroupDim->GetDatePart() != 0 ) ||
1348cdf0e10cSrcweir                  ( pNumGroupDim && pNumGroupDim->GetDatePart() != 0 ) )
1349cdf0e10cSrcweir             {
1350cdf0e10cSrcweir                 // Date grouping: need to remove all affected group dimensions.
1351cdf0e10cSrcweir                 // This is done using DateGroupDataPilot with nParts=0.
1352cdf0e10cSrcweir 
1353cdf0e10cSrcweir                 DateGroupDataPilot( ScDPNumGroupInfo(), 0 );
1354cdf0e10cSrcweir                 // bApply remains FALSE
1355cdf0e10cSrcweir                 // dimension pointers become invalid
1356cdf0e10cSrcweir             }
1357cdf0e10cSrcweir             else if ( pGroupDim )
1358cdf0e10cSrcweir             {
1359cdf0e10cSrcweir                 sal_uInt16 nEntryCount = aEntries.GetCount();
1360cdf0e10cSrcweir                 for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
1361cdf0e10cSrcweir                 {
1362cdf0e10cSrcweir                     String aEntryName = aEntries[nEntry]->GetString();
1363cdf0e10cSrcweir                     pGroupDim->RemoveGroup( aEntryName );
1364cdf0e10cSrcweir                 }
1365cdf0e10cSrcweir                 // remove group dimension if empty
1366cdf0e10cSrcweir                 bool bEmptyDim = pGroupDim->IsEmpty();
1367cdf0e10cSrcweir                 if ( !bEmptyDim )
1368cdf0e10cSrcweir                 {
1369cdf0e10cSrcweir                     // If all remaining groups in the dimension aren't shown, remove
1370cdf0e10cSrcweir                     // the dimension too, as if it was completely empty.
1371cdf0e10cSrcweir                     ScStrCollection aVisibleEntries;
1372cdf0e10cSrcweir                     pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension );
1373cdf0e10cSrcweir                     bEmptyDim = pGroupDim->HasOnlyHidden( aVisibleEntries );
1374cdf0e10cSrcweir                 }
1375cdf0e10cSrcweir                 if ( bEmptyDim )
1376cdf0e10cSrcweir                 {
1377cdf0e10cSrcweir                     pDimData->RemoveGroupDimension( aDimName );     // pGroupDim is deleted
1378cdf0e10cSrcweir 
1379cdf0e10cSrcweir                     // also remove SaveData settings for the dimension that no longer exists
1380cdf0e10cSrcweir                     aData.RemoveDimensionByName( aDimName );
1381cdf0e10cSrcweir                 }
1382cdf0e10cSrcweir                 bApply = sal_True;
1383cdf0e10cSrcweir             }
1384cdf0e10cSrcweir             else if ( pNumGroupDim )
1385cdf0e10cSrcweir             {
1386cdf0e10cSrcweir                 // remove the numerical grouping
1387cdf0e10cSrcweir                 pDimData->RemoveNumGroupDimension( aDimName );
1388cdf0e10cSrcweir                 // SaveData settings can remain unchanged - the same dimension still exists
1389cdf0e10cSrcweir                 bApply = sal_True;
1390cdf0e10cSrcweir             }
1391cdf0e10cSrcweir 
1392cdf0e10cSrcweir             if ( bApply )
1393cdf0e10cSrcweir             {
1394cdf0e10cSrcweir                 // apply changes
1395cdf0e10cSrcweir                 ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1396cdf0e10cSrcweir                 ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1397cdf0e10cSrcweir                 pNewObj->SetSaveData( aData );
1398cdf0e10cSrcweir                 aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1399cdf0e10cSrcweir                 delete pNewObj;
1400cdf0e10cSrcweir 
1401cdf0e10cSrcweir                 // unmark cell selection
1402cdf0e10cSrcweir                 Unmark();
1403cdf0e10cSrcweir             }
1404cdf0e10cSrcweir         }
1405cdf0e10cSrcweir     }
1406cdf0e10cSrcweir }
1407cdf0e10cSrcweir 
1408cdf0e10cSrcweir static OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName)
1409cdf0e10cSrcweir {
1410cdf0e10cSrcweir     sal_Int32 n = rSubtotal.getLength();
1411cdf0e10cSrcweir     const sal_Unicode* p = rSubtotal.getStr();
1412cdf0e10cSrcweir     OUStringBuffer aBuf, aWordBuf;
1413cdf0e10cSrcweir     for (sal_Int32 i = 0; i < n; ++i)
1414cdf0e10cSrcweir     {
1415cdf0e10cSrcweir         sal_Unicode c = p[i];
1416cdf0e10cSrcweir         if (c == sal_Unicode(' '))
1417cdf0e10cSrcweir         {
1418cdf0e10cSrcweir             OUString aWord = aWordBuf.makeStringAndClear();
1419cdf0e10cSrcweir             if (aWord.equals(rMemberName))
1420cdf0e10cSrcweir                 aBuf.append(sal_Unicode('?'));
1421cdf0e10cSrcweir             else
1422cdf0e10cSrcweir                 aBuf.append(aWord);
1423cdf0e10cSrcweir             aBuf.append(c);
1424cdf0e10cSrcweir         }
1425cdf0e10cSrcweir         else if (c == sal_Unicode('\\'))
1426cdf0e10cSrcweir         {
1427cdf0e10cSrcweir             // Escape a backslash character.
1428cdf0e10cSrcweir             aWordBuf.append(c);
1429cdf0e10cSrcweir             aWordBuf.append(c);
1430cdf0e10cSrcweir         }
1431cdf0e10cSrcweir         else if (c == sal_Unicode('?'))
1432cdf0e10cSrcweir         {
1433cdf0e10cSrcweir             // A literal '?' must be escaped with a backslash ('\');
1434cdf0e10cSrcweir             aWordBuf.append(sal_Unicode('\\'));
1435cdf0e10cSrcweir             aWordBuf.append(c);
1436cdf0e10cSrcweir         }
1437cdf0e10cSrcweir         else
1438cdf0e10cSrcweir             aWordBuf.append(c);
1439cdf0e10cSrcweir     }
1440cdf0e10cSrcweir 
1441cdf0e10cSrcweir     if (aWordBuf.getLength() > 0)
1442cdf0e10cSrcweir     {
1443cdf0e10cSrcweir         OUString aWord = aWordBuf.makeStringAndClear();
1444cdf0e10cSrcweir         if (aWord.equals(rMemberName))
1445cdf0e10cSrcweir             aBuf.append(sal_Unicode('?'));
1446cdf0e10cSrcweir         else
1447cdf0e10cSrcweir             aBuf.append(aWord);
1448cdf0e10cSrcweir     }
1449cdf0e10cSrcweir 
1450cdf0e10cSrcweir     return aBuf.makeStringAndClear();
1451cdf0e10cSrcweir }
1452cdf0e10cSrcweir 
1453cdf0e10cSrcweir void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString )
1454cdf0e10cSrcweir {
1455cdf0e10cSrcweir     using namespace ::com::sun::star::sheet;
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir     String aNewName( rString );
1458cdf0e10cSrcweir 
1459cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
1460cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() );
1461cdf0e10cSrcweir     if (!pDPObj)
1462cdf0e10cSrcweir         return;
1463cdf0e10cSrcweir 
1464cdf0e10cSrcweir     String aOldText;
1465cdf0e10cSrcweir     pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText );
1466cdf0e10cSrcweir 
1467cdf0e10cSrcweir     if ( aOldText == rString )
1468cdf0e10cSrcweir     {
1469cdf0e10cSrcweir         // nothing to do: silently exit
1470cdf0e10cSrcweir         return;
1471cdf0e10cSrcweir     }
1472cdf0e10cSrcweir 
1473cdf0e10cSrcweir     sal_uInt16 nErrorId = 0;
1474cdf0e10cSrcweir 
1475cdf0e10cSrcweir     pDPObj->BuildAllDimensionMembers();
1476cdf0e10cSrcweir     ScDPSaveData aData( *pDPObj->GetSaveData() );
1477cdf0e10cSrcweir     sal_Bool bChange = sal_False;
1478cdf0e10cSrcweir 
1479cdf0e10cSrcweir     sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN;
1480cdf0e10cSrcweir     long nField = pDPObj->GetHeaderDim( rPos, nOrient );
1481cdf0e10cSrcweir     if ( nField >= 0 )
1482cdf0e10cSrcweir     {
1483cdf0e10cSrcweir         // changing a field title
1484cdf0e10cSrcweir         if ( aData.GetExistingDimensionData() )
1485cdf0e10cSrcweir         {
1486cdf0e10cSrcweir             // only group dimensions can be renamed
1487cdf0e10cSrcweir 
1488cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1489cdf0e10cSrcweir             ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
1490cdf0e10cSrcweir             if ( pGroupDim )
1491cdf0e10cSrcweir             {
1492cdf0e10cSrcweir                 // valid name: not empty, no existing dimension (group or other)
1493cdf0e10cSrcweir                 if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) )
1494cdf0e10cSrcweir                 {
1495cdf0e10cSrcweir                     pGroupDim->Rename( aNewName );
1496cdf0e10cSrcweir 
1497cdf0e10cSrcweir                     // also rename in SaveData to preserve the field settings
1498cdf0e10cSrcweir                     ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
1499cdf0e10cSrcweir                     pSaveDim->SetName( aNewName );
1500cdf0e10cSrcweir 
1501cdf0e10cSrcweir                     bChange = sal_True;
1502cdf0e10cSrcweir                 }
1503cdf0e10cSrcweir                 else
1504cdf0e10cSrcweir                     nErrorId = STR_INVALIDNAME;
1505cdf0e10cSrcweir             }
1506cdf0e10cSrcweir         }
1507cdf0e10cSrcweir         else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW)
1508cdf0e10cSrcweir         {
1509cdf0e10cSrcweir             sal_Bool bDataLayout = false;
1510cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName(nField, bDataLayout);
1511cdf0e10cSrcweir             ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName);
1512cdf0e10cSrcweir             if (pDim)
1513cdf0e10cSrcweir             {
1514cdf0e10cSrcweir                 if (rString.Len())
1515cdf0e10cSrcweir                 {
1516cdf0e10cSrcweir                     if (rString.EqualsIgnoreCaseAscii(aDimName))
1517cdf0e10cSrcweir                     {
1518cdf0e10cSrcweir                         pDim->RemoveLayoutName();
1519cdf0e10cSrcweir                         bChange = true;
1520cdf0e10cSrcweir                     }
1521cdf0e10cSrcweir                     else if (!pDPObj->IsDimNameInUse(rString))
1522cdf0e10cSrcweir                     {
1523cdf0e10cSrcweir                         pDim->SetLayoutName(rString);
1524cdf0e10cSrcweir                         bChange = true;
1525cdf0e10cSrcweir                     }
1526cdf0e10cSrcweir                     else
1527cdf0e10cSrcweir                         nErrorId = STR_INVALIDNAME;
1528cdf0e10cSrcweir                 }
1529cdf0e10cSrcweir                 else
1530cdf0e10cSrcweir                     nErrorId = STR_INVALIDNAME;
1531cdf0e10cSrcweir             }
1532cdf0e10cSrcweir         }
1533cdf0e10cSrcweir     }
1534cdf0e10cSrcweir     else if (pDPObj->IsDataDescriptionCell(rPos))
1535cdf0e10cSrcweir     {
1536cdf0e10cSrcweir         // There is only one data dimension.
1537cdf0e10cSrcweir         ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA);
1538cdf0e10cSrcweir         if (pDim)
1539cdf0e10cSrcweir         {
1540cdf0e10cSrcweir             if (rString.Len())
1541cdf0e10cSrcweir             {
1542cdf0e10cSrcweir                 if (rString.EqualsIgnoreCaseAscii(pDim->GetName()))
1543cdf0e10cSrcweir                 {
1544cdf0e10cSrcweir                     pDim->RemoveLayoutName();
1545cdf0e10cSrcweir                     bChange = true;
1546cdf0e10cSrcweir                 }
1547cdf0e10cSrcweir                 else if (!pDPObj->IsDimNameInUse(rString))
1548cdf0e10cSrcweir                 {
1549cdf0e10cSrcweir                     pDim->SetLayoutName(rString);
1550cdf0e10cSrcweir                     bChange = true;
1551cdf0e10cSrcweir                 }
1552cdf0e10cSrcweir                 else
1553cdf0e10cSrcweir                     nErrorId = STR_INVALIDNAME;
1554cdf0e10cSrcweir             }
1555cdf0e10cSrcweir             else
1556cdf0e10cSrcweir                 nErrorId = STR_INVALIDNAME;
1557cdf0e10cSrcweir         }
1558cdf0e10cSrcweir     }
1559cdf0e10cSrcweir     else
1560cdf0e10cSrcweir     {
1561cdf0e10cSrcweir         // This is not a field header.
1562cdf0e10cSrcweir         sheet::DataPilotTableHeaderData aPosData;
1563cdf0e10cSrcweir         pDPObj->GetHeaderPositionData(rPos, aPosData);
1564cdf0e10cSrcweir 
1565cdf0e10cSrcweir         if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() )
1566cdf0e10cSrcweir         {
1567cdf0e10cSrcweir             if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL))
1568cdf0e10cSrcweir             {
1569cdf0e10cSrcweir                 sal_Bool bIsDataLayout;
1570cdf0e10cSrcweir                 String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
1571cdf0e10cSrcweir 
1572cdf0e10cSrcweir                 ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1573cdf0e10cSrcweir                 ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
1574cdf0e10cSrcweir                 if ( pGroupDim )
1575cdf0e10cSrcweir                 {
1576cdf0e10cSrcweir                     // valid name: not empty, no existing group in this dimension
1577cdf0e10cSrcweir                     //! ignore case?
1578cdf0e10cSrcweir                     if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) )
1579cdf0e10cSrcweir                     {
1580cdf0e10cSrcweir                         ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
1581cdf0e10cSrcweir                         if ( pGroup )
1582cdf0e10cSrcweir                             pGroup->Rename( aNewName );     // rename the existing group
1583cdf0e10cSrcweir                         else
1584cdf0e10cSrcweir                         {
1585cdf0e10cSrcweir                             // create a new group to replace the automatic group
1586cdf0e10cSrcweir                             ScDPSaveGroupItem aGroup( aNewName );
1587cdf0e10cSrcweir                             aGroup.AddElement( aOldText );
1588cdf0e10cSrcweir                             pGroupDim->AddGroupItem( aGroup );
1589cdf0e10cSrcweir                         }
1590cdf0e10cSrcweir 
1591cdf0e10cSrcweir                         // in both cases also adjust savedata, to preserve member settings (show details)
1592cdf0e10cSrcweir                         ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
1593cdf0e10cSrcweir                         ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
1594cdf0e10cSrcweir                         if ( pSaveMember )
1595cdf0e10cSrcweir                             pSaveMember->SetName( aNewName );
1596cdf0e10cSrcweir 
1597cdf0e10cSrcweir                         bChange = sal_True;
1598cdf0e10cSrcweir                     }
1599cdf0e10cSrcweir                     else
1600cdf0e10cSrcweir                         nErrorId = STR_INVALIDNAME;
1601cdf0e10cSrcweir                  }
1602cdf0e10cSrcweir             }
1603cdf0e10cSrcweir             else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL))
1604cdf0e10cSrcweir             {
1605cdf0e10cSrcweir                 aData.SetGrandTotalName(rString);
1606cdf0e10cSrcweir                 bChange = true;
1607cdf0e10cSrcweir             }
1608cdf0e10cSrcweir             else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0)
1609cdf0e10cSrcweir             {
1610cdf0e10cSrcweir                 sal_Bool bDataLayout = false;
1611cdf0e10cSrcweir                 String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout);
1612cdf0e10cSrcweir                 if (bDataLayout)
1613cdf0e10cSrcweir                 {
1614cdf0e10cSrcweir                     // data dimension
1615cdf0e10cSrcweir                     do
1616cdf0e10cSrcweir                     {
1617cdf0e10cSrcweir                         if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
1618cdf0e10cSrcweir                             break;
1619cdf0e10cSrcweir 
1620cdf0e10cSrcweir                         ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName);
1621cdf0e10cSrcweir                         if (!pDim)
1622cdf0e10cSrcweir                             break;
1623cdf0e10cSrcweir 
1624cdf0e10cSrcweir                         if (!rString.Len())
1625cdf0e10cSrcweir                         {
1626cdf0e10cSrcweir                             nErrorId = STR_INVALIDNAME;
1627cdf0e10cSrcweir                             break;
1628cdf0e10cSrcweir                         }
1629cdf0e10cSrcweir 
1630cdf0e10cSrcweir                         if (aPosData.MemberName.equalsIgnoreAsciiCase(rString))
1631cdf0e10cSrcweir                         {
1632cdf0e10cSrcweir                             pDim->RemoveLayoutName();
1633cdf0e10cSrcweir                             bChange = true;
1634cdf0e10cSrcweir                         }
1635cdf0e10cSrcweir                         else if (!pDPObj->IsDimNameInUse(rString))
1636cdf0e10cSrcweir                         {
1637cdf0e10cSrcweir                             pDim->SetLayoutName(rString);
1638cdf0e10cSrcweir                             bChange = true;
1639cdf0e10cSrcweir                         }
1640cdf0e10cSrcweir                         else
1641cdf0e10cSrcweir                             nErrorId = STR_INVALIDNAME;
1642cdf0e10cSrcweir                     }
1643cdf0e10cSrcweir                     while (false);
1644cdf0e10cSrcweir                 }
1645cdf0e10cSrcweir                 else
1646cdf0e10cSrcweir                 {
1647cdf0e10cSrcweir                     // field member
1648cdf0e10cSrcweir                     do
1649cdf0e10cSrcweir                     {
1650cdf0e10cSrcweir                         ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName);
1651cdf0e10cSrcweir                         if (!pDim)
1652cdf0e10cSrcweir                             break;
1653cdf0e10cSrcweir 
1654cdf0e10cSrcweir                         ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName);
1655cdf0e10cSrcweir                         if (!pMem)
1656cdf0e10cSrcweir                             break;
1657cdf0e10cSrcweir 
1658cdf0e10cSrcweir                         if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
1659cdf0e10cSrcweir                         {
1660cdf0e10cSrcweir                             // Change subtotal only when the table has one data dimension.
1661cdf0e10cSrcweir                             if (aData.GetDataDimensionCount() > 1)
1662cdf0e10cSrcweir                                 break;
1663cdf0e10cSrcweir 
1664cdf0e10cSrcweir                             // display name for subtotal is allowed only if the subtotal type is 'Automatic'.
1665cdf0e10cSrcweir                             if (pDim->GetSubTotalsCount() != 1)
1666cdf0e10cSrcweir                                 break;
1667cdf0e10cSrcweir 
1668cdf0e10cSrcweir                             if (pDim->GetSubTotalFunc(0) != sheet::GeneralFunction_AUTO)
1669cdf0e10cSrcweir                                 break;
1670cdf0e10cSrcweir 
1671cdf0e10cSrcweir                             const OUString* pLayoutName = pMem->GetLayoutName();
1672cdf0e10cSrcweir                             String aMemberName;
1673cdf0e10cSrcweir                             if (pLayoutName)
1674cdf0e10cSrcweir                                 aMemberName = *pLayoutName;
1675cdf0e10cSrcweir                             else
1676cdf0e10cSrcweir                                 aMemberName = aPosData.MemberName;
1677cdf0e10cSrcweir 
1678cdf0e10cSrcweir                             String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName);
1679cdf0e10cSrcweir                             pDim->SetSubtotalName(aNew);
1680cdf0e10cSrcweir                             bChange = true;
1681cdf0e10cSrcweir                         }
1682cdf0e10cSrcweir                         else
1683cdf0e10cSrcweir                         {
1684cdf0e10cSrcweir                             // Check to make sure the member name isn't
1685cdf0e10cSrcweir                             // already used.
1686cdf0e10cSrcweir                             if (rString.Len())
1687cdf0e10cSrcweir                             {
1688cdf0e10cSrcweir                                 if (rString.EqualsIgnoreCaseAscii(pMem->GetName()))
1689cdf0e10cSrcweir                                 {
1690cdf0e10cSrcweir                                     pMem->RemoveLayoutName();
1691cdf0e10cSrcweir                                     bChange = true;
1692cdf0e10cSrcweir                                 }
1693cdf0e10cSrcweir                                 else if (!pDim->IsMemberNameInUse(rString))
1694cdf0e10cSrcweir                                 {
1695cdf0e10cSrcweir                                     pMem->SetLayoutName(rString);
1696cdf0e10cSrcweir                                     bChange = true;
1697cdf0e10cSrcweir                                 }
1698cdf0e10cSrcweir                                 else
1699cdf0e10cSrcweir                                     nErrorId = STR_INVALIDNAME;
1700cdf0e10cSrcweir                             }
1701cdf0e10cSrcweir                             else
1702cdf0e10cSrcweir                                 nErrorId = STR_INVALIDNAME;
1703cdf0e10cSrcweir                         }
1704cdf0e10cSrcweir                     }
1705cdf0e10cSrcweir                     while (false);
1706cdf0e10cSrcweir                 }
1707cdf0e10cSrcweir             }
1708cdf0e10cSrcweir         }
1709cdf0e10cSrcweir     }
1710cdf0e10cSrcweir 
1711cdf0e10cSrcweir     if ( bChange )
1712cdf0e10cSrcweir     {
1713cdf0e10cSrcweir         // apply changes
1714cdf0e10cSrcweir         ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1715cdf0e10cSrcweir         ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1716cdf0e10cSrcweir         pNewObj->SetSaveData( aData );
1717cdf0e10cSrcweir         aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1718cdf0e10cSrcweir         delete pNewObj;
1719cdf0e10cSrcweir     }
1720cdf0e10cSrcweir     else
1721cdf0e10cSrcweir     {
1722cdf0e10cSrcweir         if ( !nErrorId )
1723cdf0e10cSrcweir             nErrorId = STR_ERR_DATAPILOT_INPUT;
1724cdf0e10cSrcweir         ErrorMessage( nErrorId );
1725cdf0e10cSrcweir     }
1726cdf0e10cSrcweir }
1727cdf0e10cSrcweir 
1728cdf0e10cSrcweir void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName )
1729cdf0e10cSrcweir {
1730cdf0e10cSrcweir     ScDPSaveMember* pNewMember = NULL;
1731cdf0e10cSrcweir     const ScDPSaveMember* pOldMember = rDim.GetExistingMemberByName( rItemName );
1732cdf0e10cSrcweir     if ( pOldMember )
1733cdf0e10cSrcweir         pNewMember = new ScDPSaveMember( *pOldMember );
1734cdf0e10cSrcweir     else
1735cdf0e10cSrcweir         pNewMember = new ScDPSaveMember( rItemName );
1736cdf0e10cSrcweir     rDim.AddMember( pNewMember );
1737cdf0e10cSrcweir     // AddMember takes ownership of the new pointer,
1738cdf0e10cSrcweir     // puts it to the end of the list even if it was in the list before.
1739cdf0e10cSrcweir }
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir struct ScOUStringCollate
1742cdf0e10cSrcweir {
1743cdf0e10cSrcweir     CollatorWrapper* mpCollator;
1744cdf0e10cSrcweir 
1745cdf0e10cSrcweir     ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {}
1746cdf0e10cSrcweir 
1747cdf0e10cSrcweir     bool operator()(const rtl::OUString& rStr1, const rtl::OUString& rStr2) const
1748cdf0e10cSrcweir     {
1749cdf0e10cSrcweir         return ( mpCollator->compareString(rStr1, rStr2) < 0 );
1750cdf0e10cSrcweir     }
1751cdf0e10cSrcweir };
1752cdf0e10cSrcweir 
1753cdf0e10cSrcweir bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId )
1754cdf0e10cSrcweir {
1755cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
1756cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor(rPos.Col(), rPos.Row(), rPos.Tab());
1757cdf0e10cSrcweir     if (!pDPObj)
1758cdf0e10cSrcweir         return false;
1759cdf0e10cSrcweir 
1760cdf0e10cSrcweir     // We need to run this to get all members later.
1761cdf0e10cSrcweir     if ( pUserListId )
1762cdf0e10cSrcweir         pDPObj->BuildAllDimensionMembers();
1763cdf0e10cSrcweir 
1764cdf0e10cSrcweir     sal_uInt16 nOrientation;
1765cdf0e10cSrcweir     long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation);
1766cdf0e10cSrcweir     if (nDimIndex < 0)
1767cdf0e10cSrcweir         // Invalid dimension index.  Bail out.
1768cdf0e10cSrcweir         return false;
1769cdf0e10cSrcweir 
1770cdf0e10cSrcweir     sal_Bool bDataLayout;
1771cdf0e10cSrcweir     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1772cdf0e10cSrcweir     if (!pSaveData)
1773cdf0e10cSrcweir         return false;
1774cdf0e10cSrcweir 
1775cdf0e10cSrcweir     ScDPSaveData aNewSaveData(*pSaveData);
1776cdf0e10cSrcweir     String aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout);
1777cdf0e10cSrcweir     ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName);
1778cdf0e10cSrcweir     if (!pSaveDim)
1779cdf0e10cSrcweir         return false;
1780cdf0e10cSrcweir 
1781cdf0e10cSrcweir     // manual evaluation of sort order is only needed if a user list id is given
1782cdf0e10cSrcweir     if ( pUserListId )
1783cdf0e10cSrcweir     {
1784cdf0e10cSrcweir         typedef ScDPSaveDimension::MemberList MemList;
1785cdf0e10cSrcweir         const MemList& rDimMembers = pSaveDim->GetMembers();
1786cdf0e10cSrcweir         list<OUString> aMembers;
1787cdf0e10cSrcweir         hash_set<OUString, ::rtl::OUStringHash> aMemberSet;
1788cdf0e10cSrcweir         size_t nMemberCount = 0;
1789cdf0e10cSrcweir         for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end();
1790cdf0e10cSrcweir               itr != itrEnd; ++itr)
1791cdf0e10cSrcweir         {
1792cdf0e10cSrcweir             ScDPSaveMember* pMem = *itr;
1793cdf0e10cSrcweir             aMembers.push_back(pMem->GetName());
1794cdf0e10cSrcweir             aMemberSet.insert(pMem->GetName());
1795cdf0e10cSrcweir             ++nMemberCount;
1796cdf0e10cSrcweir         }
1797cdf0e10cSrcweir 
1798cdf0e10cSrcweir         // Sort the member list in ascending order.
1799cdf0e10cSrcweir         ScOUStringCollate aCollate( ScGlobal::GetCollator() );
1800cdf0e10cSrcweir         aMembers.sort(aCollate);
1801cdf0e10cSrcweir 
1802cdf0e10cSrcweir         // Collect and rank those custom sort strings that also exist in the member name list.
1803cdf0e10cSrcweir 
1804cdf0e10cSrcweir         typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap;
1805cdf0e10cSrcweir         UserSortMap aSubStrs;
1806cdf0e10cSrcweir         sal_uInt16 nSubCount = 0;
1807cdf0e10cSrcweir         if (pUserListId)
1808cdf0e10cSrcweir         {
1809cdf0e10cSrcweir             ScUserList* pUserList = ScGlobal::GetUserList();
1810cdf0e10cSrcweir             if (!pUserList)
1811cdf0e10cSrcweir                 return false;
1812cdf0e10cSrcweir 
1813cdf0e10cSrcweir             {
1814cdf0e10cSrcweir                 sal_uInt16 n = pUserList->GetCount();
1815cdf0e10cSrcweir                 if (!n || *pUserListId >= n)
1816cdf0e10cSrcweir                     return false;
1817cdf0e10cSrcweir             }
1818cdf0e10cSrcweir 
1819cdf0e10cSrcweir             ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]);
1820cdf0e10cSrcweir             if (pData)
1821cdf0e10cSrcweir             {
1822cdf0e10cSrcweir                 sal_uInt16 n = pData->GetSubCount();
1823cdf0e10cSrcweir                 for (sal_uInt16 i = 0; i < n; ++i)
1824cdf0e10cSrcweir                 {
1825cdf0e10cSrcweir                     OUString aSub = pData->GetSubStr(i);
1826cdf0e10cSrcweir                     if (!aMemberSet.count(aSub))
1827cdf0e10cSrcweir                         // This string doesn't exist in the member name set.  Don't add this.
1828cdf0e10cSrcweir                         continue;
1829cdf0e10cSrcweir 
1830cdf0e10cSrcweir                     aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++));
1831cdf0e10cSrcweir                 }
1832cdf0e10cSrcweir             }
1833cdf0e10cSrcweir         }
1834cdf0e10cSrcweir 
1835cdf0e10cSrcweir         // Rank all members.
1836cdf0e10cSrcweir 
1837cdf0e10cSrcweir         vector<OUString> aRankedNames(nMemberCount);
1838cdf0e10cSrcweir         sal_uInt16 nCurStrId = 0;
1839cdf0e10cSrcweir         for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end();
1840cdf0e10cSrcweir               itr != itrEnd; ++itr)
1841cdf0e10cSrcweir         {
1842cdf0e10cSrcweir             OUString aName = *itr;
1843cdf0e10cSrcweir             sal_uInt16 nRank = 0;
1844cdf0e10cSrcweir             UserSortMap::const_iterator itrSub = aSubStrs.find(aName);
1845cdf0e10cSrcweir             if (itrSub == aSubStrs.end())
1846cdf0e10cSrcweir                 nRank = nSubCount + nCurStrId++;
1847cdf0e10cSrcweir             else
1848cdf0e10cSrcweir                 nRank = itrSub->second;
1849cdf0e10cSrcweir 
1850cdf0e10cSrcweir             if (!bAscending)
1851cdf0e10cSrcweir                 nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 );
1852cdf0e10cSrcweir 
1853cdf0e10cSrcweir             aRankedNames[nRank] = aName;
1854cdf0e10cSrcweir         }
1855cdf0e10cSrcweir 
1856cdf0e10cSrcweir         // Re-order ScDPSaveMember instances with the new ranks.
1857cdf0e10cSrcweir 
1858cdf0e10cSrcweir         for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end();
1859cdf0e10cSrcweir               itr != itrEnd; ++itr)
1860cdf0e10cSrcweir         {
1861cdf0e10cSrcweir             const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr);
1862cdf0e10cSrcweir             if (!pOldMem)
1863cdf0e10cSrcweir                 // All members are supposed to be present.
1864cdf0e10cSrcweir                 continue;
1865cdf0e10cSrcweir 
1866cdf0e10cSrcweir             ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem);
1867cdf0e10cSrcweir             pSaveDim->AddMember(pNewMem);
1868cdf0e10cSrcweir         }
1869cdf0e10cSrcweir 
1870cdf0e10cSrcweir         // Set the sorting mode to manual for now.  We may introduce a new sorting
1871cdf0e10cSrcweir         // mode later on.
1872cdf0e10cSrcweir 
1873cdf0e10cSrcweir         sheet::DataPilotFieldSortInfo aSortInfo;
1874cdf0e10cSrcweir         aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1875cdf0e10cSrcweir         pSaveDim->SetSortInfo(&aSortInfo);
1876cdf0e10cSrcweir     }
1877cdf0e10cSrcweir     else
1878cdf0e10cSrcweir     {
1879cdf0e10cSrcweir         // without user list id, just apply sorting mode
1880cdf0e10cSrcweir 
1881cdf0e10cSrcweir         sheet::DataPilotFieldSortInfo aSortInfo;
1882cdf0e10cSrcweir         aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME;
1883cdf0e10cSrcweir         aSortInfo.IsAscending = bAscending;
1884cdf0e10cSrcweir         pSaveDim->SetSortInfo(&aSortInfo);
1885cdf0e10cSrcweir     }
1886cdf0e10cSrcweir 
1887cdf0e10cSrcweir     // Update the datapilot with the newly sorted field members.
1888cdf0e10cSrcweir 
1889cdf0e10cSrcweir     auto_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj));
1890cdf0e10cSrcweir     pNewObj->SetSaveData(aNewSaveData);
1891cdf0e10cSrcweir     ScDBDocFunc aFunc(*GetViewData()->GetDocShell());
1892cdf0e10cSrcweir 
1893cdf0e10cSrcweir     return aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false);
1894cdf0e10cSrcweir }
1895cdf0e10cSrcweir 
1896cdf0e10cSrcweir sal_Bool ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
1897cdf0e10cSrcweir {
1898cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1899cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
1900cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() );
1901cdf0e10cSrcweir     if ( pDPObj && pDPObj == pDoc->GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) )
1902cdf0e10cSrcweir     {
1903cdf0e10cSrcweir         sheet::DataPilotTableHeaderData aDestData;
1904cdf0e10cSrcweir         pDPObj->GetHeaderPositionData( rDest, aDestData );
1905cdf0e10cSrcweir         bool bValid = ( aDestData.Dimension >= 0 );        // dropping onto a field
1906cdf0e10cSrcweir 
1907cdf0e10cSrcweir         // look through the source range
1908cdf0e10cSrcweir         std::hash_set< rtl::OUString, rtl::OUStringHash, std::equal_to<rtl::OUString> > aMembersSet;   // for lookup
1909cdf0e10cSrcweir         std::vector< rtl::OUString > aMembersVector;  // members in original order, for inserting
1910cdf0e10cSrcweir         aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ),
1911cdf0e10cSrcweir                                           static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) );
1912cdf0e10cSrcweir         for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow )
1913cdf0e10cSrcweir             for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol )
1914cdf0e10cSrcweir             {
1915cdf0e10cSrcweir                 sheet::DataPilotTableHeaderData aSourceData;
1916cdf0e10cSrcweir                 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData );
1917cdf0e10cSrcweir                 if ( aSourceData.Dimension == aDestData.Dimension && aSourceData.MemberName.getLength() )
1918cdf0e10cSrcweir                 {
1919cdf0e10cSrcweir                     if ( aMembersSet.find( aSourceData.MemberName ) == aMembersSet.end() )
1920cdf0e10cSrcweir                     {
1921cdf0e10cSrcweir                         aMembersSet.insert( aSourceData.MemberName );
1922cdf0e10cSrcweir                         aMembersVector.push_back( aSourceData.MemberName );
1923cdf0e10cSrcweir                     }
1924cdf0e10cSrcweir                     // duplicates are ignored
1925cdf0e10cSrcweir                 }
1926cdf0e10cSrcweir                 else
1927cdf0e10cSrcweir                     bValid = false;     // empty (subtotal) or different field
1928cdf0e10cSrcweir             }
1929cdf0e10cSrcweir 
1930cdf0e10cSrcweir         if ( bValid )
1931cdf0e10cSrcweir         {
1932cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1933cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
1934cdf0e10cSrcweir             if ( !bIsDataLayout )
1935cdf0e10cSrcweir             {
1936cdf0e10cSrcweir                 ScDPSaveData aData( *pDPObj->GetSaveData() );
1937cdf0e10cSrcweir                 ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
1938cdf0e10cSrcweir 
1939cdf0e10cSrcweir                 // get all member names in source order
1940cdf0e10cSrcweir                 uno::Sequence<rtl::OUString> aMemberNames;
1941cdf0e10cSrcweir                 pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames );
1942cdf0e10cSrcweir 
1943cdf0e10cSrcweir                 bool bInserted = false;
1944cdf0e10cSrcweir 
1945cdf0e10cSrcweir                 sal_Int32 nMemberCount = aMemberNames.getLength();
1946cdf0e10cSrcweir                 for (sal_Int32 nMemberPos=0; nMemberPos<nMemberCount; ++nMemberPos)
1947cdf0e10cSrcweir                 {
1948cdf0e10cSrcweir                     String aMemberStr( aMemberNames[nMemberPos] );
1949cdf0e10cSrcweir 
1950cdf0e10cSrcweir                     if ( !bInserted && aMemberNames[nMemberPos] == aDestData.MemberName )
1951cdf0e10cSrcweir                     {
1952cdf0e10cSrcweir                         // insert dragged items before this item
1953cdf0e10cSrcweir                         for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin();
1954cdf0e10cSrcweir                               aIter != aMembersVector.end(); ++aIter )
1955cdf0e10cSrcweir                             lcl_MoveToEnd( *pDim, *aIter );
1956cdf0e10cSrcweir                         bInserted = true;
1957cdf0e10cSrcweir                     }
1958cdf0e10cSrcweir 
1959cdf0e10cSrcweir                     if ( aMembersSet.find( aMemberStr ) == aMembersSet.end() )  // skip dragged items
1960cdf0e10cSrcweir                         lcl_MoveToEnd( *pDim, aMemberStr );
1961cdf0e10cSrcweir                 }
1962cdf0e10cSrcweir                 // insert dragged item at end if dest wasn't found (for example, empty)
1963cdf0e10cSrcweir                 if ( !bInserted )
1964cdf0e10cSrcweir                     for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin();
1965cdf0e10cSrcweir                           aIter != aMembersVector.end(); ++aIter )
1966cdf0e10cSrcweir                         lcl_MoveToEnd( *pDim, *aIter );
1967cdf0e10cSrcweir 
1968cdf0e10cSrcweir                 // Items that were in SaveData, but not in the source, end up at the start of the list.
1969cdf0e10cSrcweir 
1970cdf0e10cSrcweir                 // set flag for manual sorting
1971cdf0e10cSrcweir                 sheet::DataPilotFieldSortInfo aSortInfo;
1972cdf0e10cSrcweir                 aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1973cdf0e10cSrcweir                 pDim->SetSortInfo( &aSortInfo );
1974cdf0e10cSrcweir 
1975cdf0e10cSrcweir                 // apply changes
1976cdf0e10cSrcweir                 ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1977cdf0e10cSrcweir                 ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1978cdf0e10cSrcweir                 pNewObj->SetSaveData( aData );
1979cdf0e10cSrcweir                 aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );      //! bApi for drag&drop?
1980cdf0e10cSrcweir                 delete pNewObj;
1981cdf0e10cSrcweir 
1982cdf0e10cSrcweir                 Unmark();       // entry was moved - no use in leaving the old cell selected
1983cdf0e10cSrcweir 
1984cdf0e10cSrcweir                 bRet = sal_True;
1985cdf0e10cSrcweir             }
1986cdf0e10cSrcweir         }
1987cdf0e10cSrcweir     }
1988cdf0e10cSrcweir 
1989cdf0e10cSrcweir     return bRet;
1990cdf0e10cSrcweir }
1991cdf0e10cSrcweir 
1992cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForDrillDown( sal_uInt16& rOrientation )
1993cdf0e10cSrcweir {
1994cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1995cdf0e10cSrcweir 
1996cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1997cdf0e10cSrcweir             							GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1998cdf0e10cSrcweir     if ( pDPObj )
1999cdf0e10cSrcweir     {
2000cdf0e10cSrcweir         ScStrCollection aEntries;
2001cdf0e10cSrcweir         long nSelectDimension = -1;
2002cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
2003cdf0e10cSrcweir 
2004cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
2005cdf0e10cSrcweir         {
2006cdf0e10cSrcweir             sal_Bool bIsDataLayout;
2007cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
2008cdf0e10cSrcweir             if ( !bIsDataLayout )
2009cdf0e10cSrcweir             {
2010cdf0e10cSrcweir                 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2011cdf0e10cSrcweir             	ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aDimName );
2012cdf0e10cSrcweir             	if ( pDim )
2013cdf0e10cSrcweir             	{
2014cdf0e10cSrcweir             	    sal_uInt16 nDimOrient = pDim->GetOrientation();
2015cdf0e10cSrcweir             	    ScDPSaveDimension* pInner = pSaveData->GetInnermostDimension( nDimOrient );
2016cdf0e10cSrcweir             	    if ( pDim == pInner )
2017cdf0e10cSrcweir             	    {
2018cdf0e10cSrcweir             	        rOrientation = nDimOrient;
2019cdf0e10cSrcweir             	        bRet = sal_True;
2020cdf0e10cSrcweir             	    }
2021cdf0e10cSrcweir             	}
2022cdf0e10cSrcweir             }
2023cdf0e10cSrcweir         }
2024cdf0e10cSrcweir     }
2025cdf0e10cSrcweir 
2026cdf0e10cSrcweir     return bRet;
2027cdf0e10cSrcweir }
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir void ScDBFunc::SetDataPilotDetails( sal_Bool bShow, const String* pNewDimensionName )
2030cdf0e10cSrcweir {
2031cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
2032cdf0e10cSrcweir             							GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
2033cdf0e10cSrcweir     if ( pDPObj )
2034cdf0e10cSrcweir     {
2035cdf0e10cSrcweir         ScStrCollection aEntries;
2036cdf0e10cSrcweir         long nSelectDimension = -1;
2037cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
2038cdf0e10cSrcweir 
2039cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
2040cdf0e10cSrcweir         {
2041cdf0e10cSrcweir             sal_Bool bIsDataLayout;
2042cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
2043cdf0e10cSrcweir             if ( !bIsDataLayout )
2044cdf0e10cSrcweir             {
2045cdf0e10cSrcweir                 ScDPSaveData aData( *pDPObj->GetSaveData() );
2046cdf0e10cSrcweir                 ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
2047cdf0e10cSrcweir 
2048cdf0e10cSrcweir                 if ( bShow && pNewDimensionName )
2049cdf0e10cSrcweir                 {
2050cdf0e10cSrcweir                     //  add the new dimension with the same orientation, at the end
2051cdf0e10cSrcweir 
2052cdf0e10cSrcweir                     ScDPSaveDimension* pNewDim = aData.GetDimensionByName( *pNewDimensionName );
2053cdf0e10cSrcweir                     ScDPSaveDimension* pDuplicated = NULL;
2054cdf0e10cSrcweir                     if ( pNewDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
2055cdf0e10cSrcweir                     {
2056cdf0e10cSrcweir                         // Need to duplicate the dimension, create column/row in addition to data:
2057cdf0e10cSrcweir                         // The duplicated dimension inherits the existing settings, pNewDim is modified below.
2058cdf0e10cSrcweir                         pDuplicated = aData.DuplicateDimension( *pNewDimensionName );
2059cdf0e10cSrcweir                     }
2060cdf0e10cSrcweir 
2061cdf0e10cSrcweir                     sal_uInt16 nOrientation = pDim->GetOrientation();
2062cdf0e10cSrcweir                     pNewDim->SetOrientation( nOrientation );
2063cdf0e10cSrcweir 
2064cdf0e10cSrcweir                     long nPosition = LONG_MAX;
2065cdf0e10cSrcweir                     aData.SetPosition( pNewDim, nPosition );
2066cdf0e10cSrcweir 
2067cdf0e10cSrcweir                     ScDPSaveDimension* pDataLayout = aData.GetDataLayoutDimension();
2068cdf0e10cSrcweir                     if ( pDataLayout->GetOrientation() == nOrientation &&
2069cdf0e10cSrcweir                          aData.GetDataDimensionCount() <= 1 )
2070cdf0e10cSrcweir                     {
2071cdf0e10cSrcweir                         // If there is only one data dimension, the data layout dimension
2072cdf0e10cSrcweir                         // must still be the last one in its orientation.
2073cdf0e10cSrcweir                         aData.SetPosition( pDataLayout, nPosition );
2074cdf0e10cSrcweir                     }
2075cdf0e10cSrcweir 
2076cdf0e10cSrcweir                     if ( pDuplicated )
2077cdf0e10cSrcweir                     {
2078cdf0e10cSrcweir                         // The duplicated (data) dimension needs to be behind the original dimension
2079cdf0e10cSrcweir                         aData.SetPosition( pDuplicated, nPosition );
2080cdf0e10cSrcweir                     }
2081cdf0e10cSrcweir 
2082cdf0e10cSrcweir                     //  Hide details for all visible members (selected are changed below).
2083cdf0e10cSrcweir                     //! Use all members from source level instead (including non-visible)?
2084cdf0e10cSrcweir 
2085cdf0e10cSrcweir                     ScStrCollection aVisibleEntries;
2086cdf0e10cSrcweir                     pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension );
2087cdf0e10cSrcweir 
2088cdf0e10cSrcweir                     sal_uInt16 nVisCount = aVisibleEntries.GetCount();
2089cdf0e10cSrcweir                     for (sal_uInt16 nVisPos=0; nVisPos<nVisCount; nVisPos++)
2090cdf0e10cSrcweir                     {
2091cdf0e10cSrcweir                         String aVisName = aVisibleEntries[nVisPos]->GetString();
2092cdf0e10cSrcweir                         ScDPSaveMember* pMember = pDim->GetMemberByName( aVisName );
2093cdf0e10cSrcweir                         pMember->SetShowDetails( sal_False );
2094cdf0e10cSrcweir                     }
2095cdf0e10cSrcweir                 }
2096cdf0e10cSrcweir 
2097cdf0e10cSrcweir                 sal_uInt16 nEntryCount = aEntries.GetCount();
2098cdf0e10cSrcweir                 for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
2099cdf0e10cSrcweir                 {
2100cdf0e10cSrcweir                     String aEntryName = aEntries[nEntry]->GetString();
2101cdf0e10cSrcweir                     ScDPSaveMember* pMember = pDim->GetMemberByName( aEntryName );
2102cdf0e10cSrcweir                     pMember->SetShowDetails( bShow );
2103cdf0e10cSrcweir                 }
2104cdf0e10cSrcweir 
2105cdf0e10cSrcweir                 // apply changes
2106cdf0e10cSrcweir                 ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
2107cdf0e10cSrcweir                 ScDPObject* pNewObj = new ScDPObject( *pDPObj );
2108cdf0e10cSrcweir                 pNewObj->SetSaveData( aData );
2109cdf0e10cSrcweir                 aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
2110cdf0e10cSrcweir                 delete pNewObj;
2111cdf0e10cSrcweir 
2112cdf0e10cSrcweir                 // unmark cell selection
2113cdf0e10cSrcweir                 Unmark();
2114cdf0e10cSrcweir             }
2115cdf0e10cSrcweir         }
2116cdf0e10cSrcweir     }
2117cdf0e10cSrcweir }
2118cdf0e10cSrcweir 
2119cdf0e10cSrcweir void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters )
2120cdf0e10cSrcweir {
2121cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
2122cdf0e10cSrcweir     if (pDoc->GetDocumentShell()->IsReadOnly())
2123cdf0e10cSrcweir     {
2124cdf0e10cSrcweir         ErrorMessage(STR_READONLYERR);
2125cdf0e10cSrcweir         return;
2126cdf0e10cSrcweir     }
2127cdf0e10cSrcweir 
2128cdf0e10cSrcweir     Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource();
2129cdf0e10cSrcweir     Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions();
2130cdf0e10cSrcweir     Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY);
2131cdf0e10cSrcweir     if (!xDDSupplier.is())
2132cdf0e10cSrcweir         return;
2133cdf0e10cSrcweir 
2134cdf0e10cSrcweir     Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters);
2135cdf0e10cSrcweir     sal_Int32 nRowSize = aTabData.getLength();
2136cdf0e10cSrcweir     if (nRowSize <= 1)
2137cdf0e10cSrcweir         // There is no data to show.  Bail out.
2138cdf0e10cSrcweir         return;
2139cdf0e10cSrcweir 
2140cdf0e10cSrcweir     sal_Int32 nColSize = aTabData[0].getLength();
2141cdf0e10cSrcweir 
2142cdf0e10cSrcweir     SCTAB nNewTab = GetViewData()->GetTabNo();
2143cdf0e10cSrcweir 
2144cdf0e10cSrcweir     auto_ptr<ScDocument> pInsDoc(new ScDocument(SCDOCMODE_CLIP));
2145cdf0e10cSrcweir     pInsDoc->ResetClip( pDoc, nNewTab );
2146cdf0e10cSrcweir     for (SCROW nRow = 0; nRow < nRowSize; ++nRow)
2147cdf0e10cSrcweir     {
2148cdf0e10cSrcweir         for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2149cdf0e10cSrcweir         {
2150cdf0e10cSrcweir             const Any& rAny = aTabData[nRow][nCol];
2151cdf0e10cSrcweir             rtl::OUString aStr;
2152cdf0e10cSrcweir             double fVal;
2153cdf0e10cSrcweir             if (rAny >>= aStr)
2154cdf0e10cSrcweir                 pInsDoc->PutCell( ScAddress(nCol, nRow, nNewTab), new ScStringCell(String(aStr)) );
2155cdf0e10cSrcweir             else if (rAny >>= fVal)
2156cdf0e10cSrcweir                 pInsDoc->SetValue(nCol, nRow, nNewTab, fVal);
2157cdf0e10cSrcweir         }
2158cdf0e10cSrcweir     }
2159cdf0e10cSrcweir 
2160cdf0e10cSrcweir     // set number format (important for dates)
2161cdf0e10cSrcweir     for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2162cdf0e10cSrcweir     {
2163cdf0e10cSrcweir         rtl::OUString aStr;
2164cdf0e10cSrcweir         if (!(aTabData[0][nCol] >>= aStr))
2165cdf0e10cSrcweir             continue;
2166cdf0e10cSrcweir 
2167cdf0e10cSrcweir         Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY);
2168cdf0e10cSrcweir         if (!xPropSet.is())
2169cdf0e10cSrcweir             continue;
2170cdf0e10cSrcweir 
2171cdf0e10cSrcweir         Any any = xPropSet->getPropertyValue( rtl::OUString::createFromAscii(SC_UNO_NUMBERFO) );
2172cdf0e10cSrcweir         sal_Int32 nNumFmt = 0;
2173cdf0e10cSrcweir         if (!(any >>= nNumFmt))
2174cdf0e10cSrcweir             continue;
2175cdf0e10cSrcweir 
2176cdf0e10cSrcweir         ScPatternAttr aPattern( pInsDoc->GetPool() );
2177cdf0e10cSrcweir         aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<sal_uInt32>(nNumFmt)) );
2178cdf0e10cSrcweir         pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern);
2179cdf0e10cSrcweir     }
2180cdf0e10cSrcweir 
2181cdf0e10cSrcweir     SCCOL nEndCol = 0;
2182cdf0e10cSrcweir     SCROW nEndRow = 0;
2183cdf0e10cSrcweir     pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow );
2184cdf0e10cSrcweir     pInsDoc->SetClipArea( ScRange( 0, 0, nNewTab, nEndCol, nEndRow, nNewTab ) );
2185cdf0e10cSrcweir 
2186cdf0e10cSrcweir     ::svl::IUndoManager* pMgr = GetViewData()->GetDocShell()->GetUndoManager();
2187cdf0e10cSrcweir     String aUndo = ScGlobal::GetRscString( STR_UNDO_DOOUTLINE );
2188cdf0e10cSrcweir     pMgr->EnterListAction( aUndo, aUndo );
2189cdf0e10cSrcweir 
2190cdf0e10cSrcweir     String aNewTabName;
2191cdf0e10cSrcweir     pDoc->CreateValidTabName(aNewTabName);
2192cdf0e10cSrcweir     if ( InsertTable(aNewTabName, nNewTab) )
2193cdf0e10cSrcweir         PasteFromClip( IDF_ALL, pInsDoc.get() );
2194cdf0e10cSrcweir 
2195cdf0e10cSrcweir     pMgr->LeaveListAction();
2196cdf0e10cSrcweir }
2197cdf0e10cSrcweir 
2198cdf0e10cSrcweir //
2199cdf0e10cSrcweir //			DB-Operationen (Sortieren, Filtern, Teilergebnisse) wiederholen
2200cdf0e10cSrcweir //
2201cdf0e10cSrcweir 
2202cdf0e10cSrcweir void ScDBFunc::RepeatDB( sal_Bool bRecord )
2203cdf0e10cSrcweir {
2204cdf0e10cSrcweir 	SCCOL nCurX = GetViewData()->GetCurX();
2205cdf0e10cSrcweir 	SCROW nCurY = GetViewData()->GetCurY();
2206cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
2207cdf0e10cSrcweir 	ScDocument* pDoc = GetViewData()->GetDocument();
2208cdf0e10cSrcweir 	ScDBData* pDBData = GetDBData();
2209cdf0e10cSrcweir 	if (bRecord && !pDoc->IsUndoEnabled())
2210cdf0e10cSrcweir 		bRecord = sal_False;
2211cdf0e10cSrcweir 
2212cdf0e10cSrcweir 	ScQueryParam aQueryParam;
2213cdf0e10cSrcweir 	pDBData->GetQueryParam( aQueryParam );
2214cdf0e10cSrcweir 	sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
2215cdf0e10cSrcweir 
2216cdf0e10cSrcweir 	ScSortParam aSortParam;
2217cdf0e10cSrcweir 	pDBData->GetSortParam( aSortParam );
2218cdf0e10cSrcweir 	sal_Bool bSort = aSortParam.bDoSort[0];
2219cdf0e10cSrcweir 
2220cdf0e10cSrcweir 	ScSubTotalParam aSubTotalParam;
2221cdf0e10cSrcweir 	pDBData->GetSubTotalParam( aSubTotalParam );
2222cdf0e10cSrcweir 	sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
2223cdf0e10cSrcweir 
2224cdf0e10cSrcweir 	if ( bQuery || bSort || bSubTotal )
2225cdf0e10cSrcweir 	{
2226cdf0e10cSrcweir 		sal_Bool bQuerySize = sal_False;
2227cdf0e10cSrcweir 		ScRange aOldQuery;
2228cdf0e10cSrcweir 		ScRange aNewQuery;
2229cdf0e10cSrcweir 		if (bQuery && !aQueryParam.bInplace)
2230cdf0e10cSrcweir 		{
2231cdf0e10cSrcweir 			ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2232cdf0e10cSrcweir 													aQueryParam.nDestTab, sal_True );
2233cdf0e10cSrcweir 			if (pDest && pDest->IsDoSize())
2234cdf0e10cSrcweir 			{
2235cdf0e10cSrcweir 				pDest->GetArea( aOldQuery );
2236cdf0e10cSrcweir 				bQuerySize = sal_True;
2237cdf0e10cSrcweir 			}
2238cdf0e10cSrcweir 		}
2239cdf0e10cSrcweir 
2240cdf0e10cSrcweir 		SCTAB nDummy;
2241cdf0e10cSrcweir 		SCCOL nStartCol;
2242cdf0e10cSrcweir 		SCROW nStartRow;
2243cdf0e10cSrcweir 		SCCOL nEndCol;
2244cdf0e10cSrcweir 		SCROW nEndRow;
2245cdf0e10cSrcweir 		pDBData->GetArea( nDummy, nStartCol, nStartRow, nEndCol, nEndRow );
2246cdf0e10cSrcweir 
2247cdf0e10cSrcweir 		//!		Undo nur benoetigte Daten ?
2248cdf0e10cSrcweir 
2249cdf0e10cSrcweir 		ScDocument* pUndoDoc = NULL;
2250cdf0e10cSrcweir 		ScOutlineTable* pUndoTab = NULL;
2251cdf0e10cSrcweir 		ScRangeName* pUndoRange = NULL;
2252cdf0e10cSrcweir 		ScDBCollection* pUndoDB = NULL;
2253cdf0e10cSrcweir 
2254cdf0e10cSrcweir 		if (bRecord)
2255cdf0e10cSrcweir 		{
2256cdf0e10cSrcweir 			SCTAB nTabCount = pDoc->GetTableCount();
2257cdf0e10cSrcweir 			pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2258cdf0e10cSrcweir 			ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
2259cdf0e10cSrcweir 			if (pTable)
2260cdf0e10cSrcweir 			{
2261cdf0e10cSrcweir 				pUndoTab = new ScOutlineTable( *pTable );
2262cdf0e10cSrcweir 
2263cdf0e10cSrcweir 				SCCOLROW nOutStartCol;							// Zeilen/Spaltenstatus
2264cdf0e10cSrcweir 				SCCOLROW nOutStartRow;
2265cdf0e10cSrcweir 				SCCOLROW nOutEndCol;
2266cdf0e10cSrcweir 				SCCOLROW nOutEndRow;
2267cdf0e10cSrcweir 				pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
2268cdf0e10cSrcweir 				pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
2269cdf0e10cSrcweir 
2270cdf0e10cSrcweir 				pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
2271cdf0e10cSrcweir 				pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc );
2272cdf0e10cSrcweir 				pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc );
2273cdf0e10cSrcweir 			}
2274cdf0e10cSrcweir 			else
2275cdf0e10cSrcweir 				pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True );
2276cdf0e10cSrcweir 
2277cdf0e10cSrcweir 			//	Datenbereich sichern - incl. Filter-Ergebnis
2278cdf0e10cSrcweir 			pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, sal_False, pUndoDoc );
2279cdf0e10cSrcweir 
2280cdf0e10cSrcweir 			//	alle Formeln wegen Referenzen
2281cdf0e10cSrcweir 			pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, sal_False, pUndoDoc );
2282cdf0e10cSrcweir 
2283cdf0e10cSrcweir 			//	DB- und andere Bereiche
2284cdf0e10cSrcweir 			ScRangeName* pDocRange = pDoc->GetRangeName();
2285cdf0e10cSrcweir 			if (pDocRange->GetCount())
2286cdf0e10cSrcweir 				pUndoRange = new ScRangeName( *pDocRange );
2287cdf0e10cSrcweir 			ScDBCollection* pDocDB = pDoc->GetDBCollection();
2288cdf0e10cSrcweir 			if (pDocDB->GetCount())
2289cdf0e10cSrcweir 				pUndoDB = new ScDBCollection( *pDocDB );
2290cdf0e10cSrcweir 		}
2291cdf0e10cSrcweir 
2292cdf0e10cSrcweir 		if (bSort && bSubTotal)
2293cdf0e10cSrcweir 		{
2294cdf0e10cSrcweir 			//	Sortieren ohne SubTotals
2295cdf0e10cSrcweir 
2296cdf0e10cSrcweir 			aSubTotalParam.bRemoveOnly = sal_True;		// wird unten wieder zurueckgesetzt
2297cdf0e10cSrcweir 			DoSubTotals( aSubTotalParam, sal_False );
2298cdf0e10cSrcweir 		}
2299cdf0e10cSrcweir 
2300cdf0e10cSrcweir 		if (bSort)
2301cdf0e10cSrcweir 		{
2302cdf0e10cSrcweir 			pDBData->GetSortParam( aSortParam );			// Bereich kann sich geaendert haben
2303cdf0e10cSrcweir 			Sort( aSortParam, sal_False, sal_False);
2304cdf0e10cSrcweir 		}
2305cdf0e10cSrcweir 		if (bQuery)
2306cdf0e10cSrcweir 		{
2307cdf0e10cSrcweir 			pDBData->GetQueryParam( aQueryParam );			// Bereich kann sich geaendert haben
2308cdf0e10cSrcweir 			ScRange aAdvSource;
2309cdf0e10cSrcweir 			if (pDBData->GetAdvancedQuerySource(aAdvSource))
2310cdf0e10cSrcweir 			{
2311cdf0e10cSrcweir 				pDoc->CreateQueryParam(
2312cdf0e10cSrcweir 					aAdvSource.aStart.Col(), aAdvSource.aStart.Row(),
2313cdf0e10cSrcweir 					aAdvSource.aEnd.Col(), aAdvSource.aEnd.Row(),
2314cdf0e10cSrcweir 					aAdvSource.aStart.Tab(), aQueryParam );
2315cdf0e10cSrcweir 				Query( aQueryParam, &aAdvSource, sal_False );
2316cdf0e10cSrcweir 			}
2317cdf0e10cSrcweir 			else
2318cdf0e10cSrcweir 				Query( aQueryParam, NULL, sal_False );
2319cdf0e10cSrcweir 
2320cdf0e10cSrcweir 			//	bei nicht-inplace kann die Tabelle umgestellt worden sein
2321cdf0e10cSrcweir 			if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
2322cdf0e10cSrcweir 				SetTabNo( nTab );
2323cdf0e10cSrcweir 		}
2324cdf0e10cSrcweir 		if (bSubTotal)
2325cdf0e10cSrcweir 		{
2326cdf0e10cSrcweir 			pDBData->GetSubTotalParam( aSubTotalParam );	// Bereich kann sich geaendert haben
2327cdf0e10cSrcweir 			aSubTotalParam.bRemoveOnly = sal_False;
2328cdf0e10cSrcweir 			DoSubTotals( aSubTotalParam, sal_False );
2329cdf0e10cSrcweir 		}
2330cdf0e10cSrcweir 
2331cdf0e10cSrcweir 		if (bRecord)
2332cdf0e10cSrcweir 		{
2333cdf0e10cSrcweir 			SCTAB nDummyTab;
2334cdf0e10cSrcweir             SCCOL nDummyCol;
2335cdf0e10cSrcweir 			SCROW nDummyRow, nNewEndRow;
2336cdf0e10cSrcweir 			pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
2337cdf0e10cSrcweir 
2338cdf0e10cSrcweir 			const ScRange* pOld = NULL;
2339cdf0e10cSrcweir 			const ScRange* pNew = NULL;
2340cdf0e10cSrcweir 			if (bQuerySize)
2341cdf0e10cSrcweir 			{
2342cdf0e10cSrcweir 				ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2343cdf0e10cSrcweir 														aQueryParam.nDestTab, sal_True );
2344cdf0e10cSrcweir 				if (pDest)
2345cdf0e10cSrcweir 				{
2346cdf0e10cSrcweir 					pDest->GetArea( aNewQuery );
2347cdf0e10cSrcweir 					pOld = &aOldQuery;
2348cdf0e10cSrcweir 					pNew = &aNewQuery;
2349cdf0e10cSrcweir 				}
2350cdf0e10cSrcweir 			}
2351cdf0e10cSrcweir 
2352cdf0e10cSrcweir 			GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction(
2353cdf0e10cSrcweir 				new ScUndoRepeatDB( GetViewData()->GetDocShell(), nTab,
2354cdf0e10cSrcweir 										nStartCol, nStartRow, nEndCol, nEndRow,
2355cdf0e10cSrcweir 										nNewEndRow,
2356cdf0e10cSrcweir 										nCurX, nCurY,
2357cdf0e10cSrcweir 										pUndoDoc, pUndoTab,
2358cdf0e10cSrcweir 										pUndoRange, pUndoDB,
2359cdf0e10cSrcweir 										pOld, pNew ) );
2360cdf0e10cSrcweir 		}
2361cdf0e10cSrcweir 
2362cdf0e10cSrcweir 		GetViewData()->GetDocShell()->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
2363cdf0e10cSrcweir 													PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
2364cdf0e10cSrcweir 	}
2365cdf0e10cSrcweir 	else		// "Keine Operationen auszufuehren"
2366cdf0e10cSrcweir 		ErrorMessage(STR_MSSG_REPEATDB_0);
2367cdf0e10cSrcweir }
2368cdf0e10cSrcweir 
2369cdf0e10cSrcweir 
2370cdf0e10cSrcweir 
2371cdf0e10cSrcweir 
2372