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