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