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 
75 using namespace com::sun::star;
76 using ::com::sun::star::uno::Any;
77 using ::com::sun::star::uno::Sequence;
78 using ::com::sun::star::uno::Reference;
79 using ::com::sun::star::uno::UNO_QUERY;
80 using ::com::sun::star::beans::XPropertySet;
81 using ::com::sun::star::container::XNameAccess;
82 using ::com::sun::star::sheet::XDimensionsSupplier;
83 using ::std::vector;
84 
85 // outliner
86 
87 // create outline grouping
88 
89 void ScDBFunc::MakeOutline( bool bColumns, bool bRecord )
90 {
91  ScRange aRange;
92  if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
93  {
94  ScDocShell* pDocSh = GetViewData().GetDocShell();
95  ScOutlineDocFunc aFunc(*pDocSh);
96  aFunc.MakeOutline( aRange, bColumns, bRecord, false );
97 
98  ScTabViewShell::notifyAllViewsHeaderInvalidation(GetViewData().GetViewShell(), bColumns ? COLUMN_HEADER : ROW_HEADER, GetViewData().GetTabNo());
99  ScTabViewShell::notifyAllViewsSheetGeomInvalidation(GetViewData().GetViewShell(),
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 
110 void 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 
119  ScTabViewShell::notifyAllViewsHeaderInvalidation(GetViewData().GetViewShell(), bColumns ? COLUMN_HEADER : ROW_HEADER, GetViewData().GetTabNo());
120  ScTabViewShell::notifyAllViewsSheetGeomInvalidation(GetViewData().GetViewShell(),
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 
131 void 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;
142  ScDocument& rDoc = GetViewData().GetDocument();
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 
194 void 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  {
204  ScTabViewShell::notifyAllViewsSheetGeomInvalidation(GetViewData().GetViewShell(),
205  true /* bColumns */, true /* bRows */, false /* bSizes*/,
206  true /* bHidden */, true /* bFiltered */,
207  true /* bGroups */, nTab);
208  UpdateScrollBars(BOTH_HEADERS);
209  }
210 }
211 
212 // auto outlines
213 
215 {
216  ScDocument& rDoc = GetViewData().GetDocument();
217  SCTAB nTab = GetViewData().GetTabNo();
218  ScRange aRange( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab ); // the complete sheet, if nothing is marked
219  ScMarkData& rMark = GetViewData().GetMarkData();
220  if ( rMark.IsMarked() || rMark.IsMultiMarked() )
221  {
222  rMark.MarkToMulti();
223  rMark.GetMultiMarkArea( aRange );
224  }
225 
226  ScDocShell* pDocSh = GetViewData().GetDocShell();
227  ScOutlineDocFunc aFunc(*pDocSh);
228  aFunc.AutoOutline( aRange, true );
229 }
230 
231 // select outline level
232 
233 void 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  {
243  ScTabViewShell::notifyAllViewsSheetGeomInvalidation(GetViewData().GetViewShell(),
244  bColumns, !bColumns, false /* bSizes*/,
245  true /* bHidden */, true /* bFiltered */,
246  true /* bGroups */, nTab);
247  UpdateScrollBars(bColumns ? COLUMN_HEADER : ROW_HEADER);
248  }
249 }
250 
251 // show individual outline groups
252 
253 void 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 
267 void 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  {
277  ScTabViewShell::notifyAllViewsSheetGeomInvalidation(GetViewData().GetViewShell(),
278  bColumns, !bColumns, false /* bSizes*/,
279  true /* bHidden */, true /* bFiltered */,
280  true /* bGroups */, nTab);
281  UpdateScrollBars(bColumns ? COLUMN_HEADER : ROW_HEADER);
282  }
283 }
284 
285 // hide individual outline groups
286 
287 void 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  {
297  ScTabViewShell::notifyAllViewsSheetGeomInvalidation(GetViewData().GetViewShell(),
298  bColumns, !bColumns, false /* bSizes*/,
299  true /* bHidden */, true /* bFiltered */,
300  true /* bGroups */, nTab);
301  UpdateScrollBars(bColumns ? COLUMN_HEADER : ROW_HEADER);
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  {
320  ScDocument& rDoc = GetViewData().GetDocument();
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 
385 void ScDBFunc::ShowMarkedOutlines( bool bRecord )
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());
399  UpdateScrollBars();
400  }
401  }
402  else
403  ErrorMessage(STR_NOMULTISELECT);
404 }
405 
406 // hide marked range
407 
408 void ScDBFunc::HideMarkedOutlines( bool bRecord )
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());
422  UpdateScrollBars();
423  }
424  }
425  else
426  ErrorMessage(STR_NOMULTISELECT);
427 }
428 
429 // sub totals
430 
431 void 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();
438  ScMarkData& rMark = GetViewData().GetMarkData();
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,
459  rParam.nCol2, rParam.nRow2, nTab, HasAttrFlags::Merged | HasAttrFlags::Overlapped ))
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  DoneBlockMode();
591  InitOwnBlockMode();
592  rMark.SetMarkArea( ScRange( aNewParam.nCol1,aNewParam.nRow1,nTab,
593  aNewParam.nCol2,aNewParam.nRow2,nTab ) );
594  MarkDataChanged();
595 
596  pDocSh->PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
598 
599  aModificator.SetDocumentModified();
600 
601  SelectionChanged();
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 
615 static 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();
635  ScDocument& rDoc = GetViewData().GetDocument();
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();
726  ScDocument& rDoc = GetViewData().GetDocument();
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 {
746  ScDPObject* pDPObj = GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
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 
806 bool 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();
815  ScDocument& rDoc = GetViewData().GetDocument();
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 =
834  const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() );
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();
900  SvNumFormatType nType = rDoc.GetFormatTable()->GetType(nIndex);
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();
928  ScDocument& rDoc = GetViewData().GetDocument();
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 =
945  const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() );
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 
987 void ScDBFunc::DateGroupDataPilot( const ScDPNumGroupInfo& rInfo, sal_Int32 nParts )
988 {
989  ScDPObject* pDPObj = GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
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 
1294  DateGroupDataPilot( ScDPNumGroupInfo(), 0 );
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 
1337 static OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, std::u16string_view rMemberName)
1338 {
1339  sal_Int32 n = rSubtotal.getLength();
1340  const sal_Unicode* p = rSubtotal.getStr();
1341  OUStringBuffer aBuf, aWordBuf;
1342  for (sal_Int32 i = 0; i < n; ++i)
1343  {
1344  sal_Unicode c = p[i];
1345  if (c == ' ')
1346  {
1347  OUString aWord = aWordBuf.makeStringAndClear();
1348  if (aWord == rMemberName)
1349  aBuf.append('?');
1350  else
1351  aBuf.append(aWord);
1352  aBuf.append(c);
1353  }
1354  else if (c == '\\')
1355  {
1356  // Escape a backslash character.
1357  aWordBuf.append(c);
1358  aWordBuf.append(c);
1359  }
1360  else if (c == '?')
1361  {
1362  // A literal '?' must be escaped with a backslash ('\');
1363  aWordBuf.append('\\');
1364  aWordBuf.append(c);
1365  }
1366  else
1367  aWordBuf.append(c);
1368  }
1369 
1370  if (!aWordBuf.isEmpty())
1371  {
1372  OUString aWord = aWordBuf.makeStringAndClear();
1373  if (aWord == rMemberName)
1374  aBuf.append('?');
1375  else
1376  aBuf.append(aWord);
1377  }
1378 
1379  return aBuf.makeStringAndClear();
1380 }
1381 
1382 void ScDBFunc::DataPilotInput( const ScAddress& rPos, const OUString& rString )
1383 {
1384  using namespace ::com::sun::star::sheet;
1385 
1386  ScDocument& rDoc = GetViewData().GetDocument();
1387  ScDPObject* pDPObj = rDoc.GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() );
1388  if (!pDPObj)
1389  return;
1390 
1391  OUString aOldText = rDoc.GetString(rPos.Col(), rPos.Row(), rPos.Tab());
1392 
1393  if ( aOldText == rString )
1394  {
1395  // nothing to do: silently exit
1396  return;
1397  }
1398 
1399  TranslateId pErrorId;
1400 
1401  pDPObj->BuildAllDimensionMembers();
1402  ScDPSaveData aData( *pDPObj->GetSaveData() );
1403  bool bChange = false;
1404  bool bNeedReloadGroups = false;
1405 
1406  DataPilotFieldOrientation nOrient = DataPilotFieldOrientation_HIDDEN;
1407  tools::Long nField = pDPObj->GetHeaderDim( rPos, nOrient );
1408  if ( nField >= 0 )
1409  {
1410  // changing a field title
1411  if ( aData.GetExistingDimensionData() )
1412  {
1413  // only group dimensions can be renamed
1414 
1415  ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1416  ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
1417  if ( pGroupDim )
1418  {
1419  // valid name: not empty, no existing dimension (group or other)
1420  if (!rString.isEmpty() && !pDPObj->IsDimNameInUse(rString))
1421  {
1422  pGroupDim->Rename( rString );
1423 
1424  // also rename in SaveData to preserve the field settings
1425  ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
1426  pSaveDim->SetName( rString );
1427 
1428  bChange = true;
1429  }
1430  else
1431  pErrorId = STR_INVALIDNAME;
1432  }
1433  }
1434  else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW)
1435  {
1436  bool bDataLayout = false;
1437  OUString aDimName = pDPObj->GetDimName(nField, bDataLayout);
1438  ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName);
1439  if (pDim)
1440  {
1441  if (!rString.isEmpty())
1442  {
1443  if (rString.equalsIgnoreAsciiCase(aDimName))
1444  {
1445  pDim->RemoveLayoutName();
1446  bChange = true;
1447  }
1448  else if (!pDPObj->IsDimNameInUse(rString))
1449  {
1450  pDim->SetLayoutName(rString);
1451  bChange = true;
1452  }
1453  else
1454  pErrorId = STR_INVALIDNAME;
1455  }
1456  else
1457  pErrorId = STR_INVALIDNAME;
1458  }
1459  }
1460  }
1461  else if (pDPObj->IsDataDescriptionCell(rPos))
1462  {
1463  // There is only one data dimension.
1464  ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA);
1465  if (pDim)
1466  {
1467  if (!rString.isEmpty())
1468  {
1469  if (pDim->GetName().equalsIgnoreAsciiCase(rString))
1470  {
1471  pDim->RemoveLayoutName();
1472  bChange = true;
1473  }
1474  else if (!pDPObj->IsDimNameInUse(rString))
1475  {
1476  pDim->SetLayoutName(rString);
1477  bChange = true;
1478  }
1479  else
1480  pErrorId = STR_INVALIDNAME;
1481  }
1482  else
1483  pErrorId = STR_INVALIDNAME;
1484  }
1485  }
1486  else
1487  {
1488  // This is not a field header.
1489  sheet::DataPilotTableHeaderData aPosData;
1490  pDPObj->GetHeaderPositionData(rPos, aPosData);
1491 
1492  if ((aPosData.Flags & MemberResultFlags::HASMEMBER) && !aOldText.isEmpty())
1493  {
1494  if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL))
1495  {
1496  bool bIsDataLayout;
1497  OUString aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
1498 
1499  ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
1500  ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
1501  if ( pGroupDim )
1502  {
1503  // valid name: not empty, no existing group in this dimension
1505  if (!rString.isEmpty() && !pGroupDim->GetNamedGroup(rString))
1506  {
1507  ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
1508  if ( pGroup )
1509  pGroup->Rename( rString ); // rename the existing group
1510  else
1511  {
1512  // create a new group to replace the automatic group
1513  ScDPSaveGroupItem aGroup( rString );
1514  aGroup.AddElement( aOldText );
1515  pGroupDim->AddGroupItem( aGroup );
1516  }
1517 
1518  // in both cases also adjust savedata, to preserve member settings (show details)
1519  ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
1520  ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
1521  if ( pSaveMember )
1522  pSaveMember->SetName( rString );
1523 
1524  bChange = true;
1525  bNeedReloadGroups = true;
1526  }
1527  else
1528  pErrorId = STR_INVALIDNAME;
1529  }
1530  }
1531  else if (aPosData.Flags & MemberResultFlags::GRANDTOTAL)
1532  {
1533  aData.SetGrandTotalName(rString);
1534  bChange = true;
1535  }
1536  else if (aPosData.Dimension >= 0 && !aPosData.MemberName.isEmpty())
1537  {
1538  bool bDataLayout = false;
1539  OUString aDimName = pDPObj->GetDimName(static_cast<tools::Long>(aPosData.Dimension), bDataLayout);
1540  if (bDataLayout)
1541  {
1542  // data dimension
1543  do
1544  {
1545  if (aPosData.Flags & MemberResultFlags::SUBTOTAL)
1546  break;
1547 
1548  ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName);
1549  if (!pDim)
1550  break;
1551 
1552  if (rString.isEmpty())
1553  {
1554  pErrorId = STR_INVALIDNAME;
1555  break;
1556  }
1557 
1558  if (aPosData.MemberName.equalsIgnoreAsciiCase(rString))
1559  {
1560  pDim->RemoveLayoutName();
1561  bChange = true;
1562  }
1563  else if (!pDPObj->IsDimNameInUse(rString))
1564  {
1565  pDim->SetLayoutName(rString);
1566  bChange = true;
1567  }
1568  else
1569  pErrorId = STR_INVALIDNAME;
1570  }
1571  while (false);
1572  }
1573  else
1574  {
1575  // field member
1576  do
1577  {
1578  ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName);
1579  if (!pDim)
1580  break;
1581 
1582  ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName);
1583  if (!pMem)
1584  break;
1585 
1586  if (aPosData.Flags & MemberResultFlags::SUBTOTAL)
1587  {
1588  // Change subtotal only when the table has one data dimension.
1589  if (aData.GetDataDimensionCount() > 1)
1590  break;
1591 
1592  // display name for subtotal is allowed only if the subtotal type is 'Automatic'.
1593  if (pDim->GetSubTotalsCount() != 1)
1594  break;
1595 
1596  if (pDim->GetSubTotalFunc(0) != ScGeneralFunction::AUTO)
1597  break;
1598 
1599  const std::optional<OUString> & pLayoutName = pMem->GetLayoutName();
1600  OUString aMemberName;
1601  if (pLayoutName)
1602  aMemberName = *pLayoutName;
1603  else
1604  aMemberName = aPosData.MemberName;
1605 
1606  OUString aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName);
1607  pDim->SetSubtotalName(aNew);
1608  bChange = true;
1609  }
1610  else
1611  {
1612  // Check to make sure the member name isn't
1613  // already used.
1614  if (!rString.isEmpty())
1615  {
1616  if (rString.equalsIgnoreAsciiCase(pMem->GetName()))
1617  {
1618  pMem->RemoveLayoutName();
1619  bChange = true;
1620  }
1621  else if (!pDim->IsMemberNameInUse(rString))
1622  {
1623  pMem->SetLayoutName(rString);
1624  bChange = true;
1625  }
1626  else
1627  pErrorId = STR_INVALIDNAME;
1628  }
1629  else
1630  pErrorId = STR_INVALIDNAME;
1631  }
1632  }
1633  while (false);
1634  }
1635  }
1636  }
1637  }
1638 
1639  if ( bChange )
1640  {
1641  // apply changes
1642  ScDBDocFunc aFunc( *GetViewData().GetDocShell() );
1643  pDPObj->SetSaveData( aData );
1644  if (bNeedReloadGroups)
1645  {
1646  ScDPCollection* pDPs = rDoc.GetDPCollection();
1647  if (pDPs)
1648  {
1650  // tdf#111305: Reload groups in cache after modifications.
1651  pDPs->ReloadGroupsInCache(pDPObj, aRefs);
1652  } // pDPs
1653  } // bNeedReloadGroups
1654  aFunc.UpdatePivotTable(*pDPObj, true, false);
1655  }
1656  else
1657  {
1658  if (!pErrorId)
1659  pErrorId = STR_ERR_DATAPILOT_INPUT;
1660  ErrorMessage(pErrorId);
1661  }
1662 }
1663 
1664 static void lcl_MoveToEnd( ScDPSaveDimension& rDim, const OUString& rItemName )
1665 {
1666  std::unique_ptr<ScDPSaveMember> pNewMember;
1667  const ScDPSaveMember* pOldMember = rDim.GetExistingMemberByName( rItemName );
1668  if ( pOldMember )
1669  pNewMember.reset(new ScDPSaveMember( *pOldMember ));
1670  else
1671  pNewMember.reset(new ScDPSaveMember( rItemName ));
1672  rDim.AddMember( std::move(pNewMember) );
1673  // AddMember takes ownership of the new pointer,
1674  // puts it to the end of the list even if it was in the list before.
1675 }
1676 
1677 namespace {
1678 
1679 struct ScOUStringCollate
1680 {
1681  CollatorWrapper* mpCollator;
1682 
1683  explicit ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {}
1684 
1685  bool operator()(const OUString& rStr1, const OUString& rStr2) const
1686  {
1687  return ( mpCollator->compareString(rStr1, rStr2) < 0 );
1688  }
1689 };
1690 
1691 }
1692 
1693 void ScDBFunc::DataPilotSort(ScDPObject* pDPObj, tools::Long nDimIndex, bool bAscending, const sal_uInt16* pUserListId)
1694 {
1695  if (!pDPObj)
1696  return;
1697 
1698  // We need to run this to get all members later.
1699  if ( pUserListId )
1700  pDPObj->BuildAllDimensionMembers();
1701 
1702  if (nDimIndex < 0)
1703  // Invalid dimension index. Bail out.
1704  return;
1705 
1706  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1707  if (!pSaveData)
1708  return;
1709 
1710  ScDPSaveData aNewSaveData(*pSaveData);
1711  bool bDataLayout;
1712  OUString aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout);
1713  ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName);
1714  if (!pSaveDim)
1715  return;
1716 
1717  // manual evaluation of sort order is only needed if a user list id is given
1718  if ( pUserListId )
1719  {
1720  typedef ScDPSaveDimension::MemberList MemList;
1721  const MemList& rDimMembers = pSaveDim->GetMembers();
1722  vector<OUString> aMembers;
1723  std::unordered_set<OUString> aMemberSet;
1724  size_t nMemberCount = 0;
1725  for (ScDPSaveMember* pMem : rDimMembers)
1726  {
1727  aMembers.push_back(pMem->GetName());
1728  aMemberSet.insert(pMem->GetName());
1729  ++nMemberCount;
1730  }
1731 
1732  // Sort the member list in ascending order.
1733  ScOUStringCollate aCollate( &ScGlobal::GetCollator() );
1734  std::stable_sort(aMembers.begin(), aMembers.end(), aCollate);
1735 
1736  // Collect and rank those custom sort strings that also exist in the member name list.
1737 
1738  typedef std::unordered_map<OUString, sal_uInt16> UserSortMap;
1739  UserSortMap aSubStrs;
1740  sal_uInt16 nSubCount = 0;
1741  ScUserList* pUserList = ScGlobal::GetUserList();
1742  if (!pUserList)
1743  return;
1744 
1745  {
1746  size_t n = pUserList->size();
1747  if (!n || *pUserListId >= static_cast<sal_uInt16>(n))
1748  return;
1749  }
1750 
1751  const ScUserListData& rData = (*pUserList)[*pUserListId];
1752  sal_uInt16 n = rData.GetSubCount();
1753  for (sal_uInt16 i = 0; i < n; ++i)
1754  {
1755  OUString aSub = rData.GetSubStr(i);
1756  if (!aMemberSet.count(aSub))
1757  // This string doesn't exist in the member name set. Don't add this.
1758  continue;
1759 
1760  aSubStrs.emplace(aSub, nSubCount++);
1761  }
1762 
1763  // Rank all members.
1764 
1765  vector<OUString> aRankedNames(nMemberCount);
1766  sal_uInt16 nCurStrId = 0;
1767  for (auto const& aMemberName : aMembers)
1768  {
1769  sal_uInt16 nRank = 0;
1770  UserSortMap::const_iterator itrSub = aSubStrs.find(aMemberName);
1771  if (itrSub == aSubStrs.end())
1772  nRank = nSubCount + nCurStrId++;
1773  else
1774  nRank = itrSub->second;
1775 
1776  if (!bAscending)
1777  nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 );
1778 
1779  aRankedNames[nRank] = aMemberName;
1780  }
1781 
1782  // Re-order ScDPSaveMember instances with the new ranks.
1783  for (auto const& aRankedName : aRankedNames)
1784  {
1785  const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(aRankedName);
1786  if (!pOldMem)
1787  // All members are supposed to be present.
1788  continue;
1789 
1790  pSaveDim->AddMember(std::unique_ptr<ScDPSaveMember>(new ScDPSaveMember(*pOldMem)));
1791  }
1792 
1793  // Set the sorting mode to manual for now. We may introduce a new sorting
1794  // mode later on.
1795 
1796  sheet::DataPilotFieldSortInfo aSortInfo;
1797  aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1798  pSaveDim->SetSortInfo(&aSortInfo);
1799  }
1800  else
1801  {
1802  // without user list id, just apply sorting mode
1803 
1804  sheet::DataPilotFieldSortInfo aSortInfo;
1805  aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME;
1806  aSortInfo.IsAscending = bAscending;
1807  pSaveDim->SetSortInfo(&aSortInfo);
1808  }
1809 
1810  // Update the datapilot with the newly sorted field members.
1811 
1812  std::unique_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj));
1813  pNewObj->SetSaveData(aNewSaveData);
1814  ScDBDocFunc aFunc(*GetViewData().GetDocShell());
1815 
1816  aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false);
1817 }
1818 
1819 bool ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest )
1820 {
1821  bool bRet = false;
1822  ScDocument& rDoc = GetViewData().GetDocument();
1823  ScDPObject* pDPObj = rDoc.GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() );
1824  if ( pDPObj && pDPObj == rDoc.GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) )
1825  {
1826  sheet::DataPilotTableHeaderData aDestData;
1827  pDPObj->GetHeaderPositionData( rDest, aDestData );
1828  bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field
1829 
1830  // look through the source range
1831  std::unordered_set< OUString > aMembersSet; // for lookup
1832  std::vector< OUString > aMembersVector; // members in original order, for inserting
1833  aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ),
1834  static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) );
1835  for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow )
1836  for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol )
1837  {
1838  sheet::DataPilotTableHeaderData aSourceData;
1839  pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData );
1840  if ( aSourceData.Dimension == aDestData.Dimension && !aSourceData.MemberName.isEmpty() )
1841  {
1842  if ( aMembersSet.insert( aSourceData.MemberName ).second )
1843  {
1844  aMembersVector.push_back( aSourceData.MemberName );
1845  }
1846  // duplicates are ignored
1847  }
1848  else
1849  bValid = false; // empty (subtotal) or different field
1850  }
1851 
1852  if ( bValid )
1853  {
1854  bool bIsDataLayout;
1855  OUString aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout );
1856  if ( !bIsDataLayout )
1857  {
1858  ScDPSaveData aData( *pDPObj->GetSaveData() );
1859  ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
1860 
1861  // get all member names in source order
1862  uno::Sequence<OUString> aMemberNames;
1863  pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames );
1864 
1865  bool bInserted = false;
1866 
1867  for (const OUString& aMemberStr : std::as_const(aMemberNames))
1868  {
1869  if ( !bInserted && aMemberStr == aDestData.MemberName )
1870  {
1871  // insert dragged items before this item
1872  for ( const auto& rMember : aMembersVector )
1873  lcl_MoveToEnd( *pDim, rMember );
1874  bInserted = true;
1875  }
1876 
1877  if ( aMembersSet.find( aMemberStr ) == aMembersSet.end() ) // skip dragged items
1878  lcl_MoveToEnd( *pDim, aMemberStr );
1879  }
1880  // insert dragged item at end if dest wasn't found (for example, empty)
1881  if ( !bInserted )
1882  for ( const auto& rMember : aMembersVector )
1883  lcl_MoveToEnd( *pDim, rMember );
1884 
1885  // Items that were in SaveData, but not in the source, end up at the start of the list.
1886 
1887  // set flag for manual sorting
1888  sheet::DataPilotFieldSortInfo aSortInfo;
1889  aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL;
1890  pDim->SetSortInfo( &aSortInfo );
1891 
1892  // apply changes
1893  ScDBDocFunc aFunc( *GetViewData().GetDocShell() );
1894  std::unique_ptr<ScDPObject> pNewObj(new ScDPObject( *pDPObj ));
1895  pNewObj->SetSaveData( aData );
1896  aFunc.DataPilotUpdate( pDPObj, pNewObj.get(), true, false );
1897  pNewObj.reset();
1898 
1899  Unmark(); // entry was moved - no use in leaving the old cell selected
1900 
1901  bRet = true;
1902  }
1903  }
1904  }
1905 
1906  return bRet;
1907 }
1908 
1909 bool ScDBFunc::HasSelectionForDrillDown( css::sheet::DataPilotFieldOrientation& rOrientation )
1910 {
1911  bool bRet = false;
1912 
1913  ScDPObject* pDPObj = GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1914  GetViewData().GetCurY(), GetViewData().GetTabNo() );
1915  if ( pDPObj )
1916  {
1918  tools::Long nSelectDimension = -1;
1919  GetSelectedMemberList( aEntries, nSelectDimension );
1920 
1921  if (!aEntries.empty())
1922  {
1923  bool bIsDataLayout;
1924  OUString aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1925  if ( !bIsDataLayout )
1926  {
1927  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1928  ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aDimName );
1929  if ( pDim )
1930  {
1931  css::sheet::DataPilotFieldOrientation nDimOrient = pDim->GetOrientation();
1932  ScDPSaveDimension* pInner = pSaveData->GetInnermostDimension( nDimOrient );
1933  if ( pDim == pInner )
1934  {
1935  rOrientation = nDimOrient;
1936  bRet = true;
1937  }
1938  }
1939  }
1940  }
1941  }
1942 
1943  return bRet;
1944 }
1945 
1946 void ScDBFunc::SetDataPilotDetails(bool bShow, const OUString* pNewDimensionName)
1947 {
1948  ScDPObject* pDPObj = GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1949  GetViewData().GetCurY(), GetViewData().GetTabNo() );
1950  if ( !pDPObj )
1951  return;
1952 
1954  tools::Long nSelectDimension = -1;
1955  GetSelectedMemberList( aEntries, nSelectDimension );
1956 
1957  if (aEntries.empty())
1958  return;
1959 
1960  bool bIsDataLayout;
1961  OUString aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout );
1962  if ( bIsDataLayout )
1963  return;
1964 
1965  ScDPSaveData aData( *pDPObj->GetSaveData() );
1966  ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName );
1967 
1968  if ( bShow && pNewDimensionName )
1969  {
1970  // add the new dimension with the same orientation, at the end
1971 
1972  ScDPSaveDimension* pNewDim = aData.GetDimensionByName( *pNewDimensionName );
1973  ScDPSaveDimension* pDuplicated = nullptr;
1974  if ( pNewDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA )
1975  {
1976  // Need to duplicate the dimension, create column/row in addition to data:
1977  // The duplicated dimension inherits the existing settings, pNewDim is modified below.
1978  pDuplicated = aData.DuplicateDimension( *pNewDimensionName );
1979  }
1980 
1981  css::sheet::DataPilotFieldOrientation nOrientation = pDim->GetOrientation();
1982  pNewDim->SetOrientation( nOrientation );
1983 
1984  tools::Long nPosition = LONG_MAX;
1985  aData.SetPosition( pNewDim, nPosition );
1986 
1987  ScDPSaveDimension* pDataLayout = aData.GetDataLayoutDimension();
1988  if ( pDataLayout->GetOrientation() == nOrientation &&
1989  aData.GetDataDimensionCount() <= 1 )
1990  {
1991  // If there is only one data dimension, the data layout dimension
1992  // must still be the last one in its orientation.
1993  aData.SetPosition( pDataLayout, nPosition );
1994  }
1995 
1996  if ( pDuplicated )
1997  {
1998  // The duplicated (data) dimension needs to be behind the original dimension
1999  aData.SetPosition( pDuplicated, nPosition );
2000  }
2001 
2002  // Hide details for all visible members (selected are changed below).
2004 
2005  ScDPUniqueStringSet aVisibleEntries;
2006  pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension );
2007 
2008  for (const OUString& aVisName : aVisibleEntries)
2009  {
2010  ScDPSaveMember* pMember = pDim->GetMemberByName( aVisName );
2011  pMember->SetShowDetails( false );
2012  }
2013  }
2014 
2015  for (const auto& rEntry : aEntries)
2016  {
2017  ScDPSaveMember* pMember = pDim->GetMemberByName(rEntry);
2018  pMember->SetShowDetails( bShow );
2019  }
2020 
2021  // apply changes
2022  ScDBDocFunc aFunc( *GetViewData().GetDocShell() );
2023  std::unique_ptr<ScDPObject> pNewObj(new ScDPObject( *pDPObj ));
2024  pNewObj->SetSaveData( aData );
2025  aFunc.DataPilotUpdate( pDPObj, pNewObj.get(), true, false );
2026  pNewObj.reset();
2027 
2028  // unmark cell selection
2029  Unmark();
2030 }
2031 
2032 void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters )
2033 {
2034  ScDocument& rDoc = GetViewData().GetDocument();
2035  if (rDoc.GetDocumentShell()->IsReadOnly())
2036  {
2037  ErrorMessage(STR_READONLYERR);
2038  return;
2039  }
2040 
2041  Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource();
2042  Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions();
2043  Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY);
2044  if (!xDDSupplier.is())
2045  return;
2046 
2047  Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters);
2048  sal_Int32 nRowSize = aTabData.getLength();
2049  if (nRowSize <= 1)
2050  // There is no data to show. Bail out.
2051  return;
2052 
2053  SCCOL nColSize = aTabData[0].getLength();
2054 
2055  SCTAB nNewTab = GetViewData().GetTabNo();
2056 
2058  pInsDoc->ResetClip( &rDoc, nNewTab );
2059  for (SCROW nRow = 0; nRow < nRowSize; ++nRow)
2060  {
2061  for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2062  {
2063  const Any& rAny = aTabData[nRow][nCol];
2064  OUString aStr;
2065  double fVal;
2066  if (rAny >>= aStr)
2067  {
2068  pInsDoc->SetString(ScAddress(nCol,nRow,nNewTab), aStr);
2069  }
2070  else if (rAny >>= fVal)
2071  pInsDoc->SetValue(nCol, nRow, nNewTab, fVal);
2072  }
2073  }
2074 
2075  // set number format (important for dates)
2076  for (SCCOL nCol = 0; nCol < nColSize; ++nCol)
2077  {
2078  OUString aStr;
2079  if (!(aTabData[0][nCol] >>= aStr))
2080  continue;
2081 
2082  Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY);
2083  if (!xPropSet.is())
2084  continue;
2085 
2086  Any any = xPropSet->getPropertyValue( SC_UNO_DP_NUMBERFO );
2087  sal_Int32 nNumFmt = 0;
2088  if (!(any >>= nNumFmt))
2089  continue;
2090 
2091  ScPatternAttr aPattern( pInsDoc->GetPool() );
2092  aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<sal_uInt32>(nNumFmt)) );
2093  pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern);
2094  }
2095 
2096  SCCOL nEndCol = 0;
2097  SCROW nEndRow = 0;
2098  pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow );
2099  pInsDoc->SetClipArea( ScRange( 0, 0, nNewTab, nEndCol, nEndRow, nNewTab ) );
2100 
2101  SfxUndoManager* pMgr = GetViewData().GetDocShell()->GetUndoManager();
2102  OUString aUndo = ScResId( STR_UNDO_DOOUTLINE );
2103  pMgr->EnterListAction( aUndo, aUndo, 0, GetViewData().GetViewShell()->GetViewShellId() );
2104 
2105  OUString aNewTabName;
2106  rDoc.CreateValidTabName(aNewTabName);
2107  if ( InsertTable(aNewTabName, nNewTab) )
2108  PasteFromClip( InsertDeleteFlags::ALL, pInsDoc.get() );
2109 
2110  pMgr->LeaveListAction();
2111 }
2112 
2113 // repeat data base operations (sorting, filtering, subtotals)
2114 
2115 void ScDBFunc::RepeatDB( bool bRecord )
2116 {
2117  SCCOL nCurX = GetViewData().GetCurX();
2118  SCROW nCurY = GetViewData().GetCurY();
2119  SCTAB nTab = GetViewData().GetTabNo();
2120  ScDocument& rDoc = GetViewData().GetDocument();
2121  ScDBData* pDBData = GetDBData();
2122  if (bRecord && !rDoc.IsUndoEnabled())
2123  bRecord = false;
2124 
2125  ScQueryParam aQueryParam;
2126  pDBData->GetQueryParam( aQueryParam );
2127  bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
2128 
2129  ScSortParam aSortParam;
2130  pDBData->GetSortParam( aSortParam );
2131  bool bSort = aSortParam.maKeyState[0].bDoSort;
2132 
2133  ScSubTotalParam aSubTotalParam;
2134  pDBData->GetSubTotalParam( aSubTotalParam );
2135  bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
2136 
2137  if ( bQuery || bSort || bSubTotal )
2138  {
2139  bool bQuerySize = false;
2140  ScRange aOldQuery;
2141  ScRange aNewQuery;
2142  if (bQuery && !aQueryParam.bInplace)
2143  {
2144  ScDBData* pDest = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2145  aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
2146  if (pDest && pDest->IsDoSize())
2147  {
2148  pDest->GetArea( aOldQuery );
2149  bQuerySize = true;
2150  }
2151  }
2152 
2153  SCTAB nDummy;
2154  SCCOL nStartCol;
2155  SCROW nStartRow;
2156  SCCOL nEndCol;
2157  SCROW nEndRow;
2158  pDBData->GetArea( nDummy, nStartCol, nStartRow, nEndCol, nEndRow );
2159 
2161 
2162  ScDocumentUniquePtr pUndoDoc;
2163  std::unique_ptr<ScOutlineTable> pUndoTab;
2164  std::unique_ptr<ScRangeName> pUndoRange;
2165  std::unique_ptr<ScDBCollection> pUndoDB;
2166 
2167  if (bRecord)
2168  {
2169  SCTAB nTabCount = rDoc.GetTableCount();
2170  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
2171  ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
2172  if (pTable)
2173  {
2174  pUndoTab.reset(new ScOutlineTable( *pTable ));
2175 
2176  SCCOLROW nOutStartCol; // row/column status
2177  SCCOLROW nOutStartRow;
2178  SCCOLROW nOutEndCol;
2179  SCCOLROW nOutEndRow;
2180  pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol );
2181  pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow );
2182 
2183  pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
2184  rDoc.CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc );
2185  rDoc.CopyToDocument( 0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc );
2186  }
2187  else
2188  pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
2189 
2190  // Record data range - including filter results
2191  rDoc.CopyToDocument( 0,nStartRow,nTab, rDoc.MaxCol(),nEndRow,nTab, InsertDeleteFlags::ALL, false, *pUndoDoc );
2192 
2193  // all formulas for reference
2194  rDoc.CopyToDocument( 0,0,0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1, InsertDeleteFlags::FORMULA, false, *pUndoDoc );
2195 
2196  // data base and other ranges
2197  ScRangeName* pDocRange = rDoc.GetRangeName();
2198  if (!pDocRange->empty())
2199  pUndoRange.reset(new ScRangeName( *pDocRange ));
2200  ScDBCollection* pDocDB = rDoc.GetDBCollection();
2201  if (!pDocDB->empty())
2202  pUndoDB.reset(new ScDBCollection( *pDocDB ));
2203  }
2204 
2205  if (bSort && bSubTotal)
2206  {
2207  // sort without subtotals
2208 
2209  aSubTotalParam.bRemoveOnly = true; // is reset below
2210  DoSubTotals( aSubTotalParam, false );
2211  }
2212 
2213  if (bSort)
2214  {
2215  pDBData->GetSortParam( aSortParam ); // range may have changed
2216  Sort( aSortParam, false, false);
2217  }
2218  if (bQuery)
2219  {
2220  pDBData->GetQueryParam( aQueryParam ); // range may have changed
2221  ScRange aAdvSource;
2222  if (pDBData->GetAdvancedQuerySource(aAdvSource))
2223  {
2224  rDoc.CreateQueryParam(aAdvSource, aQueryParam);
2225  Query( aQueryParam, &aAdvSource, false );
2226  }
2227  else
2228  Query( aQueryParam, nullptr, false );
2229 
2230  // if not inplace the sheet may have changed
2231  if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
2232  SetTabNo( nTab );
2233  }
2234  if (bSubTotal)
2235  {
2236  pDBData->GetSubTotalParam( aSubTotalParam ); // range may have changed
2237  aSubTotalParam.bRemoveOnly = false;
2238  DoSubTotals( aSubTotalParam, false );
2239  }
2240 
2241  if (bRecord)
2242  {
2243  SCTAB nDummyTab;
2244  SCCOL nDummyCol;
2245  SCROW nDummyRow, nNewEndRow;
2246  pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
2247 
2248  const ScRange* pOld = nullptr;
2249  const ScRange* pNew = nullptr;
2250  if (bQuerySize)
2251  {
2252  ScDBData* pDest = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
2253  aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
2254  if (pDest)
2255  {
2256  pDest->GetArea( aNewQuery );
2257  pOld = &aOldQuery;
2258  pNew = &aNewQuery;
2259  }
2260  }
2261 
2262  GetViewData().GetDocShell()->GetUndoManager()->AddUndoAction(
2263  std::make_unique<ScUndoRepeatDB>( GetViewData().GetDocShell(), nTab,
2264  nStartCol, nStartRow, nEndCol, nEndRow,
2265  nNewEndRow,
2266  nCurX, nCurY,
2267  std::move(pUndoDoc), std::move(pUndoTab),
2268  std::move(pUndoRange), std::move(pUndoDB),
2269  pOld, pNew ) );
2270  }
2271 
2272  GetViewData().GetDocShell()->PostPaint(
2273  ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
2275  }
2276  else // "no not execute any operations"
2277  ErrorMessage(STR_MSSG_REPEATDB_0);
2278 }
2279 
2280 void ScDBFunc::OnLOKShowHideColRow(bool bColumns, SCCOLROW nStart)
2281 {
2283  return;
2284 
2285  SCTAB nCurrentTabIndex = GetViewData().GetTabNo();
2286  SfxViewShell* pThisViewShell = GetViewData().GetViewShell();
2287  SfxViewShell* pViewShell = SfxViewShell::GetFirst();
2288  while (pViewShell)
2289  {
2290  ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
2291  if (pTabViewShell && pTabViewShell->GetDocId() == pThisViewShell->GetDocId())
2292  {
2293  if (bColumns)
2294  {
2295  if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKWidthHelper(nCurrentTabIndex))
2296  pPosHelper->invalidateByIndex(nStart);
2297  }
2298  else
2299  {
2300  if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nCurrentTabIndex))
2301  pPosHelper->invalidateByIndex(nStart);
2302  }
2303 
2304  if (pTabViewShell->getPart() == nCurrentTabIndex)
2305  {
2306  pTabViewShell->ShowCursor();
2307  pTabViewShell->MarkDataChanged();
2308  }
2309  }
2310  pViewShell = SfxViewShell::GetNext(*pViewShell);
2311  }
2312 }
2313 
2314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:121
bool bGroupActive[MAXSUBTOTAL]
active groups
const ScDPDimensionSaveData * GetExistingDimensionData() const
Definition: dpsave.hxx:348
SC_DLLPUBLIC ScDPObject * GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: documen3.cxx:377
const OUString & GetGroupDimName() const
Definition: dpdimsave.hxx:107
void RecalcPivotTable()
Definition: dbfunc3.cxx:723
function is determined automatically.
Collection of user-defined sort lists.
Definition: userlist.hxx:66
bool IsDimNameInUse(std::u16string_view rName) const
Definition: dpobject.cxx:1172
void GetHeaderPositionData(const ScAddress &rPos, css::sheet::DataPilotTableHeaderData &rData)
Definition: dpobject.cxx:1292
sal_Int32 nIndex
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:814
ScAddress aStart
Definition: address.hxx:499
void DataPilotInput(const ScAddress &rPos, const OUString &rString)
Definition: dbfunc3.cxx:1382
void ShowDataPilotSourceData(ScDPObject &rDPObj, const css::uno::Sequence< css::sheet::DataPilotFieldFilter > &rFilters)
Definition: dbfunc3.cxx:2032
void UngroupDataPilot()
Definition: dbfunc3.cxx:1262
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:163
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
SCCOL nCol1
selected area
void Rename(const OUString &rNewName)
Definition: dpdimsave.cxx:82
void SetOrientation(css::sheet::DataPilotFieldOrientation nNew)
Definition: dpsave.cxx:317
SC_DLLPUBLIC bool IsHidden() const
Definition: olinetab.hxx:49
SCROW Row() const
Definition: address.hxx:261
bool RemoveAllOutlines(SCTAB nTab, bool bRecord)
Definition: olinefun.cxx:201
void MarkToMulti()
Definition: markdata.cxx:223
bool MakePivotTable(const ScDPSaveData &rData, const ScRange &rDest, bool bNewTable, const ScDPObject &rSource)
Definition: dbfunc3.cxx:621
bool IsMemberNameInUse(const OUString &rName) const
Definition: dpsave.cxx:368
const MemberList & GetMembers() const
Definition: dpsave.hxx:128
css::sheet::DataPilotFieldOrientation GetOrientation() const
Definition: dpsave.hxx:202
SC_DLLPUBLIC void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:401
SC_DLLPUBLIC SCCOLROW GetEnd() const
Definition: olinetab.cxx:42
static void lcl_MoveToEnd(ScDPSaveDimension &rDim, const OUString &rItemName)
Definition: dbfunc3.cxx:1664
int getPart() const override
See SfxViewShell::getPart().
Definition: tabvwshc.cxx:435
ScGeneralFunction GetSubTotalFunc(tools::Long nIndex) const
Definition: dpsave.hxx:152
sal_uIntPtr sal_uLong
long Long
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
Classes to save Data Pilot settings that create new dimensions (fields).
Definition: dpdimsave.hxx:46
const OUString & GetGroupName() const
Definition: dpdimsave.hxx:65
sal_Int64 n
SC_DLLPUBLIC ScDPCollection * GetDPCollection()
Definition: documen3.cxx:365
ViewShellDocId GetDocId() const override
void SetOutRange(const ScRange &rRange)
Definition: dpobject.cxx:402
const OUString & GetSourceDimName() const
Definition: dpdimsave.hxx:108
void RemoveGroupDimension(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:581
aBuf
SvNumFormatType GetType(sal_uInt32 nFIndex) const
void MakeOutline(bool bColumns, bool bRecord=true)
Definition: dbfunc3.cxx:89
const SfxItemSet & GetItemSet() const
const ContentProperties & rData
void PostPaintExtras()
Definition: docsh3.cxx:198
SC_DLLPUBLIC const ScDBData * GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
Definition: documen3.cxx:338
size_t size() const
Definition: userlist.cxx:345
ScAddress aEnd
Definition: address.hxx:500
bool bDoSort
presort
sal_Int32 GetDatePart() const
Definition: dpdimsave.hxx:152
ScDPSaveMember * GetExistingMemberByName(const OUString &rName)
Definition: dpsave.cxx:448
SC_DLLPUBLIC bool CreateQueryParam(const ScRange &rRange, ScQueryParam &rQueryParam)
Definition: documen3.cxx:1487
void RemoveNumGroupDimension(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:606
const ScDPNumGroupInfo & GetDateInfo() const
Definition: dpdimsave.hxx:153
void SetName(const OUString &rNew)
Definition: dpsave.cxx:309
static OUString lcl_MakePivotTabName(std::u16string_view rPrefix, SCTAB nNumber)
Definition: dbfunc3.cxx:615
bool DoSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:777
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5205
bool IsDoSize() const
Definition: dbdata.hxx:136
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:556
void HideMarkedOutlines(bool bRecord=true)
Definition: dbfunc3.cxx:408
virtual void ShowCursor(bool bOn) override
Definition: tabvwsh4.cxx:467
bool HasSelectionForDateGroup(ScDPNumGroupInfo &rOldInfo, sal_Int32 &rParts)
Definition: dbfunc3.cxx:806
SfxApplication * SfxGetpApp()
void ShowOutline(bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bRecord=true, bool bPaint=true)
Definition: dbfunc3.cxx:267
bool UpdatePivotTable(ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1592
Query
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2927
void DateGroupDataPilot(const ScDPNumGroupInfo &rInfo, sal_Int32 nParts)
Definition: dbfunc3.cxx:987
sal_uInt16 sal_Unicode
Stores individual user-defined sort list.
Definition: userlist.hxx:32
RET_YES
const ScDPSaveGroupDimension * GetNamedGroupDim(const OUString &rGroupDimName) const
Definition: dpdimsave.cxx:636
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
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:872
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:314
bool RemovePivotTable(const ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1399
bool empty() const
Definition: rangenam.cxx:809
void MarkDataChanged()
Definition: tabview3.cxx:1746
size_t GetDepth() const
Definition: olinetab.hxx:110
static SfxViewShell * GetNext(const SfxViewShell &rPrev, bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3517
void DataPilotSort(ScDPObject *pDPObject, tools::Long nDimIndex, bool bAscending, const sal_uInt16 *pUserListId=nullptr)
Definition: dbfunc3.cxx:1693
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:2050
void DoSubTotals(const ScSubTotalParam &rParam, bool bRecord=true, const ScSortParam *pForceNewSort=nullptr)
Definition: dbfunc3.cxx:431
oslFileHandle & pOut
Sort
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:125
const OUString & GetName() const
Definition: dpsave.hxx:66
SCTAB Tab() const
Definition: address.hxx:270
bool ReloadGroupsInCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3433
void MakeOutline(const ScRange &rRange, bool bColumns, bool bRecord, bool bApi)
Definition: olinefun.cxx:80
void AddElementsFromGroup(const ScDPSaveGroupItem &rGroup)
Definition: dpdimsave.cxx:50
size_t GetSubCount() const
Definition: userlist.cxx:109
bool IsEmpty() const
Definition: dpsave.cxx:1148
bool HasSelectionForNumGroup(ScDPNumGroupInfo &rOldInfo)
Definition: dbfunc3.cxx:919
void SetGroupInfo(const ScDPNumGroupInfo &rNew)
Definition: dpdimsave.cxx:525
sal_Int32 GetDatePart() const
Definition: dpdimsave.hxx:110
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
ScViewData & GetViewData()
Definition: tabview.hxx:333
std::vector< ScDPSaveMember * > MemberList
Definition: dpsave.hxx:115
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4745
void GetRange(SCCOLROW &rStart, SCCOLROW &rEnd) const
Definition: olinetab.cxx:555
void SetOutlineState(bool bColumn, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bHidden)
Definition: dbfunc3.cxx:253
constexpr OUStringLiteral aData
ScDPSaveGroupDimension * GetNamedGroupDimAcc(const OUString &rGroupDimName)
Definition: dpdimsave.cxx:662
ScDPSaveDimension * GetInnermostDimension(css::sheet::DataPilotFieldOrientation nOrientation)
Definition: dpsave.cxx:918
void SetLayoutName(const OUString &rName)
Definition: dpsave.cxx:379
SC_DLLPUBLIC double GetValue(const ScAddress &rPos) const
Definition: document.cxx:3659
void SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dbdata.cxx:322
tools::Long GetGroupCount() const
Definition: dpdimsave.cxx:199
void SetMarkArea(const ScRange &rRange)
Definition: markdata.cxx:96
void AutoOutline()
Definition: dbfunc3.cxx:214
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:871
void RepeatDB(bool bRecord=true)
Definition: dbfunc3.cxx:2115
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:441
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
const ScDPSaveGroupItem & GetGroupByIndex(tools::Long nIndex) const
Definition: dpdimsave.cxx:204
void RemoveOutline(const ScRange &rRange, bool bColumns, bool bRecord, bool bApi)
Definition: olinefun.cxx:138
tools::Long GetSubTotalsCount() const
Definition: dpsave.hxx:149
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
Definition: dpsave.cxx:1202
bool HideMarkedOutlines(const ScRange &rRange, bool bRecord)
Definition: olinefun.cxx:540
int i
Represents a group dimension that introduces a new hierarchy for an existing dimension.
Definition: dpdimsave.hxx:135
bool empty() const
Definition: dbdata.cxx:1513
SC_DLLPUBLIC SCCOLROW GetStart() const
Definition: olinetab.hxx:42
SC_DLLPUBLIC void SetLayoutName(const OUString &rName)
Definition: dpsave.cxx:118
css::uno::Reference< css::sheet::XDimensionsSupplier > const & GetSource()
Definition: dpobject.cxx:516
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2622
const ScOutlineArray & GetRowArray() const
Definition: olinetab.hxx:160
void RemoveGroup(const OUString &rGroupName)
Definition: dpdimsave.cxx:225
sal_Int16 SCCOL
Definition: types.hxx:21
const ScOutlineArray & GetColArray() const
Definition: olinetab.hxx:158
bool DataPilotUpdate(ScDPObject *pOldObj, const ScDPObject *pNewObj, bool bRecord, bool bApi, bool bAllowMove=false)
Definition: dbdocfun.cxx:1297
void OnLOKShowHideColRow(bool bColumns, SCCOLROW nStartRow)
Definition: dbfunc3.cxx:2280
void SetSaveData(const ScDPSaveData &rData)
Definition: dpobject.cxx:387
void SetName(const OUString &rNew)
Definition: dpsave.cxx:110
const Any & any
SC_DLLPUBLIC void CreateValidTabName(OUString &rName) const
Definition: document.cxx:392
bool OutlinePossible(bool bHide)
Definition: dbfunc3.cxx:307
size_t size() const
Definition: rangelst.hxx:89
static SC_DLLPUBLIC ScUserList * GetUserList()
Definition: global.cxx:276
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
SC_DLLPUBLIC bool InsertTab(SCTAB nPos, const OUString &rName, bool bExternalDocument=false, bool bUndoDeleteTab=false)
Definition: document.cxx:504
SvNumFormatType
bool Remove(SCCOLROW nBlockStart, SCCOLROW nBlockEnd, bool &rSizeChanged)
Definition: olinetab.cxx:395
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:141
void Consolidate(const ScConsolidateParam &rParam)
Definition: dbfunc3.cxx:606
void RemoveAllOutlines(bool bRecord=true)
Definition: dbfunc3.cxx:194
const ScDPNumGroupInfo & GetDateInfo() const
Definition: dpdimsave.hxx:111
void AutoOutline(const ScRange &rRange, bool bRecord)
Definition: olinefun.cxx:253
void SelectLevel(bool bColumns, sal_uInt16 nLevel, bool bRecord=true)
Definition: dbfunc3.cxx:233
SC_DLLPUBLIC ScDPSaveDimension * GetExistingDimensionByName(std::u16string_view rName) const
Definition: dpsave.cxx:845
void ShowMarkedOutlines(bool bRecord=true)
Definition: dbfunc3.cxx:385
const SCTAB MAXTAB
Definition: address.hxx:70
SC_DLLPUBLIC bool HasValueData(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3796
static SfxViewShell * GetFirst(bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
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:498
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 GetArea(SCTAB &rTab, SCCOL &rCol1, SCROW &rRow1, SCCOL &rCol2, SCROW &rRow2) const
Definition: dbdata.cxx:300
void CompileDBFormula()
Definition: documen4.cxx:558
SfxViewShell * GetViewShell() const
const long LONG_MAX
SCCOL Col() const
Definition: address.hxx:266
bool IsReadOnly() const
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:463
size_t LeaveListAction()
SC_DLLPUBLIC void SetShowDetails(bool bSet)
Definition: dpsave.cxx:105
void RemoveSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:771
top left cell of area
bool bReplace
replace existing results
bool SelectLevel(SCTAB nTab, bool bColumns, sal_uInt16 nLevel, bool bRecord, bool bPaint)
Definition: olinefun.cxx:314
OUString GetDimName(tools::Long nDim, bool &rIsDataLayout, sal_Int32 *pFlags=nullptr)
Definition: dpobject.cxx:1196
bool GetMemberNames(sal_Int32 nDim, css::uno::Sequence< OUString > &rNames)
Definition: dpobject.cxx:997
bool DataPilotMove(const ScRange &rSource, const ScAddress &rDest)
Definition: dbfunc3.cxx:1819
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
sal_Int32 SCROW
Definition: types.hxx:17
void SetDirty(const ScRange &, bool bIncludeEmptyCells)
Definition: document.cxx:3888
void GetSelectedMemberList(ScDPUniqueStringSet &rEntries, tools::Long &rDimension)
Definition: dbfunc3.cxx:744
void HideOutline(bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bRecord=true, bool bPaint=true)
Definition: dbfunc3.cxx:287
ScOutlineEntry * GetNext()
Definition: olinetab.cxx:810
bool ShowMarkedOutlines(const ScRange &rRange, bool bRecord)
Definition: olinefun.cxx:426
bool HasOnlyHidden(const ScDPUniqueStringSet &rVisible)
Definition: dpdimsave.cxx:240
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
ScDPSaveGroupItem * GetNamedGroupAcc(const OUString &rGroupName)
Definition: dpdimsave.cxx:187
static SC_DLLPUBLIC CollatorWrapper & GetCollator()
case-insensitive collator
Definition: global.cxx:1047
void SetSubtotalName(const OUString &rName)
Definition: dpsave.cxx:353
std::unordered_set< OUString > ScDPUniqueStringSet
Definition: dptypes.hxx:16
void RemoveFromGroups(const OUString &rItemName)
Definition: dpdimsave.cxx:210
OUString aName
const OUString & GetName() const
Definition: dpsave.hxx:139
void GroupDataPilot()
Definition: dbfunc3.cxx:1127
void RemoveLayoutName()
Definition: dpsave.cxx:389
Represents a new group dimension whose dimension ID is higher than the highest source dimension ID...
Definition: dpdimsave.hxx:90
static OUString lcl_replaceMemberNameInSubtotal(const OUString &rSubtotal, std::u16string_view rMemberName)
Definition: dbfunc3.cxx:1337
SC_DLLPUBLIC ScOutlineTable * GetOutlineTable(SCTAB nTab, bool bCreate=false)
Definition: documen3.cxx:736
void Rename(const OUString &rNewName)
Definition: dpdimsave.cxx:248
virtual void EnterListAction(const OUString &rComment, const OUString &rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId)
void NumGroupDataPilot(const ScDPNumGroupInfo &rInfo)
Definition: dbfunc3.cxx:1085
void AddElement(const OUString &rName)
Definition: dpdimsave.cxx:45
void * p
void DeletePivotTable()
Definition: dbfunc3.cxx:706
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
const ScDPSaveGroupItem * GetNamedGroup(const OUString &rGroupName) const
Definition: dpdimsave.cxx:182
void GetMemberResultNames(ScDPUniqueStringSet &rNames, tools::Long nDimension)
Definition: dpobject.cxx:1420
const ScDocument & GetDocument() const
Definition: docsh.hxx:220
sal_Int32 CollectDateParts(const OUString &rBaseDimName) const
Definition: dpdimsave.cxx:698
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:424
bool TestRemoveSubTotals(SCTAB nTab, const ScSubTotalParam &rParam)
Definition: documen3.cxx:766
void SetDataPilotDetails(bool bShow, const OUString *pNewDimensionName=nullptr)
Definition: dbfunc3.cxx:1946
ScPositionHelper & GetLOKWidthHelper()
Definition: viewdata.hxx:409
char aEntryName[20]
void SetDocumentModified()
Definition: docsh.cxx:3279
bool HasSelectionForDrillDown(css::sheet::DataPilotFieldOrientation &rOrientation)
Definition: dbfunc3.cxx:1909
const ScDPNumGroupInfo & GetInfo() const
Definition: dpdimsave.hxx:150
void DoConsolidate(const ScConsolidateParam &rParam, bool bRecord=true)
Definition: docsh5.cxx:501
void SetSubTotalParam(const ScSubTotalParam &rSubTotalParam)
Definition: dbdata.cxx:475
ScXMLEditAttributeMap::Entry const aEntries[]
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1057
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:457
bool IsUndoEnabled() const
Definition: document.hxx:1535
void ShowOutline(SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bRecord, bool bPaint)
Definition: olinefun.cxx:635
void RemoveOutline(bool bColumns, bool bRecord=true)
Definition: dbfunc3.cxx:110
SC_DLLPUBLIC const std::optional< OUString > & GetLayoutName() const
Definition: dpsave.cxx:123
ScPositionHelper & GetLOKHeightHelper()
Definition: viewdata.hxx:410
const ScDPSaveNumGroupDimension * GetNumGroupDim(const OUString &rGroupDimName) const
Definition: dpdimsave.cxx:651
const ScDBData * GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, ScDBDataPortion ePortion) const
Definition: documen3.cxx:322
void RemoveLayoutName()
Definition: dpsave.cxx:128
void BuildAllDimensionMembers()
Definition: dpobject.cxx:960
void RefreshPivotTableGroups(ScDPObject *pDPObj)
Refresh the group dimensions of all pivot tables referencing the same cache.
Definition: dbdocfun.cxx:1684
void TestRemoveOutline(bool &rCol, bool &rRow)
Definition: dbfunc3.cxx:131
aStr
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:213
void AddGroupItem(const ScDPSaveGroupItem &rItem)
Definition: dpdimsave.cxx:148
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
Definition: dpsave.cxx:834
#define SC_UNO_DP_NUMBERFO
Definition: unonames.hxx:610
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
Create before modifications of the document and destroy thereafter.
Definition: docsh.hxx:456
tools::Long GetHeaderDim(const ScAddress &rPos, css::sheet::DataPilotFieldOrientation &rOrient)
Definition: dpobject.cxx:1405
sal_Int16 SCTAB
Definition: types.hxx:22
bool HideOutline(SCTAB nTab, bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, bool bRecord, bool bPaint)
Definition: olinefun.cxx:723
void SetDateInfo(const ScDPNumGroupInfo &rInfo, sal_Int32 nPart)
Definition: dpdimsave.cxx:142
OUString CreateGroupName(std::u16string_view rPrefix)
Definition: dpdimsave.cxx:153
void AddMember(std::unique_ptr< ScDPSaveMember > pMember)
Definition: dpsave.cxx:292
bool IsEmpty() const
Definition: dpdimsave.cxx:235
OUString GetSubStr(sal_uInt16 nIndex) const
Definition: userlist.cxx:140
void SetSortInfo(const css::sheet::DataPilotFieldSortInfo *pNew)
Definition: dpsave.cxx:402