xref: /aoo41x/main/sc/source/ui/view/dbfunc3.cxx (revision ee342afc)
1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3b3f79822SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5b3f79822SAndrew Rist  * distributed with this work for additional information
6b3f79822SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7b3f79822SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist  * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist  * with the License.  You may obtain a copy of the License at
10b3f79822SAndrew Rist  *
11b3f79822SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12b3f79822SAndrew Rist  *
13b3f79822SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist  * software distributed under the License is distributed on an
15b3f79822SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist  * KIND, either express or implied.  See the License for the
17b3f79822SAndrew Rist  * specific language governing permissions and limitations
18b3f79822SAndrew Rist  * under the License.
19b3f79822SAndrew Rist  *
20b3f79822SAndrew Rist  *************************************************************/
21b3f79822SAndrew Rist 
22b3f79822SAndrew 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 
MakeOutline(sal_Bool bColumns,sal_Bool bRecord)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 
RemoveOutline(sal_Bool bColumns,sal_Bool bRecord)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 
TestRemoveOutline(sal_Bool & rCol,sal_Bool & rRow)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 
RemoveAllOutlines(sal_Bool bRecord)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 
AutoOutline(sal_Bool bRecord)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 
SelectLevel(sal_Bool bColumns,sal_uInt16 nLevel,sal_Bool bRecord,sal_Bool bPaint)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 
ShowOutline(sal_Bool bColumns,sal_uInt16 nLevel,sal_uInt16 nEntry,sal_Bool bRecord,sal_Bool bPaint)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 
HideOutline(sal_Bool bColumns,sal_uInt16 nLevel,sal_uInt16 nEntry,sal_Bool bRecord,sal_Bool bPaint)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 
OutlinePossible(sal_Bool bHide)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 
ShowMarkedOutlines(sal_Bool bRecord)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 
HideMarkedOutlines(sal_Bool bRecord)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 
DoSubTotals(const ScSubTotalParam & rParam,sal_Bool bRecord,const ScSortParam * pForceNewSort)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 
Consolidate(const ScConsolidateParam & rParam,sal_Bool bRecord)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 
lcl_MakePivotTabName(const String & rPrefix,SCTAB nNumber)579cdf0e10cSrcweir String lcl_MakePivotTabName( const String& rPrefix, SCTAB nNumber )
580cdf0e10cSrcweir {
581cdf0e10cSrcweir 	String aName = rPrefix;
582cdf0e10cSrcweir 	aName += String::CreateFromInt32( nNumber );
583cdf0e10cSrcweir 	return aName;
584cdf0e10cSrcweir }
585cdf0e10cSrcweir 
MakePivotTable(const ScDPSaveData & rData,const ScRange & rDest,sal_Bool bNewTable,const ScDPObject & rSource,sal_Bool bApi)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 
617*ee342afcSWang Lei 		const bool bDrawUndo = ( bUndo && !pDoc->IsDrawRecording() );
618*ee342afcSWang Lei 
619*ee342afcSWang Lei 		if( bDrawUndo )
620*ee342afcSWang Lei 			pDoc->BeginDrawUndo();
621*ee342afcSWang Lei 
622cdf0e10cSrcweir 		SCTAB i=1;
623cdf0e10cSrcweir 		while ( !pDoc->InsertTab( nNewTab, lcl_MakePivotTabName( aName, i ) ) && i <= MAXTAB )
624cdf0e10cSrcweir 			i++;
625cdf0e10cSrcweir 
626cdf0e10cSrcweir 		sal_Bool bAppend = ( nNewTab+1 == pDoc->GetTableCount() );
627cdf0e10cSrcweir 		if (bUndo)
628cdf0e10cSrcweir 		{
629cdf0e10cSrcweir 			pDocSh->GetUndoManager()->AddUndoAction(
630cdf0e10cSrcweir 						new ScUndoInsertTab( pDocSh, nNewTab, bAppend, lcl_MakePivotTabName( aName, i ) ));
631cdf0e10cSrcweir 		}
632cdf0e10cSrcweir 
633cdf0e10cSrcweir 		GetViewData()->InsertTab( nNewTab );
634cdf0e10cSrcweir 		SetTabNo( nNewTab, sal_True );
635cdf0e10cSrcweir 
636cdf0e10cSrcweir 		aDestRange = ScRange( 0, 0, nNewTab );
637*ee342afcSWang Lei 
638*ee342afcSWang Lei 		if( bDrawUndo )
639*ee342afcSWang Lei 			pDoc->EndDrawUndo();
640cdf0e10cSrcweir 	}
641cdf0e10cSrcweir 
642cdf0e10cSrcweir 	ScDPObject* pDPObj = pDoc->GetDPAtCursor(
643cdf0e10cSrcweir 							aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aStart.Tab() );
644cdf0e10cSrcweir 
645cdf0e10cSrcweir 	ScDPObject aObj( rSource );
646cdf0e10cSrcweir 	aObj.SetOutRange( aDestRange );
647cdf0e10cSrcweir     if ( pDPObj && !rData.GetExistingDimensionData() )
648cdf0e10cSrcweir     {
649cdf0e10cSrcweir         // copy dimension data from old object - lost in the dialog
650cdf0e10cSrcweir         //! change the dialog to keep the dimension data
651cdf0e10cSrcweir 
652cdf0e10cSrcweir         ScDPSaveData aNewData( rData );
653cdf0e10cSrcweir         const ScDPSaveData* pOldData = pDPObj->GetSaveData();
654cdf0e10cSrcweir         if ( pOldData )
655cdf0e10cSrcweir         {
656cdf0e10cSrcweir             const ScDPDimensionSaveData* pDimSave = pOldData->GetExistingDimensionData();
657cdf0e10cSrcweir             aNewData.SetDimensionData( pDimSave );
658cdf0e10cSrcweir         }
659cdf0e10cSrcweir         aObj.SetSaveData( aNewData );
660cdf0e10cSrcweir     }
661cdf0e10cSrcweir     else
662cdf0e10cSrcweir         aObj.SetSaveData( rData );
663cdf0e10cSrcweir 
664cdf0e10cSrcweir 	sal_Bool bAllowMove = ( pDPObj != NULL );	// allow re-positioning when editing existing table
665cdf0e10cSrcweir 
666cdf0e10cSrcweir 	ScDBDocFunc aFunc( *pDocSh );
667cdf0e10cSrcweir 	bool bSuccess = aFunc.DataPilotUpdate( pDPObj, &aObj, sal_True, sal_False, bAllowMove );
668cdf0e10cSrcweir 
669cdf0e10cSrcweir 	CursorPosChanged();		// shells may be switched
670cdf0e10cSrcweir 
671cdf0e10cSrcweir 	if ( bNewTable )
672cdf0e10cSrcweir 	{
673cdf0e10cSrcweir 		pDocSh->PostPaintExtras();
674cdf0e10cSrcweir 		SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
675cdf0e10cSrcweir 	}
676cdf0e10cSrcweir 
677cdf0e10cSrcweir 	return bSuccess;
678cdf0e10cSrcweir }
679cdf0e10cSrcweir 
DeletePivotTable()680cdf0e10cSrcweir void ScDBFunc::DeletePivotTable()
681cdf0e10cSrcweir {
682cdf0e10cSrcweir 	ScDocShell* pDocSh	  = GetViewData()->GetDocShell();
683cdf0e10cSrcweir 	ScDocument* pDoc	  = pDocSh->GetDocument();
684cdf0e10cSrcweir 	ScDPObject*	pDPObj    = pDoc->GetDPAtCursor( GetViewData()->GetCurX(),
685cdf0e10cSrcweir 												  GetViewData()->GetCurY(),
686cdf0e10cSrcweir 												  GetViewData()->GetTabNo() );
687cdf0e10cSrcweir 	if ( pDPObj )
688cdf0e10cSrcweir 	{
689cdf0e10cSrcweir 		ScDBDocFunc aFunc( *pDocSh );
690cdf0e10cSrcweir 		aFunc.DataPilotUpdate( pDPObj, NULL, sal_True, sal_False );
691cdf0e10cSrcweir 		CursorPosChanged();		// shells may be switched
692cdf0e10cSrcweir 	}
693cdf0e10cSrcweir 	else
694cdf0e10cSrcweir 		ErrorMessage(STR_PIVOT_NOTFOUND);
695cdf0e10cSrcweir }
RefreshDPObject(ScDPObject * pDPObj,ScDocument * pDoc,ScDocShell * pDocSh,sal_Bool bRecord,sal_Bool bApi)696cdf0e10cSrcweir sal_uLong RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, sal_Bool bRecord, sal_Bool bApi )
697cdf0e10cSrcweir {
698cdf0e10cSrcweir 	if( !pDPObj )
699cdf0e10cSrcweir 		return STR_PIVOT_NOTFOUND;
700cdf0e10cSrcweir 
701cdf0e10cSrcweir     if ( pDocSh && !pDoc )
702cdf0e10cSrcweir         pDoc = pDocSh->GetDocument();
703cdf0e10cSrcweir 
704cdf0e10cSrcweir 	if( !pDoc  )
705cdf0e10cSrcweir         return static_cast<sal_uLong>(-1);
706cdf0e10cSrcweir 
707cdf0e10cSrcweir 	if( !pDocSh && ( pDocSh = PTR_CAST( ScDocShell, pDoc->GetDocumentShell() ) ) == NULL )
708cdf0e10cSrcweir         return static_cast<sal_uLong>(-1);
709cdf0e10cSrcweir 
710cdf0e10cSrcweir 	if( sal_uLong nErrId = pDPObj->RefreshCache() )
711cdf0e10cSrcweir 		return nErrId;
712cdf0e10cSrcweir 	else if ( nErrId == 0 )
713cdf0e10cSrcweir 	{
714cdf0e10cSrcweir 		//Refresh all dpobjects
715cdf0e10cSrcweir 		ScDPCollection* pDPCollection = pDoc->GetDPCollection();
716cdf0e10cSrcweir 		sal_uInt16 nCount = pDPCollection->GetCount();
717cdf0e10cSrcweir 		for (sal_uInt16 i=0; i<nCount; i++)
718cdf0e10cSrcweir 		{
719cdf0e10cSrcweir 			if ( (*pDPCollection)[i]->GetCacheId() == pDPObj->GetCacheId()  )
720cdf0e10cSrcweir 			{
721cdf0e10cSrcweir 				ScDBDocFunc aFunc( * pDocSh );
722cdf0e10cSrcweir 				if ( !aFunc.DataPilotUpdate( (*pDPCollection)[i], (*pDPCollection)[i], bRecord, bApi ) )
723cdf0e10cSrcweir 					break;
724cdf0e10cSrcweir 			}
725cdf0e10cSrcweir 		}
726cdf0e10cSrcweir 
727cdf0e10cSrcweir 		return nErrId;
728cdf0e10cSrcweir 	}
729cdf0e10cSrcweir 
730cdf0e10cSrcweir 	return 0U;
731cdf0e10cSrcweir }
732cdf0e10cSrcweir 
RecalcPivotTable()733cdf0e10cSrcweir sal_uLong  ScDBFunc::RecalcPivotTable()
734cdf0e10cSrcweir {
735cdf0e10cSrcweir 	ScDocShell* pDocSh  = GetViewData()->GetDocShell();
736cdf0e10cSrcweir 	ScDocument* pDoc	= GetViewData()->GetDocument();
737cdf0e10cSrcweir 
738cdf0e10cSrcweir 	//	old pivot not used any more
739cdf0e10cSrcweir 
740cdf0e10cSrcweir 	ScDPObject*	pDPObj	= pDoc->GetDPAtCursor( GetViewData()->GetCurX(),
741cdf0e10cSrcweir 												  GetViewData()->GetCurY(),
742cdf0e10cSrcweir 												  GetViewData()->GetTabNo() );
743cdf0e10cSrcweir 	if ( pDPObj )
744cdf0e10cSrcweir 	{
745cdf0e10cSrcweir         // Wang Xu Ming -- 2009-6-17
746cdf0e10cSrcweir         // DataPilot Migration
747cdf0e10cSrcweir         //ScDBDocFunc aFunc( *pDocSh );
748cdf0e10cSrcweir         //aFunc.DataPilotUpdate( pDPObj, pDPObj, sal_True, sal_False );
749cdf0e10cSrcweir         //CursorPosChanged();      // shells may be switched
750cdf0e10cSrcweir         sal_uLong nErrId = RefreshDPObject( pDPObj, pDoc, pDocSh, sal_True, sal_False );//pDPObj->RefreshCache();
751cdf0e10cSrcweir         if ( nErrId == 0 )
752cdf0e10cSrcweir         {
753cdf0e10cSrcweir             // There is no undo for the refresh of the cache table, but the undo history for cell changes
754cdf0e10cSrcweir             // remains valid and should be preserved, so the history isn't cleared here.
755cdf0e10cSrcweir             //GetViewData()->GetDocShell()->GetUndoManager()->Clear();
756cdf0e10cSrcweir         }
757cdf0e10cSrcweir         else if (nErrId <= USHRT_MAX)
758cdf0e10cSrcweir             ErrorMessage(static_cast<sal_uInt16>(nErrId));
759cdf0e10cSrcweir       return nErrId;
760cdf0e10cSrcweir       // End Comments
761cdf0e10cSrcweir 	}
762cdf0e10cSrcweir 	else
763cdf0e10cSrcweir 		ErrorMessage(STR_PIVOT_NOTFOUND);
764cdf0e10cSrcweir     return STR_PIVOT_NOTFOUND;
765cdf0e10cSrcweir }
766cdf0e10cSrcweir 
GetSelectedMemberList(ScStrCollection & rEntries,long & rDimension)767cdf0e10cSrcweir void ScDBFunc::GetSelectedMemberList( ScStrCollection& rEntries, long& rDimension )
768cdf0e10cSrcweir {
769cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
770cdf0e10cSrcweir             							GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
771cdf0e10cSrcweir     if ( !pDPObj )
772cdf0e10cSrcweir         return;
773cdf0e10cSrcweir 
774cdf0e10cSrcweir     long nStartDimension = -1;
775cdf0e10cSrcweir     long nStartHierarchy = -1;
776cdf0e10cSrcweir     long nStartLevel     = -1;
777cdf0e10cSrcweir 
778cdf0e10cSrcweir     ScRangeListRef xRanges;
779cdf0e10cSrcweir     GetViewData()->GetMultiArea( xRanges );         // incl. cursor if nothing is selected
780cdf0e10cSrcweir     sal_uLong nRangeCount = xRanges->Count();
781cdf0e10cSrcweir     sal_Bool bContinue = sal_True;
782cdf0e10cSrcweir 
783cdf0e10cSrcweir     for (sal_uLong nRangePos=0; nRangePos<nRangeCount && bContinue; nRangePos++)
784cdf0e10cSrcweir     {
785cdf0e10cSrcweir         ScRange aRange = *xRanges->GetObject(nRangePos);
786cdf0e10cSrcweir         SCCOL nStartCol = aRange.aStart.Col();
787cdf0e10cSrcweir         SCROW nStartRow = aRange.aStart.Row();
788cdf0e10cSrcweir         SCCOL nEndCol = aRange.aEnd.Col();
789cdf0e10cSrcweir         SCROW nEndRow = aRange.aEnd.Row();
790cdf0e10cSrcweir         SCTAB nTab = aRange.aStart.Tab();
791cdf0e10cSrcweir 
792cdf0e10cSrcweir         for (SCROW nRow=nStartRow; nRow<=nEndRow && bContinue; nRow++)
793cdf0e10cSrcweir             for (SCCOL nCol=nStartCol; nCol<=nEndCol && bContinue; nCol++)
794cdf0e10cSrcweir             {
795cdf0e10cSrcweir                 sheet::DataPilotTableHeaderData aData;
796cdf0e10cSrcweir                 pDPObj->GetHeaderPositionData(ScAddress(nCol, nRow, nTab), aData);
797cdf0e10cSrcweir                 if ( aData.Dimension < 0 )
798cdf0e10cSrcweir                     bContinue = sal_False;              // not part of any dimension
799cdf0e10cSrcweir                 else
800cdf0e10cSrcweir                 {
801cdf0e10cSrcweir                     if ( nStartDimension < 0 )      // first member?
802cdf0e10cSrcweir                     {
803cdf0e10cSrcweir                         nStartDimension = aData.Dimension;
804cdf0e10cSrcweir                         nStartHierarchy = aData.Hierarchy;
805cdf0e10cSrcweir                         nStartLevel     = aData.Level;
806cdf0e10cSrcweir                     }
807cdf0e10cSrcweir                     if ( aData.Dimension != nStartDimension ||
808cdf0e10cSrcweir                          aData.Hierarchy != nStartHierarchy ||
809cdf0e10cSrcweir                          aData.Level     != nStartLevel )
810cdf0e10cSrcweir                     {
811cdf0e10cSrcweir                         bContinue = sal_False;          // cannot mix dimensions
812cdf0e10cSrcweir                     }
813cdf0e10cSrcweir                 }
814cdf0e10cSrcweir                 if ( bContinue )
815cdf0e10cSrcweir                 {
816cdf0e10cSrcweir                     // accept any part of a member description, also subtotals,
817cdf0e10cSrcweir                     // but don't stop if empty parts are contained
818cdf0e10cSrcweir                     if ( aData.Flags & sheet::MemberResultFlags::HASMEMBER )
819cdf0e10cSrcweir                     {
820cdf0e10cSrcweir                         StrData* pNew = new StrData( aData.MemberName );
821cdf0e10cSrcweir                         if ( !rEntries.Insert( pNew ) )
822cdf0e10cSrcweir                             delete pNew;
823cdf0e10cSrcweir                     }
824cdf0e10cSrcweir                 }
825cdf0e10cSrcweir             }
826cdf0e10cSrcweir     }
827cdf0e10cSrcweir 
828cdf0e10cSrcweir     rDimension = nStartDimension;   // dimension from which the found members came
829cdf0e10cSrcweir     if (!bContinue)
830cdf0e10cSrcweir         rEntries.FreeAll();         // remove all if not valid
831cdf0e10cSrcweir }
832cdf0e10cSrcweir 
HasSelectionForDateGroup(ScDPNumGroupInfo & rOldInfo,sal_Int32 & rParts)833cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForDateGroup( ScDPNumGroupInfo& rOldInfo, sal_Int32& rParts )
834cdf0e10cSrcweir {
835cdf0e10cSrcweir     // determine if the date group dialog has to be shown for the current selection
836cdf0e10cSrcweir 
837cdf0e10cSrcweir     sal_Bool bFound = sal_False;
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     SCCOL nCurX = GetViewData()->GetCurX();
840cdf0e10cSrcweir     SCROW nCurY = GetViewData()->GetCurY();
841cdf0e10cSrcweir     SCTAB nTab = GetViewData()->GetTabNo();
842cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
843cdf0e10cSrcweir 
844cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab );
845cdf0e10cSrcweir     if ( pDPObj )
846cdf0e10cSrcweir     {
847cdf0e10cSrcweir         ScStrCollection aEntries;
848cdf0e10cSrcweir         long nSelectDimension = -1;
849cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
850cdf0e10cSrcweir 
851cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
852cdf0e10cSrcweir         {
853cdf0e10cSrcweir             sal_Bool bIsDataLayout;
854cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
855cdf0e10cSrcweir             String aBaseDimName( aDimName );
856cdf0e10cSrcweir 
857cdf0e10cSrcweir             sal_Bool bInGroupDim = sal_False;
858cdf0e10cSrcweir             sal_Bool bFoundParts = sal_False;
859cdf0e10cSrcweir 
860cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData =
861cdf0e10cSrcweir                 const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() );
862cdf0e10cSrcweir             if ( pDimData )
863cdf0e10cSrcweir             {
864cdf0e10cSrcweir                 const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName );
865cdf0e10cSrcweir                 const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( aDimName );
866cdf0e10cSrcweir                 if ( pNumGroupDim )
867cdf0e10cSrcweir                 {
868cdf0e10cSrcweir                     //  existing num group dimension
869cdf0e10cSrcweir 
870cdf0e10cSrcweir                     if ( pNumGroupDim->GetDatePart() != 0 )
871cdf0e10cSrcweir                     {
872cdf0e10cSrcweir                         //  dimension has date info -> edit settings of this dimension
873cdf0e10cSrcweir                         //  (parts are collected below)
874cdf0e10cSrcweir 
875cdf0e10cSrcweir                         rOldInfo = pNumGroupDim->GetDateInfo();
876cdf0e10cSrcweir                         bFound = sal_True;
877cdf0e10cSrcweir                     }
878cdf0e10cSrcweir                     else if ( pNumGroupDim->GetInfo().DateValues )
879cdf0e10cSrcweir                     {
880cdf0e10cSrcweir                         //  Numerical grouping with DateValues flag is used for grouping
881cdf0e10cSrcweir                         //  of days with a "Number of days" value.
882cdf0e10cSrcweir 
883cdf0e10cSrcweir                         rOldInfo = pNumGroupDim->GetInfo();
884cdf0e10cSrcweir                         rParts = com::sun::star::sheet::DataPilotFieldGroupBy::DAYS;               // not found in CollectDateParts
885cdf0e10cSrcweir                         bFoundParts = sal_True;
886cdf0e10cSrcweir                         bFound = sal_True;
887cdf0e10cSrcweir                     }
888cdf0e10cSrcweir                     bInGroupDim = sal_True;
889cdf0e10cSrcweir                 }
890cdf0e10cSrcweir                 else if ( pGroupDim )
891cdf0e10cSrcweir                 {
892cdf0e10cSrcweir                     //  existing additional group dimension
893cdf0e10cSrcweir 
894cdf0e10cSrcweir                     if ( pGroupDim->GetDatePart() != 0 )
895cdf0e10cSrcweir                     {
896cdf0e10cSrcweir                         //  dimension has date info -> edit settings of this dimension
897cdf0e10cSrcweir                         //  (parts are collected below)
898cdf0e10cSrcweir 
899cdf0e10cSrcweir                         rOldInfo = pGroupDim->GetDateInfo();
900cdf0e10cSrcweir                         aBaseDimName = pGroupDim->GetSourceDimName();
901cdf0e10cSrcweir                         bFound = sal_True;
902cdf0e10cSrcweir                     }
903cdf0e10cSrcweir                     bInGroupDim = sal_True;
904cdf0e10cSrcweir                 }
905cdf0e10cSrcweir             }
906cdf0e10cSrcweir             if ( bFound && !bFoundParts )
907cdf0e10cSrcweir             {
908cdf0e10cSrcweir                 // collect date parts from all group dimensions
909cdf0e10cSrcweir                 rParts = pDimData->CollectDateParts( aBaseDimName );
910cdf0e10cSrcweir             }
911cdf0e10cSrcweir             if ( !bFound && !bInGroupDim )
912cdf0e10cSrcweir             {
913cdf0e10cSrcweir                 // create new date group dimensions if the selection is a single cell
914cdf0e10cSrcweir                 // in a normal dimension with date content
915cdf0e10cSrcweir 
916cdf0e10cSrcweir                 ScRange aSelRange;
917cdf0e10cSrcweir                 if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) &&
918cdf0e10cSrcweir                         aSelRange.aStart == aSelRange.aEnd )
919cdf0e10cSrcweir                 {
920cdf0e10cSrcweir                     SCCOL nSelCol = aSelRange.aStart.Col();
921cdf0e10cSrcweir                     SCROW nSelRow = aSelRange.aStart.Row();
922cdf0e10cSrcweir                     SCTAB nSelTab = aSelRange.aStart.Tab();
923cdf0e10cSrcweir                     if ( pDoc->HasValueData( nSelCol, nSelRow, nSelTab ) )
924cdf0e10cSrcweir                     {
925cdf0e10cSrcweir                         sal_uLong nIndex = static_cast<const SfxUInt32Item*>(pDoc->GetAttr(
926cdf0e10cSrcweir                                         nSelCol, nSelRow, nSelTab, ATTR_VALUE_FORMAT))->GetValue();
927cdf0e10cSrcweir                         short nType = pDoc->GetFormatTable()->GetType(nIndex);
928cdf0e10cSrcweir                         if ( nType == NUMBERFORMAT_DATE || nType == NUMBERFORMAT_TIME || nType == NUMBERFORMAT_DATETIME )
929cdf0e10cSrcweir                         {
930cdf0e10cSrcweir                             bFound = sal_True;
931cdf0e10cSrcweir                             // use currently selected value for automatic limits
932cdf0e10cSrcweir                             if( rOldInfo.AutoStart )
933cdf0e10cSrcweir                                 rOldInfo.Start = pDoc->GetValue( aSelRange.aStart );
934cdf0e10cSrcweir                             if( rOldInfo.AutoEnd )
935cdf0e10cSrcweir                                 rOldInfo.End = pDoc->GetValue( aSelRange.aStart );
936cdf0e10cSrcweir                         }
937cdf0e10cSrcweir                     }
938cdf0e10cSrcweir                 }
939cdf0e10cSrcweir             }
940cdf0e10cSrcweir         }
941cdf0e10cSrcweir     }
942cdf0e10cSrcweir 
943cdf0e10cSrcweir     return bFound;
944cdf0e10cSrcweir }
945cdf0e10cSrcweir 
HasSelectionForNumGroup(ScDPNumGroupInfo & rOldInfo)946cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForNumGroup( ScDPNumGroupInfo& rOldInfo )
947cdf0e10cSrcweir {
948cdf0e10cSrcweir     // determine if the numeric group dialog has to be shown for the current selection
949cdf0e10cSrcweir 
950cdf0e10cSrcweir     sal_Bool bFound = sal_False;
951cdf0e10cSrcweir 
952cdf0e10cSrcweir     SCCOL nCurX = GetViewData()->GetCurX();
953cdf0e10cSrcweir     SCROW nCurY = GetViewData()->GetCurY();
954cdf0e10cSrcweir     SCTAB nTab = GetViewData()->GetTabNo();
955cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
956cdf0e10cSrcweir 
957cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab );
958cdf0e10cSrcweir     if ( pDPObj )
959cdf0e10cSrcweir     {
960cdf0e10cSrcweir         ScStrCollection aEntries;
961cdf0e10cSrcweir         long nSelectDimension = -1;
962cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
963cdf0e10cSrcweir 
964cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
965cdf0e10cSrcweir         {
966cdf0e10cSrcweir             sal_Bool bIsDataLayout;
967cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
968cdf0e10cSrcweir 
969cdf0e10cSrcweir             sal_Bool bInGroupDim = sal_False;
970cdf0e10cSrcweir 
971cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData =
972cdf0e10cSrcweir                 const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() );
973cdf0e10cSrcweir             if ( pDimData )
974cdf0e10cSrcweir             {
975cdf0e10cSrcweir                 const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName );
976cdf0e10cSrcweir                 if ( pNumGroupDim )
977cdf0e10cSrcweir                 {
978cdf0e10cSrcweir                     //  existing num group dimension
979cdf0e10cSrcweir                     //  -> edit settings of this dimension
980cdf0e10cSrcweir 
981cdf0e10cSrcweir                     rOldInfo = pNumGroupDim->GetInfo();
982cdf0e10cSrcweir                     bFound = sal_True;
983cdf0e10cSrcweir                 }
984cdf0e10cSrcweir                 else if ( pDimData->GetNamedGroupDim( aDimName ) )
985cdf0e10cSrcweir                     bInGroupDim = sal_True;                                    // in a group dimension
986cdf0e10cSrcweir             }
987cdf0e10cSrcweir             if ( !bFound && !bInGroupDim )
988cdf0e10cSrcweir             {
989cdf0e10cSrcweir                 // create a new num group dimension if the selection is a single cell
990cdf0e10cSrcweir                 // in a normal dimension with numeric content
991cdf0e10cSrcweir 
992cdf0e10cSrcweir                 ScRange aSelRange;
993cdf0e10cSrcweir                 if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) &&
994cdf0e10cSrcweir                         aSelRange.aStart == aSelRange.aEnd )
995cdf0e10cSrcweir                 {
996cdf0e10cSrcweir                     if ( pDoc->HasValueData( aSelRange.aStart.Col(), aSelRange.aStart.Row(),
997cdf0e10cSrcweir                                              aSelRange.aStart.Tab() ) )
998cdf0e10cSrcweir                     {
999cdf0e10cSrcweir                         bFound = sal_True;
1000cdf0e10cSrcweir                         // use currently selected value for automatic limits
1001cdf0e10cSrcweir                         if( rOldInfo.AutoStart )
1002cdf0e10cSrcweir                             rOldInfo.Start = pDoc->GetValue( aSelRange.aStart );
1003cdf0e10cSrcweir                         if( rOldInfo.AutoEnd )
1004cdf0e10cSrcweir                             rOldInfo.End = pDoc->GetValue( aSelRange.aStart );
1005cdf0e10cSrcweir                     }
1006cdf0e10cSrcweir                 }
1007cdf0e10cSrcweir             }
1008cdf0e10cSrcweir         }
1009cdf0e10cSrcweir     }
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir     return bFound;
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir 
DateGroupDataPilot(const ScDPNumGroupInfo & rInfo,sal_Int32 nParts)1014cdf0e10cSrcweir void ScDBFunc::DateGroupDataPilot( const ScDPNumGroupInfo& rInfo, sal_Int32 nParts )
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1017cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1018cdf0e10cSrcweir     if ( pDPObj )
1019cdf0e10cSrcweir     {
1020cdf0e10cSrcweir         ScStrCollection aEntries;
1021cdf0e10cSrcweir         long nSelectDimension = -1;
1022cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1023cdf0e10cSrcweir 
1024cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1025cdf0e10cSrcweir         {
1026cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1027cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1028cdf0e10cSrcweir 
1029cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1030cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1031cdf0e10cSrcweir 
1032cdf0e10cSrcweir             // find original base
1033cdf0e10cSrcweir             String aBaseDimName = aDimName;
1034cdf0e10cSrcweir             if( const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ) )
1035cdf0e10cSrcweir                 aBaseDimName = pBaseGroupDim->GetSourceDimName();
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir             // remove all existing parts (the grouping is built completely new)
1038cdf0e10cSrcweir 
1039cdf0e10cSrcweir             /*  Remove numeric group dimension (exists once at most). No need
1040cdf0e10cSrcweir                 to delete anything in save data (grouping was done inplace in
1041cdf0e10cSrcweir                 an existing base dimension). */
1042cdf0e10cSrcweir             pDimData->RemoveNumGroupDimension( aBaseDimName );
1043cdf0e10cSrcweir 
1044cdf0e10cSrcweir             /*  Remove named group dimension(s). Collect deleted dimension
1045cdf0e10cSrcweir                 names which may be reused while recreating the groups.
1046cdf0e10cSrcweir                 Dimensions have to be removed from dimension save data and from
1047cdf0e10cSrcweir                 save data too. */
1048cdf0e10cSrcweir             std::vector< String > aDeletedNames;
1049cdf0e10cSrcweir             const ScDPSaveGroupDimension* pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName );
1050cdf0e10cSrcweir             while ( pExistingGroup )
1051cdf0e10cSrcweir             {
1052cdf0e10cSrcweir                 String aGroupDimName = pExistingGroup->GetGroupDimName();
1053cdf0e10cSrcweir                 pDimData->RemoveGroupDimension( aGroupDimName );     // pExistingGroup is deleted
1054cdf0e10cSrcweir 
1055cdf0e10cSrcweir                 // also remove SaveData settings for the dimension that no longer exists
1056cdf0e10cSrcweir                 aData.RemoveDimensionByName( aGroupDimName );
1057cdf0e10cSrcweir 
1058cdf0e10cSrcweir                 /*  The name can be used for the new group dimensions, although
1059cdf0e10cSrcweir                     it is still in use with the DataPilotSource. */
1060cdf0e10cSrcweir                 aDeletedNames.push_back( aGroupDimName );
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir                 // see if there are more group dimensions
1063cdf0e10cSrcweir                 pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName );
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir                 if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName )
1066cdf0e10cSrcweir                 {
1067cdf0e10cSrcweir                     // still get the same group dimension?
1068cdf0e10cSrcweir                     DBG_ERROR("couldn't remove group dimension");
1069cdf0e10cSrcweir                     pExistingGroup = NULL;      // avoid endless loop
1070cdf0e10cSrcweir                 }
1071cdf0e10cSrcweir             }
1072cdf0e10cSrcweir 
1073cdf0e10cSrcweir             if ( nParts )
1074cdf0e10cSrcweir             {
1075cdf0e10cSrcweir                 // create date group dimensions
1076cdf0e10cSrcweir 
1077cdf0e10cSrcweir                 ScDPNumGroupInfo aEmpty;
1078cdf0e10cSrcweir                 bool bFirst = true;
1079cdf0e10cSrcweir                 sal_Int32 nMask = 1;
1080cdf0e10cSrcweir                 for (sal_uInt16 nBit=0; nBit<32; nBit++)
1081cdf0e10cSrcweir                 {
1082cdf0e10cSrcweir                     if ( nParts & nMask )
1083cdf0e10cSrcweir                     {
1084cdf0e10cSrcweir                         if ( bFirst )
1085cdf0e10cSrcweir                         {
1086cdf0e10cSrcweir                             // innermost part: create NumGroupDimension (replacing original values)
1087cdf0e10cSrcweir                             // Dimension name is left unchanged
1088cdf0e10cSrcweir 
1089cdf0e10cSrcweir                             if ( (nParts == sheet::DataPilotFieldGroupBy::DAYS) && (rInfo.Step >= 1.0) )
1090cdf0e10cSrcweir                             {
1091cdf0e10cSrcweir                                 // only days, and a step value specified: use numerical grouping
1092cdf0e10cSrcweir                                 // with DateValues flag, not date grouping
1093cdf0e10cSrcweir 
1094cdf0e10cSrcweir                                 ScDPNumGroupInfo aNumInfo( rInfo );
1095cdf0e10cSrcweir                                 aNumInfo.DateValues = sal_True;
1096cdf0e10cSrcweir 
1097cdf0e10cSrcweir                                 ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, aNumInfo );
1098cdf0e10cSrcweir                                 pDimData->AddNumGroupDimension( aNumGroupDim );
1099cdf0e10cSrcweir                             }
1100cdf0e10cSrcweir                             else
1101cdf0e10cSrcweir                             {
1102cdf0e10cSrcweir                                 ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, rInfo, nMask );
1103cdf0e10cSrcweir                                 pDimData->AddNumGroupDimension( aNumGroupDim );
1104cdf0e10cSrcweir                             }
1105cdf0e10cSrcweir 
1106cdf0e10cSrcweir                             bFirst = false;
1107cdf0e10cSrcweir                         }
1108cdf0e10cSrcweir                         else
1109cdf0e10cSrcweir                         {
1110cdf0e10cSrcweir                             // additional parts: create GroupDimension (shown as additional dimensions)
1111cdf0e10cSrcweir                             String aGroupDimName = pDimData->CreateDateGroupDimName( nMask, *pDPObj, true, &aDeletedNames );
1112cdf0e10cSrcweir                             ScDPSaveGroupDimension aGroupDim( aBaseDimName, aGroupDimName );
1113cdf0e10cSrcweir                             aGroupDim.SetDateInfo( rInfo, nMask );
1114cdf0e10cSrcweir                             pDimData->AddGroupDimension( aGroupDim );
1115cdf0e10cSrcweir 
1116cdf0e10cSrcweir                             // set orientation
1117cdf0e10cSrcweir                             ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName );
1118cdf0e10cSrcweir                             if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN )
1119cdf0e10cSrcweir                             {
1120cdf0e10cSrcweir                                 ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aBaseDimName );
1121cdf0e10cSrcweir                                 pSaveDimension->SetOrientation( pOldDimension->GetOrientation() );
1122cdf0e10cSrcweir                                 long nPosition = 0;     //! before (immediate) base
1123cdf0e10cSrcweir                                 aData.SetPosition( pSaveDimension, nPosition );
1124cdf0e10cSrcweir                             }
1125cdf0e10cSrcweir                         }
1126cdf0e10cSrcweir                     }
1127cdf0e10cSrcweir                     nMask *= 2;
1128cdf0e10cSrcweir                 }
1129cdf0e10cSrcweir             }
1130cdf0e10cSrcweir 
1131cdf0e10cSrcweir             // apply changes
1132cdf0e10cSrcweir             ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1133cdf0e10cSrcweir             ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1134cdf0e10cSrcweir             pNewObj->SetSaveData( aData );
1135cdf0e10cSrcweir             aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1136cdf0e10cSrcweir             delete pNewObj;
1137cdf0e10cSrcweir 
1138cdf0e10cSrcweir             // unmark cell selection
1139cdf0e10cSrcweir             Unmark();
1140cdf0e10cSrcweir         }
1141cdf0e10cSrcweir     }
1142cdf0e10cSrcweir }
1143cdf0e10cSrcweir 
NumGroupDataPilot(const ScDPNumGroupInfo & rInfo)1144cdf0e10cSrcweir void ScDBFunc::NumGroupDataPilot( const ScDPNumGroupInfo& rInfo )
1145cdf0e10cSrcweir {
1146cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1147cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1148cdf0e10cSrcweir     if ( pDPObj )
1149cdf0e10cSrcweir     {
1150cdf0e10cSrcweir         ScStrCollection aEntries;
1151cdf0e10cSrcweir         long nSelectDimension = -1;
1152cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1153cdf0e10cSrcweir 
1154cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1155cdf0e10cSrcweir         {
1156cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1157cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1158cdf0e10cSrcweir 
1159cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1160cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1161cdf0e10cSrcweir 
1162cdf0e10cSrcweir             ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( aDimName );
1163cdf0e10cSrcweir             if ( pExisting )
1164cdf0e10cSrcweir             {
1165cdf0e10cSrcweir                 // modify existing group dimension
1166cdf0e10cSrcweir                 pExisting->SetGroupInfo( rInfo );
1167cdf0e10cSrcweir             }
1168cdf0e10cSrcweir             else
1169cdf0e10cSrcweir             {
1170cdf0e10cSrcweir                 // create new group dimension
1171cdf0e10cSrcweir                 ScDPSaveNumGroupDimension aNumGroupDim( aDimName, rInfo );
1172cdf0e10cSrcweir                 pDimData->AddNumGroupDimension( aNumGroupDim );
1173cdf0e10cSrcweir             }
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir             // apply changes
1176cdf0e10cSrcweir             ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1177cdf0e10cSrcweir             ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1178cdf0e10cSrcweir             pNewObj->SetSaveData( aData );
1179cdf0e10cSrcweir             aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1180cdf0e10cSrcweir             delete pNewObj;
1181cdf0e10cSrcweir 
1182cdf0e10cSrcweir             // unmark cell selection
1183cdf0e10cSrcweir             Unmark();
1184cdf0e10cSrcweir         }
1185cdf0e10cSrcweir     }
1186cdf0e10cSrcweir }
1187cdf0e10cSrcweir 
GroupDataPilot()1188cdf0e10cSrcweir void ScDBFunc::GroupDataPilot()
1189cdf0e10cSrcweir {
1190cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1191cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1192cdf0e10cSrcweir     if ( pDPObj )
1193cdf0e10cSrcweir     {
1194cdf0e10cSrcweir         ScStrCollection aEntries;
1195cdf0e10cSrcweir         long nSelectDimension = -1;
1196cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1197cdf0e10cSrcweir 
1198cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1199cdf0e10cSrcweir         {
1200cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1201cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1202cdf0e10cSrcweir 
1203cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1204cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir             // find original base
1207cdf0e10cSrcweir             String aBaseDimName( aDimName );
1208cdf0e10cSrcweir             const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName );
1209cdf0e10cSrcweir             if ( pBaseGroupDim )
1210cdf0e10cSrcweir             {
1211cdf0e10cSrcweir                 // any entry's SourceDimName is the original base
1212cdf0e10cSrcweir                 aBaseDimName = pBaseGroupDim->GetSourceDimName();
1213cdf0e10cSrcweir             }
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir             // find existing group dimension
1216cdf0e10cSrcweir             // (using the selected dim, can be intermediate group dim)
1217cdf0e10cSrcweir             ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName );
1218cdf0e10cSrcweir 
1219cdf0e10cSrcweir             // remove the selected items from their groups
1220cdf0e10cSrcweir             // (empty groups are removed, too)
1221cdf0e10cSrcweir             sal_uInt16 nEntryCount = aEntries.GetCount();
1222cdf0e10cSrcweir             sal_uInt16 nEntry;
1223cdf0e10cSrcweir             if ( pGroupDimension )
1224cdf0e10cSrcweir             {
1225cdf0e10cSrcweir                 for (nEntry=0; nEntry<nEntryCount; nEntry++)
1226cdf0e10cSrcweir                 {
1227cdf0e10cSrcweir                     String aEntryName = aEntries[nEntry]->GetString();
1228cdf0e10cSrcweir                     if ( pBaseGroupDim )
1229cdf0e10cSrcweir                     {
1230cdf0e10cSrcweir                         // for each selected (intermediate) group, remove all its items
1231cdf0e10cSrcweir                         // (same logic as for adding, below)
1232cdf0e10cSrcweir                         const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
1233cdf0e10cSrcweir                         if ( pBaseGroup )
1234cdf0e10cSrcweir                             pBaseGroup->RemoveElementsFromGroups( *pGroupDimension );   // remove all elements
1235cdf0e10cSrcweir                         else
1236cdf0e10cSrcweir                             pGroupDimension->RemoveFromGroups( aEntryName );
1237cdf0e10cSrcweir                     }
1238cdf0e10cSrcweir                     else
1239cdf0e10cSrcweir                         pGroupDimension->RemoveFromGroups( aEntryName );
1240cdf0e10cSrcweir                 }
1241cdf0e10cSrcweir             }
1242cdf0e10cSrcweir 
1243cdf0e10cSrcweir             ScDPSaveGroupDimension* pNewGroupDim = NULL;
1244cdf0e10cSrcweir             if ( !pGroupDimension )
1245cdf0e10cSrcweir             {
1246cdf0e10cSrcweir                 // create a new group dimension
1247cdf0e10cSrcweir                 String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL );
1248cdf0e10cSrcweir                 pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName );
1249cdf0e10cSrcweir 
1250cdf0e10cSrcweir                 pGroupDimension = pNewGroupDim;     // make changes to the new dim if none existed
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir                 if ( pBaseGroupDim )
1253cdf0e10cSrcweir                 {
1254cdf0e10cSrcweir                     // If it's a higher-order group dimension, pre-allocate groups for all
1255cdf0e10cSrcweir                     // non-selected original groups, so the individual base members aren't
1256cdf0e10cSrcweir                     // used for automatic groups (this would make the original groups hard
1257cdf0e10cSrcweir                     // to find).
1258cdf0e10cSrcweir                     //! Also do this when removing groups?
1259cdf0e10cSrcweir                     //! Handle this case dynamically with automatic groups?
1260cdf0e10cSrcweir 
1261cdf0e10cSrcweir                     long nGroupCount = pBaseGroupDim->GetGroupCount();
1262cdf0e10cSrcweir                     for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ )
1263cdf0e10cSrcweir                     {
1264cdf0e10cSrcweir                         const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup );
1265cdf0e10cSrcweir 
1266cdf0e10cSrcweir                         StrData aStrData( pBaseGroup->GetGroupName() );
1267cdf0e10cSrcweir                         sal_uInt16 nCollIndex;
1268cdf0e10cSrcweir                         if ( !aEntries.Search( &aStrData, nCollIndex ) )    //! ignore case?
1269cdf0e10cSrcweir                         {
1270cdf0e10cSrcweir                             // add an additional group for each item that is not in the selection
1271cdf0e10cSrcweir                             ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() );
1272cdf0e10cSrcweir                             aGroup.AddElementsFromGroup( *pBaseGroup );
1273cdf0e10cSrcweir                             pGroupDimension->AddGroupItem( aGroup );
1274cdf0e10cSrcweir                         }
1275cdf0e10cSrcweir                     }
1276cdf0e10cSrcweir                 }
1277cdf0e10cSrcweir             }
1278cdf0e10cSrcweir             String aGroupDimName = pGroupDimension->GetGroupDimName();
1279cdf0e10cSrcweir 
1280cdf0e10cSrcweir             //! localized prefix string
1281cdf0e10cSrcweir             String aGroupName = pGroupDimension->CreateGroupName( String::CreateFromAscii("Group") );
1282cdf0e10cSrcweir             ScDPSaveGroupItem aGroup( aGroupName );
1283cdf0e10cSrcweir             for (nEntry=0; nEntry<nEntryCount; nEntry++)
1284cdf0e10cSrcweir             {
1285cdf0e10cSrcweir                 String aEntryName = aEntries[nEntry]->GetString();
1286cdf0e10cSrcweir                 if ( pBaseGroupDim )
1287cdf0e10cSrcweir                 {
1288cdf0e10cSrcweir                     // for each selected (intermediate) group, add all its items
1289cdf0e10cSrcweir                     const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName );
1290cdf0e10cSrcweir                     if ( pBaseGroup )
1291cdf0e10cSrcweir                         aGroup.AddElementsFromGroup( *pBaseGroup );
1292cdf0e10cSrcweir                     else
1293cdf0e10cSrcweir                         aGroup.AddElement( aEntryName );    // no group found -> automatic group, add the item itself
1294cdf0e10cSrcweir                 }
1295cdf0e10cSrcweir                 else
1296cdf0e10cSrcweir                     aGroup.AddElement( aEntryName );        // no group dimension, add all items directly
1297cdf0e10cSrcweir             }
1298cdf0e10cSrcweir 
1299cdf0e10cSrcweir             pGroupDimension->AddGroupItem( aGroup );
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir             if ( pNewGroupDim )
1302cdf0e10cSrcweir             {
1303cdf0e10cSrcweir                 pDimData->AddGroupDimension( *pNewGroupDim );
1304cdf0e10cSrcweir                 delete pNewGroupDim;        // AddGroupDimension copies the object
1305cdf0e10cSrcweir                 // don't access pGroupDimension after here
1306cdf0e10cSrcweir             }
1307cdf0e10cSrcweir             pGroupDimension = pNewGroupDim = NULL;
1308cdf0e10cSrcweir 
1309cdf0e10cSrcweir             // set orientation
1310cdf0e10cSrcweir             ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName );
1311cdf0e10cSrcweir             if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN )
1312cdf0e10cSrcweir             {
1313cdf0e10cSrcweir                 ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aDimName );
1314cdf0e10cSrcweir                 pSaveDimension->SetOrientation( pOldDimension->GetOrientation() );
1315cdf0e10cSrcweir                 long nPosition = 0;     //! before (immediate) base
1316cdf0e10cSrcweir                 aData.SetPosition( pSaveDimension, nPosition );
1317cdf0e10cSrcweir             }
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir             // apply changes
1320cdf0e10cSrcweir             ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1321cdf0e10cSrcweir             ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1322cdf0e10cSrcweir             pNewObj->SetSaveData( aData );
1323cdf0e10cSrcweir             aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1324cdf0e10cSrcweir             delete pNewObj;
1325cdf0e10cSrcweir 
1326cdf0e10cSrcweir             // unmark cell selection
1327cdf0e10cSrcweir             Unmark();
1328cdf0e10cSrcweir         }
1329cdf0e10cSrcweir     }
1330cdf0e10cSrcweir }
1331cdf0e10cSrcweir 
UngroupDataPilot()1332cdf0e10cSrcweir void ScDBFunc::UngroupDataPilot()
1333cdf0e10cSrcweir {
1334cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
1335cdf0e10cSrcweir                                         GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1336cdf0e10cSrcweir     if ( pDPObj )
1337cdf0e10cSrcweir     {
1338cdf0e10cSrcweir         ScStrCollection aEntries;
1339cdf0e10cSrcweir         long nSelectDimension = -1;
1340cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
1341cdf0e10cSrcweir 
1342cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
1343cdf0e10cSrcweir         {
1344cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1345cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1346cdf0e10cSrcweir 
1347cdf0e10cSrcweir             ScDPSaveData aData( *pDPObj->GetSaveData() );
1348cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();     // created if not there
1349cdf0e10cSrcweir             //! test first if DimensionData exists?
1350cdf0e10cSrcweir 
1351cdf0e10cSrcweir             sal_Bool bApply = sal_False;
1352cdf0e10cSrcweir 
1353cdf0e10cSrcweir             ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
1354cdf0e10cSrcweir             const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName );
1355cdf0e10cSrcweir             if ( ( pGroupDim && pGroupDim->GetDatePart() != 0 ) ||
1356cdf0e10cSrcweir                  ( pNumGroupDim && pNumGroupDim->GetDatePart() != 0 ) )
1357cdf0e10cSrcweir             {
1358cdf0e10cSrcweir                 // Date grouping: need to remove all affected group dimensions.
1359cdf0e10cSrcweir                 // This is done using DateGroupDataPilot with nParts=0.
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir                 DateGroupDataPilot( ScDPNumGroupInfo(), 0 );
1362cdf0e10cSrcweir                 // bApply remains FALSE
1363cdf0e10cSrcweir                 // dimension pointers become invalid
1364cdf0e10cSrcweir             }
1365cdf0e10cSrcweir             else if ( pGroupDim )
1366cdf0e10cSrcweir             {
1367cdf0e10cSrcweir                 sal_uInt16 nEntryCount = aEntries.GetCount();
1368cdf0e10cSrcweir                 for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
1369cdf0e10cSrcweir                 {
1370cdf0e10cSrcweir                     String aEntryName = aEntries[nEntry]->GetString();
1371cdf0e10cSrcweir                     pGroupDim->RemoveGroup( aEntryName );
1372cdf0e10cSrcweir                 }
1373cdf0e10cSrcweir                 // remove group dimension if empty
1374cdf0e10cSrcweir                 bool bEmptyDim = pGroupDim->IsEmpty();
1375cdf0e10cSrcweir                 if ( !bEmptyDim )
1376cdf0e10cSrcweir                 {
1377cdf0e10cSrcweir                     // If all remaining groups in the dimension aren't shown, remove
1378cdf0e10cSrcweir                     // the dimension too, as if it was completely empty.
1379cdf0e10cSrcweir                     ScStrCollection aVisibleEntries;
1380cdf0e10cSrcweir                     pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension );
1381cdf0e10cSrcweir                     bEmptyDim = pGroupDim->HasOnlyHidden( aVisibleEntries );
1382cdf0e10cSrcweir                 }
1383cdf0e10cSrcweir                 if ( bEmptyDim )
1384cdf0e10cSrcweir                 {
1385cdf0e10cSrcweir                     pDimData->RemoveGroupDimension( aDimName );     // pGroupDim is deleted
1386cdf0e10cSrcweir 
1387cdf0e10cSrcweir                     // also remove SaveData settings for the dimension that no longer exists
1388cdf0e10cSrcweir                     aData.RemoveDimensionByName( aDimName );
1389cdf0e10cSrcweir                 }
1390cdf0e10cSrcweir                 bApply = sal_True;
1391cdf0e10cSrcweir             }
1392cdf0e10cSrcweir             else if ( pNumGroupDim )
1393cdf0e10cSrcweir             {
1394cdf0e10cSrcweir                 // remove the numerical grouping
1395cdf0e10cSrcweir                 pDimData->RemoveNumGroupDimension( aDimName );
1396cdf0e10cSrcweir                 // SaveData settings can remain unchanged - the same dimension still exists
1397cdf0e10cSrcweir                 bApply = sal_True;
1398cdf0e10cSrcweir             }
1399cdf0e10cSrcweir 
1400cdf0e10cSrcweir             if ( bApply )
1401cdf0e10cSrcweir             {
1402cdf0e10cSrcweir                 // apply changes
1403cdf0e10cSrcweir                 ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1404cdf0e10cSrcweir                 ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1405cdf0e10cSrcweir                 pNewObj->SetSaveData( aData );
1406cdf0e10cSrcweir                 aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1407cdf0e10cSrcweir                 delete pNewObj;
1408cdf0e10cSrcweir 
1409cdf0e10cSrcweir                 // unmark cell selection
1410cdf0e10cSrcweir                 Unmark();
1411cdf0e10cSrcweir             }
1412cdf0e10cSrcweir         }
1413cdf0e10cSrcweir     }
1414cdf0e10cSrcweir }
1415cdf0e10cSrcweir 
lcl_replaceMemberNameInSubtotal(const OUString & rSubtotal,const OUString & rMemberName)1416cdf0e10cSrcweir static OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName)
1417cdf0e10cSrcweir {
1418cdf0e10cSrcweir     sal_Int32 n = rSubtotal.getLength();
1419cdf0e10cSrcweir     const sal_Unicode* p = rSubtotal.getStr();
1420cdf0e10cSrcweir     OUStringBuffer aBuf, aWordBuf;
1421cdf0e10cSrcweir     for (sal_Int32 i = 0; i < n; ++i)
1422cdf0e10cSrcweir     {
1423cdf0e10cSrcweir         sal_Unicode c = p[i];
1424cdf0e10cSrcweir         if (c == sal_Unicode(' '))
1425cdf0e10cSrcweir         {
1426cdf0e10cSrcweir             OUString aWord = aWordBuf.makeStringAndClear();
1427cdf0e10cSrcweir             if (aWord.equals(rMemberName))
1428cdf0e10cSrcweir                 aBuf.append(sal_Unicode('?'));
1429cdf0e10cSrcweir             else
1430cdf0e10cSrcweir                 aBuf.append(aWord);
1431cdf0e10cSrcweir             aBuf.append(c);
1432cdf0e10cSrcweir         }
1433cdf0e10cSrcweir         else if (c == sal_Unicode('\\'))
1434cdf0e10cSrcweir         {
1435cdf0e10cSrcweir             // Escape a backslash character.
1436cdf0e10cSrcweir             aWordBuf.append(c);
1437cdf0e10cSrcweir             aWordBuf.append(c);
1438cdf0e10cSrcweir         }
1439cdf0e10cSrcweir         else if (c == sal_Unicode('?'))
1440cdf0e10cSrcweir         {
1441cdf0e10cSrcweir             // A literal '?' must be escaped with a backslash ('\');
1442cdf0e10cSrcweir             aWordBuf.append(sal_Unicode('\\'));
1443cdf0e10cSrcweir             aWordBuf.append(c);
1444cdf0e10cSrcweir         }
1445cdf0e10cSrcweir         else
1446cdf0e10cSrcweir             aWordBuf.append(c);
1447cdf0e10cSrcweir     }
1448cdf0e10cSrcweir 
1449cdf0e10cSrcweir     if (aWordBuf.getLength() > 0)
1450cdf0e10cSrcweir     {
1451cdf0e10cSrcweir         OUString aWord = aWordBuf.makeStringAndClear();
1452cdf0e10cSrcweir         if (aWord.equals(rMemberName))
1453cdf0e10cSrcweir             aBuf.append(sal_Unicode('?'));
1454cdf0e10cSrcweir         else
1455cdf0e10cSrcweir             aBuf.append(aWord);
1456cdf0e10cSrcweir     }
1457cdf0e10cSrcweir 
1458cdf0e10cSrcweir     return aBuf.makeStringAndClear();
1459cdf0e10cSrcweir }
1460cdf0e10cSrcweir 
DataPilotInput(const ScAddress & rPos,const String & rString)1461cdf0e10cSrcweir void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString )
1462cdf0e10cSrcweir {
1463cdf0e10cSrcweir     using namespace ::com::sun::star::sheet;
1464cdf0e10cSrcweir 
1465cdf0e10cSrcweir     String aNewName( rString );
1466cdf0e10cSrcweir 
1467cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
1468cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() );
1469cdf0e10cSrcweir     if (!pDPObj)
1470cdf0e10cSrcweir         return;
1471cdf0e10cSrcweir 
1472cdf0e10cSrcweir     String aOldText;
1473cdf0e10cSrcweir     pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText );
1474cdf0e10cSrcweir 
1475cdf0e10cSrcweir     if ( aOldText == rString )
1476cdf0e10cSrcweir     {
1477cdf0e10cSrcweir         // nothing to do: silently exit
1478cdf0e10cSrcweir         return;
1479cdf0e10cSrcweir     }
1480cdf0e10cSrcweir 
1481cdf0e10cSrcweir     sal_uInt16 nErrorId = 0;
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir     pDPObj->BuildAllDimensionMembers();
1484cdf0e10cSrcweir     ScDPSaveData aData( *pDPObj->GetSaveData() );
1485cdf0e10cSrcweir     sal_Bool bChange = sal_False;
1486cdf0e10cSrcweir 
1487cdf0e10cSrcweir     sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN;
1488cdf0e10cSrcweir     long nField = pDPObj->GetHeaderDim( rPos, nOrient );
1489cdf0e10cSrcweir     if ( nField >= 0 )
1490cdf0e10cSrcweir     {
1491cdf0e10cSrcweir         // changing a field title
1492cdf0e10cSrcweir         if ( aData.GetExistingDimensionData() )
1493cdf0e10cSrcweir         {
1494cdf0e10cSrcweir             // only group dimensions can be renamed
1495cdf0e10cSrcweir 
1496cdf0e10cSrcweir             ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1497cdf0e10cSrcweir             ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
1498cdf0e10cSrcweir             if ( pGroupDim )
1499cdf0e10cSrcweir             {
1500cdf0e10cSrcweir                 // valid name: not empty, no existing dimension (group or other)
1501cdf0e10cSrcweir                 if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) )
1502cdf0e10cSrcweir                 {
1503cdf0e10cSrcweir                     pGroupDim->Rename( aNewName );
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir                     // also rename in SaveData to preserve the field settings
1506cdf0e10cSrcweir                     ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
1507cdf0e10cSrcweir                     pSaveDim->SetName( aNewName );
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir                     bChange = sal_True;
1510cdf0e10cSrcweir                 }
1511cdf0e10cSrcweir                 else
1512cdf0e10cSrcweir                     nErrorId = STR_INVALIDNAME;
1513cdf0e10cSrcweir             }
1514cdf0e10cSrcweir         }
1515cdf0e10cSrcweir         else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW)
1516cdf0e10cSrcweir         {
1517cdf0e10cSrcweir             sal_Bool bDataLayout = false;
1518cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName(nField, bDataLayout);
1519cdf0e10cSrcweir             ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName);
1520cdf0e10cSrcweir             if (pDim)
1521cdf0e10cSrcweir             {
1522cdf0e10cSrcweir                 if (rString.Len())
1523cdf0e10cSrcweir                 {
1524cdf0e10cSrcweir                     if (rString.EqualsIgnoreCaseAscii(aDimName))
1525cdf0e10cSrcweir                     {
1526cdf0e10cSrcweir                         pDim->RemoveLayoutName();
1527cdf0e10cSrcweir                         bChange = true;
1528cdf0e10cSrcweir                     }
1529cdf0e10cSrcweir                     else if (!pDPObj->IsDimNameInUse(rString))
1530cdf0e10cSrcweir                     {
1531cdf0e10cSrcweir                         pDim->SetLayoutName(rString);
1532cdf0e10cSrcweir                         bChange = true;
1533cdf0e10cSrcweir                     }
1534cdf0e10cSrcweir                     else
1535cdf0e10cSrcweir                         nErrorId = STR_INVALIDNAME;
1536cdf0e10cSrcweir                 }
1537cdf0e10cSrcweir                 else
1538cdf0e10cSrcweir                     nErrorId = STR_INVALIDNAME;
1539cdf0e10cSrcweir             }
1540cdf0e10cSrcweir         }
1541cdf0e10cSrcweir     }
1542cdf0e10cSrcweir     else if (pDPObj->IsDataDescriptionCell(rPos))
1543cdf0e10cSrcweir     {
1544cdf0e10cSrcweir         // There is only one data dimension.
1545cdf0e10cSrcweir         ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA);
1546cdf0e10cSrcweir         if (pDim)
1547cdf0e10cSrcweir         {
1548cdf0e10cSrcweir             if (rString.Len())
1549cdf0e10cSrcweir             {
1550cdf0e10cSrcweir                 if (rString.EqualsIgnoreCaseAscii(pDim->GetName()))
1551cdf0e10cSrcweir                 {
1552cdf0e10cSrcweir                     pDim->RemoveLayoutName();
1553cdf0e10cSrcweir                     bChange = true;
1554cdf0e10cSrcweir                 }
1555cdf0e10cSrcweir                 else if (!pDPObj->IsDimNameInUse(rString))
1556cdf0e10cSrcweir                 {
1557cdf0e10cSrcweir                     pDim->SetLayoutName(rString);
1558cdf0e10cSrcweir                     bChange = true;
1559cdf0e10cSrcweir                 }
1560cdf0e10cSrcweir                 else
1561cdf0e10cSrcweir                     nErrorId = STR_INVALIDNAME;
1562cdf0e10cSrcweir             }
1563cdf0e10cSrcweir             else
1564cdf0e10cSrcweir                 nErrorId = STR_INVALIDNAME;
1565cdf0e10cSrcweir         }
1566cdf0e10cSrcweir     }
1567cdf0e10cSrcweir     else
1568cdf0e10cSrcweir     {
1569cdf0e10cSrcweir         // This is not a field header.
1570cdf0e10cSrcweir         sheet::DataPilotTableHeaderData aPosData;
1571cdf0e10cSrcweir         pDPObj->GetHeaderPositionData(rPos, aPosData);
1572cdf0e10cSrcweir 
1573cdf0e10cSrcweir         if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() )
1574cdf0e10cSrcweir         {
1575cdf0e10cSrcweir             if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL))
1576cdf0e10cSrcweir             {
1577cdf0e10cSrcweir                 sal_Bool bIsDataLayout;
1578cdf0e10cSrcweir                 String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
1579cdf0e10cSrcweir 
1580cdf0e10cSrcweir                 ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1581cdf0e10cSrcweir                 ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
1582cdf0e10cSrcweir                 if ( pGroupDim )
1583cdf0e10cSrcweir                 {
1584cdf0e10cSrcweir                     // valid name: not empty, no existing group in this dimension
1585cdf0e10cSrcweir                     //! ignore case?
1586cdf0e10cSrcweir                     if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) )
1587cdf0e10cSrcweir                     {
1588cdf0e10cSrcweir                         ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
1589cdf0e10cSrcweir                         if ( pGroup )
1590cdf0e10cSrcweir                             pGroup->Rename( aNewName );     // rename the existing group
1591cdf0e10cSrcweir                         else
1592cdf0e10cSrcweir                         {
1593cdf0e10cSrcweir                             // create a new group to replace the automatic group
1594cdf0e10cSrcweir                             ScDPSaveGroupItem aGroup( aNewName );
1595cdf0e10cSrcweir                             aGroup.AddElement( aOldText );
1596cdf0e10cSrcweir                             pGroupDim->AddGroupItem( aGroup );
1597cdf0e10cSrcweir                         }
1598cdf0e10cSrcweir 
1599cdf0e10cSrcweir                         // in both cases also adjust savedata, to preserve member settings (show details)
1600cdf0e10cSrcweir                         ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
1601cdf0e10cSrcweir                         ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
1602cdf0e10cSrcweir                         if ( pSaveMember )
1603cdf0e10cSrcweir                             pSaveMember->SetName( aNewName );
1604cdf0e10cSrcweir 
1605cdf0e10cSrcweir                         bChange = sal_True;
1606cdf0e10cSrcweir                     }
1607cdf0e10cSrcweir                     else
1608cdf0e10cSrcweir                         nErrorId = STR_INVALIDNAME;
1609cdf0e10cSrcweir                  }
1610cdf0e10cSrcweir             }
1611cdf0e10cSrcweir             else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL))
1612cdf0e10cSrcweir             {
1613cdf0e10cSrcweir                 aData.SetGrandTotalName(rString);
1614cdf0e10cSrcweir                 bChange = true;
1615cdf0e10cSrcweir             }
1616cdf0e10cSrcweir             else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0)
1617cdf0e10cSrcweir             {
1618cdf0e10cSrcweir                 sal_Bool bDataLayout = false;
1619cdf0e10cSrcweir                 String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout);
1620cdf0e10cSrcweir                 if (bDataLayout)
1621cdf0e10cSrcweir                 {
1622cdf0e10cSrcweir                     // data dimension
1623cdf0e10cSrcweir                     do
1624cdf0e10cSrcweir                     {
1625cdf0e10cSrcweir                         if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
1626cdf0e10cSrcweir                             break;
1627cdf0e10cSrcweir 
1628cdf0e10cSrcweir                         ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName);
1629cdf0e10cSrcweir                         if (!pDim)
1630cdf0e10cSrcweir                             break;
1631cdf0e10cSrcweir 
1632cdf0e10cSrcweir                         if (!rString.Len())
1633cdf0e10cSrcweir                         {
1634cdf0e10cSrcweir                             nErrorId = STR_INVALIDNAME;
1635cdf0e10cSrcweir                             break;
1636cdf0e10cSrcweir                         }
1637cdf0e10cSrcweir 
1638cdf0e10cSrcweir                         if (aPosData.MemberName.equalsIgnoreAsciiCase(rString))
1639cdf0e10cSrcweir                         {
1640cdf0e10cSrcweir                             pDim->RemoveLayoutName();
1641cdf0e10cSrcweir                             bChange = true;
1642cdf0e10cSrcweir                         }
1643cdf0e10cSrcweir                         else if (!pDPObj->IsDimNameInUse(rString))
1644cdf0e10cSrcweir                         {
1645cdf0e10cSrcweir                             pDim->SetLayoutName(rString);
1646cdf0e10cSrcweir                             bChange = true;
1647cdf0e10cSrcweir                         }
1648cdf0e10cSrcweir                         else
1649cdf0e10cSrcweir                             nErrorId = STR_INVALIDNAME;
1650cdf0e10cSrcweir                     }
1651cdf0e10cSrcweir                     while (false);
1652cdf0e10cSrcweir                 }
1653cdf0e10cSrcweir                 else
1654cdf0e10cSrcweir                 {
1655cdf0e10cSrcweir                     // field member
1656cdf0e10cSrcweir                     do
1657cdf0e10cSrcweir                     {
1658cdf0e10cSrcweir                         ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName);
1659cdf0e10cSrcweir                         if (!pDim)
1660cdf0e10cSrcweir                             break;
1661cdf0e10cSrcweir 
1662cdf0e10cSrcweir                         ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName);
1663cdf0e10cSrcweir                         if (!pMem)
1664cdf0e10cSrcweir                             break;
1665cdf0e10cSrcweir 
1666cdf0e10cSrcweir                         if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
1667cdf0e10cSrcweir                         {
1668cdf0e10cSrcweir                             // Change subtotal only when the table has one data dimension.
1669cdf0e10cSrcweir                             if (aData.GetDataDimensionCount() > 1)
1670cdf0e10cSrcweir                                 break;
1671cdf0e10cSrcweir 
1672cdf0e10cSrcweir                             // display name for subtotal is allowed only if the subtotal type is 'Automatic'.
1673cdf0e10cSrcweir                             if (pDim->GetSubTotalsCount() != 1)
1674cdf0e10cSrcweir                                 break;
1675cdf0e10cSrcweir 
1676cdf0e10cSrcweir                             if (pDim->GetSubTotalFunc(0) != sheet::GeneralFunction_AUTO)
1677cdf0e10cSrcweir                                 break;
1678cdf0e10cSrcweir 
1679cdf0e10cSrcweir                             const OUString* pLayoutName = pMem->GetLayoutName();
1680cdf0e10cSrcweir                             String aMemberName;
1681cdf0e10cSrcweir                             if (pLayoutName)
1682cdf0e10cSrcweir                                 aMemberName = *pLayoutName;
1683cdf0e10cSrcweir                             else
1684cdf0e10cSrcweir                                 aMemberName = aPosData.MemberName;
1685cdf0e10cSrcweir 
1686cdf0e10cSrcweir                             String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName);
1687cdf0e10cSrcweir                             pDim->SetSubtotalName(aNew);
1688cdf0e10cSrcweir                             bChange = true;
1689cdf0e10cSrcweir                         }
1690cdf0e10cSrcweir                         else
1691cdf0e10cSrcweir                         {
1692cdf0e10cSrcweir                             // Check to make sure the member name isn't
1693cdf0e10cSrcweir                             // already used.
1694cdf0e10cSrcweir                             if (rString.Len())
1695cdf0e10cSrcweir                             {
1696cdf0e10cSrcweir                                 if (rString.EqualsIgnoreCaseAscii(pMem->GetName()))
1697cdf0e10cSrcweir                                 {
1698cdf0e10cSrcweir                                     pMem->RemoveLayoutName();
1699cdf0e10cSrcweir                                     bChange = true;
1700cdf0e10cSrcweir                                 }
1701cdf0e10cSrcweir                                 else if (!pDim->IsMemberNameInUse(rString))
1702cdf0e10cSrcweir                                 {
1703cdf0e10cSrcweir                                     pMem->SetLayoutName(rString);
1704cdf0e10cSrcweir                                     bChange = true;
1705cdf0e10cSrcweir                                 }
1706cdf0e10cSrcweir                                 else
1707cdf0e10cSrcweir                                     nErrorId = STR_INVALIDNAME;
1708cdf0e10cSrcweir                             }
1709cdf0e10cSrcweir                             else
1710cdf0e10cSrcweir                                 nErrorId = STR_INVALIDNAME;
1711cdf0e10cSrcweir                         }
1712cdf0e10cSrcweir                     }
1713cdf0e10cSrcweir                     while (false);
1714cdf0e10cSrcweir                 }
1715cdf0e10cSrcweir             }
1716cdf0e10cSrcweir         }
1717cdf0e10cSrcweir     }
1718cdf0e10cSrcweir 
1719cdf0e10cSrcweir     if ( bChange )
1720cdf0e10cSrcweir     {
1721cdf0e10cSrcweir         // apply changes
1722cdf0e10cSrcweir         ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1723cdf0e10cSrcweir         ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1724cdf0e10cSrcweir         pNewObj->SetSaveData( aData );
1725cdf0e10cSrcweir         aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
1726cdf0e10cSrcweir         delete pNewObj;
1727cdf0e10cSrcweir     }
1728cdf0e10cSrcweir     else
1729cdf0e10cSrcweir     {
1730cdf0e10cSrcweir         if ( !nErrorId )
1731cdf0e10cSrcweir             nErrorId = STR_ERR_DATAPILOT_INPUT;
1732cdf0e10cSrcweir         ErrorMessage( nErrorId );
1733cdf0e10cSrcweir     }
1734cdf0e10cSrcweir }
1735cdf0e10cSrcweir 
lcl_MoveToEnd(ScDPSaveDimension & rDim,const String & rItemName)1736cdf0e10cSrcweir void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName )
1737cdf0e10cSrcweir {
1738cdf0e10cSrcweir     ScDPSaveMember* pNewMember = NULL;
1739cdf0e10cSrcweir     const ScDPSaveMember* pOldMember = rDim.GetExistingMemberByName( rItemName );
1740cdf0e10cSrcweir     if ( pOldMember )
1741cdf0e10cSrcweir         pNewMember = new ScDPSaveMember( *pOldMember );
1742cdf0e10cSrcweir     else
1743cdf0e10cSrcweir         pNewMember = new ScDPSaveMember( rItemName );
1744cdf0e10cSrcweir     rDim.AddMember( pNewMember );
1745cdf0e10cSrcweir     // AddMember takes ownership of the new pointer,
1746cdf0e10cSrcweir     // puts it to the end of the list even if it was in the list before.
1747cdf0e10cSrcweir }
1748cdf0e10cSrcweir 
1749cdf0e10cSrcweir struct ScOUStringCollate
1750cdf0e10cSrcweir {
1751cdf0e10cSrcweir     CollatorWrapper* mpCollator;
1752cdf0e10cSrcweir 
ScOUStringCollateScOUStringCollate1753cdf0e10cSrcweir     ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {}
1754cdf0e10cSrcweir 
operator ()ScOUStringCollate1755cdf0e10cSrcweir     bool operator()(const rtl::OUString& rStr1, const rtl::OUString& rStr2) const
1756cdf0e10cSrcweir     {
1757cdf0e10cSrcweir         return ( mpCollator->compareString(rStr1, rStr2) < 0 );
1758cdf0e10cSrcweir     }
1759cdf0e10cSrcweir };
1760cdf0e10cSrcweir 
DataPilotSort(const ScAddress & rPos,bool bAscending,sal_uInt16 * pUserListId)1761cdf0e10cSrcweir bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId )
1762cdf0e10cSrcweir {
1763cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
1764cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor(rPos.Col(), rPos.Row(), rPos.Tab());
1765cdf0e10cSrcweir     if (!pDPObj)
1766cdf0e10cSrcweir         return false;
1767cdf0e10cSrcweir 
1768cdf0e10cSrcweir     // We need to run this to get all members later.
1769cdf0e10cSrcweir     if ( pUserListId )
1770cdf0e10cSrcweir         pDPObj->BuildAllDimensionMembers();
1771cdf0e10cSrcweir 
1772cdf0e10cSrcweir     sal_uInt16 nOrientation;
1773cdf0e10cSrcweir     long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation);
1774cdf0e10cSrcweir     if (nDimIndex < 0)
1775cdf0e10cSrcweir         // Invalid dimension index.  Bail out.
1776cdf0e10cSrcweir         return false;
1777cdf0e10cSrcweir 
1778cdf0e10cSrcweir     sal_Bool bDataLayout;
1779cdf0e10cSrcweir     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1780cdf0e10cSrcweir     if (!pSaveData)
1781cdf0e10cSrcweir         return false;
1782cdf0e10cSrcweir 
1783cdf0e10cSrcweir     ScDPSaveData aNewSaveData(*pSaveData);
1784cdf0e10cSrcweir     String aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout);
1785cdf0e10cSrcweir     ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName);
1786cdf0e10cSrcweir     if (!pSaveDim)
1787cdf0e10cSrcweir         return false;
1788cdf0e10cSrcweir 
1789cdf0e10cSrcweir     // manual evaluation of sort order is only needed if a user list id is given
1790cdf0e10cSrcweir     if ( pUserListId )
1791cdf0e10cSrcweir     {
1792cdf0e10cSrcweir         typedef ScDPSaveDimension::MemberList MemList;
1793cdf0e10cSrcweir         const MemList& rDimMembers = pSaveDim->GetMembers();
1794cdf0e10cSrcweir         list<OUString> aMembers;
1795cdf0e10cSrcweir         hash_set<OUString, ::rtl::OUStringHash> aMemberSet;
1796cdf0e10cSrcweir         size_t nMemberCount = 0;
1797cdf0e10cSrcweir         for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end();
1798cdf0e10cSrcweir               itr != itrEnd; ++itr)
1799cdf0e10cSrcweir         {
1800cdf0e10cSrcweir             ScDPSaveMember* pMem = *itr;
1801cdf0e10cSrcweir             aMembers.push_back(pMem->GetName());
1802cdf0e10cSrcweir             aMemberSet.insert(pMem->GetName());
1803cdf0e10cSrcweir             ++nMemberCount;
1804cdf0e10cSrcweir         }
1805cdf0e10cSrcweir 
1806cdf0e10cSrcweir         // Sort the member list in ascending order.
1807cdf0e10cSrcweir         ScOUStringCollate aCollate( ScGlobal::GetCollator() );
1808cdf0e10cSrcweir         aMembers.sort(aCollate);
1809cdf0e10cSrcweir 
1810cdf0e10cSrcweir         // Collect and rank those custom sort strings that also exist in the member name list.
1811cdf0e10cSrcweir 
1812cdf0e10cSrcweir         typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap;
1813cdf0e10cSrcweir         UserSortMap aSubStrs;
1814cdf0e10cSrcweir         sal_uInt16 nSubCount = 0;
1815cdf0e10cSrcweir         if (pUserListId)
1816cdf0e10cSrcweir         {
1817cdf0e10cSrcweir             ScUserList* pUserList = ScGlobal::GetUserList();
1818cdf0e10cSrcweir             if (!pUserList)
1819cdf0e10cSrcweir                 return false;
1820cdf0e10cSrcweir 
1821cdf0e10cSrcweir             {
1822cdf0e10cSrcweir                 sal_uInt16 n = pUserList->GetCount();
1823cdf0e10cSrcweir                 if (!n || *pUserListId >= n)
1824cdf0e10cSrcweir                     return false;
1825cdf0e10cSrcweir             }
1826cdf0e10cSrcweir 
1827cdf0e10cSrcweir             ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]);
1828cdf0e10cSrcweir             if (pData)
1829cdf0e10cSrcweir             {
1830cdf0e10cSrcweir                 sal_uInt16 n = pData->GetSubCount();
1831cdf0e10cSrcweir                 for (sal_uInt16 i = 0; i < n; ++i)
1832cdf0e10cSrcweir                 {
1833cdf0e10cSrcweir                     OUString aSub = pData->GetSubStr(i);
1834cdf0e10cSrcweir                     if (!aMemberSet.count(aSub))
1835cdf0e10cSrcweir                         // This string doesn't exist in the member name set.  Don't add this.
1836cdf0e10cSrcweir                         continue;
1837cdf0e10cSrcweir 
1838cdf0e10cSrcweir                     aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++));
1839cdf0e10cSrcweir                 }
1840cdf0e10cSrcweir             }
1841cdf0e10cSrcweir         }
1842cdf0e10cSrcweir 
1843cdf0e10cSrcweir         // Rank all members.
1844cdf0e10cSrcweir 
1845cdf0e10cSrcweir         vector<OUString> aRankedNames(nMemberCount);
1846cdf0e10cSrcweir         sal_uInt16 nCurStrId = 0;
1847cdf0e10cSrcweir         for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end();
1848cdf0e10cSrcweir               itr != itrEnd; ++itr)
1849cdf0e10cSrcweir         {
1850cdf0e10cSrcweir             OUString aName = *itr;
1851cdf0e10cSrcweir             sal_uInt16 nRank = 0;
1852cdf0e10cSrcweir             UserSortMap::const_iterator itrSub = aSubStrs.find(aName);
1853cdf0e10cSrcweir             if (itrSub == aSubStrs.end())
1854cdf0e10cSrcweir                 nRank = nSubCount + nCurStrId++;
1855cdf0e10cSrcweir             else
1856cdf0e10cSrcweir                 nRank = itrSub->second;
1857cdf0e10cSrcweir 
1858cdf0e10cSrcweir             if (!bAscending)
1859cdf0e10cSrcweir                 nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 );
1860cdf0e10cSrcweir 
1861cdf0e10cSrcweir             aRankedNames[nRank] = aName;
1862cdf0e10cSrcweir         }
1863cdf0e10cSrcweir 
1864cdf0e10cSrcweir         // Re-order ScDPSaveMember instances with the new ranks.
1865cdf0e10cSrcweir 
1866cdf0e10cSrcweir         for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end();
1867cdf0e10cSrcweir               itr != itrEnd; ++itr)
1868cdf0e10cSrcweir         {
1869cdf0e10cSrcweir             const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr);
1870cdf0e10cSrcweir             if (!pOldMem)
1871cdf0e10cSrcweir                 // All members are supposed to be present.
1872cdf0e10cSrcweir                 continue;
1873cdf0e10cSrcweir 
1874cdf0e10cSrcweir             ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem);
1875cdf0e10cSrcweir             pSaveDim->AddMember(pNewMem);
1876cdf0e10cSrcweir         }
1877cdf0e10cSrcweir 
1878cdf0e10cSrcweir         // Set the sorting mode to manual for now.  We may introduce a new sorting
1879cdf0e10cSrcweir         // mode later on.
1880cdf0e10cSrcweir 
1881cdf0e10cSrcweir         sheet::DataPilotFieldSortInfo aSortInfo;
1882cdf0e10cSrcweir         aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1883cdf0e10cSrcweir         pSaveDim->SetSortInfo(&aSortInfo);
1884cdf0e10cSrcweir     }
1885cdf0e10cSrcweir     else
1886cdf0e10cSrcweir     {
1887cdf0e10cSrcweir         // without user list id, just apply sorting mode
1888cdf0e10cSrcweir 
1889cdf0e10cSrcweir         sheet::DataPilotFieldSortInfo aSortInfo;
1890cdf0e10cSrcweir         aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME;
1891cdf0e10cSrcweir         aSortInfo.IsAscending = bAscending;
1892cdf0e10cSrcweir         pSaveDim->SetSortInfo(&aSortInfo);
1893cdf0e10cSrcweir     }
1894cdf0e10cSrcweir 
1895cdf0e10cSrcweir     // Update the datapilot with the newly sorted field members.
1896cdf0e10cSrcweir 
1897cdf0e10cSrcweir     auto_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj));
1898cdf0e10cSrcweir     pNewObj->SetSaveData(aNewSaveData);
1899cdf0e10cSrcweir     ScDBDocFunc aFunc(*GetViewData()->GetDocShell());
1900cdf0e10cSrcweir 
1901cdf0e10cSrcweir     return aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false);
1902cdf0e10cSrcweir }
1903cdf0e10cSrcweir 
DataPilotMove(const ScRange & rSource,const ScAddress & rDest)1904cdf0e10cSrcweir sal_Bool ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
1905cdf0e10cSrcweir {
1906cdf0e10cSrcweir     sal_Bool bRet = sal_False;
1907cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
1908cdf0e10cSrcweir     ScDPObject* pDPObj = pDoc->GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() );
1909cdf0e10cSrcweir     if ( pDPObj && pDPObj == pDoc->GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) )
1910cdf0e10cSrcweir     {
1911cdf0e10cSrcweir         sheet::DataPilotTableHeaderData aDestData;
1912cdf0e10cSrcweir         pDPObj->GetHeaderPositionData( rDest, aDestData );
1913cdf0e10cSrcweir         bool bValid = ( aDestData.Dimension >= 0 );        // dropping onto a field
1914cdf0e10cSrcweir 
1915cdf0e10cSrcweir         // look through the source range
1916cdf0e10cSrcweir         std::hash_set< rtl::OUString, rtl::OUStringHash, std::equal_to<rtl::OUString> > aMembersSet;   // for lookup
1917cdf0e10cSrcweir         std::vector< rtl::OUString > aMembersVector;  // members in original order, for inserting
1918cdf0e10cSrcweir         aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ),
1919cdf0e10cSrcweir                                           static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) );
1920cdf0e10cSrcweir         for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow )
1921cdf0e10cSrcweir             for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol )
1922cdf0e10cSrcweir             {
1923cdf0e10cSrcweir                 sheet::DataPilotTableHeaderData aSourceData;
1924cdf0e10cSrcweir                 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData );
1925cdf0e10cSrcweir                 if ( aSourceData.Dimension == aDestData.Dimension && aSourceData.MemberName.getLength() )
1926cdf0e10cSrcweir                 {
1927cdf0e10cSrcweir                     if ( aMembersSet.find( aSourceData.MemberName ) == aMembersSet.end() )
1928cdf0e10cSrcweir                     {
1929cdf0e10cSrcweir                         aMembersSet.insert( aSourceData.MemberName );
1930cdf0e10cSrcweir                         aMembersVector.push_back( aSourceData.MemberName );
1931cdf0e10cSrcweir                     }
1932cdf0e10cSrcweir                     // duplicates are ignored
1933cdf0e10cSrcweir                 }
1934cdf0e10cSrcweir                 else
1935cdf0e10cSrcweir                     bValid = false;     // empty (subtotal) or different field
1936cdf0e10cSrcweir             }
1937cdf0e10cSrcweir 
1938cdf0e10cSrcweir         if ( bValid )
1939cdf0e10cSrcweir         {
1940cdf0e10cSrcweir             sal_Bool bIsDataLayout;
1941cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
1942cdf0e10cSrcweir             if ( !bIsDataLayout )
1943cdf0e10cSrcweir             {
1944cdf0e10cSrcweir                 ScDPSaveData aData( *pDPObj->GetSaveData() );
1945cdf0e10cSrcweir                 ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
1946cdf0e10cSrcweir 
1947cdf0e10cSrcweir                 // get all member names in source order
1948cdf0e10cSrcweir                 uno::Sequence<rtl::OUString> aMemberNames;
1949cdf0e10cSrcweir                 pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames );
1950cdf0e10cSrcweir 
1951cdf0e10cSrcweir                 bool bInserted = false;
1952cdf0e10cSrcweir 
1953cdf0e10cSrcweir                 sal_Int32 nMemberCount = aMemberNames.getLength();
1954cdf0e10cSrcweir                 for (sal_Int32 nMemberPos=0; nMemberPos<nMemberCount; ++nMemberPos)
1955cdf0e10cSrcweir                 {
1956cdf0e10cSrcweir                     String aMemberStr( aMemberNames[nMemberPos] );
1957cdf0e10cSrcweir 
1958cdf0e10cSrcweir                     if ( !bInserted && aMemberNames[nMemberPos] == aDestData.MemberName )
1959cdf0e10cSrcweir                     {
1960cdf0e10cSrcweir                         // insert dragged items before this item
1961cdf0e10cSrcweir                         for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin();
1962cdf0e10cSrcweir                               aIter != aMembersVector.end(); ++aIter )
1963cdf0e10cSrcweir                             lcl_MoveToEnd( *pDim, *aIter );
1964cdf0e10cSrcweir                         bInserted = true;
1965cdf0e10cSrcweir                     }
1966cdf0e10cSrcweir 
1967cdf0e10cSrcweir                     if ( aMembersSet.find( aMemberStr ) == aMembersSet.end() )  // skip dragged items
1968cdf0e10cSrcweir                         lcl_MoveToEnd( *pDim, aMemberStr );
1969cdf0e10cSrcweir                 }
1970cdf0e10cSrcweir                 // insert dragged item at end if dest wasn't found (for example, empty)
1971cdf0e10cSrcweir                 if ( !bInserted )
1972cdf0e10cSrcweir                     for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin();
1973cdf0e10cSrcweir                           aIter != aMembersVector.end(); ++aIter )
1974cdf0e10cSrcweir                         lcl_MoveToEnd( *pDim, *aIter );
1975cdf0e10cSrcweir 
1976cdf0e10cSrcweir                 // Items that were in SaveData, but not in the source, end up at the start of the list.
1977cdf0e10cSrcweir 
1978cdf0e10cSrcweir                 // set flag for manual sorting
1979cdf0e10cSrcweir                 sheet::DataPilotFieldSortInfo aSortInfo;
1980cdf0e10cSrcweir                 aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1981cdf0e10cSrcweir                 pDim->SetSortInfo( &aSortInfo );
1982cdf0e10cSrcweir 
1983cdf0e10cSrcweir                 // apply changes
1984cdf0e10cSrcweir                 ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
1985cdf0e10cSrcweir                 ScDPObject* pNewObj = new ScDPObject( *pDPObj );
1986cdf0e10cSrcweir                 pNewObj->SetSaveData( aData );
1987cdf0e10cSrcweir                 aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );      //! bApi for drag&drop?
1988cdf0e10cSrcweir                 delete pNewObj;
1989cdf0e10cSrcweir 
1990cdf0e10cSrcweir                 Unmark();       // entry was moved - no use in leaving the old cell selected
1991cdf0e10cSrcweir 
1992cdf0e10cSrcweir                 bRet = sal_True;
1993cdf0e10cSrcweir             }
1994cdf0e10cSrcweir         }
1995cdf0e10cSrcweir     }
1996cdf0e10cSrcweir 
1997cdf0e10cSrcweir     return bRet;
1998cdf0e10cSrcweir }
1999cdf0e10cSrcweir 
HasSelectionForDrillDown(sal_uInt16 & rOrientation)2000cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForDrillDown( sal_uInt16& rOrientation )
2001cdf0e10cSrcweir {
2002cdf0e10cSrcweir     sal_Bool bRet = sal_False;
2003cdf0e10cSrcweir 
2004cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
2005cdf0e10cSrcweir             							GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
2006cdf0e10cSrcweir     if ( pDPObj )
2007cdf0e10cSrcweir     {
2008cdf0e10cSrcweir         ScStrCollection aEntries;
2009cdf0e10cSrcweir         long nSelectDimension = -1;
2010cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
2011cdf0e10cSrcweir 
2012cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
2013cdf0e10cSrcweir         {
2014cdf0e10cSrcweir             sal_Bool bIsDataLayout;
2015cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
2016cdf0e10cSrcweir             if ( !bIsDataLayout )
2017cdf0e10cSrcweir             {
2018cdf0e10cSrcweir                 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
2019cdf0e10cSrcweir             	ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aDimName );
2020cdf0e10cSrcweir             	if ( pDim )
2021cdf0e10cSrcweir             	{
2022cdf0e10cSrcweir             	    sal_uInt16 nDimOrient = pDim->GetOrientation();
2023cdf0e10cSrcweir             	    ScDPSaveDimension* pInner = pSaveData->GetInnermostDimension( nDimOrient );
2024cdf0e10cSrcweir             	    if ( pDim == pInner )
2025cdf0e10cSrcweir             	    {
2026cdf0e10cSrcweir             	        rOrientation = nDimOrient;
2027cdf0e10cSrcweir             	        bRet = sal_True;
2028cdf0e10cSrcweir             	    }
2029cdf0e10cSrcweir             	}
2030cdf0e10cSrcweir             }
2031cdf0e10cSrcweir         }
2032cdf0e10cSrcweir     }
2033cdf0e10cSrcweir 
2034cdf0e10cSrcweir     return bRet;
2035cdf0e10cSrcweir }
2036cdf0e10cSrcweir 
SetDataPilotDetails(sal_Bool bShow,const String * pNewDimensionName)2037cdf0e10cSrcweir void ScDBFunc::SetDataPilotDetails( sal_Bool bShow, const String* pNewDimensionName )
2038cdf0e10cSrcweir {
2039cdf0e10cSrcweir     ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(),
2040cdf0e10cSrcweir             							GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
2041cdf0e10cSrcweir     if ( pDPObj )
2042cdf0e10cSrcweir     {
2043cdf0e10cSrcweir         ScStrCollection aEntries;
2044cdf0e10cSrcweir         long nSelectDimension = -1;
2045cdf0e10cSrcweir         GetSelectedMemberList( aEntries, nSelectDimension );
2046cdf0e10cSrcweir 
2047cdf0e10cSrcweir         if ( aEntries.GetCount() > 0 )
2048cdf0e10cSrcweir         {
2049cdf0e10cSrcweir             sal_Bool bIsDataLayout;
2050cdf0e10cSrcweir             String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
2051cdf0e10cSrcweir             if ( !bIsDataLayout )
2052cdf0e10cSrcweir             {
2053cdf0e10cSrcweir                 ScDPSaveData aData( *pDPObj->GetSaveData() );
2054cdf0e10cSrcweir                 ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
2055cdf0e10cSrcweir 
2056cdf0e10cSrcweir                 if ( bShow && pNewDimensionName )
2057cdf0e10cSrcweir                 {
2058cdf0e10cSrcweir                     //  add the new dimension with the same orientation, at the end
2059cdf0e10cSrcweir 
2060cdf0e10cSrcweir                     ScDPSaveDimension* pNewDim = aData.GetDimensionByName( *pNewDimensionName );
2061cdf0e10cSrcweir                     ScDPSaveDimension* pDuplicated = NULL;
2062cdf0e10cSrcweir                     if ( pNewDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
2063cdf0e10cSrcweir                     {
2064cdf0e10cSrcweir                         // Need to duplicate the dimension, create column/row in addition to data:
2065cdf0e10cSrcweir                         // The duplicated dimension inherits the existing settings, pNewDim is modified below.
2066cdf0e10cSrcweir                         pDuplicated = aData.DuplicateDimension( *pNewDimensionName );
2067cdf0e10cSrcweir                     }
2068cdf0e10cSrcweir 
2069cdf0e10cSrcweir                     sal_uInt16 nOrientation = pDim->GetOrientation();
2070cdf0e10cSrcweir                     pNewDim->SetOrientation( nOrientation );
2071cdf0e10cSrcweir 
2072cdf0e10cSrcweir                     long nPosition = LONG_MAX;
2073cdf0e10cSrcweir                     aData.SetPosition( pNewDim, nPosition );
2074cdf0e10cSrcweir 
2075cdf0e10cSrcweir                     ScDPSaveDimension* pDataLayout = aData.GetDataLayoutDimension();
2076cdf0e10cSrcweir                     if ( pDataLayout->GetOrientation() == nOrientation &&
2077cdf0e10cSrcweir                          aData.GetDataDimensionCount() <= 1 )
2078cdf0e10cSrcweir                     {
2079cdf0e10cSrcweir                         // If there is only one data dimension, the data layout dimension
2080cdf0e10cSrcweir                         // must still be the last one in its orientation.
2081cdf0e10cSrcweir                         aData.SetPosition( pDataLayout, nPosition );
2082cdf0e10cSrcweir                     }
2083cdf0e10cSrcweir 
2084cdf0e10cSrcweir                     if ( pDuplicated )
2085cdf0e10cSrcweir                     {
2086cdf0e10cSrcweir                         // The duplicated (data) dimension needs to be behind the original dimension
2087cdf0e10cSrcweir                         aData.SetPosition( pDuplicated, nPosition );
2088cdf0e10cSrcweir                     }
2089cdf0e10cSrcweir 
2090cdf0e10cSrcweir                     //  Hide details for all visible members (selected are changed below).
2091cdf0e10cSrcweir                     //! Use all members from source level instead (including non-visible)?
2092cdf0e10cSrcweir 
2093cdf0e10cSrcweir                     ScStrCollection aVisibleEntries;
2094cdf0e10cSrcweir                     pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension );
2095cdf0e10cSrcweir 
2096cdf0e10cSrcweir                     sal_uInt16 nVisCount = aVisibleEntries.GetCount();
2097cdf0e10cSrcweir                     for (sal_uInt16 nVisPos=0; nVisPos<nVisCount; nVisPos++)
2098cdf0e10cSrcweir                     {
2099cdf0e10cSrcweir                         String aVisName = aVisibleEntries[nVisPos]->GetString();
2100cdf0e10cSrcweir                         ScDPSaveMember* pMember = pDim->GetMemberByName( aVisName );
2101cdf0e10cSrcweir                         pMember->SetShowDetails( sal_False );
2102cdf0e10cSrcweir                     }
2103cdf0e10cSrcweir                 }
2104cdf0e10cSrcweir 
2105cdf0e10cSrcweir                 sal_uInt16 nEntryCount = aEntries.GetCount();
2106cdf0e10cSrcweir                 for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++)
2107cdf0e10cSrcweir                 {
2108cdf0e10cSrcweir                     String aEntryName = aEntries[nEntry]->GetString();
2109cdf0e10cSrcweir                     ScDPSaveMember* pMember = pDim->GetMemberByName( aEntryName );
2110cdf0e10cSrcweir                     pMember->SetShowDetails( bShow );
2111cdf0e10cSrcweir                 }
2112cdf0e10cSrcweir 
2113cdf0e10cSrcweir                 // apply changes
2114cdf0e10cSrcweir                 ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
2115cdf0e10cSrcweir                 ScDPObject* pNewObj = new ScDPObject( *pDPObj );
2116cdf0e10cSrcweir                 pNewObj->SetSaveData( aData );
2117cdf0e10cSrcweir                 aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False );
2118cdf0e10cSrcweir                 delete pNewObj;
2119cdf0e10cSrcweir 
2120cdf0e10cSrcweir                 // unmark cell selection
2121cdf0e10cSrcweir                 Unmark();
2122cdf0e10cSrcweir             }
2123cdf0e10cSrcweir         }
2124cdf0e10cSrcweir     }
2125cdf0e10cSrcweir }
2126cdf0e10cSrcweir 
ShowDataPilotSourceData(ScDPObject & rDPObj,const Sequence<sheet::DataPilotFieldFilter> & rFilters)2127cdf0e10cSrcweir void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters )
2128cdf0e10cSrcweir {
2129cdf0e10cSrcweir     ScDocument* pDoc = GetViewData()->GetDocument();
2130cdf0e10cSrcweir     if (pDoc->GetDocumentShell()->IsReadOnly())
2131cdf0e10cSrcweir     {
2132cdf0e10cSrcweir         ErrorMessage(STR_READONLYERR);
2133cdf0e10cSrcweir         return;
2134cdf0e10cSrcweir     }
2135cdf0e10cSrcweir 
2136cdf0e10cSrcweir     Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource();
2137cdf0e10cSrcweir     Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions();
2138cdf0e10cSrcweir     Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY);
2139cdf0e10cSrcweir     if (!xDDSupplier.is())
2140cdf0e10cSrcweir         return;
2141cdf0e10cSrcweir 
2142cdf0e10cSrcweir     Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters);
2143cdf0e10cSrcweir     sal_Int32 nRowSize = aTabData.getLength();
2144cdf0e10cSrcweir     if (nRowSize <= 1)
2145cdf0e10cSrcweir         // There is no data to show.  Bail out.
2146cdf0e10cSrcweir         return;
2147cdf0e10cSrcweir 
2148cdf0e10cSrcweir     sal_Int32 nColSize = aTabData[0].getLength();
2149cdf0e10cSrcweir 
2150cdf0e10cSrcweir     SCTAB nNewTab = GetViewData()->GetTabNo();
2151cdf0e10cSrcweir 
2152cdf0e10cSrcweir     auto_ptr<ScDocument> pInsDoc(new ScDocument(SCDOCMODE_CLIP));
2153cdf0e10cSrcweir     pInsDoc->ResetClip( pDoc, nNewTab );
2154cdf0e10cSrcweir     for (SCROW nRow = 0; nRow < nRowSize; ++nRow)
2155cdf0e10cSrcweir     {
2156cdf0e10cSrcweir         for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2157cdf0e10cSrcweir         {
2158cdf0e10cSrcweir             const Any& rAny = aTabData[nRow][nCol];
2159cdf0e10cSrcweir             rtl::OUString aStr;
2160cdf0e10cSrcweir             double fVal;
2161cdf0e10cSrcweir             if (rAny >>= aStr)
2162cdf0e10cSrcweir                 pInsDoc->PutCell( ScAddress(nCol, nRow, nNewTab), new ScStringCell(String(aStr)) );
2163cdf0e10cSrcweir             else if (rAny >>= fVal)
2164cdf0e10cSrcweir                 pInsDoc->SetValue(nCol, nRow, nNewTab, fVal);
2165cdf0e10cSrcweir         }
2166cdf0e10cSrcweir     }
2167cdf0e10cSrcweir 
2168cdf0e10cSrcweir     // set number format (important for dates)
2169cdf0e10cSrcweir     for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2170cdf0e10cSrcweir     {
2171cdf0e10cSrcweir         rtl::OUString aStr;
2172cdf0e10cSrcweir         if (!(aTabData[0][nCol] >>= aStr))
2173cdf0e10cSrcweir             continue;
2174cdf0e10cSrcweir 
2175cdf0e10cSrcweir         Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY);
2176cdf0e10cSrcweir         if (!xPropSet.is())
2177cdf0e10cSrcweir             continue;
2178cdf0e10cSrcweir 
2179cdf0e10cSrcweir         Any any = xPropSet->getPropertyValue( rtl::OUString::createFromAscii(SC_UNO_NUMBERFO) );
2180cdf0e10cSrcweir         sal_Int32 nNumFmt = 0;
2181cdf0e10cSrcweir         if (!(any >>= nNumFmt))
2182cdf0e10cSrcweir             continue;
2183cdf0e10cSrcweir 
2184cdf0e10cSrcweir         ScPatternAttr aPattern( pInsDoc->GetPool() );
2185cdf0e10cSrcweir         aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<sal_uInt32>(nNumFmt)) );
2186cdf0e10cSrcweir         pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern);
2187cdf0e10cSrcweir     }
2188cdf0e10cSrcweir 
2189cdf0e10cSrcweir     SCCOL nEndCol = 0;
2190cdf0e10cSrcweir     SCROW nEndRow = 0;
2191cdf0e10cSrcweir     pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow );
2192cdf0e10cSrcweir     pInsDoc->SetClipArea( ScRange( 0, 0, nNewTab, nEndCol, nEndRow, nNewTab ) );
2193cdf0e10cSrcweir 
2194cdf0e10cSrcweir     ::svl::IUndoManager* pMgr = GetViewData()->GetDocShell()->GetUndoManager();
2195cdf0e10cSrcweir     String aUndo = ScGlobal::GetRscString( STR_UNDO_DOOUTLINE );
2196cdf0e10cSrcweir     pMgr->EnterListAction( aUndo, aUndo );
2197cdf0e10cSrcweir 
2198cdf0e10cSrcweir     String aNewTabName;
2199cdf0e10cSrcweir     pDoc->CreateValidTabName(aNewTabName);
2200cdf0e10cSrcweir     if ( InsertTable(aNewTabName, nNewTab) )
2201cdf0e10cSrcweir         PasteFromClip( IDF_ALL, pInsDoc.get() );
2202cdf0e10cSrcweir 
2203cdf0e10cSrcweir     pMgr->LeaveListAction();
2204cdf0e10cSrcweir }
2205cdf0e10cSrcweir 
2206cdf0e10cSrcweir //
2207cdf0e10cSrcweir //			DB-Operationen (Sortieren, Filtern, Teilergebnisse) wiederholen
2208cdf0e10cSrcweir //
2209cdf0e10cSrcweir 
RepeatDB(sal_Bool bRecord)2210cdf0e10cSrcweir void ScDBFunc::RepeatDB( sal_Bool bRecord )
2211cdf0e10cSrcweir {
2212cdf0e10cSrcweir 	SCCOL nCurX = GetViewData()->GetCurX();
2213cdf0e10cSrcweir 	SCROW nCurY = GetViewData()->GetCurY();
2214cdf0e10cSrcweir 	SCTAB nTab = GetViewData()->GetTabNo();
2215cdf0e10cSrcweir 	ScDocument* pDoc = GetViewData()->GetDocument();
2216cdf0e10cSrcweir 	ScDBData* pDBData = GetDBData();
2217cdf0e10cSrcweir 	if (bRecord && !pDoc->IsUndoEnabled())
2218cdf0e10cSrcweir 		bRecord = sal_False;
2219cdf0e10cSrcweir 
2220cdf0e10cSrcweir 	ScQueryParam aQueryParam;
2221cdf0e10cSrcweir 	pDBData->GetQueryParam( aQueryParam );
2222cdf0e10cSrcweir 	sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
2223cdf0e10cSrcweir 
2224cdf0e10cSrcweir 	ScSortParam aSortParam;
2225cdf0e10cSrcweir 	pDBData->GetSortParam( aSortParam );
2226cdf0e10cSrcweir 	sal_Bool bSort = aSortParam.bDoSort[0];
2227cdf0e10cSrcweir 
2228cdf0e10cSrcweir 	ScSubTotalParam aSubTotalParam;
2229cdf0e10cSrcweir 	pDBData->GetSubTotalParam( aSubTotalParam );
2230cdf0e10cSrcweir 	sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
2231cdf0e10cSrcweir 
2232cdf0e10cSrcweir 	if ( bQuery || bSort || bSubTotal )
2233cdf0e10cSrcweir 	{
2234cdf0e10cSrcweir 		sal_Bool bQuerySize = sal_False;
2235cdf0e10cSrcweir 		ScRange aOldQuery;
2236cdf0e10cSrcweir 		ScRange aNewQuery;
2237cdf0e10cSrcweir 		if (bQuery && !aQueryParam.bInplace)
2238cdf0e10cSrcweir 		{
2239cdf0e10cSrcweir 			ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2240cdf0e10cSrcweir 													aQueryParam.nDestTab, sal_True );
2241cdf0e10cSrcweir 			if (pDest && pDest->IsDoSize())
2242cdf0e10cSrcweir 			{
2243cdf0e10cSrcweir 				pDest->GetArea( aOldQuery );
2244cdf0e10cSrcweir 				bQuerySize = sal_True;
2245cdf0e10cSrcweir 			}
2246cdf0e10cSrcweir 		}
2247cdf0e10cSrcweir 
2248cdf0e10cSrcweir 		SCTAB nDummy;
2249cdf0e10cSrcweir 		SCCOL nStartCol;
2250cdf0e10cSrcweir 		SCROW nStartRow;
2251cdf0e10cSrcweir 		SCCOL nEndCol;
2252cdf0e10cSrcweir 		SCROW nEndRow;
2253cdf0e10cSrcweir 		pDBData->GetArea( nDummy, nStartCol, nStartRow, nEndCol, nEndRow );
2254cdf0e10cSrcweir 
2255cdf0e10cSrcweir 		//!		Undo nur benoetigte Daten ?
2256cdf0e10cSrcweir 
2257cdf0e10cSrcweir 		ScDocument* pUndoDoc = NULL;
2258cdf0e10cSrcweir 		ScOutlineTable* pUndoTab = NULL;
2259cdf0e10cSrcweir 		ScRangeName* pUndoRange = NULL;
2260cdf0e10cSrcweir 		ScDBCollection* pUndoDB = NULL;
2261cdf0e10cSrcweir 
2262cdf0e10cSrcweir 		if (bRecord)
2263cdf0e10cSrcweir 		{
2264cdf0e10cSrcweir 			SCTAB nTabCount = pDoc->GetTableCount();
2265cdf0e10cSrcweir 			pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2266cdf0e10cSrcweir 			ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
2267cdf0e10cSrcweir 			if (pTable)
2268cdf0e10cSrcweir 			{
2269cdf0e10cSrcweir 				pUndoTab = new ScOutlineTable( *pTable );
2270cdf0e10cSrcweir 
2271cdf0e10cSrcweir 				SCCOLROW nOutStartCol;							// Zeilen/Spaltenstatus
2272cdf0e10cSrcweir 				SCCOLROW nOutStartRow;
2273cdf0e10cSrcweir 				SCCOLROW nOutEndCol;
2274cdf0e10cSrcweir 				SCCOLROW nOutEndRow;
2275cdf0e10cSrcweir 				pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
2276cdf0e10cSrcweir 				pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
2277cdf0e10cSrcweir 
2278cdf0e10cSrcweir 				pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
2279cdf0e10cSrcweir 				pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc );
2280cdf0e10cSrcweir 				pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc );
2281cdf0e10cSrcweir 			}
2282cdf0e10cSrcweir 			else
2283cdf0e10cSrcweir 				pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True );
2284cdf0e10cSrcweir 
2285cdf0e10cSrcweir 			//	Datenbereich sichern - incl. Filter-Ergebnis
2286cdf0e10cSrcweir 			pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, sal_False, pUndoDoc );
2287cdf0e10cSrcweir 
2288cdf0e10cSrcweir 			//	alle Formeln wegen Referenzen
2289cdf0e10cSrcweir 			pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, sal_False, pUndoDoc );
2290cdf0e10cSrcweir 
2291cdf0e10cSrcweir 			//	DB- und andere Bereiche
2292cdf0e10cSrcweir 			ScRangeName* pDocRange = pDoc->GetRangeName();
2293cdf0e10cSrcweir 			if (pDocRange->GetCount())
2294cdf0e10cSrcweir 				pUndoRange = new ScRangeName( *pDocRange );
2295cdf0e10cSrcweir 			ScDBCollection* pDocDB = pDoc->GetDBCollection();
2296cdf0e10cSrcweir 			if (pDocDB->GetCount())
2297cdf0e10cSrcweir 				pUndoDB = new ScDBCollection( *pDocDB );
2298cdf0e10cSrcweir 		}
2299cdf0e10cSrcweir 
2300cdf0e10cSrcweir 		if (bSort && bSubTotal)
2301cdf0e10cSrcweir 		{
2302cdf0e10cSrcweir 			//	Sortieren ohne SubTotals
2303cdf0e10cSrcweir 
2304cdf0e10cSrcweir 			aSubTotalParam.bRemoveOnly = sal_True;		// wird unten wieder zurueckgesetzt
2305cdf0e10cSrcweir 			DoSubTotals( aSubTotalParam, sal_False );
2306cdf0e10cSrcweir 		}
2307cdf0e10cSrcweir 
2308cdf0e10cSrcweir 		if (bSort)
2309cdf0e10cSrcweir 		{
2310cdf0e10cSrcweir 			pDBData->GetSortParam( aSortParam );			// Bereich kann sich geaendert haben
2311cdf0e10cSrcweir 			Sort( aSortParam, sal_False, sal_False);
2312cdf0e10cSrcweir 		}
2313cdf0e10cSrcweir 		if (bQuery)
2314cdf0e10cSrcweir 		{
2315cdf0e10cSrcweir 			pDBData->GetQueryParam( aQueryParam );			// Bereich kann sich geaendert haben
2316cdf0e10cSrcweir 			ScRange aAdvSource;
2317cdf0e10cSrcweir 			if (pDBData->GetAdvancedQuerySource(aAdvSource))
2318cdf0e10cSrcweir 			{
2319cdf0e10cSrcweir 				pDoc->CreateQueryParam(
2320cdf0e10cSrcweir 					aAdvSource.aStart.Col(), aAdvSource.aStart.Row(),
2321cdf0e10cSrcweir 					aAdvSource.aEnd.Col(), aAdvSource.aEnd.Row(),
2322cdf0e10cSrcweir 					aAdvSource.aStart.Tab(), aQueryParam );
2323cdf0e10cSrcweir 				Query( aQueryParam, &aAdvSource, sal_False );
2324cdf0e10cSrcweir 			}
2325cdf0e10cSrcweir 			else
2326cdf0e10cSrcweir 				Query( aQueryParam, NULL, sal_False );
2327cdf0e10cSrcweir 
2328cdf0e10cSrcweir 			//	bei nicht-inplace kann die Tabelle umgestellt worden sein
2329cdf0e10cSrcweir 			if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
2330cdf0e10cSrcweir 				SetTabNo( nTab );
2331cdf0e10cSrcweir 		}
2332cdf0e10cSrcweir 		if (bSubTotal)
2333cdf0e10cSrcweir 		{
2334cdf0e10cSrcweir 			pDBData->GetSubTotalParam( aSubTotalParam );	// Bereich kann sich geaendert haben
2335cdf0e10cSrcweir 			aSubTotalParam.bRemoveOnly = sal_False;
2336cdf0e10cSrcweir 			DoSubTotals( aSubTotalParam, sal_False );
2337cdf0e10cSrcweir 		}
2338cdf0e10cSrcweir 
2339cdf0e10cSrcweir 		if (bRecord)
2340cdf0e10cSrcweir 		{
2341cdf0e10cSrcweir 			SCTAB nDummyTab;
2342cdf0e10cSrcweir             SCCOL nDummyCol;
2343cdf0e10cSrcweir 			SCROW nDummyRow, nNewEndRow;
2344cdf0e10cSrcweir 			pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
2345cdf0e10cSrcweir 
2346cdf0e10cSrcweir 			const ScRange* pOld = NULL;
2347cdf0e10cSrcweir 			const ScRange* pNew = NULL;
2348cdf0e10cSrcweir 			if (bQuerySize)
2349cdf0e10cSrcweir 			{
2350cdf0e10cSrcweir 				ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2351cdf0e10cSrcweir 														aQueryParam.nDestTab, sal_True );
2352cdf0e10cSrcweir 				if (pDest)
2353cdf0e10cSrcweir 				{
2354cdf0e10cSrcweir 					pDest->GetArea( aNewQuery );
2355cdf0e10cSrcweir 					pOld = &aOldQuery;
2356cdf0e10cSrcweir 					pNew = &aNewQuery;
2357cdf0e10cSrcweir 				}
2358cdf0e10cSrcweir 			}
2359cdf0e10cSrcweir 
2360cdf0e10cSrcweir 			GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction(
2361cdf0e10cSrcweir 				new ScUndoRepeatDB( GetViewData()->GetDocShell(), nTab,
2362cdf0e10cSrcweir 										nStartCol, nStartRow, nEndCol, nEndRow,
2363cdf0e10cSrcweir 										nNewEndRow,
2364cdf0e10cSrcweir 										nCurX, nCurY,
2365cdf0e10cSrcweir 										pUndoDoc, pUndoTab,
2366cdf0e10cSrcweir 										pUndoRange, pUndoDB,
2367cdf0e10cSrcweir 										pOld, pNew ) );
2368cdf0e10cSrcweir 		}
2369cdf0e10cSrcweir 
2370cdf0e10cSrcweir 		GetViewData()->GetDocShell()->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
2371cdf0e10cSrcweir 													PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE );
2372cdf0e10cSrcweir 	}
2373cdf0e10cSrcweir 	else		// "Keine Operationen auszufuehren"
2374cdf0e10cSrcweir 		ErrorMessage(STR_MSSG_REPEATDB_0);
2375cdf0e10cSrcweir }
2376cdf0e10cSrcweir 
2377cdf0e10cSrcweir 
2378cdf0e10cSrcweir 
2379cdf0e10cSrcweir 
2380