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