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