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