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