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