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