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(OUStringChar(c) + OUStringChar(c));
1358 }
1359 else if (c == '?')
1360 {
1361 // A literal '?' must be escaped with a backslash ('\');
1362 aWordBuf.append("\\" + OUStringChar(c));
1363 }
1364 else
1365 aWordBuf.append(c);
1366 }
1367
1368 if (!aWordBuf.isEmpty())
1369 {
1370 OUString aWord = aWordBuf.makeStringAndClear();
1371 if (aWord == rMemberName)
1372 aBuf.append('?');
1373 else
1374 aBuf.append(aWord);
1375 }
1376
1377 return aBuf.makeStringAndClear();
1378}
1379
1380void ScDBFunc::DataPilotInput( const ScAddress& rPos, const OUString& rString )
1381{
1382 using namespace ::com::sun::star::sheet;
1383
1385 ScDPObject* pDPObj = rDoc.GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() );
1386 if (!pDPObj)
1387 return;
1388
1389 OUString aOldText = rDoc.GetString(rPos.Col(), rPos.Row(), rPos.Tab());
1390
1391 if ( aOldText == rString )
1392 {
1393 // nothing to do: silently exit
1394 return;
1395 }
1396
1397 TranslateId pErrorId;
1398
1399 pDPObj->BuildAllDimensionMembers();
1400 ScDPSaveData aData( *pDPObj->GetSaveData() );
1401 bool bChange = false;
1402 bool bNeedReloadGroups = false;
1403
1404 DataPilotFieldOrientation nOrient = DataPilotFieldOrientation_HIDDEN;
1405 tools::Long nField = pDPObj->GetHeaderDim( rPos, nOrient );
1406 if ( nField >= 0 )
1407 {
1408 // changing a field title
1409 if ( aData.GetExistingDimensionData() )
1410 {
1411 // only group dimensions can be renamed
1412
1413 ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1414 ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
1415 if ( pGroupDim )
1416 {
1417 // valid name: not empty, no existing dimension (group or other)
1418 if (!rString.isEmpty() && !pDPObj->IsDimNameInUse(rString))
1419 {
1420 pGroupDim->Rename( rString );
1421
1422 // also rename in SaveData to preserve the field settings
1423 ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
1424 pSaveDim->SetName( rString );
1425
1426 bChange = true;
1427 }
1428 else
1429 pErrorId = STR_INVALIDNAME;
1430 }
1431 }
1432 else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW)
1433 {
1434 bool bDataLayout = false;
1435 OUString aDimName = pDPObj->GetDimName(nField, bDataLayout);
1436 ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName);
1437 if (pDim)
1438 {
1439 if (!rString.isEmpty())
1440 {
1441 if (rString.equalsIgnoreAsciiCase(aDimName))
1442 {
1443 pDim->RemoveLayoutName();
1444 bChange = true;
1445 }
1446 else if (!pDPObj->IsDimNameInUse(rString))
1447 {
1448 pDim->SetLayoutName(rString);
1449 bChange = true;
1450 }
1451 else
1452 pErrorId = STR_INVALIDNAME;
1453 }
1454 else
1455 pErrorId = STR_INVALIDNAME;
1456 }
1457 }
1458 }
1459 else if (pDPObj->IsDataDescriptionCell(rPos))
1460 {
1461 // There is only one data dimension.
1462 ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA);
1463 if (pDim)
1464 {
1465 if (!rString.isEmpty())
1466 {
1467 if (pDim->GetName().equalsIgnoreAsciiCase(rString))
1468 {
1469 pDim->RemoveLayoutName();
1470 bChange = true;
1471 }
1472 else if (!pDPObj->IsDimNameInUse(rString))
1473 {
1474 pDim->SetLayoutName(rString);
1475 bChange = true;
1476 }
1477 else
1478 pErrorId = STR_INVALIDNAME;
1479 }
1480 else
1481 pErrorId = STR_INVALIDNAME;
1482 }
1483 }
1484 else
1485 {
1486 // This is not a field header.
1487 sheet::DataPilotTableHeaderData aPosData;
1488 pDPObj->GetHeaderPositionData(rPos, aPosData);
1489
1490 if ((aPosData.Flags & MemberResultFlags::HASMEMBER) && !aOldText.isEmpty())
1491 {
1492 if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL))
1493 {
1494 bool bIsDataLayout;
1495 OUString aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
1496
1497 ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1498 ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
1499 if ( pGroupDim )
1500 {
1501 // valid name: not empty, no existing group in this dimension
1503 if (!rString.isEmpty() && !pGroupDim->GetNamedGroup(rString))
1504 {
1505 ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
1506 if ( pGroup )
1507 pGroup->Rename( rString ); // rename the existing group
1508 else
1509 {
1510 // create a new group to replace the automatic group
1511 ScDPSaveGroupItem aGroup( rString );
1512 aGroup.AddElement( aOldText );
1513 pGroupDim->AddGroupItem( aGroup );
1514 }
1515
1516 // in both cases also adjust savedata, to preserve member settings (show details)
1517 ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
1518 ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
1519 if ( pSaveMember )
1520 pSaveMember->SetName( rString );
1521
1522 bChange = true;
1523 bNeedReloadGroups = true;
1524 }
1525 else
1526 pErrorId = STR_INVALIDNAME;
1527 }
1528 }
1529 else if (aPosData.Flags & MemberResultFlags::GRANDTOTAL)
1530 {
1531 aData.SetGrandTotalName(rString);
1532 bChange = true;
1533 }
1534 else if (aPosData.Dimension >= 0 && !aPosData.MemberName.isEmpty())
1535 {
1536 bool bDataLayout = false;
1537 OUString aDimName = pDPObj->GetDimName(static_cast<tools::Long>(aPosData.Dimension), bDataLayout);
1538 if (bDataLayout)
1539 {
1540 // data dimension
1541 do
1542 {
1543 if (aPosData.Flags & MemberResultFlags::SUBTOTAL)
1544 break;
1545
1546 ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName);
1547 if (!pDim)
1548 break;
1549
1550 if (rString.isEmpty())
1551 {
1552 pErrorId = STR_INVALIDNAME;
1553 break;
1554 }
1555
1556 if (aPosData.MemberName.equalsIgnoreAsciiCase(rString))
1557 {
1558 pDim->RemoveLayoutName();
1559 bChange = true;
1560 }
1561 else if (!pDPObj->IsDimNameInUse(rString))
1562 {
1563 pDim->SetLayoutName(rString);
1564 bChange = true;
1565 }
1566 else
1567 pErrorId = STR_INVALIDNAME;
1568 }
1569 while (false);
1570 }
1571 else
1572 {
1573 // field member
1574 do
1575 {
1576 ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName);
1577 if (!pDim)
1578 break;
1579
1580 ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName);
1581 if (!pMem)
1582 break;
1583
1584 if (aPosData.Flags & MemberResultFlags::SUBTOTAL)
1585 {
1586 // Change subtotal only when the table has one data dimension.
1587 if (aData.GetDataDimensionCount() > 1)
1588 break;
1589
1590 // display name for subtotal is allowed only if the subtotal type is 'Automatic'.
1591 if (pDim->GetSubTotalsCount() != 1)
1592 break;
1593
1595 break;
1596
1597 const std::optional<OUString> & pLayoutName = pMem->GetLayoutName();
1598 OUString aMemberName;
1599 if (pLayoutName)
1600 aMemberName = *pLayoutName;
1601 else
1602 aMemberName = aPosData.MemberName;
1603
1604 OUString aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName);
1605 pDim->SetSubtotalName(aNew);
1606 bChange = true;
1607 }
1608 else
1609 {
1610 // Check to make sure the member name isn't
1611 // already used.
1612 if (!rString.isEmpty())
1613 {
1614 if (rString.equalsIgnoreAsciiCase(pMem->GetName()))
1615 {
1616 pMem->RemoveLayoutName();
1617 bChange = true;
1618 }
1619 else if (!pDim->IsMemberNameInUse(rString))
1620 {
1621 pMem->SetLayoutName(rString);
1622 bChange = true;
1623 }
1624 else
1625 pErrorId = STR_INVALIDNAME;
1626 }
1627 else
1628 pErrorId = STR_INVALIDNAME;
1629 }
1630 }
1631 while (false);
1632 }
1633 }
1634 }
1635 }
1636
1637 if ( bChange )
1638 {
1639 // apply changes
1640 ScDBDocFunc aFunc( *GetViewData().GetDocShell() );
1641 pDPObj->SetSaveData( aData );
1642 if (bNeedReloadGroups)
1643 {
1644 ScDPCollection* pDPs = rDoc.GetDPCollection();
1645 if (pDPs)
1646 {
1648 // tdf#111305: Reload groups in cache after modifications.
1649 pDPs->ReloadGroupsInCache(pDPObj, aRefs);
1650 } // pDPs
1651 } // bNeedReloadGroups
1652 aFunc.UpdatePivotTable(*pDPObj, true, false);
1653 }
1654 else
1655 {
1656 if (!pErrorId)
1657 pErrorId = STR_ERR_DATAPILOT_INPUT;
1658 ErrorMessage(pErrorId);
1659 }
1660}
1661
1662static void lcl_MoveToEnd( ScDPSaveDimension& rDim, const OUString& rItemName )
1663{
1664 std::unique_ptr<ScDPSaveMember> pNewMember;
1665 const ScDPSaveMember* pOldMember = rDim.GetExistingMemberByName( rItemName );
1666 if ( pOldMember )
1667 pNewMember.reset(new ScDPSaveMember( *pOldMember ));
1668 else
1669 pNewMember.reset(new ScDPSaveMember( rItemName ));
1670 rDim.AddMember( std::move(pNewMember) );
1671 // AddMember takes ownership of the new pointer,
1672 // puts it to the end of the list even if it was in the list before.
1673}
1674
1675namespace {
1676
1677struct ScOUStringCollate
1678{
1679 CollatorWrapper* mpCollator;
1680
1681 explicit ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {}
1682
1683 bool operator()(const OUString& rStr1, const OUString& rStr2) const
1684 {
1685 return ( mpCollator->compareString(rStr1, rStr2) < 0 );
1686 }
1687};
1688
1689}
1690
1691void ScDBFunc::DataPilotSort(ScDPObject* pDPObj, tools::Long nDimIndex, bool bAscending, const sal_uInt16* pUserListId)
1692{
1693 if (!pDPObj)
1694 return;
1695
1696 // We need to run this to get all members later.
1697 if ( pUserListId )
1698 pDPObj->BuildAllDimensionMembers();
1699
1700 if (nDimIndex < 0)
1701 // Invalid dimension index. Bail out.
1702 return;
1703
1704 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1705 if (!pSaveData)
1706 return;
1707
1708 ScDPSaveData aNewSaveData(*pSaveData);
1709 bool bDataLayout;
1710 OUString aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout);
1711 ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName);
1712 if (!pSaveDim)
1713 return;
1714
1715 // manual evaluation of sort order is only needed if a user list id is given
1716 if ( pUserListId )
1717 {
1718 typedef ScDPSaveDimension::MemberList MemList;
1719 const MemList& rDimMembers = pSaveDim->GetMembers();
1720 vector<OUString> aMembers;
1721 std::unordered_set<OUString> aMemberSet;
1722 size_t nMemberCount = 0;
1723 for (ScDPSaveMember* pMem : rDimMembers)
1724 {
1725 aMembers.push_back(pMem->GetName());
1726 aMemberSet.insert(pMem->GetName());
1727 ++nMemberCount;
1728 }
1729
1730 // Sort the member list in ascending order.
1731 ScOUStringCollate aCollate( &ScGlobal::GetCollator() );
1732 std::stable_sort(aMembers.begin(), aMembers.end(), aCollate);
1733
1734 // Collect and rank those custom sort strings that also exist in the member name list.
1735
1736 typedef std::unordered_map<OUString, sal_uInt16> UserSortMap;
1737 UserSortMap aSubStrs;
1738 sal_uInt16 nSubCount = 0;
1739 ScUserList* pUserList = ScGlobal::GetUserList();
1740 if (!pUserList)
1741 return;
1742
1743 {
1744 size_t n = pUserList->size();
1745 if (!n || *pUserListId >= static_cast<sal_uInt16>(n))
1746 return;
1747 }
1748
1749 const ScUserListData& rData = (*pUserList)[*pUserListId];
1750 sal_uInt16 n = rData.GetSubCount();
1751 for (sal_uInt16 i = 0; i < n; ++i)
1752 {
1753 OUString aSub = rData.GetSubStr(i);
1754 if (!aMemberSet.count(aSub))
1755 // This string doesn't exist in the member name set. Don't add this.
1756 continue;
1757
1758 aSubStrs.emplace(aSub, nSubCount++);
1759 }
1760
1761 // Rank all members.
1762
1763 vector<OUString> aRankedNames(nMemberCount);
1764 sal_uInt16 nCurStrId = 0;
1765 for (auto const& aMemberName : aMembers)
1766 {
1767 sal_uInt16 nRank = 0;
1768 UserSortMap::const_iterator itrSub = aSubStrs.find(aMemberName);
1769 if (itrSub == aSubStrs.end())
1770 nRank = nSubCount + nCurStrId++;
1771 else
1772 nRank = itrSub->second;
1773
1774 if (!bAscending)
1775 nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 );
1776
1777 aRankedNames[nRank] = aMemberName;
1778 }
1779
1780 // Re-order ScDPSaveMember instances with the new ranks.
1781 for (auto const& aRankedName : aRankedNames)
1782 {
1783 const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(aRankedName);
1784 if (!pOldMem)
1785 // All members are supposed to be present.
1786 continue;
1787
1788 pSaveDim->AddMember(std::unique_ptr<ScDPSaveMember>(new ScDPSaveMember(*pOldMem)));
1789 }
1790
1791 // Set the sorting mode to manual for now. We may introduce a new sorting
1792 // mode later on.
1793
1794 sheet::DataPilotFieldSortInfo aSortInfo;
1795 aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1796 pSaveDim->SetSortInfo(&aSortInfo);
1797 }
1798 else
1799 {
1800 // without user list id, just apply sorting mode
1801
1802 sheet::DataPilotFieldSortInfo aSortInfo;
1803 aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME;
1804 aSortInfo.IsAscending = bAscending;
1805 pSaveDim->SetSortInfo(&aSortInfo);
1806 }
1807
1808 // Update the datapilot with the newly sorted field members.
1809
1810 std::unique_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj));
1811 pNewObj->SetSaveData(aNewSaveData);
1812 ScDBDocFunc aFunc(*GetViewData().GetDocShell());
1813
1814 aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false);
1815}
1816
1817bool ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
1818{
1819 bool bRet = false;
1821 ScDPObject* pDPObj = rDoc.GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() );
1822 if ( pDPObj && pDPObj == rDoc.GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) )
1823 {
1824 sheet::DataPilotTableHeaderData aDestData;
1825 pDPObj->GetHeaderPositionData( rDest, aDestData );
1826 bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
1827
1828 // look through the source range
1829 std::unordered_set< OUString > aMembersSet; // for lookup
1830 std::vector< OUString > aMembersVector; // members in original order, for inserting
1831 aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ),
1832 static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) );
1833 for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow )
1834 for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol )
1835 {
1836 sheet::DataPilotTableHeaderData aSourceData;
1837 pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData );
1838 if ( aSourceData.Dimension == aDestData.Dimension && !aSourceData.MemberName.isEmpty() )
1839 {
1840 if ( aMembersSet.insert( aSourceData.MemberName ).second )
1841 {
1842 aMembersVector.push_back( aSourceData.MemberName );
1843 }
1844 // duplicates are ignored
1845 }
1846 else
1847 bValid = false; // empty (subtotal) or different field
1848 }
1849
1850 if ( bValid )
1851 {
1852 bool bIsDataLayout;
1853 OUString aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
1854 if ( !bIsDataLayout )
1855 {
1856 ScDPSaveData aData( *pDPObj->GetSaveData() );
1857 ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
1858
1859 // get all member names in source order
1860 uno::Sequence<OUString> aMemberNames;
1861 pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames );
1862
1863 bool bInserted = false;
1864
1865 for (const OUString& aMemberStr : std::as_const(aMemberNames))
1866 {
1867 if ( !bInserted && aMemberStr == aDestData.MemberName )
1868 {
1869 // insert dragged items before this item
1870 for ( const auto& rMember : aMembersVector )
1871 lcl_MoveToEnd( *pDim, rMember );
1872 bInserted = true;
1873 }
1874
1875 if ( aMembersSet.find( aMemberStr ) == aMembersSet.end() ) // skip dragged items
1876 lcl_MoveToEnd( *pDim, aMemberStr );
1877 }
1878 // insert dragged item at end if dest wasn't found (for example, empty)
1879 if ( !bInserted )
1880 for ( const auto& rMember : aMembersVector )
1881 lcl_MoveToEnd( *pDim, rMember );
1882
1883 // Items that were in SaveData, but not in the source, end up at the start of the list.
1884
1885 // set flag for manual sorting
1886 sheet::DataPilotFieldSortInfo aSortInfo;
1887 aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1888 pDim->SetSortInfo( &aSortInfo );
1889
1890 // apply changes
1891 ScDBDocFunc aFunc( *GetViewData().GetDocShell() );
1892 std::unique_ptr<ScDPObject> pNewObj(new ScDPObject( *pDPObj ));
1893 pNewObj->SetSaveData( aData );
1894 aFunc.DataPilotUpdate( pDPObj, pNewObj.get(), true, false );
1895 pNewObj.reset();
1896
1897 Unmark(); // entry was moved - no use in leaving the old cell selected
1898
1899 bRet = true;
1900 }
1901 }
1902 }
1903
1904 return bRet;
1905}
1906
1907bool ScDBFunc::HasSelectionForDrillDown( css::sheet::DataPilotFieldOrientation& rOrientation )
1908{
1909 bool bRet = false;
1910
1911 ScDPObject* pDPObj = GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1912 GetViewData().GetCurY(), GetViewData().GetTabNo() );
1913 if ( pDPObj )
1914 {
1916 tools::Long nSelectDimension = -1;
1917 GetSelectedMemberList( aEntries, nSelectDimension );
1918
1919 if (!aEntries.empty())
1920 {
1921 bool bIsDataLayout;
1922 OUString aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1923 if ( !bIsDataLayout )
1924 {
1925 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1926 ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aDimName );
1927 if ( pDim )
1928 {
1929 css::sheet::DataPilotFieldOrientation nDimOrient = pDim->GetOrientation();
1930 ScDPSaveDimension* pInner = pSaveData->GetInnermostDimension( nDimOrient );
1931 if ( pDim == pInner )
1932 {
1933 rOrientation = nDimOrient;
1934 bRet = true;
1935 }
1936 }
1937 }
1938 }
1939 }
1940
1941 return bRet;
1942}
1943
1944void ScDBFunc::SetDataPilotDetails(bool bShow, const OUString* pNewDimensionName)
1945{
1946 ScDPObject* pDPObj = GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1947 GetViewData().GetCurY(), GetViewData().GetTabNo() );
1948 if ( !pDPObj )
1949 return;
1950
1952 tools::Long nSelectDimension = -1;
1953 GetSelectedMemberList( aEntries, nSelectDimension );
1954
1955 if (aEntries.empty())
1956 return;
1957
1958 bool bIsDataLayout;
1959 OUString aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1960 if ( bIsDataLayout )
1961 return;
1962
1963 ScDPSaveData aData( *pDPObj->GetSaveData() );
1964 ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
1965
1966 if ( bShow && pNewDimensionName )
1967 {
1968 // add the new dimension with the same orientation, at the end
1969
1970 ScDPSaveDimension* pNewDim = aData.GetDimensionByName( *pNewDimensionName );
1971 ScDPSaveDimension* pDuplicated = nullptr;
1972 if ( pNewDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
1973 {
1974 // Need to duplicate the dimension, create column/row in addition to data:
1975 // The duplicated dimension inherits the existing settings, pNewDim is modified below.
1976 pDuplicated = aData.DuplicateDimension( *pNewDimensionName );
1977 }
1978
1979 css::sheet::DataPilotFieldOrientation nOrientation = pDim->GetOrientation();
1980 pNewDim->SetOrientation( nOrientation );
1981
1982 tools::Long nPosition = LONG_MAX;
1983 aData.SetPosition( pNewDim, nPosition );
1984
1985 ScDPSaveDimension* pDataLayout = aData.GetDataLayoutDimension();
1986 if ( pDataLayout->GetOrientation() == nOrientation &&
1987 aData.GetDataDimensionCount() <= 1 )
1988 {
1989 // If there is only one data dimension, the data layout dimension
1990 // must still be the last one in its orientation.
1991 aData.SetPosition( pDataLayout, nPosition );
1992 }
1993
1994 if ( pDuplicated )
1995 {
1996 // The duplicated (data) dimension needs to be behind the original dimension
1997 aData.SetPosition( pDuplicated, nPosition );
1998 }
1999
2000 // Hide details for all visible members (selected are changed below).
2002
2003 ScDPUniqueStringSet aVisibleEntries;
2004 pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension );
2005
2006 for (const OUString& aVisName : aVisibleEntries)
2007 {
2008 ScDPSaveMember* pMember = pDim->GetMemberByName( aVisName );
2009 pMember->SetShowDetails( false );
2010 }
2011 }
2012
2013 for (const auto& rEntry : aEntries)
2014 {
2015 ScDPSaveMember* pMember = pDim->GetMemberByName(rEntry);
2016 pMember->SetShowDetails( bShow );
2017 }
2018
2019 // apply changes
2020 ScDBDocFunc aFunc( *GetViewData().GetDocShell() );
2021 std::unique_ptr<ScDPObject> pNewObj(new ScDPObject( *pDPObj ));
2022 pNewObj->SetSaveData( aData );
2023 aFunc.DataPilotUpdate( pDPObj, pNewObj.get(), true, false );
2024 pNewObj.reset();
2025
2026 // unmark cell selection
2027 Unmark();
2028}
2029
2030void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters )
2031{
2033 if (rDoc.GetDocumentShell()->IsReadOnly())
2034 {
2035 ErrorMessage(STR_READONLYERR);
2036 return;
2037 }
2038
2039 Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource();
2040 Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions();
2041 Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY);
2042 if (!xDDSupplier.is())
2043 return;
2044
2045 Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters);
2046 sal_Int32 nRowSize = aTabData.getLength();
2047 if (nRowSize <= 1)
2048 // There is no data to show. Bail out.
2049 return;
2050
2051 SCCOL nColSize = aTabData[0].getLength();
2052
2053 SCTAB nNewTab = GetViewData().GetTabNo();
2054
2056 pInsDoc->ResetClip( &rDoc, nNewTab );
2057 for (SCROW nRow = 0; nRow < nRowSize; ++nRow)
2058 {
2059 for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2060 {
2061 const Any& rAny = aTabData[nRow][nCol];
2062 OUString aStr;
2063 double fVal;
2064 if (rAny >>= aStr)
2065 {
2066 pInsDoc->SetString(ScAddress(nCol,nRow,nNewTab), aStr);
2067 }
2068 else if (rAny >>= fVal)
2069 pInsDoc->SetValue(nCol, nRow, nNewTab, fVal);
2070 }
2071 }
2072
2073 // set number format (important for dates)
2074 for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2075 {
2076 OUString aStr;
2077 if (!(aTabData[0][nCol] >>= aStr))
2078 continue;
2079
2080 Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY);
2081 if (!xPropSet.is())
2082 continue;
2083
2084 Any any = xPropSet->getPropertyValue( SC_UNO_DP_NUMBERFO );
2085 sal_Int32 nNumFmt = 0;
2086 if (!(any >>= nNumFmt))
2087 continue;
2088
2089 ScPatternAttr aPattern( pInsDoc->GetPool() );
2090 aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<sal_uInt32>(nNumFmt)) );
2091 pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern);
2092 }
2093
2094 SCCOL nEndCol = 0;
2095 SCROW nEndRow = 0;
2096 pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow );
2097 pInsDoc->SetClipArea( ScRange( 0, 0, nNewTab, nEndCol, nEndRow, nNewTab ) );
2098
2100 OUString aUndo = ScResId( STR_UNDO_DOOUTLINE );
2101 pMgr->EnterListAction( aUndo, aUndo, 0, GetViewData().GetViewShell()->GetViewShellId() );
2102
2103 OUString aNewTabName;
2104 rDoc.CreateValidTabName(aNewTabName);
2105 if ( InsertTable(aNewTabName, nNewTab) )
2106 PasteFromClip( InsertDeleteFlags::ALL, pInsDoc.get() );
2107
2108 pMgr->LeaveListAction();
2109}
2110
2111// repeat data base operations (sorting, filtering, subtotals)
2112
2113void ScDBFunc::RepeatDB( bool bRecord )
2114{
2115 SCCOL nCurX = GetViewData().GetCurX();
2116 SCROW nCurY = GetViewData().GetCurY();
2117 SCTAB nTab = GetViewData().GetTabNo();
2119 ScDBData* pDBData = GetDBData();
2120 if (bRecord && !rDoc.IsUndoEnabled())
2121 bRecord = false;
2122
2123 ScQueryParam aQueryParam;
2124 pDBData->GetQueryParam( aQueryParam );
2125 bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
2126
2127 ScSortParam aSortParam;
2128 pDBData->GetSortParam( aSortParam );
2129 bool bSort = aSortParam.maKeyState[0].bDoSort;
2130
2131 ScSubTotalParam aSubTotalParam;
2132 pDBData->GetSubTotalParam( aSubTotalParam );
2133 bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
2134
2135 if ( bQuery || bSort || bSubTotal )
2136 {
2137 bool bQuerySize = false;
2138 ScRange aOldQuery;
2139 ScRange aNewQuery;
2140 if (bQuery && !aQueryParam.bInplace)
2141 {
2142 ScDBData* pDest = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2143 aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
2144 if (pDest && pDest->IsDoSize())
2145 {
2146 pDest->GetArea( aOldQuery );
2147 bQuerySize = true;
2148 }
2149 }
2150
2151 SCTAB nDummy;
2152 SCCOL nStartCol;
2153 SCROW nStartRow;
2154 SCCOL nEndCol;
2155 SCROW nEndRow;
2156 pDBData->GetArea( nDummy, nStartCol, nStartRow, nEndCol, nEndRow );
2157
2159
2160 ScDocumentUniquePtr pUndoDoc;
2161 std::unique_ptr<ScOutlineTable> pUndoTab;
2162 std::unique_ptr<ScRangeName> pUndoRange;
2163 std::unique_ptr<ScDBCollection> pUndoDB;
2164
2165 if (bRecord)
2166 {
2167 SCTAB nTabCount = rDoc.GetTableCount();
2168 pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
2169 ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
2170 if (pTable)
2171 {
2172 pUndoTab.reset(new ScOutlineTable( *pTable ));
2173
2174 SCCOLROW nOutStartCol; // row/column status
2175 SCCOLROW nOutStartRow;
2176 SCCOLROW nOutEndCol;
2177 SCCOLROW nOutEndRow;
2178 pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol );
2179 pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow );
2180
2181 pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
2182 rDoc.CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc );
2183 rDoc.CopyToDocument( 0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc );
2184 }
2185 else
2186 pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
2187
2188 // Record data range - including filter results
2189 rDoc.CopyToDocument( 0,nStartRow,nTab, rDoc.MaxCol(),nEndRow,nTab, InsertDeleteFlags::ALL, false, *pUndoDoc );
2190
2191 // all formulas for reference
2192 rDoc.CopyToDocument( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1, InsertDeleteFlags::FORMULA, false, *pUndoDoc );
2193
2194 // data base and other ranges
2195 ScRangeName* pDocRange = rDoc.GetRangeName();
2196 if (!pDocRange->empty())
2197 pUndoRange.reset(new ScRangeName( *pDocRange ));
2198 ScDBCollection* pDocDB = rDoc.GetDBCollection();
2199 if (!pDocDB->empty())
2200 pUndoDB.reset(new ScDBCollection( *pDocDB ));
2201 }
2202
2203 if (bSort && bSubTotal)
2204 {
2205 // sort without subtotals
2206
2207 aSubTotalParam.bRemoveOnly = true; // is reset below
2208 DoSubTotals( aSubTotalParam, false );
2209 }
2210
2211 if (bSort)
2212 {
2213 pDBData->GetSortParam( aSortParam ); // range may have changed
2214 Sort( aSortParam, false, false);
2215 }
2216 if (bQuery)
2217 {
2218 pDBData->GetQueryParam( aQueryParam ); // range may have changed
2219 ScRange aAdvSource;
2220 if (pDBData->GetAdvancedQuerySource(aAdvSource))
2221 {
2222 rDoc.CreateQueryParam(aAdvSource, aQueryParam);
2223 Query( aQueryParam, &aAdvSource, false );
2224 }
2225 else
2226 Query( aQueryParam, nullptr, false );
2227
2228 // if not inplace the sheet may have changed
2229 if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
2230 SetTabNo( nTab );
2231 }
2232 if (bSubTotal)
2233 {
2234 pDBData->GetSubTotalParam( aSubTotalParam ); // range may have changed
2235 aSubTotalParam.bRemoveOnly = false;
2236 DoSubTotals( aSubTotalParam, false );
2237 }
2238
2239 if (bRecord)
2240 {
2241 SCTAB nDummyTab;
2242 SCCOL nDummyCol;
2243 SCROW nDummyRow, nNewEndRow;
2244 pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
2245
2246 const ScRange* pOld = nullptr;
2247 const ScRange* pNew = nullptr;
2248 if (bQuerySize)
2249 {
2250 ScDBData* pDest = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2251 aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
2252 if (pDest)
2253 {
2254 pDest->GetArea( aNewQuery );
2255 pOld = &aOldQuery;
2256 pNew = &aNewQuery;
2257 }
2258 }
2259
2261 std::make_unique<ScUndoRepeatDB>( GetViewData().GetDocShell(), nTab,
2262 nStartCol, nStartRow, nEndCol, nEndRow,
2263 nNewEndRow,
2264 nCurX, nCurY,
2265 std::move(pUndoDoc), std::move(pUndoTab),
2266 std::move(pUndoRange), std::move(pUndoDB),
2267 pOld, pNew ) );
2268 }
2269
2271 ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
2273 }
2274 else // "no not execute any operations"
2275 ErrorMessage(STR_MSSG_REPEATDB_0);
2276}
2277
2278void ScDBFunc::OnLOKShowHideColRow(bool bColumns, SCCOLROW nStart)
2279{
2281 return;
2282
2283 SCTAB nCurrentTabIndex = GetViewData().GetTabNo();
2284 SfxViewShell* pThisViewShell = GetViewData().GetViewShell();
2285 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
2286 while (pViewShell)
2287 {
2288 ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
2289 if (pTabViewShell && pTabViewShell->GetDocId() == pThisViewShell->GetDocId())
2290 {
2291 if (bColumns)
2292 {
2293 if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex))
2294 pPosHelper->invalidateByIndex(nStart);
2295 }
2296 else
2297 {
2298 if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex))
2299 pPosHelper->invalidateByIndex(nStart);
2300 }
2301
2302 if (pTabViewShell->getPart() == nCurrentTabIndex)
2303 {
2304 pTabViewShell->ShowCursor();
2305 pTabViewShell->MarkDataChanged();
2306 }
2307 }
2308 pViewShell = SfxViewShell::GetNext(*pViewShell);
2309 }
2310}
2311
2312/* 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:1634
bool IsDoSize() const
Definition: dbdata.hxx:142
void GetArea(SCTAB &rTab, SCCOL &rCol1, SCROW &rRow1, SCCOL &rCol2, SCROW &rRow2) const
Definition: dbdata.cxx:298
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:455
void SetSubTotalParam(const ScSubTotalParam &rSubTotalParam)
Definition: dbdata.cxx:473
SC_DLLPUBLIC void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:399
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:422
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:461
void SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dbdata.cxx:320
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:1817
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:1380
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:1691
void GetSelectedMemberList(ScDPUniqueStringSet &rEntries, tools::Long &rDimension)
Definition: dbfunc3.cxx:744
bool HasSelectionForDrillDown(css::sheet::DataPilotFieldOrientation &rOrientation)
Definition: dbfunc3.cxx:1907
void OnLOKShowHideColRow(bool bColumns, SCCOLROW nStartRow)
Definition: dbfunc3.cxx:2278
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:2113
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:1944
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:2030
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:3475
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:922
SC_DLLPUBLIC ScDPSaveDimension * GetExistingDimensionByName(std::u16string_view rName) const
Definition: dpsave.cxx:849
bool IsEmpty() const
Definition: dpsave.cxx:1157
const ScDPDimensionSaveData * GetExistingDimensionData() const
Definition: dpsave.hxx:353
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
Definition: dpsave.cxx:1211
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
Definition: dpsave.cxx:838
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:455
void SetDocumentModified()
Definition: docsh.cxx:3315
const ScDocument & GetDocument() const
Definition: docsh.hxx:219
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:511
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2968
SC_DLLPUBLIC bool InsertTab(SCTAB nPos, const OUString &rName, bool bExternalDocument=false, bool bUndoDeleteTab=false)
Definition: document.cxx:485
void RemoveSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:773
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
const ScDBData * GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, ScDBDataPortion ePortion) const
Definition: documen3.cxx:322
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:893
SC_DLLPUBLIC double GetValue(const ScAddress &rPos) const
Definition: document.cxx:3626
bool DoSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:779
SC_DLLPUBLIC const ScDBData * GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
Definition: documen3.cxx:338
SC_DLLPUBLIC bool CreateQueryParam(const ScRange &rRange, ScQueryParam &rQueryParam)
Definition: documen3.cxx:1485
SC_DLLPUBLIC void CreateValidTabName(OUString &rName) const
Definition: document.cxx:375
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5161
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:2041
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:827
SC_DLLPUBLIC ScDPObject * GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: documen3.cxx:377
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1083
SC_DLLPUBLIC ScOutlineTable * GetOutlineTable(SCTAB nTab, bool bCreate=false)
Definition: documen3.cxx:737
SC_DLLPUBLIC bool HasValueData(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3750
bool TestRemoveSubTotals(SCTAB nTab, const ScSubTotalParam &rParam)
Definition: documen3.cxx:767
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:467
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:171
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3505
void CompileDBFormula()
Definition: documen4.cxx:554
bool IsUndoEnabled() const
Definition: document.hxx:1595
void SetDirty(const ScRange &, bool bIncludeEmptyCells)
Definition: document.cxx:3841
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:204
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4684
SC_DLLPUBLIC ScDPCollection * GetDPCollection()
Definition: documen3.cxx:365
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:297
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:1095
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:192
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:593
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:535
int getPart() const override
See SfxViewShell::getPart().
Definition: tabvwshc.cxx:449
void DoneBlockMode(bool bContinue=false)
Definition: tabview2.cxx:509
void ErrorMessage(TranslateId pGlobStrId)
Definition: tabview2.cxx:1553
void SelectionChanged(bool bFromPaste=false)
Definition: tabview3.cxx:532
ScViewData & GetViewData()
Definition: tabview.hxx:344
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:432
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:32
OUString GetSubStr(sal_uInt16 nIndex) const
Definition: userlist.cxx:85
size_t GetSubCount() const
Definition: userlist.hxx:51
Collection of user-defined sort lists.
Definition: userlist.hxx:62
size_t size() const
Definition: userlist.hxx:84
void GetMultiArea(ScRangeListRef &rRange) const
Definition: viewdata.cxx:1205
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3146
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
void InsertTab(SCTAB nTab)
Definition: viewdata.cxx:882
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:871
bool InsertTable(const OUString &rName, SCTAB nTabNr, bool bRecord=true)
Definition: viewfun2.cxx:2381
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:1662
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2720
@ 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:130
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:623
RET_YES
@ SC_MARK_SIMPLE
Definition: viewdata.hxx:65
oslFileHandle & pOut
SvNumFormatType