LibreOffice Module sc (master)  1
dpobject.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 <docsh.hxx>
21 #include <dpcache.hxx>
22 #include <dpobject.hxx>
23 #include <dptabsrc.hxx>
24 #include <dpsave.hxx>
25 #include <dpdimsave.hxx>
26 #include <dpoutput.hxx>
27 #include <dpshttab.hxx>
28 #include <dpsdbtab.hxx>
29 #include <dpgroup.hxx>
30 #include <document.hxx>
31 #include <pivot.hxx>
32 #include <dapiuno.hxx>
33 #include <miscuno.hxx>
34 #include <refupdat.hxx>
35 #include <attrib.hxx>
36 #include <scitems.hxx>
37 #include <unonames.hxx>
38 #include <dpglobal.hxx>
39 #include <globstr.hrc>
40 #include <queryentry.hxx>
41 #include <dputil.hxx>
42 
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/sdb/XCompletedExecution.hpp>
45 #include <com/sun/star/sdbc/DataType.hpp>
46 #include <com/sun/star/sdbc/SQLException.hpp>
47 #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
48 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
49 #include <com/sun/star/sdbc/XRow.hpp>
50 #include <com/sun/star/sdbc/XRowSet.hpp>
51 #include <com/sun/star/sheet/GeneralFunction2.hpp>
52 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
53 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
54 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
55 #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp>
56 #include <com/sun/star/sheet/DataPilotTablePositionData.hpp>
57 #include <com/sun/star/sheet/DataPilotTablePositionType.hpp>
58 #include <com/sun/star/sheet/DimensionFlags.hpp>
59 #include <com/sun/star/task/InteractionHandler.hpp>
60 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
61 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
62 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
63 #include <com/sun/star/lang/XInitialization.hpp>
64 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
65 #include <com/sun/star/sheet/XDrillDownDataSupplier.hpp>
66 
67 #include <unotools/charclass.hxx>
69 #include <comphelper/string.hxx>
70 #include <comphelper/types.hxx>
71 #include <sal/macros.h>
72 #include <svl/numformat.hxx>
73 #include <tools/diagnose_ex.h>
74 #include <svl/zforlist.hxx>
75 #include <vcl/svapp.hxx>
76 #include <vcl/weld.hxx>
77 
78 #include <utility>
79 #include <vector>
80 #include <memory>
81 #include <algorithm>
82 
83 using namespace com::sun::star;
84 using ::std::vector;
85 using ::std::shared_ptr;
86 using ::com::sun::star::uno::Sequence;
87 using ::com::sun::star::uno::Reference;
88 using ::com::sun::star::uno::UNO_QUERY;
89 using ::com::sun::star::uno::Any;
90 using ::com::sun::star::uno::Exception;
91 using ::com::sun::star::lang::XComponent;
92 using ::com::sun::star::sheet::DataPilotTableHeaderData;
93 using ::com::sun::star::sheet::DataPilotTablePositionData;
94 using ::com::sun::star::sheet::XDimensionsSupplier;
95 using ::com::sun::star::beans::XPropertySet;
96 
97 constexpr OUStringLiteral SC_SERVICE_ROWSET = u"com.sun.star.sdb.RowSet";
98 
99 constexpr OUStringLiteral SC_DBPROP_DATASOURCENAME = u"DataSourceName";
100 constexpr OUStringLiteral SC_DBPROP_COMMAND = u"Command";
101 constexpr OUStringLiteral SC_DBPROP_COMMANDTYPE = u"CommandType";
102 
103 constexpr OUStringLiteral SCDPSOURCE_SERVICE = u"com.sun.star.sheet.DataPilotSource";
104 
105 namespace {
106 
112 class DBConnector : public ScDPCache::DBConnector
113 {
114  ScDPCache& mrCache;
115 
116  uno::Reference<sdbc::XRowSet> mxRowSet;
117  uno::Reference<sdbc::XRow> mxRow;
118  uno::Reference<sdbc::XResultSetMetaData> mxMetaData;
119  Date maNullDate;
120 
121 public:
122  DBConnector(ScDPCache& rCache, const uno::Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate);
123 
124  bool isValid() const;
125 
126  virtual void getValue(tools::Long nCol, ScDPItemData &rData, SvNumFormatType& rNumType) const override;
127  virtual OUString getColumnLabel(tools::Long nCol) const override;
128  virtual tools::Long getColumnCount() const override;
129  virtual bool first() override;
130  virtual bool next() override;
131  virtual void finish() override;
132 };
133 
134 DBConnector::DBConnector(ScDPCache& rCache, const uno::Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) :
135  mrCache(rCache), mxRowSet(xRowSet), maNullDate(rNullDate)
136 {
137  Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(mxRowSet, UNO_QUERY);
138  if (xMetaSupp.is())
139  mxMetaData = xMetaSupp->getMetaData();
140 
141  mxRow.set(mxRowSet, UNO_QUERY);
142 }
143 
144 bool DBConnector::isValid() const
145 {
146  return mxRowSet.is() && mxRow.is() && mxMetaData.is();
147 }
148 
149 bool DBConnector::first()
150 {
151  return mxRowSet->first();
152 }
153 
154 bool DBConnector::next()
155 {
156  return mxRowSet->next();
157 }
158 
159 void DBConnector::finish()
160 {
161  mxRowSet->beforeFirst();
162 }
163 
164 tools::Long DBConnector::getColumnCount() const
165 {
166  return mxMetaData->getColumnCount();
167 }
168 
169 OUString DBConnector::getColumnLabel(tools::Long nCol) const
170 {
171  return mxMetaData->getColumnLabel(nCol+1);
172 }
173 
174 void DBConnector::getValue(tools::Long nCol, ScDPItemData &rData, SvNumFormatType& rNumType) const
175 {
176  rNumType = SvNumFormatType::NUMBER;
177  sal_Int32 nType = mxMetaData->getColumnType(nCol+1);
178 
179  try
180  {
181  double fValue = 0.0;
182  switch (nType)
183  {
184  case sdbc::DataType::BIT:
185  case sdbc::DataType::BOOLEAN:
186  {
187  rNumType = SvNumFormatType::LOGICAL;
188  fValue = mxRow->getBoolean(nCol+1) ? 1 : 0;
189  rData.SetValue(fValue);
190  break;
191  }
192  case sdbc::DataType::TINYINT:
193  case sdbc::DataType::SMALLINT:
194  case sdbc::DataType::INTEGER:
195  case sdbc::DataType::BIGINT:
196  case sdbc::DataType::FLOAT:
197  case sdbc::DataType::REAL:
198  case sdbc::DataType::DOUBLE:
199  case sdbc::DataType::NUMERIC:
200  case sdbc::DataType::DECIMAL:
201  {
202  //TODO: do the conversion here?
203  fValue = mxRow->getDouble(nCol+1);
204  rData.SetValue(fValue);
205  break;
206  }
208  {
209  rNumType = SvNumFormatType::DATE;
210 
211  util::Date aDate = mxRow->getDate(nCol+1);
212  fValue = Date(aDate.Day, aDate.Month, aDate.Year) - maNullDate;
213  rData.SetValue(fValue);
214  break;
215  }
216  case sdbc::DataType::TIME:
217  {
218  rNumType = SvNumFormatType::TIME;
219 
220  util::Time aTime = mxRow->getTime(nCol+1);
221  fValue = aTime.Hours / static_cast<double>(::tools::Time::hourPerDay) +
222  aTime.Minutes / static_cast<double>(::tools::Time::minutePerDay) +
223  aTime.Seconds / static_cast<double>(::tools::Time::secondPerDay) +
224  aTime.NanoSeconds / static_cast<double>(::tools::Time::nanoSecPerDay);
225  rData.SetValue(fValue);
226  break;
227  }
228  case sdbc::DataType::TIMESTAMP:
229  {
230  rNumType = SvNumFormatType::DATETIME;
231 
232  util::DateTime aStamp = mxRow->getTimestamp(nCol+1);
233  fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - maNullDate ) +
234  aStamp.Hours / static_cast<double>(::tools::Time::hourPerDay) +
235  aStamp.Minutes / static_cast<double>(::tools::Time::minutePerDay) +
236  aStamp.Seconds / static_cast<double>(::tools::Time::secondPerDay) +
237  aStamp.NanoSeconds / static_cast<double>(::tools::Time::nanoSecPerDay);
238  rData.SetValue(fValue);
239  break;
240  }
241  case sdbc::DataType::CHAR:
242  case sdbc::DataType::VARCHAR:
243  case sdbc::DataType::LONGVARCHAR:
244  case sdbc::DataType::SQLNULL:
245  case sdbc::DataType::BINARY:
246  case sdbc::DataType::VARBINARY:
247  case sdbc::DataType::LONGVARBINARY:
248  default:
249  // nCol is 0-based, and the left-most column always has nCol == 0.
250  rData.SetStringInterned(
251  mrCache.InternString(nCol, mxRow->getString(nCol+1)));
252  }
253  }
254  catch (uno::Exception&)
255  {
256  rData.SetEmpty();
257  }
258 }
259 
260 }
261 
262 static sheet::DataPilotFieldOrientation lcl_GetDataGetOrientation( const uno::Reference<sheet::XDimensionsSupplier>& xSource )
263 {
264  sheet::DataPilotFieldOrientation nRet = sheet::DataPilotFieldOrientation_HIDDEN;
265  if ( xSource.is() )
266  {
267  uno::Reference<container::XNameAccess> xDimNameAccess = xSource->getDimensions();
268  const uno::Sequence<OUString> aDimNames = xDimNameAccess->getElementNames();
269  for (const OUString& rDimName : aDimNames)
270  {
271  uno::Reference<beans::XPropertySet> xDimProp(xDimNameAccess->getByName(rDimName),
272  uno::UNO_QUERY);
273  if ( xDimProp.is() )
274  {
275  const bool bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
277  //TODO: error checking -- is "IsDataLayoutDimension" property required??
278  if (bFound)
279  {
281  xDimProp, SC_UNO_DP_ORIENTATION,
282  sheet::DataPilotFieldOrientation_HIDDEN );
283  break;
284  }
285  }
286  }
287  }
288  return nRet;
289 }
290 
292  const OUString& rServ, const OUString& rSrc, const OUString& rNam,
293  const OUString& rUser, const OUString& rPass ) :
294  aServiceName( rServ ),
295  aParSource( rSrc ),
296  aParName( rNam ),
297  aParUser( rUser ),
298  aParPass( rPass ) {}
299 
301 {
302  return aServiceName == rOther.aServiceName &&
303  aParSource == rOther.aParSource &&
304  aParName == rOther.aParName &&
305  aParUser == rOther.aParUser &&
306  aParPass == rOther.aParPass;
307 }
308 
310  pDoc( pD ),
311  nHeaderRows( 0 ),
312  mbHeaderLayout(false),
313  bAllowMove(false),
314  bSettingsChanged(false),
315  mbEnableGetPivotData(true)
316 {
317 }
318 
320  pDoc( r.pDoc ),
321  aTableName( r.aTableName ),
322  aTableTag( r.aTableTag ),
323  aOutRange( r.aOutRange ),
324  maInteropGrabBag(r.maInteropGrabBag),
325  nHeaderRows( r.nHeaderRows ),
326  mbHeaderLayout( r.mbHeaderLayout ),
327  bAllowMove(false),
328  bSettingsChanged(false),
329  mbEnableGetPivotData(r.mbEnableGetPivotData)
330 {
331  if (r.pSaveData)
332  pSaveData.reset( new ScDPSaveData(*r.pSaveData) );
333  if (r.pSheetDesc)
334  pSheetDesc.reset( new ScSheetSourceDesc(*r.pSheetDesc) );
335  if (r.pImpDesc)
336  pImpDesc.reset( new ScImportSourceDesc(*r.pImpDesc) );
337  if (r.pServDesc)
338  pServDesc.reset( new ScDPServiceDesc(*r.pServDesc) );
339  // xSource (and pOutput) is not copied
340 }
341 
343 {
344  Clear();
345 }
346 
348 {
349  if (this != &r)
350  {
351  Clear();
352 
353  pDoc = r.pDoc;
355  aTableTag = r.aTableTag;
356  aOutRange = r.aOutRange;
360  bAllowMove = false;
361  bSettingsChanged = false;
363 
364  if (r.pSaveData)
365  pSaveData.reset( new ScDPSaveData(*r.pSaveData) );
366  if (r.pSheetDesc)
367  pSheetDesc.reset( new ScSheetSourceDesc(*r.pSheetDesc) );
368  if (r.pImpDesc)
369  pImpDesc.reset( new ScImportSourceDesc(*r.pImpDesc) );
370  if (r.pServDesc)
371  pServDesc.reset( new ScDPServiceDesc(*r.pServDesc) );
372  }
373  return *this;
374 }
375 
377 {
379 }
380 
382 {
383  bAllowMove = bSet;
384 }
385 
387 {
388  if ( pSaveData.get() != &rData ) // API implementation modifies the original SaveData object
389  {
390  pSaveData.reset( new ScDPSaveData( rData ) );
391  }
392 
393  InvalidateData(); // re-init source from SaveData
394 }
395 
396 void ScDPObject::SetHeaderLayout (bool bUseGrid)
397 {
398  mbHeaderLayout = bUseGrid;
399 }
400 
401 void ScDPObject::SetOutRange(const ScRange& rRange)
402 {
403  aOutRange = rRange;
404 
405  if ( pOutput )
406  pOutput->SetPosition( rRange.aStart );
407 }
408 
410 {
411  return aOutRange;
412 }
413 
415 {
416  if ( pSheetDesc && rDesc == *pSheetDesc )
417  return; // nothing to do
418 
419  pImpDesc.reset();
420  pServDesc.reset();
421 
422  pSheetDesc.reset( new ScSheetSourceDesc(rDesc) );
423 
424  // make valid QueryParam
425 
426  const ScRange& rSrcRange = pSheetDesc->GetSourceRange();
427  ScQueryParam aParam = pSheetDesc->GetQueryParam();
428  aParam.nCol1 = rSrcRange.aStart.Col();
429  aParam.nRow1 = rSrcRange.aStart.Row();
430  aParam.nCol2 = rSrcRange.aEnd.Col();
431  aParam.nRow2 = rSrcRange.aEnd.Row();
432  aParam.bHasHeader = true;
433  pSheetDesc->SetQueryParam(aParam);
434 
435  ClearTableData(); // new source must be created
436 }
437 
439 {
440  if ( pImpDesc && rDesc == *pImpDesc )
441  return; // nothing to do
442 
443  pSheetDesc.reset();
444  pServDesc.reset();
445 
446  pImpDesc.reset( new ScImportSourceDesc(rDesc) );
447 
448  ClearTableData(); // new source must be created
449 }
450 
452 {
453  if ( pServDesc && rDesc == *pServDesc )
454  return; // nothing to do
455 
456  pSheetDesc.reset();
457  pImpDesc.reset();
458 
459  pServDesc.reset( new ScDPServiceDesc(rDesc) );
460 
461  ClearTableData(); // new source must be created
462 }
463 
465 {
466  if ( pSheetDesc )
467  rDest.SetSheetDesc( *pSheetDesc );
468  else if ( pImpDesc )
469  rDest.SetImportDesc( *pImpDesc );
470  else if ( pServDesc )
471  rDest.SetServiceData( *pServDesc );
472 
473  // name/tag are not source data, but needed along with source data
474 
475  rDest.aTableName = aTableName;
476  rDest.aTableTag = aTableTag;
477 }
478 
480 {
481  rDest.nHeaderRows = nHeaderRows;
482 }
483 
485 {
486  return ( pSheetDesc != nullptr );
487 }
488 
489 void ScDPObject::SetName(const OUString& rNew)
490 {
491  aTableName = rNew;
492 }
493 
494 void ScDPObject::SetTag(const OUString& rNew)
495 {
496  aTableTag = rNew;
497 }
498 
500 {
501  if (!pSaveData)
502  return false;
503 
504  tools::Long nDataDimCount = pSaveData->GetDataDimensionCount();
505  if (nDataDimCount != 1)
506  // There has to be exactly one data dimension for the description to
507  // appear at top-left corner.
508  return false;
509 
510  CreateOutput();
511  ScRange aTabRange = pOutput->GetOutputRange(sheet::DataPilotOutputRangeType::TABLE);
512  return (rPos == aTabRange.aStart);
513 }
514 
515 uno::Reference<sheet::XDimensionsSupplier> const & ScDPObject::GetSource()
516 {
517  CreateObjects();
518  return xSource;
519 }
520 
522 {
523  CreateObjects();
524  if (pOutput)
525  return;
526 
527  bool bFilterButton = IsSheetData() && pSaveData && pSaveData->GetFilterButton();
528  pOutput.reset( new ScDPOutput( pDoc, xSource, aOutRange.aStart, bFilterButton ) );
529  pOutput->SetHeaderLayout ( mbHeaderLayout );
530 
531  sal_Int32 nOldRows = nHeaderRows;
532  nHeaderRows = pOutput->GetHeaderRows();
533 
534  if ( !(bAllowMove && nHeaderRows != nOldRows) )
535  return;
536 
537  sal_Int32 nDiff = nOldRows - nHeaderRows;
538  if ( nOldRows == 0 )
539  --nDiff;
540  if ( nHeaderRows == 0 )
541  ++nDiff;
542 
543  sal_Int32 nNewRow = aOutRange.aStart.Row() + nDiff;
544  if ( nNewRow < 0 )
545  nNewRow = 0;
546 
547  ScAddress aStart( aOutRange.aStart );
548  aStart.SetRow(nNewRow);
549  pOutput->SetPosition( aStart );
550 
551  //TODO: modify aOutRange?
552 
553  bAllowMove = false; // use only once
554 }
555 
556 namespace {
557 
558 class DisableGetPivotData
559 {
560  ScDPObject& mrDPObj;
561  bool mbOldState;
562 public:
563  DisableGetPivotData(ScDPObject& rObj, bool bOld) : mrDPObj(rObj), mbOldState(bOld)
564  {
565  mrDPObj.EnableGetPivotData(false);
566  }
567 
568  ~DisableGetPivotData()
569  {
570  mrDPObj.EnableGetPivotData(mbOldState);
571  }
572 };
573 
574 class FindIntersectingTable
575 {
577 public:
578  explicit FindIntersectingTable(const ScRange& rRange) : maRange(rRange) {}
579 
580  bool operator() (const std::unique_ptr<ScDPObject>& rObj) const
581  {
582  return maRange.Intersects(rObj->GetOutRange());
583  }
584 };
585 
586 class FindIntersectingTableByColumns
587 {
588  SCCOL mnCol1;
589  SCCOL mnCol2;
590  SCROW mnRow;
591  SCTAB mnTab;
592 public:
593  FindIntersectingTableByColumns(SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab) :
594  mnCol1(nCol1), mnCol2(nCol2), mnRow(nRow), mnTab(nTab) {}
595 
596  bool operator() (const std::unique_ptr<ScDPObject>& rObj) const
597  {
598  const ScRange& rRange = rObj->GetOutRange();
599  if (mnTab != rRange.aStart.Tab())
600  // Not on this sheet.
601  return false;
602 
603  if (rRange.aEnd.Row() < mnRow)
604  // This table is above the row. It's safe.
605  return false;
606 
607  if (mnCol1 <= rRange.aStart.Col() && rRange.aEnd.Col() <= mnCol2)
608  // This table is fully enclosed in this column range.
609  return false;
610 
611  if (rRange.aEnd.Col() < mnCol1 || mnCol2 < rRange.aStart.Col())
612  // This table is entirely outside this column range.
613  return false;
614 
615  // This table must be intersected by this column range.
616  return true;
617  }
618 };
619 
620 class FindIntersectingTableByRows
621 {
622  SCCOL mnCol;
623  SCROW mnRow1;
624  SCROW mnRow2;
625  SCTAB mnTab;
626 public:
627  FindIntersectingTableByRows(SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab) :
628  mnCol(nCol), mnRow1(nRow1), mnRow2(nRow2), mnTab(nTab) {}
629 
630  bool operator() (const std::unique_ptr<ScDPObject>& rObj) const
631  {
632  const ScRange& rRange = rObj->GetOutRange();
633  if (mnTab != rRange.aStart.Tab())
634  // Not on this sheet.
635  return false;
636 
637  if (rRange.aEnd.Col() < mnCol)
638  // This table is to the left of the column. It's safe.
639  return false;
640 
641  if (mnRow1 <= rRange.aStart.Row() && rRange.aEnd.Row() <= mnRow2)
642  // This table is fully enclosed in this row range.
643  return false;
644 
645  if (rRange.aEnd.Row() < mnRow1 || mnRow2 < rRange.aStart.Row())
646  // This table is entirely outside this row range.
647  return false;
648 
649  // This table must be intersected by this row range.
650  return true;
651  }
652 };
653 
654 class AccumulateOutputRanges
655 {
656  ScRangeList maRanges;
657  SCTAB mnTab;
658 public:
659  explicit AccumulateOutputRanges(SCTAB nTab) : mnTab(nTab) {}
660  AccumulateOutputRanges(const AccumulateOutputRanges& r) : maRanges(r.maRanges), mnTab(r.mnTab) {}
661 
662  void operator() (const std::unique_ptr<ScDPObject>& rObj)
663  {
664  const ScRange& rRange = rObj->GetOutRange();
665  if (mnTab != rRange.aStart.Tab())
666  // Not on this sheet.
667  return;
668 
669  maRanges.Join(rRange);
670  }
671 
672  const ScRangeList& getRanges() const { return maRanges; }
673 };
674 
675 }
676 
678 {
679  if (!mpTableData)
680  {
681  shared_ptr<ScDPTableData> pData;
682  const ScDPDimensionSaveData* pDimData = pSaveData ? pSaveData->GetExistingDimensionData() : nullptr;
683 
684  if ( pImpDesc )
685  {
686  // database data
687  const ScDPCache* pCache = pImpDesc->CreateCache(pDimData);
688  if (pCache)
689  {
690  pCache->AddReference(this);
691  pData = std::make_shared<ScDatabaseDPData>(pDoc, *pCache);
692  }
693  }
694  else
695  {
696  // cell data
697  if (!pSheetDesc)
698  {
699  OSL_FAIL("no source descriptor");
700  pSheetDesc.reset( new ScSheetSourceDesc(pDoc) ); // dummy defaults
701  }
702 
703  {
704  // Temporarily disable GETPIVOTDATA to avoid having
705  // GETPIVOTDATA called onto itself from within the source
706  // range.
707  DisableGetPivotData aSwitch(*this, mbEnableGetPivotData);
708  const ScDPCache* pCache = pSheetDesc->CreateCache(pDimData);
709  if (pCache)
710  {
711  pCache->AddReference(this);
712  pData = std::make_shared<ScSheetDPData>(pDoc, *pSheetDesc, *pCache);
713  }
714  }
715  }
716 
717  // grouping (for cell or database data)
718  if (pData && pDimData)
719  {
720  auto pGroupData = std::make_shared<ScDPGroupTableData>(pData, pDoc);
721  pDimData->WriteToData(*pGroupData);
722  pData = pGroupData;
723  }
724 
725  mpTableData = pData; // after SetCacheId
726  }
727 
728  return mpTableData.get();
729 }
730 
732 {
733  if (!xSource.is())
734  {
735  pOutput.reset(); // not valid when xSource is changed
736 
737  if ( pServDesc )
738  {
740  }
741 
742  if ( !xSource.is() ) // database or sheet data, or error in CreateSource
743  {
744  OSL_ENSURE( !pServDesc, "DPSource could not be created" );
746  if (pData)
747  {
748  if (pSaveData)
749  // Make sure to transfer these flags to the table data
750  // since they may have changed.
751  pData->SetEmptyFlags(pSaveData->GetIgnoreEmptyRows(), pSaveData->GetRepeatIfEmpty());
752 
753  pData->ReloadCacheTable();
754  xSource = new ScDPSource( pData );
755  }
756  }
757 
758  if (pSaveData)
759  pSaveData->WriteToSource( xSource );
760  }
761  else if (bSettingsChanged)
762  {
763  pOutput.reset(); // not valid when xSource is changed
764 
765  uno::Reference<util::XRefreshable> xRef( xSource, uno::UNO_QUERY );
766  if (xRef.is())
767  {
768  try
769  {
770  xRef->refresh();
771  }
772  catch(uno::Exception&)
773  {
774  TOOLS_WARN_EXCEPTION( "sc", "exception in refresh");
775  }
776  }
777 
778  if (pSaveData)
779  pSaveData->WriteToSource( xSource );
780  }
781  bSettingsChanged = false;
782 }
783 
785 {
786  bSettingsChanged = true;
787 }
788 
790 {
791  pOutput.reset();
792  pSaveData.reset();
793  pSheetDesc.reset();
794  pImpDesc.reset();
795  pServDesc.reset();
796  ClearTableData();
797  maInteropGrabBag.clear();
798 }
799 
801 {
802  ClearSource();
803 
804  if (mpTableData)
805  mpTableData->GetCacheTable().getCache().RemoveReference(this);
806  mpTableData.reset();
807 }
808 
810 {
811  ClearSource();
812 
813  if (!mpTableData)
814  // Table data not built yet. No need to reload the group data.
815  return;
816 
817  if (!pSaveData)
818  // How could it not have the save data... but whatever.
819  return;
820 
821  const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
822  if (!pDimData || !pDimData->HasGroupDimensions())
823  {
824  // No group dimensions exist. Check if it currently has group
825  // dimensions, and if so, remove all of them.
826  ScDPGroupTableData* pData = dynamic_cast<ScDPGroupTableData*>(mpTableData.get());
827  if (pData)
828  {
829  // Replace the existing group table data with the source data.
830  mpTableData = pData->GetSourceTableData();
831  }
832  return;
833  }
834 
835  ScDPGroupTableData* pData = dynamic_cast<ScDPGroupTableData*>(mpTableData.get());
836  if (pData)
837  {
838  // This is already a group table data. Salvage the source data and
839  // re-create a new group data.
840  const shared_ptr<ScDPTableData>& pSource = pData->GetSourceTableData();
841  auto pGroupData = std::make_shared<ScDPGroupTableData>(pSource, pDoc);
842  pDimData->WriteToData(*pGroupData);
843  mpTableData = pGroupData;
844  }
845  else
846  {
847  // This is a source data. Create a group data based on it.
848  auto pGroupData = std::make_shared<ScDPGroupTableData>(mpTableData, pDoc);
849  pDimData->WriteToData(*pGroupData);
850  mpTableData = pGroupData;
851  }
852 
853  bSettingsChanged = true;
854 }
855 
857 {
858  Reference< XComponent > xObjectComp( xSource, UNO_QUERY );
859  if (xObjectComp.is())
860  {
861  try
862  {
863  xObjectComp->dispose();
864  }
865  catch( const Exception& )
866  {
867  DBG_UNHANDLED_EXCEPTION("sc.core");
868  }
869  }
870  xSource = nullptr;
871 }
872 
874 {
875  CreateOutput(); // create xSource and pOutput if not already done
876 
877  rOverflow = pOutput->HasError(); // range overflow or exception from source
878  if ( rOverflow )
879  return ScRange( aOutRange.aStart );
880  else
881  {
882  // don't store the result in aOutRange, because nothing has been output yet
883  return pOutput->GetOutputRange();
884  }
885 }
886 
887 void ScDPObject::Output( const ScAddress& rPos )
888 {
889  // clear old output area
896 
897  CreateOutput(); // create xSource and pOutput if not already done
898 
899  pOutput->SetPosition( rPos );
900 
901  pOutput->Output();
902 
903  // aOutRange is always the range that was last output to the document
904  aOutRange = pOutput->GetOutputRange();
905  const ScAddress& s = aOutRange.aStart;
906  const ScAddress& e = aOutRange.aEnd;
907  pDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
908 }
909 
911 {
912  CreateOutput();
913 
914  if (pOutput->HasError())
915  return ScRange(aOutRange.aStart);
916 
917  return pOutput->GetOutputRange(nType);
918 }
919 
921 {
922  if (!pOutput || pOutput->HasError())
924 
925  return pOutput->GetOutputRange(nType);
926 }
927 
928 static bool lcl_HasButton( const ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
929 {
930  return pDoc->GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG )->HasPivotButton();
931 }
932 
934 {
935  // apply drop-down attribute, initialize nHeaderRows, without accessing the source
936  // (button attribute must be present)
937 
938  // simple test: block of button cells at the top, followed by an empty cell
939 
940  SCCOL nFirstCol = aOutRange.aStart.Col();
941  SCROW nFirstRow = aOutRange.aStart.Row();
942  SCTAB nTab = aOutRange.aStart.Tab();
943 
944  SCROW nInitial = 0;
945  SCROW nOutRows = aOutRange.aEnd.Row() + 1 - aOutRange.aStart.Row();
946  while ( nInitial + 1 < nOutRows && lcl_HasButton( pDoc, nFirstCol, nFirstRow + nInitial, nTab ) )
947  ++nInitial;
948 
949  if ( nInitial + 1 < nOutRows &&
950  pDoc->IsBlockEmpty( nFirstCol, nFirstRow + nInitial, nFirstCol, nFirstRow + nInitial, nTab ) &&
951  aOutRange.aEnd.Col() > nFirstCol )
952  {
953  nHeaderRows = nInitial;
954  }
955  else
956  nHeaderRows = 0; // nothing found, no drop-down lists
957 }
958 
960 {
961  if (!pSaveData)
962  return;
963 
964  // #i111857# don't always create empty mpTableData for external service.
965  if (pServDesc)
966  return;
967 
968  ScDPTableData* pTableData = GetTableData();
969  if(pTableData)
970  pSaveData->BuildAllDimensionMembers(pTableData);
971 }
972 
974 {
975  if (!pSaveData)
976  return false;
977 
978  // #i111857# don't always create empty mpTableData for external service.
979  // Ideally, xSource should be used instead of mpTableData.
980  if (pServDesc)
981  return false;
982 
984  if (!pData)
985  // No table data exists. This can happen when refreshing from an
986  // external source which doesn't exist.
987  return false;
988 
989  // Refresh the cache wrapper since the cache may have changed.
990  pData->SetEmptyFlags(pSaveData->GetIgnoreEmptyRows(), pSaveData->GetRepeatIfEmpty());
991  pData->ReloadCacheTable();
992  pSaveData->SyncAllDimensionMembers(pData);
993  return true;
994 }
995 
996 bool ScDPObject::GetMemberNames( sal_Int32 nDim, Sequence<OUString>& rNames )
997 {
998  vector<ScDPLabelData::Member> aMembers;
999  if (!GetMembers(nDim, GetUsedHierarchy(nDim), aMembers))
1000  return false;
1001 
1002  size_t n = aMembers.size();
1003  rNames.realloc(n);
1004  auto pNames = rNames.getArray();
1005  for (size_t i = 0; i < n; ++i)
1006  pNames[i] = aMembers[i].maName;
1007 
1008  return true;
1009 }
1010 
1011 bool ScDPObject::GetMembers( sal_Int32 nDim, sal_Int32 nHier, vector<ScDPLabelData::Member>& rMembers )
1012 {
1013  Reference< sheet::XMembersAccess > xMembersNA;
1014  if (!GetMembersNA( nDim, nHier, xMembersNA ))
1015  return false;
1016 
1017  Reference<container::XIndexAccess> xMembersIA( new ScNameToIndexAccess(xMembersNA) );
1018  sal_Int32 nCount = xMembersIA->getCount();
1019  vector<ScDPLabelData::Member> aMembers;
1020  aMembers.reserve(nCount);
1021 
1022  for (sal_Int32 i = 0; i < nCount; ++i)
1023  {
1024  Reference<container::XNamed> xMember(xMembersIA->getByIndex(i), UNO_QUERY);
1025  ScDPLabelData::Member aMem;
1026 
1027  if (xMember.is())
1028  aMem.maName = xMember->getName();
1029 
1030  Reference<beans::XPropertySet> xMemProp(xMember, UNO_QUERY);
1031  if (xMemProp.is())
1032  {
1033  aMem.mbVisible = ScUnoHelpFunctions::GetBoolProperty(xMemProp, SC_UNO_DP_ISVISIBLE);
1034  aMem.mbShowDetails = ScUnoHelpFunctions::GetBoolProperty(xMemProp, SC_UNO_DP_SHOWDETAILS);
1035 
1036  aMem.maLayoutName = ScUnoHelpFunctions::GetStringProperty(
1037  xMemProp, SC_UNO_DP_LAYOUTNAME, OUString());
1038  }
1039 
1040  aMembers.push_back(aMem);
1041  }
1042  rMembers.swap(aMembers);
1043  return true;
1044 }
1045 
1047  const ScRange& rRange, SCCOL nDx, SCROW nDy, SCTAB nDz )
1048 {
1049  // Output area
1050 
1051  SCCOL nCol1 = aOutRange.aStart.Col();
1052  SCROW nRow1 = aOutRange.aStart.Row();
1053  SCTAB nTab1 = aOutRange.aStart.Tab();
1054  SCCOL nCol2 = aOutRange.aEnd.Col();
1055  SCROW nRow2 = aOutRange.aEnd.Row();
1056  SCTAB nTab2 = aOutRange.aEnd.Tab();
1057 
1058  ScRefUpdateRes eRes =
1059  ScRefUpdate::Update( pDoc, eUpdateRefMode,
1060  rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1061  rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1062  nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1063  if ( eRes != UR_NOTHING )
1064  SetOutRange( ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ) );
1065 
1066  // sheet source data
1067 
1068  if ( !pSheetDesc )
1069  return;
1070 
1071  const OUString& rRangeName = pSheetDesc->GetRangeName();
1072  if (!rRangeName.isEmpty())
1073  // Source range is a named range. No need to update.
1074  return;
1075 
1076  const ScRange& rSrcRange = pSheetDesc->GetSourceRange();
1077  nCol1 = rSrcRange.aStart.Col();
1078  nRow1 = rSrcRange.aStart.Row();
1079  nTab1 = rSrcRange.aStart.Tab();
1080  nCol2 = rSrcRange.aEnd.Col();
1081  nRow2 = rSrcRange.aEnd.Row();
1082  nTab2 = rSrcRange.aEnd.Tab();
1083 
1084  eRes = ScRefUpdate::Update( pDoc, eUpdateRefMode,
1085  rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
1086  rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(), nDx, nDy, nDz,
1087  nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
1088  if ( eRes == UR_NOTHING )
1089  return;
1090 
1091  SCCOL nDiffX = nCol1 - pSheetDesc->GetSourceRange().aStart.Col();
1092  SCROW nDiffY = nRow1 - pSheetDesc->GetSourceRange().aStart.Row();
1093 
1094  ScQueryParam aParam = pSheetDesc->GetQueryParam();
1095  aParam.nCol1 = sal::static_int_cast<SCCOL>( aParam.nCol1 + nDiffX );
1096  aParam.nCol2 = sal::static_int_cast<SCCOL>( aParam.nCol2 + nDiffX );
1097  aParam.nRow1 += nDiffY; //TODO: used?
1098  aParam.nRow2 += nDiffY; //TODO: used?
1099  SCSIZE nEC = aParam.GetEntryCount();
1100  for (SCSIZE i=0; i<nEC; i++)
1101  if (aParam.GetEntry(i).bDoQuery)
1102  aParam.GetEntry(i).nField += nDiffX;
1103 
1104  pSheetDesc->SetQueryParam(aParam);
1105  pSheetDesc->SetSourceRange(ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
1106 }
1107 
1108 bool ScDPObject::RefsEqual( const ScDPObject& r ) const
1109 {
1110  if ( aOutRange != r.aOutRange )
1111  return false;
1112 
1113  if ( pSheetDesc && r.pSheetDesc )
1114  {
1115  if ( pSheetDesc->GetSourceRange() != r.pSheetDesc->GetSourceRange() )
1116  return false;
1117  }
1118  else if ( pSheetDesc || r.pSheetDesc )
1119  {
1120  OSL_FAIL("RefsEqual: SheetDesc set at only one object");
1121  return false;
1122  }
1123 
1124  return true;
1125 }
1126 
1128 {
1129  r.SetOutRange( aOutRange );
1130  if ( pSheetDesc )
1131  r.SetSheetDesc( *pSheetDesc );
1132 }
1133 
1134 void ScDPObject::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData)
1135 {
1136  CreateOutput();
1137  pOutput->GetPositionData(rPos, rPosData);
1138 }
1139 
1141  const ScAddress& rPos, Sequence<sheet::DataPilotFieldFilter>& rFilters)
1142 {
1143  CreateOutput();
1144 
1145  vector<sheet::DataPilotFieldFilter> aFilters;
1146  if (!pOutput->GetDataResultPositionData(aFilters, rPos))
1147  return false;
1148 
1149  sal_Int32 n = static_cast<sal_Int32>(aFilters.size());
1150  rFilters.realloc(n);
1151  auto pFilters = rFilters.getArray();
1152  for (sal_Int32 i = 0; i < n; ++i)
1153  pFilters[i] = aFilters[i];
1154 
1155  return true;
1156 }
1157 
1158 void ScDPObject::GetDrillDownData(const ScAddress& rPos, Sequence< Sequence<Any> >& rTableData)
1159 {
1160  CreateOutput();
1161 
1162  Reference<sheet::XDrillDownDataSupplier> xDrillDownData(xSource, UNO_QUERY);
1163  if (!xDrillDownData.is())
1164  return;
1165 
1166  Sequence<sheet::DataPilotFieldFilter> filters;
1167  if (!GetDataFieldPositionData(rPos, filters))
1168  return;
1169 
1170  rTableData = xDrillDownData->getDrillDownData(filters);
1171 }
1172 
1173 bool ScDPObject::IsDimNameInUse(std::u16string_view rName) const
1174 {
1175  if (!xSource.is())
1176  return false;
1177 
1178  Reference<container::XNameAccess> xDims = xSource->getDimensions();
1179  const Sequence<OUString> aDimNames = xDims->getElementNames();
1180  for (const OUString& rDimName : aDimNames)
1181  {
1182  if (rDimName.equalsIgnoreAsciiCase(rName))
1183  return true;
1184 
1185  Reference<beans::XPropertySet> xPropSet(xDims->getByName(rDimName), UNO_QUERY);
1186  if (!xPropSet.is())
1187  continue;
1188 
1189  OUString aLayoutName = ScUnoHelpFunctions::GetStringProperty(
1190  xPropSet, SC_UNO_DP_LAYOUTNAME, OUString());
1191  if (aLayoutName.equalsIgnoreAsciiCase(rName))
1192  return true;
1193  }
1194  return false;
1195 }
1196 
1197 OUString ScDPObject::GetDimName( tools::Long nDim, bool& rIsDataLayout, sal_Int32* pFlags )
1198 {
1199  rIsDataLayout = false;
1200  OUString aRet;
1201 
1202  if ( xSource.is() )
1203  {
1204  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1205  uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
1206  tools::Long nDimCount = xDims->getCount();
1207  if ( nDim < nDimCount )
1208  {
1209  uno::Reference<uno::XInterface> xIntDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
1210  uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1211  uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1212  if ( xDimName.is() && xDimProp.is() )
1213  {
1214  bool bData = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1216  //TODO: error checking -- is "IsDataLayoutDimension" property required??
1217 
1218  OUString aName;
1219  try
1220  {
1221  aName = xDimName->getName();
1222  }
1223  catch(uno::Exception&)
1224  {
1225  }
1226  if ( bData )
1227  rIsDataLayout = true;
1228  else
1229  aRet = aName;
1230 
1231  if (pFlags)
1232  *pFlags = ScUnoHelpFunctions::GetLongProperty( xDimProp,
1233  SC_UNO_DP_FLAGS );
1234  }
1235  }
1236  }
1237  else if (ScDPTableData* pData = GetTableData())
1238  {
1239  aRet = pData->getDimensionName(nDim);
1240  rIsDataLayout = pData->getIsDataLayoutDimension(nDim);
1241  }
1242 
1243  return aRet;
1244 }
1245 
1247 {
1248  bool bDuplicated = false;
1249  if ( xSource.is() )
1250  {
1251  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1252  uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
1253  tools::Long nDimCount = xDims->getCount();
1254  if ( nDim < nDimCount )
1255  {
1256  uno::Reference<beans::XPropertySet> xDimProp(xDims->getByIndex(nDim), uno::UNO_QUERY);
1257  if ( xDimProp.is() )
1258  {
1259  try
1260  {
1261  uno::Any aOrigAny = xDimProp->getPropertyValue( SC_UNO_DP_ORIGINAL );
1262  uno::Reference<uno::XInterface> xIntOrig;
1263  if ( (aOrigAny >>= xIntOrig) && xIntOrig.is() )
1264  bDuplicated = true;
1265  }
1266  catch(uno::Exception&)
1267  {
1268  }
1269  }
1270  }
1271  }
1272  return bDuplicated;
1273 }
1274 
1276 {
1277  tools::Long nRet = 0;
1278  if ( xSource.is() )
1279  {
1280  try
1281  {
1282  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1283  if ( xDimsName.is() )
1284  nRet = xDimsName->getElementNames().getLength();
1285  }
1286  catch(uno::Exception&)
1287  {
1288  }
1289  }
1290  return nRet;
1291 }
1292 
1293 void ScDPObject::GetHeaderPositionData(const ScAddress& rPos, DataPilotTableHeaderData& rData)
1294 {
1295  CreateOutput(); // create xSource and pOutput if not already done
1296 
1297  // Reset member values to invalid state.
1298  rData.Dimension = rData.Hierarchy = rData.Level = -1;
1299  rData.Flags = 0;
1300 
1301  DataPilotTablePositionData aPosData;
1302  pOutput->GetPositionData(rPos, aPosData);
1303  const sal_Int32 nPosType = aPosData.PositionType;
1305  aPosData.PositionData >>= rData;
1306 }
1307 
1308 namespace {
1309 
1310 class FindByName
1311 {
1312  OUString maName; // must be all uppercase.
1313 public:
1314  explicit FindByName(const OUString& rName) : maName(rName) {}
1315  bool operator() (const ScDPSaveDimension* pDim) const
1316  {
1317  // Layout name takes precedence.
1318  const std::optional<OUString> & pLayoutName = pDim->GetLayoutName();
1319  if (pLayoutName && ScGlobal::getCharClass().uppercase(*pLayoutName) == maName)
1320  return true;
1321 
1322  ScGeneralFunction eGenFunc = pDim->GetFunction();
1323  ScSubTotalFunc eFunc = ScDPUtil::toSubTotalFunc(eGenFunc);
1324  OUString aSrcName = ScDPUtil::getSourceDimensionName(pDim->GetName());
1325  OUString aFuncName = ScDPUtil::getDisplayedMeasureName(aSrcName, eFunc);
1326  if (maName == ScGlobal::getCharClass().uppercase(aFuncName))
1327  return true;
1328 
1329  return maName == ScGlobal::getCharClass().uppercase(aSrcName);
1330  }
1331 };
1332 
1333 class LessByDimOrder
1334 {
1335  const ScDPSaveData::DimOrderType& mrDimOrder;
1336 
1337 public:
1338  explicit LessByDimOrder(const ScDPSaveData::DimOrderType& rDimOrder) : mrDimOrder(rDimOrder) {}
1339 
1340  bool operator() (const sheet::DataPilotFieldFilter& r1, const sheet::DataPilotFieldFilter& r2) const
1341  {
1342  size_t nRank1 = mrDimOrder.size();
1343  size_t nRank2 = mrDimOrder.size();
1344  ScDPSaveData::DimOrderType::const_iterator it1 = mrDimOrder.find(
1345  ScGlobal::getCharClass().uppercase(r1.FieldName));
1346  if (it1 != mrDimOrder.end())
1347  nRank1 = it1->second;
1348 
1349  ScDPSaveData::DimOrderType::const_iterator it2 = mrDimOrder.find(
1350  ScGlobal::getCharClass().uppercase(r2.FieldName));
1351  if (it2 != mrDimOrder.end())
1352  nRank2 = it2->second;
1353 
1354  return nRank1 < nRank2;
1355  }
1356 };
1357 
1358 }
1359 
1360 double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<sheet::DataPilotFieldFilter>& rFilters)
1361 {
1362  if (!mbEnableGetPivotData)
1363  return std::numeric_limits<double>::quiet_NaN();
1364 
1365  CreateObjects();
1366 
1367  std::vector<const ScDPSaveDimension*> aDataDims;
1368  pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDataDims);
1369  if (aDataDims.empty())
1370  return std::numeric_limits<double>::quiet_NaN();
1371 
1372  std::vector<const ScDPSaveDimension*>::iterator it = std::find_if(
1373  aDataDims.begin(), aDataDims.end(),
1374  FindByName(ScGlobal::getCharClass().uppercase(rDataFieldName)));
1375 
1376  if (it == aDataDims.end())
1377  return std::numeric_limits<double>::quiet_NaN();
1378 
1379  size_t nDataIndex = std::distance(aDataDims.begin(), it);
1380 
1381  uno::Reference<sheet::XDataPilotResults> xDPResults(xSource, uno::UNO_QUERY);
1382  if (!xDPResults.is())
1383  return std::numeric_limits<double>::quiet_NaN();
1384 
1385  // Dimensions must be sorted in order of appearance, and row dimensions
1386  // must come before column dimensions.
1387  std::sort(rFilters.begin(), rFilters.end(), LessByDimOrder(pSaveData->GetDimensionSortOrder()));
1388 
1389  size_t n = rFilters.size();
1390  uno::Sequence<sheet::DataPilotFieldFilter> aFilters(n);
1391  auto aFiltersRange = asNonConstRange(aFilters);
1392  for (size_t i = 0; i < n; ++i)
1393  aFiltersRange[i] = rFilters[i];
1394 
1395  uno::Sequence<double> aRes = xDPResults->getFilteredResults(aFilters);
1396  if (static_cast<sal_Int32>(nDataIndex) >= aRes.getLength())
1397  return std::numeric_limits<double>::quiet_NaN();
1398 
1399  return aRes[nDataIndex];
1400 }
1401 
1403 {
1404  CreateOutput(); // create xSource and pOutput if not already done
1405 
1406  return pOutput->IsFilterButton( rPos );
1407 }
1408 
1409 tools::Long ScDPObject::GetHeaderDim( const ScAddress& rPos, sheet::DataPilotFieldOrientation& rOrient )
1410 {
1411  CreateOutput(); // create xSource and pOutput if not already done
1412 
1413  return pOutput->GetHeaderDim( rPos, rOrient );
1414 }
1415 
1416 bool ScDPObject::GetHeaderDrag( const ScAddress& rPos, bool bMouseLeft, bool bMouseTop, tools::Long nDragDim,
1417  tools::Rectangle& rPosRect, sheet::DataPilotFieldOrientation& rOrient, tools::Long& rDimPos )
1418 {
1419  CreateOutput(); // create xSource and pOutput if not already done
1420 
1421  return pOutput->GetHeaderDrag( rPos, bMouseLeft, bMouseTop, nDragDim, rPosRect, rOrient, rDimPos );
1422 }
1423 
1425 {
1426  CreateOutput(); // create xSource and pOutput if not already done
1427 
1428  pOutput->GetMemberResultNames(rNames, nDimension); // used only with table data -> level not needed
1429 }
1430 
1431 OUString ScDPObject::GetFormattedString(std::u16string_view rDimName, const double fValue)
1432 {
1433  ScDPTableData* pTableData = GetTableData();
1434  if(!pTableData)
1435  return OUString();
1436 
1437  tools::Long nDim;
1438  for (nDim = 0; nDim < pTableData->GetColumnCount(); ++nDim)
1439  {
1440  if(rDimName == pTableData->getDimensionName(nDim))
1441  break;
1442  }
1443  ScDPItemData aItemData;
1444  aItemData.SetValue(fValue);
1445  return GetTableData()->GetFormattedString(nDim, aItemData, false);
1446 }
1447 
1448 
1449 namespace {
1450 
1451 bool dequote( const OUString& rSource, sal_Int32 nStartPos, sal_Int32& rEndPos, OUString& rResult )
1452 {
1453  // nStartPos has to point to opening quote
1454 
1455  const sal_Unicode cQuote = '\'';
1456 
1457  if (rSource[nStartPos] == cQuote)
1458  {
1459  OUStringBuffer aBuffer;
1460  sal_Int32 nPos = nStartPos + 1;
1461  const sal_Int32 nLen = rSource.getLength();
1462 
1463  while ( nPos < nLen )
1464  {
1465  const sal_Unicode cNext = rSource[nPos];
1466  if ( cNext == cQuote )
1467  {
1468  if (nPos+1 < nLen && rSource[nPos+1] == cQuote)
1469  {
1470  // double quote is used for an embedded quote
1471  aBuffer.append( cNext ); // append one quote
1472  ++nPos; // skip the next one
1473  }
1474  else
1475  {
1476  // end of quoted string
1477  rResult = aBuffer.makeStringAndClear();
1478  rEndPos = nPos + 1; // behind closing quote
1479  return true;
1480  }
1481  }
1482  else
1483  aBuffer.append( cNext );
1484 
1485  ++nPos;
1486  }
1487  // no closing quote before the end of the string -> error (bRet still false)
1488  }
1489 
1490  return false;
1491 }
1492 
1493 struct ScGetPivotDataFunctionEntry
1494 {
1495  const char* pName;
1496  sal_Int16 eFunc;
1497 };
1498 
1499 bool parseFunction( const OUString& rList, sal_Int32 nStartPos, sal_Int32& rEndPos, sal_Int16& rFunc )
1500 {
1501  static const ScGetPivotDataFunctionEntry aFunctions[] =
1502  {
1503  // our names
1504  { "Sum", sheet::GeneralFunction2::SUM },
1505  { "Count", sheet::GeneralFunction2::COUNT },
1506  { "Average", sheet::GeneralFunction2::AVERAGE },
1507  { "Max", sheet::GeneralFunction2::MAX },
1508  { "Min", sheet::GeneralFunction2::MIN },
1509  { "Product", sheet::GeneralFunction2::PRODUCT },
1510  { "CountNums", sheet::GeneralFunction2::COUNTNUMS },
1511  { "StDev", sheet::GeneralFunction2::STDEV },
1512  { "StDevp", sheet::GeneralFunction2::STDEVP },
1513  { "Var", sheet::GeneralFunction2::VAR },
1514  { "VarP", sheet::GeneralFunction2::VARP },
1515  // compatibility names
1516  { "Count Nums", sheet::GeneralFunction2::COUNTNUMS },
1517  { "StdDev", sheet::GeneralFunction2::STDEV },
1518  { "StdDevp", sheet::GeneralFunction2::STDEVP }
1519  };
1520 
1521  const sal_Int32 nListLen = rList.getLength();
1522  while (nStartPos < nListLen && rList[nStartPos] == ' ')
1523  ++nStartPos;
1524 
1525  bool bParsed = false;
1526  bool bFound = false;
1527  OUString aFuncStr;
1528  sal_Int32 nFuncEnd = 0;
1529  if (nStartPos < nListLen && rList[nStartPos] == '\'')
1530  bParsed = dequote( rList, nStartPos, nFuncEnd, aFuncStr );
1531  else
1532  {
1533  nFuncEnd = rList.indexOf(']', nStartPos);
1534  if (nFuncEnd >= 0)
1535  {
1536  aFuncStr = rList.copy(nStartPos, nFuncEnd - nStartPos);
1537  bParsed = true;
1538  }
1539  }
1540 
1541  if ( bParsed )
1542  {
1543  aFuncStr = comphelper::string::strip(aFuncStr, ' ');
1544 
1545  const sal_Int32 nFuncCount = SAL_N_ELEMENTS(aFunctions);
1546  for ( sal_Int32 nFunc=0; nFunc<nFuncCount && !bFound; nFunc++ )
1547  {
1548  if (aFuncStr.equalsIgnoreAsciiCaseAscii(aFunctions[nFunc].pName))
1549  {
1550  rFunc = aFunctions[nFunc].eFunc;
1551  bFound = true;
1552 
1553  while (nFuncEnd < nListLen && rList[nFuncEnd] == ' ')
1554  ++nFuncEnd;
1555  rEndPos = nFuncEnd;
1556  }
1557  }
1558  }
1559 
1560  return bFound;
1561 }
1562 
1563 bool extractAtStart( const OUString& rList, sal_Int32& rMatched, bool bAllowBracket, sal_Int16* pFunc,
1564  OUString& rDequoted )
1565 {
1566  sal_Int32 nMatchList = 0;
1567  sal_Unicode cFirst = rList[0];
1568  bool bParsed = false;
1569  if ( cFirst == '\'' || cFirst == '[' )
1570  {
1571  // quoted string or string in brackets must match completely
1572 
1573  OUString aDequoted;
1574  sal_Int32 nQuoteEnd = 0;
1575 
1576  if ( cFirst == '\'' )
1577  bParsed = dequote( rList, 0, nQuoteEnd, aDequoted );
1578  else if ( cFirst == '[' )
1579  {
1580  // skip spaces after the opening bracket
1581 
1582  sal_Int32 nStartPos = 1;
1583  const sal_Int32 nListLen = rList.getLength();
1584  while (nStartPos < nListLen && rList[nStartPos] == ' ')
1585  ++nStartPos;
1586 
1587  if (nStartPos < nListLen && rList[nStartPos] == '\'') // quoted within the brackets?
1588  {
1589  if ( dequote( rList, nStartPos, nQuoteEnd, aDequoted ) )
1590  {
1591  // after the quoted string, there must be the closing bracket, optionally preceded by spaces,
1592  // and/or a function name
1593  while (nQuoteEnd < nListLen && rList[nQuoteEnd] == ' ')
1594  ++nQuoteEnd;
1595 
1596  // semicolon separates function name
1597  if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ';' && pFunc)
1598  {
1599  sal_Int32 nFuncEnd = 0;
1600  if ( parseFunction( rList, nQuoteEnd + 1, nFuncEnd, *pFunc ) )
1601  nQuoteEnd = nFuncEnd;
1602  }
1603  if (nQuoteEnd < nListLen && rList[nQuoteEnd] == ']')
1604  {
1605  ++nQuoteEnd; // include the closing bracket for the matched length
1606  bParsed = true;
1607  }
1608  }
1609  }
1610  else
1611  {
1612  // implicit quoting to the closing bracket
1613 
1614  sal_Int32 nClosePos = rList.indexOf(']', nStartPos);
1615  if (nClosePos >= 0)
1616  {
1617  sal_Int32 nNameEnd = nClosePos;
1618  sal_Int32 nSemiPos = rList.indexOf(';', nStartPos);
1619  if (nSemiPos >= 0 && nSemiPos < nClosePos && pFunc)
1620  {
1621  sal_Int32 nFuncEnd = 0;
1622  if (parseFunction(rList, nSemiPos+1, nFuncEnd, *pFunc))
1623  nNameEnd = nSemiPos;
1624  }
1625 
1626  aDequoted = rList.copy(nStartPos, nNameEnd - nStartPos);
1627  // spaces before the closing bracket or semicolon
1628  aDequoted = comphelper::string::stripEnd(aDequoted, ' ');
1629  nQuoteEnd = nClosePos + 1;
1630  bParsed = true;
1631  }
1632  }
1633  }
1634 
1635  if ( bParsed )
1636  {
1637  nMatchList = nQuoteEnd; // match count in the list string, including quotes
1638  rDequoted = aDequoted;
1639  }
1640  }
1641 
1642  if (bParsed)
1643  {
1644  // look for following space or end of string
1645 
1646  bool bValid = false;
1647  if ( sal::static_int_cast<sal_Int32>(nMatchList) >= rList.getLength() )
1648  bValid = true;
1649  else
1650  {
1651  sal_Unicode cNext = rList[nMatchList];
1652  if ( cNext == ' ' || ( bAllowBracket && cNext == '[' ) )
1653  bValid = true;
1654  }
1655 
1656  if ( bValid )
1657  {
1658  rMatched = nMatchList;
1659  return true;
1660  }
1661  }
1662 
1663  return false;
1664 }
1665 
1666 bool isAtStart(
1667  const OUString& rList, const OUString& rSearch, sal_Int32& rMatched,
1668  bool bAllowBracket, sal_Int16* pFunc )
1669 {
1670  sal_Int32 nMatchList = 0;
1671  sal_Int32 nMatchSearch = 0;
1672  sal_Unicode cFirst = rList[0];
1673  if ( cFirst == '\'' || cFirst == '[' )
1674  {
1675  OUString aDequoted;
1676  bool bParsed = extractAtStart( rList, rMatched, bAllowBracket, pFunc, aDequoted);
1677  if ( bParsed && ScGlobal::GetTransliteration().isEqual( aDequoted, rSearch ) )
1678  {
1679  nMatchList = rMatched; // match count in the list string, including quotes
1680  nMatchSearch = rSearch.getLength();
1681  }
1682  }
1683  else
1684  {
1685  // otherwise look for search string at the start of rList
1687  rList, 0, rList.getLength(), nMatchList, rSearch, 0, rSearch.getLength(), nMatchSearch);
1688  }
1689 
1690  if (nMatchSearch == rSearch.getLength())
1691  {
1692  // search string is at start of rList - look for following space or end of string
1693 
1694  bool bValid = false;
1695  if ( sal::static_int_cast<sal_Int32>(nMatchList) >= rList.getLength() )
1696  bValid = true;
1697  else
1698  {
1699  sal_Unicode cNext = rList[nMatchList];
1700  if ( cNext == ' ' || ( bAllowBracket && cNext == '[' ) )
1701  bValid = true;
1702  }
1703 
1704  if ( bValid )
1705  {
1706  rMatched = nMatchList;
1707  return true;
1708  }
1709  }
1710 
1711  return false;
1712 }
1713 
1714 } // anonymous namespace
1715 
1717  OUString& rDataFieldName,
1718  std::vector<sheet::DataPilotFieldFilter>& rFilters,
1719  std::vector<sal_Int16>& rFilterFuncs, std::u16string_view rFilterList )
1720 {
1721  // parse the string rFilterList into parameters for GetPivotData
1722 
1723  CreateObjects(); // create xSource if not already done
1724 
1725  std::vector<OUString> aDataNames; // data fields (source name)
1726  std::vector<OUString> aGivenNames; // data fields (compound name)
1727  std::vector<OUString> aFieldNames; // column/row/data fields
1728  std::vector< uno::Sequence<OUString> > aFieldValueNames;
1729  std::vector< uno::Sequence<OUString> > aFieldValues;
1730 
1731  // get all the field and item names
1732 
1733  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1734  uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1735  sal_Int32 nDimCount = xIntDims->getCount();
1736  for ( sal_Int32 nDim = 0; nDim<nDimCount; nDim++ )
1737  {
1738  uno::Reference<uno::XInterface> xIntDim(xIntDims->getByIndex(nDim), uno::UNO_QUERY);
1739  uno::Reference<container::XNamed> xDim( xIntDim, uno::UNO_QUERY );
1740  uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
1741  uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDim, uno::UNO_QUERY );
1742  bool bDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
1744  sheet::DataPilotFieldOrientation nOrient = ScUnoHelpFunctions::GetEnumProperty(
1745  xDimProp, SC_UNO_DP_ORIENTATION,
1746  sheet::DataPilotFieldOrientation_HIDDEN );
1747  if ( !bDataLayout )
1748  {
1749  if ( nOrient == sheet::DataPilotFieldOrientation_DATA )
1750  {
1751  OUString aSourceName;
1752  OUString aGivenName;
1753  ScDPOutput::GetDataDimensionNames( aSourceName, aGivenName, xIntDim );
1754  aDataNames.push_back( aSourceName );
1755  aGivenNames.push_back( aGivenName );
1756  }
1757  else if ( nOrient != sheet::DataPilotFieldOrientation_HIDDEN )
1758  {
1759  // get level names, as in ScDPOutput
1760 
1761  uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
1762  sal_Int32 nHierarchy = ScUnoHelpFunctions::GetLongProperty( xDimProp,
1764  if ( nHierarchy >= xHiers->getCount() )
1765  nHierarchy = 0;
1766 
1767  uno::Reference<sheet::XLevelsSupplier> xHierSupp(xHiers->getByIndex(nHierarchy),
1768  uno::UNO_QUERY);
1769  if ( xHierSupp.is() )
1770  {
1771  uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess( xHierSupp->getLevels() );
1772  sal_Int32 nLevCount = xLevels->getCount();
1773  for (sal_Int32 nLev=0; nLev<nLevCount; nLev++)
1774  {
1775  uno::Reference<uno::XInterface> xLevel(xLevels->getByIndex(nLev),
1776  uno::UNO_QUERY);
1777  uno::Reference<container::XNamed> xLevNam( xLevel, uno::UNO_QUERY );
1778  uno::Reference<sheet::XMembersSupplier> xLevSupp( xLevel, uno::UNO_QUERY );
1779  if ( xLevNam.is() && xLevSupp.is() )
1780  {
1781  uno::Reference<sheet::XMembersAccess> xMembers = xLevSupp->getMembers();
1782 
1783  OUString aFieldName( xLevNam->getName() );
1784  // getElementNames() and getLocaleIndependentElementNames()
1785  // must be consecutive calls to obtain strings in matching order.
1786  uno::Sequence<OUString> aMemberValueNames( xMembers->getElementNames() );
1787  uno::Sequence<OUString> aMemberValues( xMembers->getLocaleIndependentElementNames() );
1788 
1789  aFieldNames.push_back( aFieldName );
1790  aFieldValueNames.push_back( aMemberValueNames );
1791  aFieldValues.push_back( aMemberValues );
1792  }
1793  }
1794  }
1795  }
1796  }
1797  }
1798 
1799  // compare and build filters
1800 
1801  SCSIZE nDataFields = aDataNames.size();
1802  SCSIZE nFieldCount = aFieldNames.size();
1803  OSL_ENSURE( aGivenNames.size() == nDataFields && aFieldValueNames.size() == nFieldCount &&
1804  aFieldValues.size() == nFieldCount, "wrong count" );
1805 
1806  bool bError = false;
1807  bool bHasData = false;
1808  OUString aRemaining(comphelper::string::strip(rFilterList, ' '));
1809  while (!aRemaining.isEmpty() && !bError)
1810  {
1811  bool bUsed = false;
1812 
1813  // look for data field name
1814 
1815  for ( SCSIZE nDataPos=0; nDataPos<nDataFields && !bUsed; nDataPos++ )
1816  {
1817  OUString aFound;
1818  sal_Int32 nMatched = 0;
1819  if (isAtStart(aRemaining, aDataNames[nDataPos], nMatched, false, nullptr))
1820  aFound = aDataNames[nDataPos];
1821  else if (isAtStart(aRemaining, aGivenNames[nDataPos], nMatched, false, nullptr))
1822  aFound = aGivenNames[nDataPos];
1823 
1824  if (!aFound.isEmpty())
1825  {
1826  rDataFieldName = aFound;
1827  aRemaining = aRemaining.copy(nMatched);
1828  bHasData = true;
1829  bUsed = true;
1830  }
1831  }
1832 
1833  // look for field name
1834 
1835  OUString aSpecField;
1836  bool bHasFieldName = false;
1837  if ( !bUsed )
1838  {
1839  sal_Int32 nMatched = 0;
1840  for ( SCSIZE nField=0; nField<nFieldCount && !bHasFieldName; nField++ )
1841  {
1842  if (isAtStart(aRemaining, aFieldNames[nField], nMatched, true, nullptr))
1843  {
1844  aSpecField = aFieldNames[nField];
1845  aRemaining = aRemaining.copy(nMatched);
1846  aRemaining = comphelper::string::stripStart(aRemaining, ' ');
1847 
1848  // field name has to be followed by item name in brackets
1849  if (aRemaining.startsWith("["))
1850  {
1851  bHasFieldName = true;
1852  // bUsed remains false - still need the item
1853  }
1854  else
1855  {
1856  bUsed = true;
1857  bError = true;
1858  }
1859  }
1860  }
1861  }
1862 
1863  // look for field item
1864 
1865  if ( !bUsed )
1866  {
1867  bool bItemFound = false;
1868  sal_Int32 nMatched = 0;
1869  OUString aFoundName;
1870  OUString aFoundValueName;
1871  OUString aFoundValue;
1872  sal_Int16 eFunc = sheet::GeneralFunction2::NONE;
1873  sal_Int16 eFoundFunc = sheet::GeneralFunction2::NONE;
1874 
1875  OUString aQueryValueName;
1876  const bool bHasQuery = extractAtStart( aRemaining, nMatched, false, &eFunc, aQueryValueName);
1877 
1878  OUString aQueryValue = aQueryValueName;
1879  if (mpTableData)
1880  {
1881  SvNumberFormatter* pFormatter = mpTableData->GetCacheTable().getCache().GetNumberFormatter();
1882  if (pFormatter)
1883  {
1884  // Parse possible number from aQueryValueName and format
1885  // locale independent as aQueryValue.
1886  sal_uInt32 nNumFormat = 0;
1887  double fValue;
1888  if (pFormatter->IsNumberFormat( aQueryValueName, nNumFormat, fValue))
1889  aQueryValue = ScDPCache::GetLocaleIndependentFormattedString( fValue, *pFormatter, nNumFormat);
1890  }
1891  }
1892 
1893  for ( SCSIZE nField=0; nField<nFieldCount; nField++ )
1894  {
1895  // If a field name is given, look in that field only, otherwise in all fields.
1896  // aSpecField is initialized from aFieldNames array, so exact comparison can be used.
1897  if ( !bHasFieldName || aFieldNames[nField] == aSpecField )
1898  {
1899  const uno::Sequence<OUString>& rItemNames = aFieldValueNames[nField];
1900  const uno::Sequence<OUString>& rItemValues = aFieldValues[nField];
1901  sal_Int32 nItemCount = rItemNames.getLength();
1902  assert(nItemCount == rItemValues.getLength());
1903  const OUString* pItemNamesArr = rItemNames.getConstArray();
1904  const OUString* pItemValuesArr = rItemValues.getConstArray();
1905  for ( sal_Int32 nItem=0; nItem<nItemCount; nItem++ )
1906  {
1907  bool bThisItemFound;
1908  if (bHasQuery)
1909  {
1910  // First check given value name against both.
1911  bThisItemFound = ScGlobal::GetTransliteration().isEqual(
1912  aQueryValueName, pItemNamesArr[nItem]);
1913  if (!bThisItemFound && pItemValuesArr[nItem] != pItemNamesArr[nItem])
1914  bThisItemFound = ScGlobal::GetTransliteration().isEqual(
1915  aQueryValueName, pItemValuesArr[nItem]);
1916  if (!bThisItemFound && aQueryValueName != aQueryValue)
1917  {
1918  // Second check locale independent value
1919  // against both.
1920  /* TODO: or check only value string against
1921  * value string, not against the value name? */
1922  bThisItemFound = ScGlobal::GetTransliteration().isEqual(
1923  aQueryValue, pItemNamesArr[nItem]);
1924  if (!bThisItemFound && pItemValuesArr[nItem] != pItemNamesArr[nItem])
1925  bThisItemFound = ScGlobal::GetTransliteration().isEqual(
1926  aQueryValue, pItemValuesArr[nItem]);
1927  }
1928  }
1929  else
1930  {
1931  bThisItemFound = isAtStart( aRemaining, pItemNamesArr[nItem], nMatched, false, &eFunc );
1932  if (!bThisItemFound && pItemValuesArr[nItem] != pItemNamesArr[nItem])
1933  bThisItemFound = isAtStart( aRemaining, pItemValuesArr[nItem], nMatched, false, &eFunc );
1934  /* TODO: this checks only the given value name,
1935  * check also locale independent value. But we'd
1936  * have to do that in each iteration of the loop
1937  * inside isAtStart() since a query could not be
1938  * extracted and a match could be on the passed
1939  * item value name string or item value string
1940  * starting at aRemaining. */
1941  }
1942  if (bThisItemFound)
1943  {
1944  if ( bItemFound )
1945  bError = true; // duplicate (also across fields)
1946  else
1947  {
1948  aFoundName = aFieldNames[nField];
1949  aFoundValueName = pItemNamesArr[nItem];
1950  aFoundValue = pItemValuesArr[nItem];
1951  eFoundFunc = eFunc;
1952  bItemFound = true;
1953  bUsed = true;
1954  }
1955  }
1956  }
1957  }
1958  }
1959 
1960  if ( bItemFound && !bError )
1961  {
1962  sheet::DataPilotFieldFilter aField;
1963  aField.FieldName = aFoundName;
1964  aField.MatchValueName = aFoundValueName;
1965  aField.MatchValue = aFoundValue;
1966  rFilters.push_back(aField);
1967  rFilterFuncs.push_back(eFoundFunc);
1968  aRemaining = aRemaining.copy(nMatched);
1969  }
1970  }
1971 
1972  if ( !bUsed )
1973  bError = true;
1974 
1975  // remove any number of spaces between entries
1976  aRemaining = comphelper::string::stripStart(aRemaining, ' ');
1977  }
1978 
1979  if ( !bError && !bHasData && aDataNames.size() == 1 )
1980  {
1981  // if there's only one data field, its name need not be specified
1982  rDataFieldName = aDataNames[0];
1983  bHasData = true;
1984  }
1985 
1986  return bHasData && !bError;
1987 }
1988 
1989 void ScDPObject::ToggleDetails(const DataPilotTableHeaderData& rElemDesc, ScDPObject* pDestObj)
1990 {
1991  CreateObjects(); // create xSource if not already done
1992 
1993  // find dimension name
1994 
1995  uno::Reference<container::XNamed> xDim;
1996  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1997  uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
1998  tools::Long nIntCount = xIntDims->getCount();
1999  if ( rElemDesc.Dimension < nIntCount )
2000  {
2001  xDim.set(xIntDims->getByIndex(rElemDesc.Dimension), uno::UNO_QUERY);
2002  }
2003  OSL_ENSURE( xDim.is(), "dimension not found" );
2004  if ( !xDim.is() ) return;
2005  OUString aDimName = xDim->getName();
2006 
2007  uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
2008  bool bDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDimProp,
2010  if (bDataLayout)
2011  {
2012  // the elements of the data layout dimension can't be found by their names
2013  // -> don't change anything
2014  return;
2015  }
2016 
2017  // query old state
2018 
2019  tools::Long nHierCount = 0;
2020  uno::Reference<container::XIndexAccess> xHiers;
2021  uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
2022  if ( xHierSupp.is() )
2023  {
2024  uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
2025  xHiers = new ScNameToIndexAccess( xHiersName );
2026  nHierCount = xHiers->getCount();
2027  }
2028  uno::Reference<uno::XInterface> xHier;
2029  if ( rElemDesc.Hierarchy < nHierCount )
2030  xHier.set(xHiers->getByIndex(rElemDesc.Hierarchy), uno::UNO_QUERY);
2031  OSL_ENSURE( xHier.is(), "hierarchy not found" );
2032  if ( !xHier.is() ) return;
2033 
2034  tools::Long nLevCount = 0;
2035  uno::Reference<container::XIndexAccess> xLevels;
2036  uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHier, uno::UNO_QUERY );
2037  if ( xLevSupp.is() )
2038  {
2039  uno::Reference<container::XNameAccess> xLevsName = xLevSupp->getLevels();
2040  xLevels = new ScNameToIndexAccess( xLevsName );
2041  nLevCount = xLevels->getCount();
2042  }
2043  uno::Reference<uno::XInterface> xLevel;
2044  if ( rElemDesc.Level < nLevCount )
2045  xLevel.set(xLevels->getByIndex(rElemDesc.Level), uno::UNO_QUERY);
2046  OSL_ENSURE( xLevel.is(), "level not found" );
2047  if ( !xLevel.is() ) return;
2048 
2049  uno::Reference<sheet::XMembersAccess> xMembers;
2050  uno::Reference<sheet::XMembersSupplier> xMbrSupp( xLevel, uno::UNO_QUERY );
2051  if ( xMbrSupp.is() )
2052  xMembers = xMbrSupp->getMembers();
2053 
2054  bool bFound = false;
2055  bool bShowDetails = true;
2056 
2057  if ( xMembers.is() )
2058  {
2059  if ( xMembers->hasByName(rElemDesc.MemberName) )
2060  {
2061  uno::Reference<beans::XPropertySet> xMbrProp(xMembers->getByName(rElemDesc.MemberName),
2062  uno::UNO_QUERY);
2063  if ( xMbrProp.is() )
2064  {
2065  bShowDetails = ScUnoHelpFunctions::GetBoolProperty( xMbrProp,
2067  //TODO: don't set bFound if property is unknown?
2068  bFound = true;
2069  }
2070  }
2071  }
2072 
2073  OSL_ENSURE( bFound, "member not found" );
2074 
2075  //TODO: use Hierarchy and Level in SaveData !!!!
2076 
2077  // modify pDestObj if set, this object otherwise
2078  ScDPSaveData* pModifyData = pDestObj ? ( pDestObj->pSaveData.get() ) : pSaveData.get();
2079  OSL_ENSURE( pModifyData, "no data?" );
2080  if ( pModifyData )
2081  {
2082  const OUString aName = rElemDesc.MemberName;
2083  pModifyData->GetDimensionByName(aDimName)->
2084  GetMemberByName(aName)->SetShowDetails( !bShowDetails ); // toggle
2085 
2086  if ( pDestObj )
2087  pDestObj->InvalidateData(); // re-init source from SaveData
2088  else
2089  InvalidateData(); // re-init source from SaveData
2090  }
2091 }
2092 
2093 static PivotFunc lcl_FirstSubTotal( const uno::Reference<beans::XPropertySet>& xDimProp ) // PIVOT_FUNC mask
2094 {
2095  uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
2096  if ( xDimProp.is() && xDimSupp.is() )
2097  {
2098  uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
2099  tools::Long nHierarchy = ScUnoHelpFunctions::GetLongProperty( xDimProp,
2101  if ( nHierarchy >= xHiers->getCount() )
2102  nHierarchy = 0;
2103 
2104  uno::Reference<sheet::XLevelsSupplier> xHierSupp(xHiers->getByIndex(nHierarchy),
2105  uno::UNO_QUERY);
2106  if ( xHierSupp.is() )
2107  {
2108  uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess( xHierSupp->getLevels() );
2109  uno::Reference<uno::XInterface> xLevel(xLevels->getByIndex(0), uno::UNO_QUERY);
2110  uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
2111  if ( xLevProp.is() )
2112  {
2113  uno::Any aSubAny;
2114  try
2115  {
2116  aSubAny = xLevProp->getPropertyValue( SC_UNO_DP_SUBTOTAL2 );
2117  }
2118  catch(uno::Exception&)
2119  {
2120  }
2121  uno::Sequence<sal_Int16> aSeq;
2122  if ( aSubAny >>= aSeq )
2123  {
2124  PivotFunc nMask = PivotFunc::NONE;
2125  for (const sal_Int16 nElem : std::as_const(aSeq))
2126  nMask |= ScDataPilotConversion::FunctionBit(nElem);
2127  return nMask;
2128  }
2129  }
2130  }
2131  }
2132 
2133  OSL_FAIL("FirstSubTotal: NULL");
2134  return PivotFunc::NONE;
2135 }
2136 
2137 namespace {
2138 
2139 class FindByColumn
2140 {
2141  SCCOL mnCol;
2142  PivotFunc mnMask;
2143 public:
2144  FindByColumn(SCCOL nCol, PivotFunc nMask) : mnCol(nCol), mnMask(nMask) {}
2145  bool operator() (const ScPivotField& r) const
2146  {
2147  return r.nCol == mnCol && r.nFuncMask == mnMask;
2148  }
2149 };
2150 
2151 }
2152 
2154  const uno::Reference<sheet::XDimensionsSupplier>& xSource,
2155  sheet::DataPilotFieldOrientation nOrient, bool bAddData )
2156 {
2157  ScPivotFieldVector aFields;
2158 
2159  bool bDataFound = false;
2160 
2161  //TODO: merge multiple occurrences (data field with different functions)
2162  //TODO: force data field in one dimension
2163 
2164  vector<tools::Long> aPos;
2165 
2166  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
2167  uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
2168  tools::Long nDimCount = xDims->getCount();
2169  for (tools::Long nDim = 0; nDim < nDimCount; ++nDim)
2170  {
2171  // dimension properties
2172  uno::Reference<beans::XPropertySet> xDimProp(xDims->getByIndex(nDim), uno::UNO_QUERY);
2173 
2174  // dimension orientation, hidden by default.
2175  sheet::DataPilotFieldOrientation nDimOrient = ScUnoHelpFunctions::GetEnumProperty(
2176  xDimProp, SC_UNO_DP_ORIENTATION,
2177  sheet::DataPilotFieldOrientation_HIDDEN );
2178 
2179  if ( xDimProp.is() && nDimOrient == nOrient )
2180  {
2181  // Let's take this dimension.
2182 
2183  // function mask.
2184  PivotFunc nMask = PivotFunc::NONE;
2185  if ( nOrient == sheet::DataPilotFieldOrientation_DATA )
2186  {
2187  sal_Int16 eFunc = ScUnoHelpFunctions::GetShortProperty(
2188  xDimProp, SC_UNO_DP_FUNCTION2,
2190  if ( eFunc == sheet::GeneralFunction2::AUTO )
2191  {
2192  //TODO: test for numeric data
2193  eFunc = sheet::GeneralFunction2::SUM;
2194  }
2195  nMask = ScDataPilotConversion::FunctionBit(eFunc);
2196  }
2197  else
2198  nMask = lcl_FirstSubTotal( xDimProp ); // from first hierarchy
2199 
2200  // is this data layout dimension?
2201  bool bDataLayout = ScUnoHelpFunctions::GetBoolProperty(
2202  xDimProp, SC_UNO_DP_ISDATALAYOUT);
2203 
2204  // is this dimension cloned?
2205  tools::Long nDupSource = -1;
2206  try
2207  {
2208  uno::Any aOrigAny = xDimProp->getPropertyValue(SC_UNO_DP_ORIGINAL_POS);
2209  sal_Int32 nTmp = 0;
2210  if (aOrigAny >>= nTmp)
2211  nDupSource = nTmp;
2212  }
2213  catch(uno::Exception&)
2214  {
2215  }
2216 
2217  sal_uInt8 nDupCount = 0;
2218  if (nDupSource >= 0)
2219  {
2220  // this dimension is cloned.
2221 
2222  SCCOL nCompCol; // ID of the original dimension.
2223  if ( bDataLayout )
2224  nCompCol = PIVOT_DATA_FIELD;
2225  else
2226  nCompCol = static_cast<SCCOL>(nDupSource); //TODO: seek source column from name
2227 
2228  ScPivotFieldVector::iterator it = std::find_if(aFields.begin(), aFields.end(), FindByColumn(nCompCol, nMask));
2229  if (it != aFields.end())
2230  nDupCount = it->mnDupCount + 1;
2231  }
2232 
2233  aFields.emplace_back();
2234  ScPivotField& rField = aFields.back();
2235  if (bDataLayout)
2236  {
2237  rField.nCol = PIVOT_DATA_FIELD;
2238  bDataFound = true;
2239  }
2240  else
2241  {
2242  rField.mnOriginalDim = nDupSource;
2243  rField.nCol = static_cast<SCCOL>(nDim); //TODO: seek source column from name
2244  }
2245 
2246  rField.nFuncMask = nMask;
2247  rField.mnDupCount = nDupCount;
2249  xDimProp, SC_UNO_DP_POSITION);
2250  aPos.push_back(nPos);
2251 
2252  try
2253  {
2254  if (nOrient == sheet::DataPilotFieldOrientation_DATA)
2255  xDimProp->getPropertyValue(SC_UNO_DP_REFVALUE)
2256  >>= rField.maFieldRef;
2257  }
2258  catch (uno::Exception&)
2259  {
2260  }
2261  }
2262  }
2263 
2264  // sort by getPosition() value
2265 
2266  size_t nOutCount = aFields.size();
2267  if (nOutCount >= 1)
2268  {
2269  for (size_t i = 0; i < nOutCount - 1; ++i)
2270  {
2271  for (size_t j = 0; j + i < nOutCount - 1; ++j)
2272  {
2273  if ( aPos[j+1] < aPos[j] )
2274  {
2275  std::swap( aPos[j], aPos[j+1] );
2276  std::swap( aFields[j], aFields[j+1] );
2277  }
2278  }
2279  }
2280  }
2281 
2282  if (bAddData && !bDataFound)
2283  aFields.emplace_back(PIVOT_DATA_FIELD);
2284 
2285  rFields.swap(aFields);
2286 }
2287 
2289 {
2290  const_cast<ScDPObject*>(this)->CreateObjects(); // xSource is needed for field numbers
2291 
2292  if (!xSource.is())
2293  return;
2294 
2295  rParam.nCol = aOutRange.aStart.Col();
2296  rParam.nRow = aOutRange.aStart.Row();
2297  rParam.nTab = aOutRange.aStart.Tab();
2298  // ppLabelArr / nLabels is not changed
2299 
2300  bool bAddData = ( lcl_GetDataGetOrientation( xSource ) == sheet::DataPilotFieldOrientation_HIDDEN );
2302  rParam.maPageFields, xSource, sheet::DataPilotFieldOrientation_PAGE, false);
2304  rParam.maColFields, xSource, sheet::DataPilotFieldOrientation_COLUMN, bAddData);
2306  rParam.maRowFields, xSource, sheet::DataPilotFieldOrientation_ROW, false);
2308  rParam.maDataFields, xSource, sheet::DataPilotFieldOrientation_DATA, false);
2309 
2310  uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY );
2311  if (!xProp.is())
2312  return;
2313 
2314  try
2315  {
2317  SC_UNO_DP_COLGRAND, true );
2319  SC_UNO_DP_ROWGRAND, true );
2320 
2321  // following properties may be missing for external sources
2326  }
2327  catch(uno::Exception&)
2328  {
2329  // no error
2330  }
2331 }
2332 
2333 static void lcl_FillLabelData( ScDPLabelData& rData, const uno::Reference< beans::XPropertySet >& xDimProp )
2334 {
2335  uno::Reference<sheet::XHierarchiesSupplier> xDimSupp( xDimProp, uno::UNO_QUERY );
2336  if (!xDimProp.is() || !xDimSupp.is())
2337  return;
2338 
2339  uno::Reference<container::XIndexAccess> xHiers = new ScNameToIndexAccess( xDimSupp->getHierarchies() );
2341  xDimProp, SC_UNO_DP_USEDHIERARCHY);
2342  if ( nHierarchy >= xHiers->getCount() )
2343  nHierarchy = 0;
2344  rData.mnUsedHier = nHierarchy;
2345 
2346  uno::Reference<sheet::XLevelsSupplier> xHierSupp(xHiers->getByIndex(nHierarchy),
2347  uno::UNO_QUERY);
2348  if (!xHierSupp.is())
2349  return;
2350 
2351  uno::Reference<container::XIndexAccess> xLevels =
2352  new ScNameToIndexAccess( xHierSupp->getLevels() );
2353 
2354  uno::Reference<beans::XPropertySet> xLevProp(xLevels->getByIndex(0), uno::UNO_QUERY);
2355  if (!xLevProp.is())
2356  return;
2357 
2359  xLevProp, SC_UNO_DP_SHOWEMPTY);
2360 
2362  xLevProp, SC_UNO_DP_REPEATITEMLABELS);
2363 
2364  try
2365  {
2366  xLevProp->getPropertyValue( SC_UNO_DP_SORTING )
2367  >>= rData.maSortInfo;
2368  xLevProp->getPropertyValue( SC_UNO_DP_LAYOUT )
2369  >>= rData.maLayoutInfo;
2370  xLevProp->getPropertyValue( SC_UNO_DP_AUTOSHOW )
2371  >>= rData.maShowInfo;
2372  }
2373  catch(uno::Exception&)
2374  {
2375  }
2376 }
2377 
2379  const uno::Reference<container::XIndexAccess>& xDims, sal_Int32 nDim, ScDPLabelData& rLabelData)
2380 {
2381  uno::Reference<uno::XInterface> xIntDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
2382  uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
2383  uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
2384 
2385  if (!xDimName.is() || !xDimProp.is())
2386  return;
2387 
2389  xDimProp, SC_UNO_DP_ISDATALAYOUT);
2390  //TODO: error checking -- is "IsDataLayoutDimension" property required??
2391 
2392  sal_Int32 nOrigPos = -1;
2393  OUString aFieldName;
2394  try
2395  {
2396  aFieldName = xDimName->getName();
2397  uno::Any aOrigAny = xDimProp->getPropertyValue(SC_UNO_DP_ORIGINAL_POS);
2398  aOrigAny >>= nOrigPos;
2399  }
2400  catch(uno::Exception&)
2401  {
2402  }
2403 
2404  OUString aLayoutName = ScUnoHelpFunctions::GetStringProperty(
2405  xDimProp, SC_UNO_DP_LAYOUTNAME, OUString());
2406 
2407  OUString aSubtotalName = ScUnoHelpFunctions::GetStringProperty(
2408  xDimProp, SC_UNO_DP_FIELD_SUBTOTALNAME, OUString());
2409 
2410  // Name from the UNO dimension object may have trailing '*'s in which
2411  // case it's a duplicate dimension. Convert that to a duplicate index.
2412 
2413  sal_uInt8 nDupCount = ScDPUtil::getDuplicateIndex(aFieldName);
2414  aFieldName = ScDPUtil::getSourceDimensionName(aFieldName);
2415 
2416  rLabelData.maName = aFieldName;
2417  rLabelData.mnCol = static_cast<SCCOL>(nDim);
2418  rLabelData.mnDupCount = nDupCount;
2419  rLabelData.mbDataLayout = bData;
2420  rLabelData.mbIsValue = true; //TODO: check
2421 
2422  if (bData)
2423  return;
2424 
2425  rLabelData.mnOriginalDim = static_cast<tools::Long>(nOrigPos);
2426  rLabelData.maLayoutName = aLayoutName;
2427  rLabelData.maSubtotalName = aSubtotalName;
2428  if (nOrigPos >= 0)
2429  // This is a duplicated dimension. Use the original dimension index.
2430  nDim = nOrigPos;
2431  GetHierarchies(nDim, rLabelData.maHiers);
2432  GetMembers(nDim, GetUsedHierarchy(nDim), rLabelData.maMembers);
2433  lcl_FillLabelData(rLabelData, xDimProp);
2435  xDimProp, SC_UNO_DP_FLAGS );
2436 }
2437 
2438 void ScDPObject::FillLabelData(sal_Int32 nDim, ScDPLabelData& rLabels)
2439 {
2440  CreateObjects();
2441  if (!xSource.is())
2442  return;
2443 
2444  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
2445  uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
2446  sal_Int32 nDimCount = xDims->getCount();
2447  if (nDimCount <= 0 || nDim >= nDimCount)
2448  return;
2449 
2450  FillLabelDataForDimension(xDims, nDim, rLabels);
2451 }
2452 
2454 {
2455  rParam.maLabelArray.clear();
2456 
2457  CreateObjects();
2458  if (!xSource.is())
2459  return;
2460 
2461  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
2462  uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
2463  sal_Int32 nDimCount = xDims->getCount();
2464  if (nDimCount <= 0)
2465  return;
2466 
2467  for (sal_Int32 nDim = 0; nDim < nDimCount; ++nDim)
2468  {
2469  ScDPLabelData* pNewLabel = new ScDPLabelData;
2470  FillLabelDataForDimension(xDims, nDim, *pNewLabel);
2471  rParam.maLabelArray.push_back(std::unique_ptr<ScDPLabelData>(pNewLabel));
2472  }
2473 }
2474 
2475 bool ScDPObject::GetHierarchiesNA( sal_Int32 nDim, uno::Reference< container::XNameAccess >& xHiers )
2476 {
2477  bool bRet = false;
2478  uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
2479  uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
2480  if( xIntDims.is() )
2481  {
2482  uno::Reference<sheet::XHierarchiesSupplier> xHierSup(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
2483  if (xHierSup.is())
2484  {
2485  xHiers.set( xHierSup->getHierarchies() );
2486  bRet = xHiers.is();
2487  }
2488  }
2489  return bRet;
2490 }
2491 
2492 void ScDPObject::GetHierarchies( sal_Int32 nDim, uno::Sequence< OUString >& rHiers )
2493 {
2494  uno::Reference< container::XNameAccess > xHiersNA;
2495  if( GetHierarchiesNA( nDim, xHiersNA ) )
2496  {
2497  rHiers = xHiersNA->getElementNames();
2498  }
2499 }
2500 
2501 sal_Int32 ScDPObject::GetUsedHierarchy( sal_Int32 nDim )
2502 {
2503  sal_Int32 nHier = 0;
2504  uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
2505  uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
2506  uno::Reference<beans::XPropertySet> xDim(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
2507  if (xDim.is())
2509  return nHier;
2510 }
2511 
2512 bool ScDPObject::GetMembersNA( sal_Int32 nDim, uno::Reference< sheet::XMembersAccess >& xMembers )
2513 {
2514  return GetMembersNA( nDim, GetUsedHierarchy( nDim ), xMembers );
2515 }
2516 
2517 bool ScDPObject::GetMembersNA( sal_Int32 nDim, sal_Int32 nHier, uno::Reference< sheet::XMembersAccess >& xMembers )
2518 {
2519  bool bRet = false;
2520  uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
2521  uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
2522  uno::Reference<beans::XPropertySet> xDim(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
2523  if (xDim.is())
2524  {
2525  uno::Reference<sheet::XHierarchiesSupplier> xHierSup(xDim, uno::UNO_QUERY);
2526  if (xHierSup.is())
2527  {
2528  uno::Reference<container::XIndexAccess> xHiers(new ScNameToIndexAccess(xHierSup->getHierarchies()));
2529  uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHiers->getByIndex(nHier), uno::UNO_QUERY );
2530  if ( xLevSupp.is() )
2531  {
2532  uno::Reference<container::XIndexAccess> xLevels(new ScNameToIndexAccess( xLevSupp->getLevels()));
2533  if (xLevels.is())
2534  {
2535  sal_Int32 nLevCount = xLevels->getCount();
2536  if (nLevCount > 0)
2537  {
2538  uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevels->getByIndex(0), uno::UNO_QUERY );
2539  if ( xMembSupp.is() )
2540  {
2541  xMembers.set(xMembSupp->getMembers());
2542  bRet = true;
2543  }
2544  }
2545  }
2546  }
2547  }
2548  }
2549  return bRet;
2550 }
2551 
2552 // convert old pivot tables into new datapilot tables
2553 
2554 namespace {
2555 
2556 OUString lcl_GetDimName( const uno::Reference<sheet::XDimensionsSupplier>& xSource, tools::Long nDim )
2557 {
2558  OUString aName;
2559  if ( xSource.is() )
2560  {
2561  uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
2562  uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
2563  tools::Long nDimCount = xDims->getCount();
2564  if ( nDim < nDimCount )
2565  {
2566  uno::Reference<container::XNamed> xDimName(xDims->getByIndex(nDim), uno::UNO_QUERY);
2567  if (xDimName.is())
2568  {
2569  try
2570  {
2571  aName = xDimName->getName();
2572  }
2573  catch(uno::Exception&)
2574  {
2575  }
2576  }
2577  }
2578  }
2579  return aName;
2580 }
2581 
2582 bool hasFieldColumn(const vector<ScPivotField>* pRefFields, SCCOL nCol)
2583 {
2584  if (!pRefFields)
2585  return false;
2586 
2587  return std::any_of(pRefFields->begin(), pRefFields->end(),
2588  [&nCol](const ScPivotField& rField) {
2589  // This array of fields contains the specified column.
2590  return rField.nCol == nCol; });
2591 }
2592 
2593 class FindByOriginalDim
2594 {
2595  tools::Long mnDim;
2596 public:
2597  explicit FindByOriginalDim(tools::Long nDim) : mnDim(nDim) {}
2598  bool operator() (const ScPivotField& r) const
2599  {
2600  return mnDim == r.getOriginalDim();
2601  }
2602 };
2603 
2604 }
2605 
2607  ScDPSaveData& rSaveData, const ScPivotFieldVector& rFields, sheet::DataPilotFieldOrientation nOrient,
2608  const Reference<XDimensionsSupplier>& xSource,
2609  const ScDPLabelDataVector& rLabels,
2610  const ScPivotFieldVector* pRefColFields,
2611  const ScPivotFieldVector* pRefRowFields,
2612  const ScPivotFieldVector* pRefPageFields )
2613 {
2614  ScPivotFieldVector::const_iterator itr, itrBeg = rFields.begin(), itrEnd = rFields.end();
2615  for (itr = itrBeg; itr != itrEnd; ++itr)
2616  {
2617  const ScPivotField& rField = *itr;
2618 
2619  tools::Long nCol = rField.getOriginalDim();
2620  PivotFunc nFuncs = rField.nFuncMask;
2621  const sheet::DataPilotFieldReference& rFieldRef = rField.maFieldRef;
2622 
2623  ScDPSaveDimension* pDim = nullptr;
2624  if ( nCol == PIVOT_DATA_FIELD )
2625  pDim = rSaveData.GetDataLayoutDimension();
2626  else
2627  {
2628  OUString aDocStr = lcl_GetDimName( xSource, nCol ); // cols must start at 0
2629  if (!aDocStr.isEmpty())
2630  pDim = rSaveData.GetDimensionByName(aDocStr);
2631  else
2632  pDim = nullptr;
2633  }
2634 
2635  if (!pDim)
2636  continue;
2637 
2638  if ( nOrient == sheet::DataPilotFieldOrientation_DATA ) // set summary function
2639  {
2640  // generate an individual entry for each function
2641  bool bFirst = true;
2642 
2643  // if a dimension is used for column/row/page and data,
2644  // use duplicated dimensions for all data occurrences
2645  if (hasFieldColumn(pRefColFields, nCol))
2646  bFirst = false;
2647 
2648  if (bFirst && hasFieldColumn(pRefRowFields, nCol))
2649  bFirst = false;
2650 
2651  if (bFirst && hasFieldColumn(pRefPageFields, nCol))
2652  bFirst = false;
2653 
2654  if (bFirst)
2655  {
2656  // if set via api, a data column may occur several times
2657  // (if the function hasn't been changed yet) -> also look for duplicate data column
2658  bFirst = std::none_of(itrBeg, itr, FindByOriginalDim(nCol));
2659  }
2660 
2662  if (!bFirst)
2663  pDim = rSaveData.DuplicateDimension(pDim->GetName());
2664  pDim->SetOrientation(nOrient);
2665  pDim->SetFunction(eFunc);
2666 
2667  if( rFieldRef.ReferenceType == sheet::DataPilotFieldReferenceType::NONE )
2668  pDim->SetReferenceValue(nullptr);
2669  else
2670  pDim->SetReferenceValue(&rFieldRef);
2671  }
2672  else // set SubTotals
2673  {
2674  pDim->SetOrientation( nOrient );
2675 
2676  std::vector<ScGeneralFunction> nSubTotalFuncs;
2677  nSubTotalFuncs.reserve(16);
2678  sal_uInt16 nMask = 1;
2679  for (sal_uInt16 nBit=0; nBit<16; nBit++)
2680  {
2681  if ( nFuncs & static_cast<PivotFunc>(nMask) )
2682  nSubTotalFuncs.push_back( ScDataPilotConversion::FirstFunc( static_cast<PivotFunc>(nMask) ) );
2683  nMask *= 2;
2684  }
2685  pDim->SetSubTotals( std::move(nSubTotalFuncs) );
2686 
2687  // ShowEmpty was implicit in old tables,
2688  // must be set for data layout dimension (not accessible in dialog)
2689  if ( nCol == PIVOT_DATA_FIELD )
2690  pDim->SetShowEmpty( true );
2691  }
2692 
2693  size_t nDimIndex = rField.nCol;
2694  pDim->RemoveLayoutName();
2695  pDim->RemoveSubtotalName();
2696  if (nDimIndex < rLabels.size())
2697  {
2698  const ScDPLabelData& rLabel = *rLabels[nDimIndex];
2699  if (!rLabel.maLayoutName.isEmpty())
2700  pDim->SetLayoutName(rLabel.maLayoutName);
2701  if (!rLabel.maSubtotalName.isEmpty())
2702  pDim->SetSubtotalName(rLabel.maSubtotalName);
2703  }
2704  }
2705 }
2706 
2707 bool ScDPObject::IsOrientationAllowed( sheet::DataPilotFieldOrientation nOrient, sal_Int32 nDimFlags )
2708 {
2709  bool bAllowed = true;
2710  switch (nOrient)
2711  {
2712  case sheet::DataPilotFieldOrientation_PAGE:
2713  bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_PAGE_ORIENTATION ) == 0;
2714  break;
2715  case sheet::DataPilotFieldOrientation_COLUMN:
2716  bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_COLUMN_ORIENTATION ) == 0;
2717  break;
2718  case sheet::DataPilotFieldOrientation_ROW:
2719  bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_ROW_ORIENTATION ) == 0;
2720  break;
2721  case sheet::DataPilotFieldOrientation_DATA:
2722  bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_DATA_ORIENTATION ) == 0;
2723  break;
2724  default:
2725  {
2726  // allowed to remove from previous orientation
2727  }
2728  }
2729  return bAllowed;
2730 }
2731 
2733 {
2734  bool bFound = false;
2735 
2736  uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
2737  uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
2738  if ( xEnAc.is() )
2739  {
2740  uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
2742  if ( xEnum.is() && xEnum->hasMoreElements() )
2743  bFound = true;
2744  }
2745 
2746  return bFound;
2747 }
2748 
2749 std::vector<OUString> ScDPObject::GetRegisteredSources()
2750 {
2751  std::vector<OUString> aVec;
2752 
2753  // use implementation names...
2754 
2755  uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
2756  uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
2757  if ( xEnAc.is() )
2758  {
2759  uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
2761  if ( xEnum.is() )
2762  {
2763  while ( xEnum->hasMoreElements() )
2764  {
2765  uno::Any aAddInAny = xEnum->nextElement();
2766 // if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
2767  {
2768  uno::Reference<uno::XInterface> xIntFac;
2769  aAddInAny >>= xIntFac;
2770  if ( xIntFac.is() )
2771  {
2772  uno::Reference<lang::XServiceInfo> xInfo( xIntFac, uno::UNO_QUERY );
2773  if ( xInfo.is() )
2774  {
2775  OUString sName = xInfo->getImplementationName();
2776  aVec.push_back( sName );
2777  }
2778  }
2779  }
2780  }
2781  }
2782  }
2783 
2784  return aVec;
2785 }
2786 
2787 uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPServiceDesc& rDesc )
2788 {
2789  OUString aImplName = rDesc.aServiceName;
2790  uno::Reference<sheet::XDimensionsSupplier> xRet;
2791 
2792  uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
2793  uno::Reference<container::XContentEnumerationAccess> xEnAc(xManager, uno::UNO_QUERY);
2794  if (!xEnAc.is())
2795  return xRet;
2796 
2797  uno::Reference<container::XEnumeration> xEnum =
2798  xEnAc->createContentEnumeration(SCDPSOURCE_SERVICE);
2799  if (!xEnum.is())
2800  return xRet;
2801 
2802  while (xEnum->hasMoreElements() && !xRet.is())
2803  {
2804  uno::Any aAddInAny = xEnum->nextElement();
2805  uno::Reference<uno::XInterface> xIntFac;
2806  aAddInAny >>= xIntFac;
2807  if (!xIntFac.is())
2808  continue;
2809 
2810  uno::Reference<lang::XServiceInfo> xInfo(xIntFac, uno::UNO_QUERY);
2811  if (!xInfo.is() || xInfo->getImplementationName() != aImplName)
2812  continue;
2813 
2814  try
2815  {
2816  // #i113160# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
2817  // passing the context to the component (see ScUnoAddInCollection::Initialize)
2818 
2819  uno::Reference<uno::XInterface> xInterface;
2820  uno::Reference<uno::XComponentContext> xCtx(
2822  uno::Reference<lang::XSingleComponentFactory> xCFac( xIntFac, uno::UNO_QUERY );
2823  if (xCFac.is())
2824  xInterface = xCFac->createInstanceWithContext(xCtx);
2825 
2826  if (!xInterface.is())
2827  {
2828  uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
2829  if ( xFac.is() )
2830  xInterface = xFac->createInstance();
2831  }
2832 
2833  uno::Reference<lang::XInitialization> xInit( xInterface, uno::UNO_QUERY );
2834  if (xInit.is())
2835  {
2836  // initialize
2837  uno::Sequence<uno::Any> aSeq(4);
2838  uno::Any* pArray = aSeq.getArray();
2839  pArray[0] <<= rDesc.aParSource;
2840  pArray[1] <<= rDesc.aParName;
2841  pArray[2] <<= rDesc.aParUser;
2842  pArray[3] <<= rDesc.aParPass;
2843  xInit->initialize( aSeq );
2844  }
2845  xRet.set( xInterface, uno::UNO_QUERY );
2846  }
2847  catch(uno::Exception&)
2848  {
2849  }
2850  }
2851 
2852  return xRet;
2853 }
2854 
2855 #if DUMP_PIVOT_TABLE
2856 
2857 void ScDPObject::Dump() const
2858 {
2859  if (pSaveData)
2860  pSaveData->Dump();
2861 
2862  if (mpTableData)
2863  mpTableData->Dump();
2864 }
2865 
2866 void ScDPObject::DumpCache() const
2867 {
2868  if (!mpTableData)
2869  return;
2870 
2871  const ScDPCache &rCache = mpTableData->GetCacheTable().getCache();
2872 
2873  rCache.Dump();
2874 }
2875 #endif
2876 
2878 
2879 namespace {
2880 
2881 struct FindInvalidRange
2882 {
2883  bool operator() (const ScRange& r) const
2884  {
2885  return !r.IsValid();
2886  }
2887 };
2888 
2889 void setGroupItemsToCache( ScDPCache& rCache, const o3tl::sorted_vector<ScDPObject*>& rRefs )
2890 {
2891  // Go through all referencing pivot tables, and re-fill the group dimension info.
2892  for (const ScDPObject* pObj : rRefs)
2893  {
2894  const ScDPSaveData* pSave = pObj->GetSaveData();
2895  if (!pSave)
2896  continue;
2897 
2898  const ScDPDimensionSaveData* pGroupDims = pSave->GetExistingDimensionData();
2899  if (!pGroupDims)
2900  continue;
2901 
2902  pGroupDims->WriteToCache(rCache);
2903  }
2904 }
2905 
2906 }
2907 
2909 {
2910  RangeIndexType::const_iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
2911  if (it == maRanges.end())
2912  return false;
2913 
2914  // Already cached.
2915  size_t nIndex = std::distance(maRanges.begin(), it);
2916  CachesType::const_iterator const itCache = m_Caches.find(nIndex);
2917  return itCache != m_Caches.end();
2918 }
2919 
2921 {
2922  RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
2923  if (it != maRanges.end())
2924  {
2925  // Already cached.
2926  size_t nIndex = std::distance(maRanges.begin(), it);
2927  CachesType::iterator const itCache = m_Caches.find(nIndex);
2928  if (itCache == m_Caches.end())
2929  {
2930  OSL_FAIL("Cache pool and index pool out-of-sync !!!");
2931  return nullptr;
2932  }
2933 
2934  if (pDimData)
2935  {
2936  (itCache->second)->ClearGroupFields();
2937  pDimData->WriteToCache(*itCache->second);
2938  }
2939 
2940  return itCache->second.get();
2941  }
2942 
2943  // Not cached. Create a new cache.
2944  ::std::unique_ptr<ScDPCache> pCache(new ScDPCache(mrDoc));
2945  pCache->InitFromDoc(mrDoc, rRange);
2946  if (pDimData)
2947  pDimData->WriteToCache(*pCache);
2948 
2949  // Get the smallest available range index.
2950  it = std::find_if(maRanges.begin(), maRanges.end(), FindInvalidRange());
2951 
2952  size_t nIndex = maRanges.size();
2953  if (it == maRanges.end())
2954  {
2955  // All range indices are valid. Append a new index.
2956  maRanges.push_back(rRange);
2957  }
2958  else
2959  {
2960  // Slot with invalid range. Re-use this slot.
2961  *it = rRange;
2962  nIndex = std::distance(maRanges.begin(), it);
2963  }
2964 
2965  const ScDPCache* p = pCache.get();
2966  m_Caches.insert(std::make_pair(nIndex, std::move(pCache)));
2967  return p;
2968 }
2969 
2971 {
2972  RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
2973  if (it == maRanges.end())
2974  // Not cached.
2975  return nullptr;
2976 
2977  // Already cached.
2978  size_t nIndex = std::distance(maRanges.begin(), it);
2979  CachesType::iterator const itCache = m_Caches.find(nIndex);
2980  if (itCache == m_Caches.end())
2981  {
2982  OSL_FAIL("Cache pool and index pool out-of-sync !!!");
2983  return nullptr;
2984  }
2985 
2986  return itCache->second.get();
2987 }
2988 
2990 {
2991  RangeIndexType::const_iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
2992  if (it == maRanges.end())
2993  // Not cached.
2994  return nullptr;
2995 
2996  // Already cached.
2997  size_t nIndex = std::distance(maRanges.begin(), it);
2998  CachesType::const_iterator const itCache = m_Caches.find(nIndex);
2999  if (itCache == m_Caches.end())
3000  {
3001  OSL_FAIL("Cache pool and index pool out-of-sync !!!");
3002  return nullptr;
3003  }
3004 
3005  return itCache->second.get();
3006 }
3007 
3009 {
3010  return m_Caches.size();
3011 }
3012 
3014  UpdateRefMode eMode, const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz)
3015 {
3016  if (maRanges.empty())
3017  // No caches.
3018  return;
3019 
3020  for (ScRange& rKeyRange : maRanges)
3021  {
3022  SCCOL nCol1 = rKeyRange.aStart.Col();
3023  SCROW nRow1 = rKeyRange.aStart.Row();
3024  SCTAB nTab1 = rKeyRange.aStart.Tab();
3025  SCCOL nCol2 = rKeyRange.aEnd.Col();
3026  SCROW nRow2 = rKeyRange.aEnd.Row();
3027  SCTAB nTab2 = rKeyRange.aEnd.Tab();
3028 
3030  &mrDoc, eMode,
3031  r.aStart.Col(), r.aStart.Row(), r.aStart.Tab(),
3032  r.aEnd.Col(), r.aEnd.Row(), r.aEnd.Tab(), nDx, nDy, nDz,
3033  nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3034 
3035  if (eRes != UR_NOTHING)
3036  {
3037  // range updated.
3038  ScRange aNew(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3039  rKeyRange = aNew;
3040  }
3041  }
3042 }
3043 
3045 {
3046  RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
3047  if (it == maRanges.end())
3048  {
3049  // Not cached. Nothing to do.
3050  rRefs.clear();
3051  return;
3052  }
3053 
3054  size_t nIndex = std::distance(maRanges.begin(), it);
3055  CachesType::iterator const itCache = m_Caches.find(nIndex);
3056  if (itCache == m_Caches.end())
3057  {
3058  OSL_FAIL("Cache pool and index pool out-of-sync !!!");
3059  rRefs.clear();
3060  return;
3061  }
3062 
3063  ScDPCache& rCache = *itCache->second;
3064 
3065  // Update the cache with new cell values. This will clear all group dimension info.
3066  rCache.InitFromDoc(mrDoc, rRange);
3067 
3069  rRefs.swap(aRefs);
3070 
3071  // Make sure to re-populate the group dimension info.
3072  setGroupItemsToCache(rCache, rRefs);
3073 }
3074 
3076 {
3077  CachesType::iterator it = std::find_if(m_Caches.begin(), m_Caches.end(),
3078  [&p](const CachesType::value_type& rEntry) { return rEntry.second.get() == p; });
3079  if (it != m_Caches.end())
3080  {
3081  size_t idx = it->first;
3082  m_Caches.erase(it);
3083  maRanges[idx].SetInvalid();
3084  return true;
3085  }
3086  return false;
3087 }
3088 
3089 const std::vector<ScRange>& ScDPCollection::SheetCaches::getAllRanges() const
3090 {
3091  return maRanges;
3092 }
3093 
3095 
3096 bool ScDPCollection::NameCaches::hasCache(const OUString& rName) const
3097 {
3098  return m_Caches.count(rName) != 0;
3099 }
3100 
3102  const OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData)
3103 {
3104  CachesType::const_iterator const itr = m_Caches.find(rName);
3105  if (itr != m_Caches.end())
3106  // already cached.
3107  return itr->second.get();
3108 
3109  ::std::unique_ptr<ScDPCache> pCache(new ScDPCache(mrDoc));
3110  pCache->InitFromDoc(mrDoc, rRange);
3111  if (pDimData)
3112  pDimData->WriteToCache(*pCache);
3113 
3114  const ScDPCache *const p = pCache.get();
3115  m_Caches.insert(std::make_pair(rName, std::move(pCache)));
3116  return p;
3117 }
3118 
3120 {
3121  CachesType::iterator const itr = m_Caches.find(rName);
3122  return itr != m_Caches.end() ? itr->second.get() : nullptr;
3123 }
3124 
3126 {
3127  return m_Caches.size();
3128 }
3129 
3131  const OUString& rName, const ScRange& rRange, o3tl::sorted_vector<ScDPObject*>& rRefs)
3132 {
3133  CachesType::iterator const itr = m_Caches.find(rName);
3134  if (itr == m_Caches.end())
3135  {
3136  rRefs.clear();
3137  return;
3138  }
3139 
3140  ScDPCache& rCache = *itr->second;
3141  // Update the cache with new cell values. This will clear all group dimension info.
3142  rCache.InitFromDoc(mrDoc, rRange);
3143 
3145  rRefs.swap(aRefs);
3146 
3147  // Make sure to re-populate the group dimension info.
3148  setGroupItemsToCache(rCache, rRefs);
3149 }
3150 
3152 {
3153  CachesType::iterator it = std::find_if(m_Caches.begin(), m_Caches.end(),
3154  [&p](const CachesType::value_type& rEntry) { return rEntry.second.get() == p; });
3155  if (it != m_Caches.end())
3156  {
3157  m_Caches.erase(it);
3158  return true;
3159  }
3160  return false;
3161 }
3162 
3163 ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) :
3164  mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {}
3165 
3166 bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& right) const
3167 {
3168  return left < right;
3169 }
3170 
3172 
3173 bool ScDPCollection::DBCaches::hasCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) const
3174 {
3175  DBType aType(nSdbType, rDBName, rCommand);
3176  CachesType::const_iterator const itr = m_Caches.find(aType);
3177  return itr != m_Caches.end();
3178 }
3179 
3181  sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
3182  const ScDPDimensionSaveData* pDimData)
3183 {
3184  DBType aType(nSdbType, rDBName, rCommand);
3185  CachesType::const_iterator const itr = m_Caches.find(aType);
3186  if (itr != m_Caches.end())
3187  // already cached.
3188  return itr->second.get();
3189 
3190  uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand);
3191  if (!xRowSet.is())
3192  return nullptr;
3193 
3194  ::std::unique_ptr<ScDPCache> pCache(new ScDPCache(mrDoc));
3196  DBConnector aDB(*pCache, xRowSet, aFormat.GetNullDate());
3197  if (!aDB.isValid())
3198  return nullptr;
3199 
3200  if (!pCache->InitFromDataBase(aDB))
3201  {
3202  // initialization failed.
3204  return nullptr;
3205  }
3206 
3207  if (pDimData)
3208  pDimData->WriteToCache(*pCache);
3209 
3210  ::comphelper::disposeComponent(xRowSet);
3211  const ScDPCache* p = pCache.get();
3212  m_Caches.insert(std::make_pair(aType, std::move(pCache)));
3213  return p;
3214 }
3215 
3217  sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
3218 {
3219  DBType aType(nSdbType, rDBName, rCommand);
3220  CachesType::iterator const itr = m_Caches.find(aType);
3221  return itr != m_Caches.end() ? itr->second.get() : nullptr;
3222 }
3223 
3224 uno::Reference<sdbc::XRowSet> ScDPCollection::DBCaches::createRowSet(
3225  sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
3226 {
3227  uno::Reference<sdbc::XRowSet> xRowSet;
3228  try
3229  {
3232  UNO_QUERY);
3233 
3234  uno::Reference<beans::XPropertySet> xRowProp(xRowSet, UNO_QUERY);
3235  OSL_ENSURE( xRowProp.is(), "can't get RowSet" );
3236  if (!xRowProp.is())
3237  {
3238  xRowSet.set(nullptr);
3239  return xRowSet;
3240  }
3241 
3242  // set source parameters
3243 
3244  xRowProp->setPropertyValue( SC_DBPROP_DATASOURCENAME, Any(rDBName) );
3245  xRowProp->setPropertyValue( SC_DBPROP_COMMAND, Any(rCommand) );
3246  xRowProp->setPropertyValue( SC_DBPROP_COMMANDTYPE, Any(nSdbType) );
3247 
3248  uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
3249  if ( xExecute.is() )
3250  {
3251  uno::Reference<task::XInteractionHandler> xHandler(
3252  task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr),
3253  uno::UNO_QUERY_THROW);
3254  xExecute->executeWithCompletion( xHandler );
3255  }
3256  else
3257  xRowSet->execute();
3258 
3259  return xRowSet;
3260  }
3261  catch ( const sdbc::SQLException& rError )
3262  {
3264  std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
3265  VclMessageType::Info, VclButtonsType::Ok,
3266  rError.Message));
3267  xInfoBox->run();
3268  }
3269  catch ( uno::Exception& )
3270  {
3271  TOOLS_WARN_EXCEPTION( "sc", "Unexpected exception in database");
3272  }
3273 
3274  xRowSet.set(nullptr);
3275  return xRowSet;
3276 }
3277 
3279  sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
3281 {
3282  DBType aType(nSdbType, rDBName, rCommand);
3283  CachesType::iterator const it = m_Caches.find(aType);
3284  if (it == m_Caches.end())
3285  {
3286  // not cached.
3287  rRefs.clear();
3288  return;
3289  }
3290 
3291  ScDPCache& rCache = *it->second;
3292 
3293  uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand);
3294  if (!xRowSet.is())
3295  {
3296  rRefs.clear();
3297  return;
3298  }
3299 
3301  DBConnector aDB(rCache, xRowSet, aFormat.GetNullDate());
3302  if (!aDB.isValid())
3303  return;
3304 
3305  if (!rCache.InitFromDataBase(aDB))
3306  {
3307  // initialization failed.
3308  rRefs.clear();
3310  return;
3311  }
3312 
3315  aRefs.swap(rRefs);
3316 
3317  // Make sure to re-populate the group dimension info.
3318  setGroupItemsToCache(rCache, rRefs);
3319 }
3320 
3322 {
3323  CachesType::iterator it = std::find_if(m_Caches.begin(), m_Caches.end(),
3324  [&p](const CachesType::value_type& rEntry) { return rEntry.second.get() == p; });
3325  if (it != m_Caches.end())
3326  {
3327  m_Caches.erase(it);
3328  return true;
3329  }
3330  return false;
3331 }
3332 
3334  mrDoc(rDocument),
3335  maSheetCaches(rDocument),
3336  maNameCaches(rDocument),
3337  maDBCaches(rDocument)
3338 {
3339 }
3340 
3342  mrDoc(r.mrDoc),
3343  maSheetCaches(r.mrDoc),
3344  maNameCaches(r.mrDoc),
3345  maDBCaches(r.mrDoc)
3346 {
3347 }
3348 
3350 {
3351  maTables.clear();
3352 }
3353 
3354 namespace {
3355 
3359 class MatchByTable
3360 {
3361  SCTAB mnTab;
3362 public:
3363  explicit MatchByTable(SCTAB nTab) : mnTab(nTab) {}
3364 
3365  bool operator() (const std::unique_ptr<ScDPObject>& rObj) const
3366  {
3367  return rObj->GetOutRange().aStart.Tab() == mnTab;
3368  }
3369 };
3370 
3371 }
3372 
3374 {
3375  if (!pDPObj)
3376  return STR_ERR_DATAPILOTSOURCE;
3377 
3378  if (pDPObj->IsSheetData())
3379  {
3380  // data source is internal sheet.
3381  const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
3382  if (!pDesc)
3383  return STR_ERR_DATAPILOTSOURCE;
3384 
3385  TranslateId pErrId = pDesc->CheckSourceRange();
3386  if (pErrId)
3387  return pErrId;
3388 
3389  if (pDesc->HasRangeName())
3390  {
3391  // cache by named range
3393  if (rCaches.hasCache(pDesc->GetRangeName()))
3394  rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs);
3395  else
3396  {
3397  // Not cached yet. Collect all tables that use this named
3398  // range as data source.
3399  GetAllTables(pDesc->GetRangeName(), rRefs);
3400  }
3401  }
3402  else
3403  {
3404  // cache by cell range
3406  if (rCaches.hasCache(pDesc->GetSourceRange()))
3407  rCaches.updateCache(pDesc->GetSourceRange(), rRefs);
3408  else
3409  {
3410  // Not cached yet. Collect all tables that use this range as
3411  // data source.
3412  GetAllTables(pDesc->GetSourceRange(), rRefs);
3413  }
3414  }
3415  }
3416  else if (pDPObj->IsImportData())
3417  {
3418  // data source is external database.
3419  const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
3420  if (!pDesc)
3421  return STR_ERR_DATAPILOTSOURCE;
3422 
3424  if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
3425  rCaches.updateCache(
3426  pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
3427  else
3428  {
3429  // Not cached yet. Collect all tables that use this range as
3430  // data source.
3431  GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
3432  }
3433  }
3434  return {};
3435 }
3436 
3438 {
3439  if (!pDPObj)
3440  return false;
3441 
3442  const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
3443  if (!pSaveData)
3444  return false;
3445 
3446  // Note: Unlike reloading cache, when modifying the group dimensions the
3447  // cache may not have all its references when this method is called.
3448  // Therefore, we need to always call GetAllTables to get its correct
3449  // references even when the cache exists. This may become a non-issue
3450  // if/when we implement loading and saving of pivot caches.
3451 
3452  ScDPCache* pCache = nullptr;
3453 
3454  if (pDPObj->IsSheetData())
3455  {
3456  // data source is internal sheet.
3457  const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
3458  if (!pDesc)
3459  return false;
3460 
3461  if (pDesc->HasRangeName())
3462  {
3463  // cache by named range
3465  if (rCaches.hasCache(pDesc->GetRangeName()))
3466  pCache = rCaches.getExistingCache(pDesc->GetRangeName());
3467  else
3468  {
3469  // Not cached yet. Cache the source dimensions. Groups will
3470  // be added below.
3471  pCache = const_cast<ScDPCache*>(
3472  rCaches.getCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), nullptr));
3473  }
3474  GetAllTables(pDesc->GetRangeName(), rRefs);
3475  }
3476  else
3477  {
3478  // cache by cell range
3480  if (rCaches.hasCache(pDesc->GetSourceRange()))
3481  pCache = rCaches.getExistingCache(pDesc->GetSourceRange());
3482  else
3483  {
3484  // Not cached yet. Cache the source dimensions. Groups will
3485  // be added below.
3486  pCache = const_cast<ScDPCache*>(
3487  rCaches.getCache(pDesc->GetSourceRange(), nullptr));
3488  }
3489  GetAllTables(pDesc->GetSourceRange(), rRefs);
3490  }
3491  }
3492  else if (pDPObj->IsImportData())
3493  {
3494  // data source is external database.
3495  const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
3496  if (!pDesc)
3497  return false;
3498 
3500  if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
3501  pCache = rCaches.getExistingCache(
3502  pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject);
3503  else
3504  {
3505  // Not cached yet. Cache the source dimensions. Groups will
3506  // be added below.
3507  pCache = const_cast<ScDPCache*>(
3508  rCaches.getCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, nullptr));
3509  }
3510  GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
3511  }
3512 
3513  if (!pCache)
3514  return false;
3515 
3516  // Clear the existing group/field data from the cache, and rebuild it from the
3517  // dimension data.
3518  pCache->ClearAllFields();
3519  const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
3520  if (pDimData)
3521  pDimData->WriteToCache(*pCache);
3522  return true;
3523 }
3524 
3525 bool ScDPCollection::GetReferenceGroups(const ScDPObject& rDPObj, const ScDPDimensionSaveData** pGroups) const
3526 {
3527  for (const std::unique_ptr<ScDPObject>& aTable : maTables)
3528  {
3529  const ScDPObject& rRefObj = *aTable;
3530 
3531  if (&rRefObj == &rDPObj)
3532  continue;
3533 
3534  if (rDPObj.IsSheetData()){
3535  if(!rRefObj.IsSheetData())
3536  continue;
3537 
3538  const ScSheetSourceDesc* pDesc = rDPObj.GetSheetDesc();
3539  const ScSheetSourceDesc* pRefDesc = rRefObj.GetSheetDesc();
3540  if (pDesc == nullptr || pRefDesc == nullptr)
3541  continue;
3542 
3543  if (pDesc->HasRangeName())
3544  {
3545  if (!pRefDesc->HasRangeName())
3546  continue;
3547 
3548  if (pDesc->GetRangeName() == pRefDesc->GetRangeName())
3549  {
3550  *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
3551  return true;
3552  }
3553  }
3554  else
3555  {
3556  if (pRefDesc->HasRangeName())
3557  continue;
3558 
3559  if (pDesc->GetSourceRange() == pRefDesc->GetSourceRange())
3560  {
3561  *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
3562  return true;
3563  }
3564  }
3565  }
3566  else if (rDPObj.IsImportData())
3567  {
3568  if (!rRefObj.IsImportData ())
3569  continue;
3570 
3571  const ScImportSourceDesc* pDesc = rDPObj.GetImportSourceDesc();
3572  const ScImportSourceDesc* pRefDesc = rRefObj.GetImportSourceDesc();
3573  if (pDesc == nullptr || pRefDesc == nullptr)
3574  continue;
3575 
3576  if (pDesc->aDBName == pRefDesc->aDBName &&
3577  pDesc->aObject == pRefDesc->aObject &&
3578  pDesc->GetCommandType() == pRefDesc->GetCommandType())
3579  {
3580  *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
3581  return true;
3582  }
3583 
3584  }
3585  }
3586  return false;
3587 }
3588 
3589 
3591 {
3592  maTables.erase( std::remove_if(maTables.begin(), maTables.end(), MatchByTable(nTab)), maTables.end());
3593 }
3594 
3596  const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz )
3597 {
3598  for (auto& rxTable : maTables)
3599  rxTable->UpdateReference(eUpdateRefMode, r, nDx, nDy, nDz);
3600 
3601  // Update the source ranges of the caches.
3602  maSheetCaches.updateReference(eUpdateRefMode, r, nDx, nDy, nDz);
3603 }
3604 
3606 {
3607  TablesType aAdded;
3608  for (const auto& rxTable : maTables)
3609  {
3610  const ScDPObject& rObj = *rxTable;
3611  ScRange aOutRange = rObj.GetOutRange();
3612  if (aOutRange.aStart.Tab() != nOld)
3613  continue;
3614 
3615  ScAddress& s = aOutRange.aStart;
3616  ScAddress& e = aOutRange.aEnd;
3617  s.SetTab(nNew);
3618  e.SetTab(nNew);
3619  ScDPObject* pNew = new ScDPObject(rObj);
3620  pNew->SetOutRange(aOutRange);
3621  mrDoc.ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
3622  aAdded.push_back(std::unique_ptr<ScDPObject>(pNew));
3623  }
3624 
3625  std::move(aAdded.begin(), aAdded.end(), std::back_inserter(maTables));
3626 }
3627 
3629 {
3630  return std::equal(maTables.begin(), maTables.end(), r.maTables.begin(), r.maTables.end(),
3631  [](const TablesType::value_type& a, const TablesType::value_type& b) { return a->RefsEqual(*b); });
3632 }
3633 
3635 {
3636  if ( maTables.size() == r.maTables.size() )
3637  {
3638  //TODO: assert equal names?
3639  TablesType::iterator itr2 = r.maTables.begin();
3640  for (const auto& rxTable : maTables)
3641  {
3642  rxTable->WriteRefsTo(**itr2);
3643  ++itr2;
3644  }
3645  }
3646  else
3647  {
3648  // #i8180# If data pilot tables were deleted with their sheet,
3649  // this collection contains extra entries that must be restored.
3650  // Matching objects are found by their names.
3651  size_t nSrcSize = maTables.size();
3652  size_t nDestSize = r.maTables.size();
3653  OSL_ENSURE( nSrcSize >= nDestSize, "WriteRefsTo: missing entries in document" );
3654  for (size_t nSrcPos = 0; nSrcPos < nSrcSize; ++nSrcPos)
3655  {
3656  const ScDPObject& rSrcObj = *maTables[nSrcPos];
3657  const OUString& aName = rSrcObj.GetName();
3658  bool bFound = false;
3659  for (size_t nDestPos = 0; nDestPos < nDestSize && !bFound; ++nDestPos)
3660  {
3661  ScDPObject& rDestObj = *r.maTables[nDestPos];
3662  if (rDestObj.GetName() == aName)
3663  {
3664  rSrcObj.WriteRefsTo(rDestObj); // found object, copy refs
3665  bFound = true;
3666  }
3667  }
3668 
3669  if (!bFound)
3670  {
3671  // none found, re-insert deleted object (see ScUndoDataPilot::Undo)
3672  r.InsertNewTable(std::make_unique<ScDPObject>(rSrcObj));
3673  }
3674  }
3675  OSL_ENSURE( maTables.size() == r.maTables.size(), "WriteRefsTo: couldn't restore all entries" );
3676  }
3677 }
3678 
3680 {
3681  return maTables.size();
3682 }
3683 
3685 {
3686  return *maTables[nIndex];
3687 }
3688 
3689 const ScDPObject& ScDPCollection::operator [](size_t nIndex) const
3690 {
3691  return *maTables[nIndex];
3692 }
3693 
3694 ScDPObject* ScDPCollection::GetByName(std::u16string_view rName) const
3695 {
3696  for (std::unique_ptr<ScDPObject> const & pObject : maTables)
3697  {
3698  if (pObject->GetName() == rName)
3699  return pObject.get();
3700  }
3701 
3702  return nullptr;
3703 }
3704 
3706 {
3707  size_t n = maTables.size();
3708  for (size_t nAdd = 0; nAdd <= n; ++nAdd) // nCount+1 tries
3709  {
3710  OUString aNewName = "DataPilot" + OUString::number(1 + nAdd);
3711  if (std::none_of(maTables.begin(), maTables.end(),
3712  [&aNewName](const TablesType::value_type& rxObj) { return rxObj->GetName() == aNewName; }))
3713  return aNewName; // found unused Name
3714  }
3715  return OUString(); // should not happen
3716 }
3717 
3719 {
3720  const ScRange& rOutRange = pDPObject->GetOutRange();
3721  const ScAddress& s = rOutRange.aStart;
3722  const ScAddress& e = rOutRange.aEnd;
3723  mrDoc.RemoveFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
3724 
3725  auto funcRemoveCondition = [pDPObject] (std::unique_ptr<ScDPObject> const & pCurrent)
3726  {
3727  return pCurrent.get() == pDPObject;
3728  };
3729 
3730  maTables.erase(std::remove_if(maTables.begin(), maTables.end(), funcRemoveCondition), maTables.end());
3731 }
3732 
3733 ScDPObject* ScDPCollection::InsertNewTable(std::unique_ptr<ScDPObject> pDPObj)
3734 {
3735  const ScRange& rOutRange = pDPObj->GetOutRange();
3736  const ScAddress& s = rOutRange.aStart;
3737  const ScAddress& e = rOutRange.aEnd;
3738  mrDoc.ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
3739 
3740  maTables.push_back(std::move(pDPObj));
3741  return maTables.back().get();
3742 }
3743 
3744 bool ScDPCollection::HasTable(const ScDPObject* pDPObj) const
3745 {
3746  for (const std::unique_ptr<ScDPObject>& aTable : maTables)
3747  {
3748  if (aTable.get() == pDPObj)
3749  {
3750  return true;
3751  }
3752  }
3753  return false;
3754 }
3755 
3757 {
3758  return maSheetCaches;
3759 }
3760 
3762 {
3763  return maSheetCaches;
3764 }
3765 
3767 {
3768  return maNameCaches;
3769 }
3770 
3772 {
3773  return maNameCaches;
3774 }
3775 
3777 {
3778  return maDBCaches;
3779 }
3780 
3782 {
3783  return maDBCaches;
3784 }
3785 
3787 {
3788  return std::for_each(maTables.begin(), maTables.end(), AccumulateOutputRanges(nTab)).getRanges();
3789 }
3790 
3791 bool ScDPCollection::IntersectsTableByColumns( SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab ) const
3792 {
3793  return std::any_of(maTables.begin(), maTables.end(), FindIntersectingTableByColumns(nCol1, nCol2, nRow, nTab));
3794 }
3795 
3796 bool ScDPCollection::IntersectsTableByRows( SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab ) const
3797 {
3798  return std::any_of(maTables.begin(), maTables.end(), FindIntersectingTableByRows(nCol, nRow1, nRow2, nTab));
3799 }
3800 
3801 bool ScDPCollection::HasTable( const ScRange& rRange ) const
3802 {
3803  return std::any_of(maTables.begin(), maTables.end(), FindIntersectingTable(rRange));
3804 }
3805 
3806 #if DEBUG_PIVOT_TABLE
3807 
3808 namespace {
3809 
3810 struct DumpTable
3811 {
3812  void operator() (const std::unique_ptr<ScDPObject>& rObj) const
3813  {
3814  cout << "-- '" << rObj->GetName() << "'" << endl;
3815  ScDPSaveData* pSaveData = rObj->GetSaveData();
3816  if (!pSaveData)
3817  return;
3818 
3819  pSaveData->Dump();
3820 
3821  cout << endl; // blank line
3822  }
3823 };
3824 
3825 }
3826 
3827 void ScDPCollection::DumpTables() const
3828 {
3829  std::for_each(maTables.begin(), maTables.end(), DumpTable());
3830 }
3831 
3832 #endif
3833 
3835 {
3836  if (maSheetCaches.remove(pCache))
3837  // sheet cache removed.
3838  return;
3839 
3840  if (maNameCaches.remove(pCache))
3841  // named range cache removed.
3842  return;
3843 
3844  if (maDBCaches.remove(pCache))
3845  // database cache removed.
3846  return;
3847 }
3848 
3850 {
3852  for (const auto& rxTable : maTables)
3853  {
3854  const ScDPObject& rObj = *rxTable;
3855  if (!rObj.IsSheetData())
3856  // Source is not a sheet range.
3857  continue;
3858 
3859  const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc();
3860  if (!pDesc)
3861  continue;
3862 
3863  if (pDesc->HasRangeName())
3864  // This table has a range name as its source.
3865  continue;
3866 
3867  if (pDesc->GetSourceRange() != rSrcRange)
3868  // Different source range.
3869  continue;
3870 
3871  aRefs.insert(const_cast<ScDPObject*>(&rObj));
3872  }
3873 
3874  rRefs.swap(aRefs);
3875 }
3876 
3877 void ScDPCollection::GetAllTables(std::u16string_view rSrcName, o3tl::sorted_vector<ScDPObject*>& rRefs) const
3878 {
3880  for (const auto& rxTable : maTables)
3881  {
3882  const ScDPObject& rObj = *rxTable;
3883  if (!rObj.IsSheetData())
3884  // Source is not a sheet range.
3885  continue;
3886 
3887  const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc();
3888  if (!pDesc)
3889  continue;
3890 
3891  if (!pDesc->HasRangeName())
3892  // This table probably has a sheet range as its source.
3893  continue;
3894 
3895  if (pDesc->GetRangeName() != rSrcName)
3896  // Different source name.
3897  continue;
3898 
3899  aRefs.insert(const_cast<ScDPObject*>(&rObj));
3900  }
3901 
3902  rRefs.swap(aRefs);
3903 }
3904 
3906  sal_Int32 nSdbType, std::u16string_view rDBName, std::u16string_view rCommand,
3907  o3tl::sorted_vector<ScDPObject*>& rRefs) const
3908 {
3910  for (const auto& rxTable : maTables)
3911  {
3912  const ScDPObject& rObj = *rxTable;
3913  if (!rObj.IsImportData())
3914  // Source data is not a database.
3915  continue;
3916 
3918  if (!pDesc)
3919  continue;
3920 
3921  if (pDesc->aDBName != rDBName || pDesc->aObject != rCommand || pDesc->GetCommandType() != nSdbType)
3922  // Different database source.
3923  continue;
3924 
3925  aRefs.insert(const_cast<ScDPObject*>(&rObj));
3926  }
3927 
3928  rRefs.swap(aRefs);
3929 }
3930 
3932 {
3933  if (left.mnSdbType != right.mnSdbType)
3934  return left.mnSdbType < right.mnSdbType;
3935 
3936  if (left.maDBName != right.maDBName)
3937  return left.maDBName < right.maDBName;
3938 
3939  return left.maCommand < right.maCommand;
3940 }
3941 
3942 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SheetCaches(ScDocument &rDoc)
Definition: dpobject.cxx:2877
void SetValue(double fVal)
Definition: dpitemdata.cxx:153
OString stripEnd(const OString &rIn, char c)
bool operator()(const DBType &left, const DBType &right) const
Definition: dpobject.cxx:3166
#define SC_UNO_DP_LAYOUT
Definition: unonames.hxx:627
const ScDPDimensionSaveData * GetExistingDimensionData() const
Definition: dpsave.hxx:348
OUString aTableTag
Definition: dpobject.hxx:90
NameCaches maNameCaches
Definition: dpobject.hxx:448
static const sal_Int64 hourPerDay
SAL_DLLPRIVATE ScDPTableData * GetTableData()
Definition: dpobject.cxx:677
#define SC_UNO_DP_FIELD_SUBTOTALNAME
Definition: unonames.hxx:619
bool IsDimNameInUse(std::u16string_view rName) const
Definition: dpobject.cxx:1173
virtual sal_Int32 SAL_CALL getCount() override
Definition: miscuno.cxx:256
const std::optional< OUString > & GetLayoutName() const
Definition: dpsave.cxx:385
void GetHeaderPositionData(const ScAddress &rPos, css::sheet::DataPilotTableHeaderData &rData)
Definition: dpobject.cxx:1293
static ScRefUpdateRes Update(const ScDocument *pDoc, UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCCOL nDx, SCROW nDy, SCTAB nDz, SCCOL &theCol1, SCROW &theRow1, SCTAB &theTab1, SCCOL &theCol2, SCROW &theRow2, SCTAB &theTab2)
Definition: refupdat.cxx:188
void ReloadGroupTableData()
Definition: dpobject.cxx:809
#define SC_UNO_DP_IGNOREEMPTY
Definition: unonames.hxx:611
sal_Int32 nIndex
static ScGeneralFunction FirstFunc(PivotFunc nBits)
Definition: dapiuno.cxx:194
ScPivotFieldVector maDataFields
Definition: pivot.hxx:141
ScAddress aStart
Definition: address.hxx:497
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:163
void CopyToTab(SCTAB nOld, SCTAB nNew)
Definition: dpobject.cxx:3605
constexpr OUStringLiteral SC_DBPROP_COMMAND
Definition: dpobject.cxx:100
SC_DLLPUBLIC size_t GetCount() const
Definition: dpobject.cxx:3679
sal_uInt8 mnDupCount
Definition: pivot.hxx:76
void SetOrientation(css::sheet::DataPilotFieldOrientation nNew)
Definition: dpsave.cxx:318
std::vector< Member > maMembers
Definition: pivot.hxx:98
SCROW Row() const
Definition: address.hxx:274
void FillOldParam(ScPivotParam &rParam) const
Definition: dpobject.cxx:2288
static OUString GetLocaleIndependentFormattedString(double fValue, SvNumberFormatter &rFormatter, sal_uInt32 nNumFormat)
Definition: dpcache.cxx:1192
#define SC_UNO_DP_REFVALUE
Definition: unonames.hxx:624
static sal_Int32 GetLongProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName)
Definition: miscuno.cxx:71
SC_DLLPUBLIC SheetCaches & GetSheetCaches()
Definition: dpobject.cxx:3756
bool HasGroupDimensions() const
Definition: dpdimsave.cxx:692
void WriteSourceDataTo(ScDPObject &rDest) const
Definition: dpobject.cxx:464
static void ConvertOrientation(ScDPSaveData &rSaveData, const ScPivotFieldVector &rFields, css::sheet::DataPilotFieldOrientation nOrient, const css::uno::Reference< css::sheet::XDimensionsSupplier > &xSource, const ScDPLabelDataVector &rLabels, const ScPivotFieldVector *pRefColFields=nullptr, const ScPivotFieldVector *pRefRowFields=nullptr, const ScPivotFieldVector *pRefPageFields=nullptr)
Definition: dpobject.cxx:2606
bool mbEnableGetPivotData
Definition: dpobject.hxx:108
static weld::Window * GetActiveDialogParent()
Definition: docsh.cxx:3076
DBType(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand)
Definition: dpobject.cxx:3163
bool RefsEqual(const ScDPCollection &r) const
Definition: dpobject.cxx:3628
OUString aParPass
Definition: dpobject.hxx:75
std::unique_ptr< sal_Int32[]> pData
static void GetDataDimensionNames(OUString &rSourceName, OUString &rGivenName, const css::uno::Reference< css::uno::XInterface > &xDim)
Definition: dpoutput.cxx:1514
sal_uInt16 char char * pDesc
Definition: callform.cxx:57
tools::Long GetDimCount()
Definition: dpobject.cxx:1275
bool Intersects(const ScRange &rRange) const
Definition: address.hxx:734
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject &rDPObj, const ScDPDimensionSaveData **pGroups) const
Definition: dpobject.cxx:3525
long Long
void GetDrillDownData(const ScAddress &rPos, css::uno::Sequence< css::uno::Sequence< css::uno::Any > > &rTableData)
Definition: dpobject.cxx:1158
void InvalidateData()
Definition: dpobject.cxx:784
#define SC_UNO_DP_COLGRAND
Definition: unonames.hxx:594
constexpr OUStringLiteral SC_DBPROP_DATASOURCENAME
Definition: dpobject.cxx:99
dp field button with presence of hidden member
SC_DLLPUBLIC bool ApplyFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
Definition: document.cxx:5069
bool remove(const ScDPCache *p)
Definition: dpobject.cxx:3151
#define SC_UNO_DP_SORTING
Definition: unonames.hxx:625
sal_Int64 n
TranslateId CheckSourceRange() const
Check the sanity of the data source range.
Definition: dpshttab.cxx:307
void SetOutRange(const ScRange &rRange)
Definition: dpobject.cxx:401
sal_Int32 mnCol
void FillLabelData(sal_Int32 nDim, ScDPLabelData &Labels)
Definition: dpobject.cxx:2438
void SetSubTotals(std::vector< ScGeneralFunction > &&rFuncs)
Definition: dpsave.cxx:323
bool mbDataLayout
Definition: pivot.hxx:79
static const sal_Int64 minutePerDay
const ContentProperties & rData
sal_Int32 mnUsedHier
Used hierarchy.
Definition: pivot.hxx:74
void SetAllowMove(bool bSet)
Definition: dpobject.cxx:381
bool mbShowAll
true = Show all (also empty) results.
Definition: pivot.hxx:77
void updateReference(UpdateRefMode eMode, const ScRange &r, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: dpobject.cxx:3013
SCCOLROW nField
Definition: queryentry.hxx:61
ScAddress aEnd
Definition: address.hxx:498
static EnumT GetEnumProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, EnumT nDefault)
Definition: miscuno.hxx:159
std::vector< std::unique_ptr< ScDPObject > > TablesType
Definition: dpobject.hxx:443
#define SC_UNO_DP_REPEATEMPTY
Definition: unonames.hxx:612
void EnableGetPivotData(bool b)
Definition: dpobject.cxx:376
#define SC_UNO_DP_POSITION
Definition: unonames.hxx:600
void swap(sorted_vector &other)
void SetImportDesc(const ScImportSourceDesc &rDesc)
Definition: dpobject.cxx:438
Data caches for range name based source data.
Definition: dpobject.hxx:317
static OUString GetStringProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, const OUString &rDefault)
Definition: miscuno.cxx:119
This class represents the cached data part of the datapilot cache table implementation.
Definition: dpcache.hxx:47
OUString aParSource
Definition: dpobject.hxx:72
EmbeddedObjectRef * pObject
int nDimCount
void InitFromDoc(ScDocument &rDoc, const ScRange &rRange)
Definition: dpcache.cxx:510
SCTAB nTab
Definition: pivot.hxx:135
ScDPObject * GetByName(std::u16string_view rName) const
Definition: dpobject.cxx:3694
constexpr OUStringLiteral SC_SERVICE_ROWSET
Definition: dpobject.cxx:97
SAL_DLLPRIVATE void ClearSource()
Definition: dpobject.cxx:856
bool IsImportData() const
Definition: dpobject.hxx:163
OUString aTableName
Definition: dpobject.hxx:89
bool mbIsValue
true = Sum or count in data field.
Definition: pivot.hxx:78
css::sheet::DataPilotFieldLayoutInfo maLayoutInfo
Layout info.
Definition: pivot.hxx:101
ScDPServiceDesc(const OUString &rServ, const OUString &rSrc, const OUString &rNam, const OUString &rUser, const OUString &rPass)
Definition: dpobject.cxx:291
#define SC_UNO_DP_ORIGINAL
Definition: unonames.hxx:596
ScDPCollection(ScDocument &rDocument)
Definition: dpobject.cxx:3333
OUString CreateNewName() const
Create a new name that's not yet used by any existing data pilot objects.
Definition: dpobject.cxx:3705
#define SC_UNO_DP_LAYOUTNAME
Definition: unonames.hxx:618
std::shared_ptr< ScDPTableData > mpTableData
Definition: dpobject.hxx:95
sal_uInt16 sal_Unicode
ScDocument & mrDoc
Definition: dpobject.hxx:445
css::uno::Reference< css::sheet::XDimensionsSupplier > xSource
Definition: dpobject.hxx:97
bool mbRepeatItemLabels
Definition: pivot.hxx:80
static bool HasRegisteredSources()
Definition: dpobject.cxx:2732
void GetHierarchies(sal_Int32 nDim, css::uno::Sequence< OUString > &rHiers)
Definition: dpobject.cxx:2492
constexpr OUStringLiteral SC_DBPROP_COMMANDTYPE
Definition: dpobject.cxx:101
const ScRange & GetOutRange() const
Definition: dpobject.cxx:409
#define PIVOT_DATA_FIELD
Definition: pivot.hxx:54
Data caches for external database sources.
Definition: dpobject.hxx:357
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
bool bAllowMove
Definition: dpobject.hxx:106
int nCount
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:110
sal_Int32 mnFlags
Flags from the DataPilotSource dimension.
Definition: pivot.hxx:75
std::unique_ptr< ScDPServiceDesc > pServDesc
Definition: dpobject.hxx:94
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1137
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:115
Defines connection type to external data source.
Definition: dpobject.hxx:341
void AddReference(ScDPObject *pObj) const
Definition: dpcache.cxx:1101
bool SyncAllDimensionMembers()
Remove in the save data entries for members that don't exist anymore.
Definition: dpobject.cxx:973
SCTAB Tab() const
Definition: address.hxx:283
bool ReloadGroupsInCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3437
void SetRow(SCROW nRowP)
Definition: address.hxx:287
SC_DLLPUBLIC const ScRange & GetSourceRange() const
Get the range that contains the source data.
Definition: dpshttab.cxx:230
ScGeneralFunction GetFunction() const
Definition: dpsave.hxx:165
PivotFunc
Definition: dpglobal.hxx:24
bool GetMembersNA(sal_Int32 nDim, css::uno::Reference< css::sheet::XMembersAccess > &xMembers)
virtual void ReloadCacheTable()=0
void SetStringInterned(rtl_uString *pS)
Definition: dpitemdata.cxx:145
void SetSheetDesc(const ScSheetSourceDesc &rDesc)
Definition: dpobject.cxx:414
virtual void SetEmptyFlags(bool bIgnoreEmptyRows, bool bRepeatIfEmpty)=0
friend class ScDPCache
Definition: dpobject.hxx:282
void Output(const ScAddress &rPos)
Definition: dpobject.cxx:887
std::unordered_map< OUString, size_t > DimOrderType
Definition: dpsave.hxx:237
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
void Clear()
Definition: dpobject.cxx:789
const char * sName
void SetFunction(ScGeneralFunction nNew)
Definition: dpsave.cxx:344
static SC_DLLPUBLIC OUString getSourceDimensionName(std::u16string_view rName)
Definition: dputil.cxx:66
void GetAllTables(const ScRange &rSrcRange, o3tl::sorted_vector< ScDPObject * > &rRefs) const
Definition: dpobject.cxx:3849
void DumpCache() const
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4764
OUString maName
Original name of the dimension.
Definition: pivot.hxx:68
#define SC_UNO_DP_REPEATITEMLABELS
Definition: unonames.hxx:608
static css::uno::Reference< css::sheet::XDimensionsSupplier > CreateSource(const ScDPServiceDesc &rDesc)
Definition: dpobject.cxx:2787
void WriteRefsTo(ScDPObject &r) const
Definition: dpobject.cxx:1127
bool empty() const
Definition: rangelst.hxx:88
#define SAL_N_ELEMENTS(arr)
void SetName(const OUString &rNew)
Definition: dpobject.cxx:489
void SetLayoutName(const OUString &rName)
Definition: dpsave.cxx:380
OUString aParUser
Definition: dpobject.hxx:74
ScDPLabelDataVector maLabelArray
Definition: pivot.hxx:137
sal_uInt8 mnDupCount
Definition: pivot.hxx:122
bool IsFilterButton(const ScAddress &rPos)
Definition: dpobject.cxx:1402
bool IsBlockEmpty(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:5391
static PivotFunc FunctionBit(sal_Int16 eFunc)
Definition: dapiuno.cxx:212
Interface for connecting to database source.
Definition: dpcache.hxx:97
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
void SetHeaderLayout(bool bUseGrid)
Definition: dpobject.cxx:396
#define DBG_UNHANDLED_EXCEPTION(...)
bool IntersectsTableByColumns(SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab) const
Definition: dpobject.cxx:3791
sal_uInt16 char * pName
Definition: callform.cxx:57
bool RefsEqual(const ScDPObject &r) const
Definition: dpobject.cxx:1108
bool bMakeTotalCol
Definition: pivot.hxx:145
const ScDPCache * getCache(const OUString &rName, const ScRange &rRange, const ScDPDimensionSaveData *pDimData)
Definition: dpobject.cxx:3101
bool IntersectsTableByRows(SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab) const
Definition: dpobject.cxx:3796
#define TOOLS_WARN_EXCEPTION(area, stream)
ScPivotFieldVector maColFields
Definition: pivot.hxx:139
When assigning a string value, you can also assign an interned string whose life-cycle is managed by ...
Definition: dpitemdata.hxx:28
#define SC_UNO_DP_FUNCTION2
Definition: unonames.hxx:602
ScDPCache * getExistingCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand)
Definition: dpobject.cxx:3216
SC_DLLPUBLIC ScDPObject & operator[](size_t nIndex)
Definition: dpobject.cxx:3684
int i
SC_DLLPUBLIC const std::vector< ScRange > & getAllRanges() const
Definition: dpobject.cxx:3089
std::vector< std::unique_ptr< ScDPLabelData > > ScDPLabelDataVector
Definition: pivot.hxx:113
uno_Any a
tools::Long mnOriginalDim
>= 0 for duplicated field.
Definition: pivot.hxx:119
Stores and manages all caches from internal sheets.
Definition: dpobject.hxx:288
std::vector< ScPivotField > ScPivotFieldVector
Definition: pivot.hxx:129
virtual OUString getDimensionName(sal_Int32 nColumn)=0
const ScDPCache * getCache(const ScRange &rRange, const ScDPDimensionSaveData *pDimData)
Definition: dpobject.cxx:2920
css::uno::Reference< css::sheet::XDimensionsSupplier > const & GetSource()
Definition: dpobject.cxx:515
sal_Int16 SCCOL
Definition: types.hxx:21
void SetSaveData(const ScDPSaveData &rData)
Definition: dpobject.cxx:386
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1024
DBCaches & GetDBCaches()
Definition: dpobject.cxx:3776
const OUString & GetName() const
Definition: dpobject.hxx:167
void Dump() const
::std::vector< ScRange >::const_iterator end() const
Definition: rangelst.hxx:98
bool IsSheetData() const
Definition: dpobject.cxx:484
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
size_t size() const
Definition: rangelst.hxx:89
void SetTag(const OUString &rNew)
Definition: dpobject.cxx:494
static bool GetBoolProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, bool bDefault=false)
Definition: miscuno.cxx:35
std::unique_ptr< ScDPSaveData > pSaveData
Definition: dpobject.hxx:88
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
bool GetHeaderDrag(const ScAddress &rPos, bool bMouseLeft, bool bMouseTop, tools::Long nDragDim, tools::Rectangle &rPosRect, css::sheet::DataPilotFieldOrientation &rOrient, tools::Long &rDimPos)
Definition: dpobject.cxx:1416
float u
NameCaches(ScDocument &rDoc)
Definition: dpobject.cxx:3094
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
const int COUNT
Definition: sheetevents.cxx:56
static sheet::DataPilotFieldOrientation lcl_GetDataGetOrientation(const uno::Reference< sheet::XDimensionsSupplier > &xSource)
Definition: dpobject.cxx:262
SvNumFormatType
bool hasCache(const ScRange &rRange) const
Definition: dpobject.cxx:2908
TranslateId ReloadCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3373
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:141
bool GetHierarchiesNA(sal_Int32 nDim, css::uno::Reference< css::container::XNameAccess > &xHiers)
Definition: dpobject.cxx:2475
void ClearTableData()
Definition: dpobject.cxx:800
SC_DLLPUBLIC ScDPObject * InsertNewTable(std::unique_ptr< ScDPObject > pDPObj)
Definition: dpobject.cxx:3733
void ClearAllFields()
Definition: dpcache.cxx:1362
const ScImportSourceDesc * GetImportSourceDesc() const
Definition: dpobject.hxx:157
css::sheet::DataPilotFieldReference maFieldRef
Definition: pivot.hxx:117
static bool lcl_HasButton(const ScDocument *pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: dpobject.cxx:928
bool ParseFilters(OUString &rDataFieldName, std::vector< css::sheet::DataPilotFieldFilter > &rFilters, std::vector< sal_Int16 > &rFilterFuncs, std::u16string_view rFilterList)
Definition: dpobject.cxx:1716
#define SC_UNO_DP_AUTOSHOW
Definition: unonames.hxx:626
bool bSettingsChanged
Definition: dpobject.hxx:107
ScDPObject & operator=(const ScDPObject &r)
Definition: dpobject.cxx:347
css::beans::Optional< css::uno::Any > getValue(std::u16string_view id)
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:545
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
SCCOL nCol
Cursor Position /.
Definition: pivot.hxx:133
bool IsValid() const
Definition: address.hxx:544
ScDPSaveDimension * DuplicateDimension(std::u16string_view rName)
Definition: dpsave.cxx:886
void SetReferenceValue(const css::sheet::DataPilotFieldReference *pNew)
Definition: dpsave.cxx:395
OUString aDBName
Definition: dpsdbtab.hxx:35
TablesType maTables
Definition: dpobject.hxx:446
Reference not affected, no change at all.
Definition: refupdat.hxx:31
static PivotFunc lcl_FirstSubTotal(const uno::Reference< beans::XPropertySet > &xDimProp)
Definition: dpobject.cxx:2093
SCCOL Col() const
Definition: address.hxx:279
bool GetMembers(sal_Int32 nDim, sal_Int32 nHier,::std::vector< ScDPLabelData::Member > &rMembers)
Definition: dpobject.cxx:1011
bool hasCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand) const
Definition: dpobject.cxx:3173
PivotFunc nFuncMask
Definition: pivot.hxx:120
bool GetDataFieldPositionData(const ScAddress &rPos, css::uno::Sequence< css::sheet::DataPilotFieldFilter > &rFilters)
Definition: dpobject.cxx:1140
bool hasCache(const OUString &rName) const
Definition: dpobject.cxx:3096
DBCaches(ScDocument &rDoc)
Definition: dpobject.cxx:3171
static sal_uInt8 getDuplicateIndex(const OUString &rName)
Get a duplicate index in case the dimension is a duplicate.
Definition: dputil.cxx:71
const std::shared_ptr< ScDPTableData > & GetSourceTableData() const
Definition: dpgroup.hxx:137
bool remove(const ScDPCache *p)
Definition: dpobject.cxx:3321
const sal_uInt16 idx[]
OUString aObject
Definition: dpsdbtab.hxx:36
void Dump() const
#define SC_UNO_DP_ROWGRAND
Definition: unonames.hxx:595
void RemoveCache(const ScDPCache *pCache)
Only to be called from ScDPCache::RemoveReference().
Definition: dpobject.cxx:3834
bool HasRangeName() const
Definition: dpshttab.cxx:265
#define SC_UNO_DP_FLAGS
Definition: unonames.hxx:622
#define SC_UNO_DP_ORIENTATION
Definition: unonames.hxx:599
bool bMakeTotalRow
Definition: pivot.hxx:146
#define SC_UNO_DP_ORIGINAL_POS
Definition: unonames.hxx:597
SC_DLLPUBLIC size_t size() const
Definition: dpobject.cxx:3008
OUString GetDimName(tools::Long nDim, bool &rIsDataLayout, sal_Int32 *pFlags=nullptr)
Definition: dpobject.cxx:1197
SAL_DLLPRIVATE void FillLabelDataForDimension(const css::uno::Reference< css::container::XIndexAccess > &xDims, sal_Int32 nDim, ScDPLabelData &rLabelData)
Definition: dpobject.cxx:2378
OUString maLayoutName
Layout name (display name)
Definition: pivot.hxx:69
#define SC_UNO_DP_SHOWEMPTY
Definition: unonames.hxx:607
UpdateRefMode
Definition: global.hxx:298
bool GetMemberNames(sal_Int32 nDim, css::uno::Sequence< OUString > &rNames)
Definition: dpobject.cxx:996
static bool IsOrientationAllowed(css::sheet::DataPilotFieldOrientation nOrient, sal_Int32 nDimFlags)
Definition: dpobject.cxx:2707
constexpr TypedWhichId< ScMergeFlagAttr > ATTR_MERGE_FLAG(145)
Base class that abstracts different data source types of a datapilot table.
Definition: dptabdat.hxx:56
bool InitFromDataBase(DBConnector &rDB)
Definition: dpcache.cxx:626
sal_Int32 SCROW
Definition: types.hxx:17
ScDPObject(ScDocument *pD)
Definition: dpobject.cxx:309
bool operator<(const ScDPCollection::DBType &left, const ScDPCollection::DBType &right)
Definition: dpobject.cxx:3931
Reference< XMultiServiceFactory > getProcessServiceFactory()
std::unique_ptr< char[]> aBuffer
void UpdateReference(UpdateRefMode eUpdateRefMode, const ScRange &r, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: dpobject.cxx:1046
SC_DLLPUBLIC bool HasTable(const ScDPObject *pDPObj) const
Definition: dpobject.cxx:3744
void updateCache(const OUString &rName, const ScRange &rRange, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3130
ScRangeList GetAllTableRanges(SCTAB nTab) const
Definition: dpobject.cxx:3786
#define SC_UNO_DP_USEDHIERARCHY
Definition: unonames.hxx:603
css::uno::Sequence< OUString > maHiers
Hierarchies.
Definition: pivot.hxx:99
void Join(const ScRange &, bool bIsInList=false)
Definition: rangelst.cxx:152
unsigned char sal_uInt8
OUString aParName
Definition: dpobject.hxx:73
SheetCaches maSheetCaches
Definition: dpobject.hxx:447
OUString aServiceName
Definition: dpobject.hxx:71
void SetSubtotalName(const OUString &rName)
Definition: dpsave.cxx:354
std::unordered_set< OUString > ScDPUniqueStringSet
Definition: dptypes.hxx:16
DBCaches maDBCaches
Definition: dpobject.hxx:449
SvStream & endl(SvStream &rStr)
void SetServiceData(const ScDPServiceDesc &rDesc)
Definition: dpobject.cxx:451
ScGeneralFunction
the css::sheet::GeneralFunction enum is extended by constants in GeneralFunction2, which causes some type-safety issues.
std::unique_ptr< ScImportSourceDesc > pImpDesc
Definition: dpobject.hxx:93
OUString maName
OUString aName
const OUString & GetName() const
Definition: dpsave.hxx:139
SCROW nRow
or start of destination area
Definition: pivot.hxx:134
#define SC_UNO_DP_ISVISIBLE
Definition: unonames.hxx:609
void RemoveLayoutName()
Definition: dpsave.cxx:390
css::sheet::DataPilotFieldSortInfo maSortInfo
Sorting info.
Definition: pivot.hxx:100
OString strip(const OString &rIn, char c)
SC_DLLPUBLIC bool RemoveFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
Definition: document.cxx:5080
static void lcl_FillLabelData(ScDPLabelData &rData, const uno::Reference< beans::XPropertySet > &xDimProp)
Definition: dpobject.cxx:2333
const ScDPObjectSet & GetAllReferences() const
Definition: dpcache.cxx:1117
bool remove(const ScDPCache *p)
Definition: dpobject.cxx:3075
const ScSheetSourceDesc * GetSheetDesc() const
Definition: dpobject.hxx:156
const OUString & GetRangeName() const
Definition: dpshttab.hxx:60
OUString GetFormattedString(std::u16string_view rDimName, const double fValue)
Definition: dpobject.cxx:1431
void RemoveSubtotalName()
Definition: dpsave.cxx:364
bool operator==(const ScDPServiceDesc &rOther) const
Definition: dpobject.cxx:300
ScPivotFieldVector maRowFields
Definition: pivot.hxx:140
sal_Int32 GetUsedHierarchy(sal_Int32 nDim)
Definition: dpobject.cxx:2501
void * p
Reference< XComponentContext > getProcessComponentContext()
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
Sequence< sal_Int8 > aSeq
static sal_Int16 GetShortProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, sal_Int16 nDefault)
Definition: miscuno.cxx:53
OString stripStart(const OString &rIn, char c)
void UpdateReference(UpdateRefMode eUpdateRefMode, const ScRange &r, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: dpobject.cxx:3595
void GetMemberResultNames(ScDPUniqueStringSet &rNames, tools::Long nDimension)
Definition: dpobject.cxx:1424
ScRefUpdateRes
Definition: refupdat.hxx:30
void SetShowEmpty(bool bSet)
Definition: dpsave.cxx:334
void Dump() const
bool mbHeaderLayout
Definition: dpobject.hxx:105
OUString GetFormattedString(sal_Int32 nDim, const ScDPItemData &rItem, bool bLocaleIndependent) const
Definition: dptabdat.cxx:51
bool IsDuplicated(tools::Long nDim)
Definition: dpobject.cxx:1246
std::map< OUString, css::uno::Any > maInteropGrabBag
Definition: dpobject.hxx:102
void WriteRefsTo(ScDPCollection &r) const
Definition: dpobject.cxx:3634
static const sal_Int64 nanoSecPerDay
ScDocument * pDoc
Definition: dpobject.hxx:86
void WriteToData(ScDPGroupTableData &rData) const
Definition: dpdimsave.cxx:610
void disposeComponent(css::uno::Reference< TYPE > &_rxComp)
double GetPivotData(const OUString &rDataFieldName, std::vector< css::sheet::DataPilotFieldFilter > &rFilters)
Definition: dpobject.cxx:1360
void RefreshAfterLoad()
Definition: dpobject.cxx:933
static SC_DLLPUBLIC OUString getDisplayedMeasureName(const OUString &rName, ScSubTotalFunc eFunc)
Definition: dputil.cxx:384
std::unique_ptr< ScSheetSourceDesc > pSheetDesc
Definition: dpobject.hxx:92
::std::vector< ScRange >::const_iterator begin() const
Definition: rangelst.hxx:97
bool bIgnoreEmptyRows
Definition: pivot.hxx:143
constexpr OUStringLiteral SCDPSOURCE_SERVICE
Definition: dpobject.cxx:103
void WriteToCache(ScDPCache &rCache) const
Definition: dpdimsave.cxx:622
#define SC_UNO_DP_SHOWDETAILS
Definition: unonames.hxx:610
ScPivotFieldVector maPageFields
Definition: pivot.hxx:138
void WriteTempDataTo(ScDPObject &rDest) const
Definition: dpobject.cxx:479
SAL_DLLPRIVATE void CreateOutput()
Definition: dpobject.cxx:521
void DeleteOnTab(SCTAB nTab)
Definition: dpobject.cxx:3590
#define SC_UNO_DP_ISDATALAYOUT
Definition: unonames.hxx:598
sal_Int32 mnRow
sal_Int32 nHeaderRows
Definition: dpobject.hxx:104
ScSubTotalFunc
Definition: global.hxx:843
static css::uno::Reference< css::sdbc::XRowSet > createRowSet(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand)
Definition: dpobject.cxx:3224
const char *const aFieldNames[]
static SC_DLLPUBLIC::utl::TransliterationWrapper & GetTransliteration()
Definition: global.cxx:986
std::unique_ptr< ScDPOutput > pOutput
Definition: dpobject.hxx:98
std::pair< const_iterator, bool > insert(Value &&x)
void BuildAllDimensionMembers()
Definition: dpobject.cxx:959
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
Definition: document.cxx:1942
NameCaches & GetNameCaches()
Definition: dpobject.cxx:3766
bool bDetectCategories
Definition: pivot.hxx:144
const Date & GetNullDate() const
SAL_DLLPRIVATE void CreateObjects()
Definition: dpobject.cxx:731
constexpr OUStringLiteral first
static void lcl_FillOldFields(ScPivotFieldVector &rFields, const uno::Reference< sheet::XDimensionsSupplier > &xSource, sheet::DataPilotFieldOrientation nOrient, bool bAddData)
Definition: dpobject.cxx:2153
ScRange GetNewOutputRange(bool &rOverflow)
Definition: dpobject.cxx:873
static std::vector< OUString > GetRegisteredSources()
Definition: dpobject.cxx:2749
sal_Int32 GetCommandType() const
Definition: dpsdbtab.cxx:35
SC_DLLPUBLIC ScDPCache * getExistingCache(const ScRange &rRange)
Definition: dpobject.cxx:2970
#define SC_UNO_DP_SUBTOTAL2
Definition: unonames.hxx:606
This class contains authoritative information on the internal reference used as the data source for d...
Definition: dpshttab.hxx:39
void updateCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3278
ScRange GetOutputRangeByType(sal_Int32 nType)
Definition: dpobject.cxx:910
tools::Long getOriginalDim() const
Definition: pivot2.cxx:83
tools::Long mnOriginalDim
original dimension index (>= 0 for duplicated dimension)
Definition: pivot.hxx:72
const ScDPCache * getCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand, const ScDPDimensionSaveData *pDimData)
Definition: dpobject.cxx:3180
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
Definition: dpsave.cxx:835
void SetEmpty()
Definition: dpitemdata.cxx:131
SCCOL nCol
0-based dimension index (not source column index)
Definition: pivot.hxx:121
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
OUString maSubtotalName
Definition: pivot.hxx:70
ScDPCache * getExistingCache(const OUString &rName)
Definition: dpobject.cxx:3119
ScRange aOutRange
Definition: dpobject.hxx:91
tools::Long GetHeaderDim(const ScAddress &rPos, css::sheet::DataPilotFieldOrientation &rOrient)
Definition: dpobject.cxx:1409
SC_DLLPUBLIC ScDPSaveDimension * GetDataLayoutDimension()
Definition: dpsave.cxx:867
B2DRange maRange
sal_uInt16 nPos
void ToggleDetails(const css::sheet::DataPilotTableHeaderData &rElemDesc, ScDPObject *pDestObj)
Definition: dpobject.cxx:1989
static SC_DLLPUBLIC ScSubTotalFunc toSubTotalFunc(ScGeneralFunction eGenFunc)
Definition: dputil.cxx:395
sal_Int16 SCTAB
Definition: types.hxx:22
SCCOL mnCol
0-based field index (not the source column index)
Definition: pivot.hxx:71
css::sheet::DataPilotFieldAutoShowInfo maShowInfo
AutoShow info.
Definition: pivot.hxx:102
void GetPositionData(const ScAddress &rPos, css::sheet::DataPilotTablePositionData &rPosData)
Definition: dpobject.cxx:1134
void updateCache(const ScRange &rRange, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3044
void FreeTable(const ScDPObject *pDPObj)
Definition: dpobject.cxx:3718
bool m_bDetectedRangeSegmentation false
virtual sal_Int32 GetColumnCount()=0
use (new) typed collection instead of ScStrCollection or separate Str and ValueCollection ...
static const sal_Int64 secondPerDay