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