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, pSaveData ? pSaveData->GetExpandCollapse() : false ) );
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( std::u16string_view 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.size();
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( std::u16string_view 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.size();
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.find(']', nStartPos);
1544 if (nFuncEnd >= 0)
1545 {
1546 aFuncStr = rList.substr(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( std::u16string_view rList, sal_Int32& rMatched, bool bAllowBracket, sal_Int16* pFunc,
1574 OUString& rDequoted )
1575{
1576 size_t 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.size();
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.find(']', nStartPos);
1625 if (nClosePos >= 0)
1626 {
1627 sal_Int32 nNameEnd = nClosePos;
1628 sal_Int32 nSemiPos = rList.find(';', 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.substr(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 ( nMatchList >= rList.size() )
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
2485void ScDPObject::GetFieldIdsNames(sheet::DataPilotFieldOrientation nOrient, std::vector<tools::Long>& rIndices,
2486 std::vector<OUString>& rNames)
2487{
2488 CreateObjects();
2489 if (!xSource.is())
2490 return;
2491
2492 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
2493 uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
2494 tools::Long nDimCount = xDims->getCount();
2495 for (tools::Long nDim = 0; nDim < nDimCount; ++nDim)
2496 {
2497 uno::Reference<uno::XInterface> xIntDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
2498 uno::Reference<container::XNamed> xDimName(xIntDim, uno::UNO_QUERY);
2499 uno::Reference<beans::XPropertySet> xDimProp(xIntDim, uno::UNO_QUERY);
2500
2501 sheet::DataPilotFieldOrientation nDimOrient = ScUnoHelpFunctions::GetEnumProperty(
2502 xDimProp, SC_UNO_DP_ORIENTATION,
2503 sheet::DataPilotFieldOrientation_HIDDEN );
2504
2505 if ( xDimProp.is() && nDimOrient == nOrient)
2506 {
2507 rIndices.push_back(nDim);
2508 rNames.push_back(xDimName->getName());
2509 }
2510 }
2511}
2512
2513bool ScDPObject::GetHierarchiesNA( sal_Int32 nDim, uno::Reference< container::XNameAccess >& xHiers )
2514{
2515 bool bRet = false;
2516 uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
2517 uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
2518 if( xIntDims.is() )
2519 {
2520 uno::Reference<sheet::XHierarchiesSupplier> xHierSup(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
2521 if (xHierSup.is())
2522 {
2523 xHiers.set( xHierSup->getHierarchies() );
2524 bRet = xHiers.is();
2525 }
2526 }
2527 return bRet;
2528}
2529
2530void ScDPObject::GetHierarchies( sal_Int32 nDim, uno::Sequence< OUString >& rHiers )
2531{
2532 uno::Reference< container::XNameAccess > xHiersNA;
2533 if( GetHierarchiesNA( nDim, xHiersNA ) )
2534 {
2535 rHiers = xHiersNA->getElementNames();
2536 }
2537}
2538
2539sal_Int32 ScDPObject::GetUsedHierarchy( sal_Int32 nDim )
2540{
2541 sal_Int32 nHier = 0;
2542 uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
2543 uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
2544 uno::Reference<beans::XPropertySet> xDim(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
2545 if (xDim.is())
2547 return nHier;
2548}
2549
2550bool ScDPObject::GetMembersNA( sal_Int32 nDim, uno::Reference< sheet::XMembersAccess >& xMembers )
2551{
2552 return GetMembersNA( nDim, GetUsedHierarchy( nDim ), xMembers );
2553}
2554
2555bool ScDPObject::GetMembersNA( sal_Int32 nDim, sal_Int32 nHier, uno::Reference< sheet::XMembersAccess >& xMembers )
2556{
2557 bool bRet = false;
2558 uno::Reference<container::XNameAccess> xDimsName( GetSource()->getDimensions() );
2559 uno::Reference<container::XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName ));
2560 uno::Reference<beans::XPropertySet> xDim(xIntDims->getByIndex( nDim ), uno::UNO_QUERY);
2561 if (xDim.is())
2562 {
2563 uno::Reference<sheet::XHierarchiesSupplier> xHierSup(xDim, uno::UNO_QUERY);
2564 if (xHierSup.is())
2565 {
2566 uno::Reference<container::XIndexAccess> xHiers(new ScNameToIndexAccess(xHierSup->getHierarchies()));
2567 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHiers->getByIndex(nHier), uno::UNO_QUERY );
2568 if ( xLevSupp.is() )
2569 {
2570 uno::Reference<container::XIndexAccess> xLevels(new ScNameToIndexAccess( xLevSupp->getLevels()));
2571 if (xLevels.is())
2572 {
2573 sal_Int32 nLevCount = xLevels->getCount();
2574 if (nLevCount > 0)
2575 {
2576 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevels->getByIndex(0), uno::UNO_QUERY );
2577 if ( xMembSupp.is() )
2578 {
2579 xMembers.set(xMembSupp->getMembers());
2580 bRet = true;
2581 }
2582 }
2583 }
2584 }
2585 }
2586 }
2587 return bRet;
2588}
2589
2590// convert old pivot tables into new datapilot tables
2591
2592namespace {
2593
2594OUString lcl_GetDimName( const uno::Reference<sheet::XDimensionsSupplier>& xSource, tools::Long nDim )
2595{
2596 OUString aName;
2597 if ( xSource.is() )
2598 {
2599 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
2600 uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess( xDimsName );
2601 tools::Long nDimCount = xDims->getCount();
2602 if ( nDim < nDimCount )
2603 {
2604 uno::Reference<container::XNamed> xDimName(xDims->getByIndex(nDim), uno::UNO_QUERY);
2605 if (xDimName.is())
2606 {
2607 try
2608 {
2609 aName = xDimName->getName();
2610 }
2611 catch(uno::Exception&)
2612 {
2613 }
2614 }
2615 }
2616 }
2617 return aName;
2618}
2619
2620bool hasFieldColumn(const vector<ScPivotField>* pRefFields, SCCOL nCol)
2621{
2622 if (!pRefFields)
2623 return false;
2624
2625 return std::any_of(pRefFields->begin(), pRefFields->end(),
2626 [&nCol](const ScPivotField& rField) {
2627 // This array of fields contains the specified column.
2628 return rField.nCol == nCol; });
2629}
2630
2631class FindByOriginalDim
2632{
2633 tools::Long mnDim;
2634public:
2635 explicit FindByOriginalDim(tools::Long nDim) : mnDim(nDim) {}
2636 bool operator() (const ScPivotField& r) const
2637 {
2638 return mnDim == r.getOriginalDim();
2639 }
2640};
2641
2642}
2643
2645 ScDPSaveData& rSaveData, const ScPivotFieldVector& rFields, sheet::DataPilotFieldOrientation nOrient,
2646 const Reference<XDimensionsSupplier>& xSource,
2647 const ScDPLabelDataVector& rLabels,
2648 const ScPivotFieldVector* pRefColFields,
2649 const ScPivotFieldVector* pRefRowFields,
2650 const ScPivotFieldVector* pRefPageFields )
2651{
2652 ScPivotFieldVector::const_iterator itr, itrBeg = rFields.begin(), itrEnd = rFields.end();
2653 for (itr = itrBeg; itr != itrEnd; ++itr)
2654 {
2655 const ScPivotField& rField = *itr;
2656
2657 tools::Long nCol = rField.getOriginalDim();
2658 PivotFunc nFuncs = rField.nFuncMask;
2659 const sheet::DataPilotFieldReference& rFieldRef = rField.maFieldRef;
2660
2661 ScDPSaveDimension* pDim = nullptr;
2662 if ( nCol == PIVOT_DATA_FIELD )
2663 pDim = rSaveData.GetDataLayoutDimension();
2664 else
2665 {
2666 OUString aDocStr = lcl_GetDimName( xSource, nCol ); // cols must start at 0
2667 if (!aDocStr.isEmpty())
2668 pDim = rSaveData.GetDimensionByName(aDocStr);
2669 else
2670 pDim = nullptr;
2671 }
2672
2673 if (!pDim)
2674 continue;
2675
2676 if ( nOrient == sheet::DataPilotFieldOrientation_DATA ) // set summary function
2677 {
2678 // generate an individual entry for each function
2679 bool bFirst = true;
2680
2681 // if a dimension is used for column/row/page and data,
2682 // use duplicated dimensions for all data occurrences
2683 if (hasFieldColumn(pRefColFields, nCol))
2684 bFirst = false;
2685
2686 if (bFirst && hasFieldColumn(pRefRowFields, nCol))
2687 bFirst = false;
2688
2689 if (bFirst && hasFieldColumn(pRefPageFields, nCol))
2690 bFirst = false;
2691
2692 if (bFirst)
2693 {
2694 // if set via api, a data column may occur several times
2695 // (if the function hasn't been changed yet) -> also look for duplicate data column
2696 bFirst = std::none_of(itrBeg, itr, FindByOriginalDim(nCol));
2697 }
2698
2700 if (!bFirst)
2701 pDim = rSaveData.DuplicateDimension(pDim->GetName());
2702 pDim->SetOrientation(nOrient);
2703 pDim->SetFunction(eFunc);
2704
2705 if( rFieldRef.ReferenceType == sheet::DataPilotFieldReferenceType::NONE )
2706 pDim->SetReferenceValue(nullptr);
2707 else
2708 pDim->SetReferenceValue(&rFieldRef);
2709 }
2710 else // set SubTotals
2711 {
2712 pDim->SetOrientation( nOrient );
2713
2714 std::vector<ScGeneralFunction> nSubTotalFuncs;
2715 nSubTotalFuncs.reserve(16);
2716 sal_uInt16 nMask = 1;
2717 for (sal_uInt16 nBit=0; nBit<16; nBit++)
2718 {
2719 if ( nFuncs & static_cast<PivotFunc>(nMask) )
2720 nSubTotalFuncs.push_back( ScDataPilotConversion::FirstFunc( static_cast<PivotFunc>(nMask) ) );
2721 nMask *= 2;
2722 }
2723 pDim->SetSubTotals( std::move(nSubTotalFuncs) );
2724
2725 // ShowEmpty was implicit in old tables,
2726 // must be set for data layout dimension (not accessible in dialog)
2727 if ( nCol == PIVOT_DATA_FIELD )
2728 pDim->SetShowEmpty( true );
2729 }
2730
2731 size_t nDimIndex = rField.nCol;
2732 pDim->RemoveLayoutName();
2733 pDim->RemoveSubtotalName();
2734 if (nDimIndex < rLabels.size())
2735 {
2736 const ScDPLabelData& rLabel = *rLabels[nDimIndex];
2737 if (!rLabel.maLayoutName.isEmpty())
2738 pDim->SetLayoutName(rLabel.maLayoutName);
2739 if (!rLabel.maSubtotalName.isEmpty())
2740 pDim->SetSubtotalName(rLabel.maSubtotalName);
2741 }
2742 }
2743}
2744
2745bool ScDPObject::IsOrientationAllowed( sheet::DataPilotFieldOrientation nOrient, sal_Int32 nDimFlags )
2746{
2747 bool bAllowed = true;
2748 switch (nOrient)
2749 {
2750 case sheet::DataPilotFieldOrientation_PAGE:
2751 bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_PAGE_ORIENTATION ) == 0;
2752 break;
2753 case sheet::DataPilotFieldOrientation_COLUMN:
2754 bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_COLUMN_ORIENTATION ) == 0;
2755 break;
2756 case sheet::DataPilotFieldOrientation_ROW:
2757 bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_ROW_ORIENTATION ) == 0;
2758 break;
2759 case sheet::DataPilotFieldOrientation_DATA:
2760 bAllowed = ( nDimFlags & sheet::DimensionFlags::NO_DATA_ORIENTATION ) == 0;
2761 break;
2762 default:
2763 {
2764 // allowed to remove from previous orientation
2765 }
2766 }
2767 return bAllowed;
2768}
2769
2771{
2772 bool bFound = false;
2773
2774 uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
2775 uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
2776 if ( xEnAc.is() )
2777 {
2778 uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
2780 if ( xEnum.is() && xEnum->hasMoreElements() )
2781 bFound = true;
2782 }
2783
2784 return bFound;
2785}
2786
2788{
2789 std::vector<OUString> aVec;
2790
2791 // use implementation names...
2792
2793 uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
2794 uno::Reference<container::XContentEnumerationAccess> xEnAc( xManager, uno::UNO_QUERY );
2795 if ( xEnAc.is() )
2796 {
2797 uno::Reference<container::XEnumeration> xEnum = xEnAc->createContentEnumeration(
2799 if ( xEnum.is() )
2800 {
2801 while ( xEnum->hasMoreElements() )
2802 {
2803 uno::Any aAddInAny = xEnum->nextElement();
2804// if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
2805 {
2806 uno::Reference<uno::XInterface> xIntFac;
2807 aAddInAny >>= xIntFac;
2808 if ( xIntFac.is() )
2809 {
2810 uno::Reference<lang::XServiceInfo> xInfo( xIntFac, uno::UNO_QUERY );
2811 if ( xInfo.is() )
2812 {
2813 OUString sName = xInfo->getImplementationName();
2814 aVec.push_back( sName );
2815 }
2816 }
2817 }
2818 }
2819 }
2820 }
2821
2822 return aVec;
2823}
2824
2825uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPServiceDesc& rDesc )
2826{
2827 OUString aImplName = rDesc.aServiceName;
2828 uno::Reference<sheet::XDimensionsSupplier> xRet;
2829
2830 uno::Reference<lang::XMultiServiceFactory> xManager = comphelper::getProcessServiceFactory();
2831 uno::Reference<container::XContentEnumerationAccess> xEnAc(xManager, uno::UNO_QUERY);
2832 if (!xEnAc.is())
2833 return xRet;
2834
2835 uno::Reference<container::XEnumeration> xEnum =
2836 xEnAc->createContentEnumeration(SCDPSOURCE_SERVICE);
2837 if (!xEnum.is())
2838 return xRet;
2839
2840 while (xEnum->hasMoreElements() && !xRet.is())
2841 {
2842 uno::Any aAddInAny = xEnum->nextElement();
2843 uno::Reference<uno::XInterface> xIntFac;
2844 aAddInAny >>= xIntFac;
2845 if (!xIntFac.is())
2846 continue;
2847
2848 uno::Reference<lang::XServiceInfo> xInfo(xIntFac, uno::UNO_QUERY);
2849 if (!xInfo.is() || xInfo->getImplementationName() != aImplName)
2850 continue;
2851
2852 try
2853 {
2854 // #i113160# try XSingleComponentFactory in addition to (old) XSingleServiceFactory,
2855 // passing the context to the component (see ScUnoAddInCollection::Initialize)
2856
2857 uno::Reference<uno::XInterface> xInterface;
2858 uno::Reference<uno::XComponentContext> xCtx(
2860 uno::Reference<lang::XSingleComponentFactory> xCFac( xIntFac, uno::UNO_QUERY );
2861 if (xCFac.is())
2862 xInterface = xCFac->createInstanceWithContext(xCtx);
2863
2864 if (!xInterface.is())
2865 {
2866 uno::Reference<lang::XSingleServiceFactory> xFac( xIntFac, uno::UNO_QUERY );
2867 if ( xFac.is() )
2868 xInterface = xFac->createInstance();
2869 }
2870
2871 uno::Reference<lang::XInitialization> xInit( xInterface, uno::UNO_QUERY );
2872 if (xInit.is())
2873 {
2874 // initialize
2875 uno::Sequence<uno::Any> aSeq(4);
2876 uno::Any* pArray = aSeq.getArray();
2877 pArray[0] <<= rDesc.aParSource;
2878 pArray[1] <<= rDesc.aParName;
2879 pArray[2] <<= rDesc.aParUser;
2880 pArray[3] <<= rDesc.aParPass;
2881 xInit->initialize( aSeq );
2882 }
2883 xRet.set( xInterface, uno::UNO_QUERY );
2884 }
2885 catch(uno::Exception&)
2886 {
2887 }
2888 }
2889
2890 return xRet;
2891}
2892
2893#if DUMP_PIVOT_TABLE
2894
2895void ScDPObject::Dump() const
2896{
2897 if (pSaveData)
2898 pSaveData->Dump();
2899
2900 if (mpTableData)
2901 mpTableData->Dump();
2902}
2903
2904void ScDPObject::DumpCache() const
2905{
2906 if (!mpTableData)
2907 return;
2908
2909 const ScDPCache &rCache = mpTableData->GetCacheTable().getCache();
2910
2911 rCache.Dump();
2912}
2913#endif
2914
2916
2917namespace {
2918
2919struct FindInvalidRange
2920{
2921 bool operator() (const ScRange& r) const
2922 {
2923 return !r.IsValid();
2924 }
2925};
2926
2927void setGroupItemsToCache( ScDPCache& rCache, const o3tl::sorted_vector<ScDPObject*>& rRefs )
2928{
2929 // Go through all referencing pivot tables, and re-fill the group dimension info.
2930 for (const ScDPObject* pObj : rRefs)
2931 {
2932 const ScDPSaveData* pSave = pObj->GetSaveData();
2933 if (!pSave)
2934 continue;
2935
2936 const ScDPDimensionSaveData* pGroupDims = pSave->GetExistingDimensionData();
2937 if (!pGroupDims)
2938 continue;
2939
2940 pGroupDims->WriteToCache(rCache);
2941 }
2942}
2943
2944}
2945
2947{
2948 RangeIndexType::const_iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
2949 if (it == maRanges.end())
2950 return false;
2951
2952 // Already cached.
2953 size_t nIndex = std::distance(maRanges.begin(), it);
2954 CachesType::const_iterator const itCache = m_Caches.find(nIndex);
2955 return itCache != m_Caches.end();
2956}
2957
2959{
2960 RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
2961 if (it != maRanges.end())
2962 {
2963 // Already cached.
2964 size_t nIndex = std::distance(maRanges.begin(), it);
2965 CachesType::iterator const itCache = m_Caches.find(nIndex);
2966 if (itCache == m_Caches.end())
2967 {
2968 OSL_FAIL("Cache pool and index pool out-of-sync !!!");
2969 return nullptr;
2970 }
2971
2972 if (pDimData)
2973 {
2974 (itCache->second)->ClearGroupFields();
2975 pDimData->WriteToCache(*itCache->second);
2976 }
2977
2978 return itCache->second.get();
2979 }
2980
2981 // Not cached. Create a new cache.
2982 ::std::unique_ptr<ScDPCache> pCache(new ScDPCache(mrDoc));
2983 pCache->InitFromDoc(mrDoc, rRange);
2984 if (pDimData)
2985 pDimData->WriteToCache(*pCache);
2986
2987 // Get the smallest available range index.
2988 it = std::find_if(maRanges.begin(), maRanges.end(), FindInvalidRange());
2989
2990 size_t nIndex = maRanges.size();
2991 if (it == maRanges.end())
2992 {
2993 // All range indices are valid. Append a new index.
2994 maRanges.push_back(rRange);
2995 }
2996 else
2997 {
2998 // Slot with invalid range. Re-use this slot.
2999 *it = rRange;
3000 nIndex = std::distance(maRanges.begin(), it);
3001 }
3002
3003 const ScDPCache* p = pCache.get();
3004 m_Caches.insert(std::make_pair(nIndex, std::move(pCache)));
3005 return p;
3006}
3007
3009{
3010 RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
3011 if (it == maRanges.end())
3012 // Not cached.
3013 return nullptr;
3014
3015 // Already cached.
3016 size_t nIndex = std::distance(maRanges.begin(), it);
3017 CachesType::iterator const itCache = m_Caches.find(nIndex);
3018 if (itCache == m_Caches.end())
3019 {
3020 OSL_FAIL("Cache pool and index pool out-of-sync !!!");
3021 return nullptr;
3022 }
3023
3024 return itCache->second.get();
3025}
3026
3028{
3029 RangeIndexType::const_iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
3030 if (it == maRanges.end())
3031 // Not cached.
3032 return nullptr;
3033
3034 // Already cached.
3035 size_t nIndex = std::distance(maRanges.begin(), it);
3036 CachesType::const_iterator const itCache = m_Caches.find(nIndex);
3037 if (itCache == m_Caches.end())
3038 {
3039 OSL_FAIL("Cache pool and index pool out-of-sync !!!");
3040 return nullptr;
3041 }
3042
3043 return itCache->second.get();
3044}
3045
3047{
3048 return m_Caches.size();
3049}
3050
3052 UpdateRefMode eMode, const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz)
3053{
3054 if (maRanges.empty())
3055 // No caches.
3056 return;
3057
3058 for (ScRange& rKeyRange : maRanges)
3059 {
3060 SCCOL nCol1 = rKeyRange.aStart.Col();
3061 SCROW nRow1 = rKeyRange.aStart.Row();
3062 SCTAB nTab1 = rKeyRange.aStart.Tab();
3063 SCCOL nCol2 = rKeyRange.aEnd.Col();
3064 SCROW nRow2 = rKeyRange.aEnd.Row();
3065 SCTAB nTab2 = rKeyRange.aEnd.Tab();
3066
3068 &mrDoc, eMode,
3069 r.aStart.Col(), r.aStart.Row(), r.aStart.Tab(),
3070 r.aEnd.Col(), r.aEnd.Row(), r.aEnd.Tab(), nDx, nDy, nDz,
3071 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3072
3073 if (eRes != UR_NOTHING)
3074 {
3075 // range updated.
3076 ScRange aNew(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3077 rKeyRange = aNew;
3078 }
3079 }
3080}
3081
3083{
3084 RangeIndexType::iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
3085 if (it == maRanges.end())
3086 {
3087 // Not cached. Nothing to do.
3088 rRefs.clear();
3089 return;
3090 }
3091
3092 size_t nIndex = std::distance(maRanges.begin(), it);
3093 CachesType::iterator const itCache = m_Caches.find(nIndex);
3094 if (itCache == m_Caches.end())
3095 {
3096 OSL_FAIL("Cache pool and index pool out-of-sync !!!");
3097 rRefs.clear();
3098 return;
3099 }
3100
3101 ScDPCache& rCache = *itCache->second;
3102
3103 // Update the cache with new cell values. This will clear all group dimension info.
3104 rCache.InitFromDoc(mrDoc, rRange);
3105
3107 rRefs.swap(aRefs);
3108
3109 // Make sure to re-populate the group dimension info.
3110 setGroupItemsToCache(rCache, rRefs);
3111}
3112
3114{
3115 CachesType::iterator it = std::find_if(m_Caches.begin(), m_Caches.end(),
3116 [&p](const CachesType::value_type& rEntry) { return rEntry.second.get() == p; });
3117 if (it != m_Caches.end())
3118 {
3119 size_t idx = it->first;
3120 m_Caches.erase(it);
3121 maRanges[idx].SetInvalid();
3122 return true;
3123 }
3124 return false;
3125}
3126
3127const std::vector<ScRange>& ScDPCollection::SheetCaches::getAllRanges() const
3128{
3129 return maRanges;
3130}
3131
3133
3134bool ScDPCollection::NameCaches::hasCache(const OUString& rName) const
3135{
3136 return m_Caches.count(rName) != 0;
3137}
3138
3140 const OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData)
3141{
3142 CachesType::const_iterator const itr = m_Caches.find(rName);
3143 if (itr != m_Caches.end())
3144 // already cached.
3145 return itr->second.get();
3146
3147 ::std::unique_ptr<ScDPCache> pCache(new ScDPCache(mrDoc));
3148 pCache->InitFromDoc(mrDoc, rRange);
3149 if (pDimData)
3150 pDimData->WriteToCache(*pCache);
3151
3152 const ScDPCache *const p = pCache.get();
3153 m_Caches.insert(std::make_pair(rName, std::move(pCache)));
3154 return p;
3155}
3156
3158{
3159 CachesType::iterator const itr = m_Caches.find(rName);
3160 return itr != m_Caches.end() ? itr->second.get() : nullptr;
3161}
3162
3164{
3165 return m_Caches.size();
3166}
3167
3169 const OUString& rName, const ScRange& rRange, o3tl::sorted_vector<ScDPObject*>& rRefs)
3170{
3171 CachesType::iterator const itr = m_Caches.find(rName);
3172 if (itr == m_Caches.end())
3173 {
3174 rRefs.clear();
3175 return;
3176 }
3177
3178 ScDPCache& rCache = *itr->second;
3179 // Update the cache with new cell values. This will clear all group dimension info.
3180 rCache.InitFromDoc(mrDoc, rRange);
3181
3183 rRefs.swap(aRefs);
3184
3185 // Make sure to re-populate the group dimension info.
3186 setGroupItemsToCache(rCache, rRefs);
3187}
3188
3190{
3191 CachesType::iterator it = std::find_if(m_Caches.begin(), m_Caches.end(),
3192 [&p](const CachesType::value_type& rEntry) { return rEntry.second.get() == p; });
3193 if (it != m_Caches.end())
3194 {
3195 m_Caches.erase(it);
3196 return true;
3197 }
3198 return false;
3199}
3200
3201ScDPCollection::DBType::DBType(sal_Int32 nSdbType, OUString aDBName, OUString aCommand) :
3202 mnSdbType(nSdbType), maDBName(std::move(aDBName)), maCommand(std::move(aCommand)) {}
3203
3204bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& right) const
3205{
3206 return left < right;
3207}
3208
3210
3211bool ScDPCollection::DBCaches::hasCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) const
3212{
3213 DBType aType(nSdbType, rDBName, rCommand);
3214 CachesType::const_iterator const itr = m_Caches.find(aType);
3215 return itr != m_Caches.end();
3216}
3217
3219 sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
3220 const ScDPDimensionSaveData* pDimData)
3221{
3222 DBType aType(nSdbType, rDBName, rCommand);
3223 CachesType::const_iterator const itr = m_Caches.find(aType);
3224 if (itr != m_Caches.end())
3225 // already cached.
3226 return itr->second.get();
3227
3228 uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand);
3229 if (!xRowSet.is())
3230 return nullptr;
3231
3232 ::std::unique_ptr<ScDPCache> pCache(new ScDPCache(mrDoc));
3234 DBConnector aDB(*pCache, xRowSet, aFormat.GetNullDate());
3235 if (!aDB.isValid())
3236 return nullptr;
3237
3238 if (!pCache->InitFromDataBase(aDB))
3239 {
3240 // initialization failed.
3242 return nullptr;
3243 }
3244
3245 if (pDimData)
3246 pDimData->WriteToCache(*pCache);
3247
3248 ::comphelper::disposeComponent(xRowSet);
3249 const ScDPCache* p = pCache.get();
3250 m_Caches.insert(std::make_pair(aType, std::move(pCache)));
3251 return p;
3252}
3253
3255 sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
3256{
3257 DBType aType(nSdbType, rDBName, rCommand);
3258 CachesType::iterator const itr = m_Caches.find(aType);
3259 return itr != m_Caches.end() ? itr->second.get() : nullptr;
3260}
3261
3262uno::Reference<sdbc::XRowSet> ScDPCollection::DBCaches::createRowSet(
3263 sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand)
3264{
3265 uno::Reference<sdbc::XRowSet> xRowSet;
3266 try
3267 {
3270 UNO_QUERY);
3271
3272 uno::Reference<beans::XPropertySet> xRowProp(xRowSet, UNO_QUERY);
3273 OSL_ENSURE( xRowProp.is(), "can't get RowSet" );
3274 if (!xRowProp.is())
3275 {
3276 xRowSet.set(nullptr);
3277 return xRowSet;
3278 }
3279
3280 // set source parameters
3281
3282 xRowProp->setPropertyValue( SC_DBPROP_DATASOURCENAME, Any(rDBName) );
3283 xRowProp->setPropertyValue( SC_DBPROP_COMMAND, Any(rCommand) );
3284 xRowProp->setPropertyValue( SC_DBPROP_COMMANDTYPE, Any(nSdbType) );
3285
3286 uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY );
3287 if ( xExecute.is() )
3288 {
3289 uno::Reference<task::XInteractionHandler> xHandler(
3290 task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr),
3291 uno::UNO_QUERY_THROW);
3292 xExecute->executeWithCompletion( xHandler );
3293 }
3294 else
3295 xRowSet->execute();
3296
3297 return xRowSet;
3298 }
3299 catch ( const sdbc::SQLException& rError )
3300 {
3302 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
3303 VclMessageType::Info, VclButtonsType::Ok,
3304 rError.Message));
3305 xInfoBox->run();
3306 }
3307 catch ( uno::Exception& )
3308 {
3309 TOOLS_WARN_EXCEPTION( "sc", "Unexpected exception in database");
3310 }
3311
3312 xRowSet.set(nullptr);
3313 return xRowSet;
3314}
3315
3317 sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
3319{
3320 DBType aType(nSdbType, rDBName, rCommand);
3321 CachesType::iterator const it = m_Caches.find(aType);
3322 if (it == m_Caches.end())
3323 {
3324 // not cached.
3325 rRefs.clear();
3326 return;
3327 }
3328
3329 ScDPCache& rCache = *it->second;
3330
3331 uno::Reference<sdbc::XRowSet> xRowSet = createRowSet(nSdbType, rDBName, rCommand);
3332 if (!xRowSet.is())
3333 {
3334 rRefs.clear();
3335 return;
3336 }
3337
3339 DBConnector aDB(rCache, xRowSet, aFormat.GetNullDate());
3340 if (!aDB.isValid())
3341 return;
3342
3343 if (!rCache.InitFromDataBase(aDB))
3344 {
3345 // initialization failed.
3346 rRefs.clear();
3348 return;
3349 }
3350
3353 aRefs.swap(rRefs);
3354
3355 // Make sure to re-populate the group dimension info.
3356 setGroupItemsToCache(rCache, rRefs);
3357}
3358
3360{
3361 CachesType::iterator it = std::find_if(m_Caches.begin(), m_Caches.end(),
3362 [&p](const CachesType::value_type& rEntry) { return rEntry.second.get() == p; });
3363 if (it != m_Caches.end())
3364 {
3365 m_Caches.erase(it);
3366 return true;
3367 }
3368 return false;
3369}
3370
3372 mrDoc(rDocument),
3373 maSheetCaches(rDocument),
3374 maNameCaches(rDocument),
3375 maDBCaches(rDocument)
3376{
3377}
3378
3380 mrDoc(r.mrDoc),
3381 maSheetCaches(r.mrDoc),
3382 maNameCaches(r.mrDoc),
3383 maDBCaches(r.mrDoc)
3384{
3385}
3386
3388{
3389 maTables.clear();
3390}
3391
3392namespace {
3393
3397class MatchByTable
3398{
3399 SCTAB mnTab;
3400public:
3401 explicit MatchByTable(SCTAB nTab) : mnTab(nTab) {}
3402
3403 bool operator() (const std::unique_ptr<ScDPObject>& rObj) const
3404 {
3405 return rObj->GetOutRange().aStart.Tab() == mnTab;
3406 }
3407};
3408
3409}
3410
3412{
3413 if (!pDPObj)
3414 return STR_ERR_DATAPILOTSOURCE;
3415
3416 if (pDPObj->IsSheetData())
3417 {
3418 // data source is internal sheet.
3419 const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
3420 if (!pDesc)
3421 return STR_ERR_DATAPILOTSOURCE;
3422
3423 TranslateId pErrId = pDesc->CheckSourceRange();
3424 if (pErrId)
3425 return pErrId;
3426
3427 if (pDesc->HasRangeName())
3428 {
3429 // cache by named range
3431 if (rCaches.hasCache(pDesc->GetRangeName()))
3432 rCaches.updateCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), rRefs);
3433 else
3434 {
3435 // Not cached yet. Collect all tables that use this named
3436 // range as data source.
3437 GetAllTables(pDesc->GetRangeName(), rRefs);
3438 }
3439 }
3440 else
3441 {
3442 // cache by cell range
3444 if (rCaches.hasCache(pDesc->GetSourceRange()))
3445 rCaches.updateCache(pDesc->GetSourceRange(), rRefs);
3446 else
3447 {
3448 // Not cached yet. Collect all tables that use this range as
3449 // data source.
3450 GetAllTables(pDesc->GetSourceRange(), rRefs);
3451 }
3452 }
3453 }
3454 else if (pDPObj->IsImportData())
3455 {
3456 // data source is external database.
3457 const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
3458 if (!pDesc)
3459 return STR_ERR_DATAPILOTSOURCE;
3460
3462 if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
3463 rCaches.updateCache(
3464 pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
3465 else
3466 {
3467 // Not cached yet. Collect all tables that use this range as
3468 // data source.
3469 GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
3470 }
3471 }
3472 return {};
3473}
3474
3476{
3477 if (!pDPObj)
3478 return false;
3479
3480 const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
3481 if (!pSaveData)
3482 return false;
3483
3484 // Note: Unlike reloading cache, when modifying the group dimensions the
3485 // cache may not have all its references when this method is called.
3486 // Therefore, we need to always call GetAllTables to get its correct
3487 // references even when the cache exists. This may become a non-issue
3488 // if/when we implement loading and saving of pivot caches.
3489
3490 ScDPCache* pCache = nullptr;
3491
3492 if (pDPObj->IsSheetData())
3493 {
3494 // data source is internal sheet.
3495 const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
3496 if (!pDesc)
3497 return false;
3498
3499 if (pDesc->HasRangeName())
3500 {
3501 // cache by named range
3503 if (rCaches.hasCache(pDesc->GetRangeName()))
3504 pCache = rCaches.getExistingCache(pDesc->GetRangeName());
3505 else
3506 {
3507 // Not cached yet. Cache the source dimensions. Groups will
3508 // be added below.
3509 pCache = const_cast<ScDPCache*>(
3510 rCaches.getCache(pDesc->GetRangeName(), pDesc->GetSourceRange(), nullptr));
3511 }
3512 GetAllTables(pDesc->GetRangeName(), rRefs);
3513 }
3514 else
3515 {
3516 // cache by cell range
3518 if (rCaches.hasCache(pDesc->GetSourceRange()))
3519 pCache = rCaches.getExistingCache(pDesc->GetSourceRange());
3520 else
3521 {
3522 // Not cached yet. Cache the source dimensions. Groups will
3523 // be added below.
3524 pCache = const_cast<ScDPCache*>(
3525 rCaches.getCache(pDesc->GetSourceRange(), nullptr));
3526 }
3527 GetAllTables(pDesc->GetSourceRange(), rRefs);
3528 }
3529 }
3530 else if (pDPObj->IsImportData())
3531 {
3532 // data source is external database.
3533 const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc();
3534 if (!pDesc)
3535 return false;
3536
3538 if (rCaches.hasCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject))
3539 pCache = rCaches.getExistingCache(
3540 pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject);
3541 else
3542 {
3543 // Not cached yet. Cache the source dimensions. Groups will
3544 // be added below.
3545 pCache = const_cast<ScDPCache*>(
3546 rCaches.getCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, nullptr));
3547 }
3548 GetAllTables(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject, rRefs);
3549 }
3550
3551 if (!pCache)
3552 return false;
3553
3554 // Clear the existing group/field data from the cache, and rebuild it from the
3555 // dimension data.
3556 pCache->ClearAllFields();
3557 const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
3558 if (pDimData)
3559 pDimData->WriteToCache(*pCache);
3560 return true;
3561}
3562
3564{
3565 for (const std::unique_ptr<ScDPObject>& aTable : maTables)
3566 {
3567 const ScDPObject& rRefObj = *aTable;
3568
3569 if (&rRefObj == &rDPObj)
3570 continue;
3571
3572 if (rDPObj.IsSheetData()){
3573 if(!rRefObj.IsSheetData())
3574 continue;
3575
3576 const ScSheetSourceDesc* pDesc = rDPObj.GetSheetDesc();
3577 const ScSheetSourceDesc* pRefDesc = rRefObj.GetSheetDesc();
3578 if (pDesc == nullptr || pRefDesc == nullptr)
3579 continue;
3580
3581 if (pDesc->HasRangeName())
3582 {
3583 if (!pRefDesc->HasRangeName())
3584 continue;
3585
3586 if (pDesc->GetRangeName() == pRefDesc->GetRangeName())
3587 {
3588 *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
3589 return true;
3590 }
3591 }
3592 else
3593 {
3594 if (pRefDesc->HasRangeName())
3595 continue;
3596
3597 if (pDesc->GetSourceRange() == pRefDesc->GetSourceRange())
3598 {
3599 *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
3600 return true;
3601 }
3602 }
3603 }
3604 else if (rDPObj.IsImportData())
3605 {
3606 if (!rRefObj.IsImportData ())
3607 continue;
3608
3609 const ScImportSourceDesc* pDesc = rDPObj.GetImportSourceDesc();
3610 const ScImportSourceDesc* pRefDesc = rRefObj.GetImportSourceDesc();
3611 if (pDesc == nullptr || pRefDesc == nullptr)
3612 continue;
3613
3614 if (pDesc->aDBName == pRefDesc->aDBName &&
3615 pDesc->aObject == pRefDesc->aObject &&
3616 pDesc->GetCommandType() == pRefDesc->GetCommandType())
3617 {
3618 *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
3619 return true;
3620 }
3621
3622 }
3623 }
3624 return false;
3625}
3626
3627
3629{
3630 maTables.erase( std::remove_if(maTables.begin(), maTables.end(), MatchByTable(nTab)), maTables.end());
3631}
3632
3634 const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz )
3635{
3636 for (auto& rxTable : maTables)
3637 rxTable->UpdateReference(eUpdateRefMode, r, nDx, nDy, nDz);
3638
3639 // Update the source ranges of the caches.
3640 maSheetCaches.updateReference(eUpdateRefMode, r, nDx, nDy, nDz);
3641}
3642
3644{
3645 TablesType aAdded;
3646 for (const auto& rxTable : maTables)
3647 {
3648 const ScDPObject& rObj = *rxTable;
3649 ScRange aOutRange = rObj.GetOutRange();
3650 if (aOutRange.aStart.Tab() != nOld)
3651 continue;
3652
3653 ScAddress& s = aOutRange.aStart;
3654 ScAddress& e = aOutRange.aEnd;
3655 s.SetTab(nNew);
3656 e.SetTab(nNew);
3657 ScDPObject* pNew = new ScDPObject(rObj);
3658 pNew->SetOutRange(aOutRange);
3659 mrDoc.ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
3660 aAdded.push_back(std::unique_ptr<ScDPObject>(pNew));
3661 }
3662
3663 std::move(aAdded.begin(), aAdded.end(), std::back_inserter(maTables));
3664}
3665
3667{
3668 return std::equal(maTables.begin(), maTables.end(), r.maTables.begin(), r.maTables.end(),
3669 [](const TablesType::value_type& a, const TablesType::value_type& b) { return a->RefsEqual(*b); });
3670}
3671
3673{
3674 if ( maTables.size() == r.maTables.size() )
3675 {
3676 //TODO: assert equal names?
3677 TablesType::iterator itr2 = r.maTables.begin();
3678 for (const auto& rxTable : maTables)
3679 {
3680 rxTable->WriteRefsTo(**itr2);
3681 ++itr2;
3682 }
3683 }
3684 else
3685 {
3686 // #i8180# If data pilot tables were deleted with their sheet,
3687 // this collection contains extra entries that must be restored.
3688 // Matching objects are found by their names.
3689 size_t nSrcSize = maTables.size();
3690 size_t nDestSize = r.maTables.size();
3691 OSL_ENSURE( nSrcSize >= nDestSize, "WriteRefsTo: missing entries in document" );
3692 for (size_t nSrcPos = 0; nSrcPos < nSrcSize; ++nSrcPos)
3693 {
3694 const ScDPObject& rSrcObj = *maTables[nSrcPos];
3695 const OUString& aName = rSrcObj.GetName();
3696 bool bFound = false;
3697 for (size_t nDestPos = 0; nDestPos < nDestSize && !bFound; ++nDestPos)
3698 {
3699 ScDPObject& rDestObj = *r.maTables[nDestPos];
3700 if (rDestObj.GetName() == aName)
3701 {
3702 rSrcObj.WriteRefsTo(rDestObj); // found object, copy refs
3703 bFound = true;
3704 }
3705 }
3706
3707 if (!bFound)
3708 {
3709 // none found, re-insert deleted object (see ScUndoDataPilot::Undo)
3710 r.InsertNewTable(std::make_unique<ScDPObject>(rSrcObj));
3711 }
3712 }
3713 OSL_ENSURE( maTables.size() == r.maTables.size(), "WriteRefsTo: couldn't restore all entries" );
3714 }
3715}
3716
3718{
3719 return maTables.size();
3720}
3721
3723{
3724 return *maTables[nIndex];
3725}
3726
3727const ScDPObject& ScDPCollection::operator [](size_t nIndex) const
3728{
3729 return *maTables[nIndex];
3730}
3731
3732ScDPObject* ScDPCollection::GetByName(std::u16string_view rName) const
3733{
3734 for (std::unique_ptr<ScDPObject> const & pObject : maTables)
3735 {
3736 if (pObject->GetName() == rName)
3737 return pObject.get();
3738 }
3739
3740 return nullptr;
3741}
3742
3744{
3745 size_t n = maTables.size();
3746 for (size_t nAdd = 0; nAdd <= n; ++nAdd) // nCount+1 tries
3747 {
3748 OUString aNewName = "DataPilot" + OUString::number(1 + nAdd);
3749 if (std::none_of(maTables.begin(), maTables.end(),
3750 [&aNewName](const TablesType::value_type& rxObj) { return rxObj->GetName() == aNewName; }))
3751 return aNewName; // found unused Name
3752 }
3753 return OUString(); // should not happen
3754}
3755
3757{
3758 const ScRange& rOutRange = pDPObject->GetOutRange();
3759 const ScAddress& s = rOutRange.aStart;
3760 const ScAddress& e = rOutRange.aEnd;
3761 mrDoc.RemoveFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
3762
3763 auto funcRemoveCondition = [pDPObject] (std::unique_ptr<ScDPObject> const & pCurrent)
3764 {
3765 return pCurrent.get() == pDPObject;
3766 };
3767
3768 maTables.erase(std::remove_if(maTables.begin(), maTables.end(), funcRemoveCondition), maTables.end());
3769}
3770
3771ScDPObject* ScDPCollection::InsertNewTable(std::unique_ptr<ScDPObject> pDPObj)
3772{
3773 const ScRange& rOutRange = pDPObj->GetOutRange();
3774 const ScAddress& s = rOutRange.aStart;
3775 const ScAddress& e = rOutRange.aEnd;
3776 mrDoc.ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), ScMF::DpTable);
3777
3778 maTables.push_back(std::move(pDPObj));
3779 return maTables.back().get();
3780}
3781
3782bool ScDPCollection::HasTable(const ScDPObject* pDPObj) const
3783{
3784 for (const std::unique_ptr<ScDPObject>& aTable : maTables)
3785 {
3786 if (aTable.get() == pDPObj)
3787 {
3788 return true;
3789 }
3790 }
3791 return false;
3792}
3793
3795{
3796 return maSheetCaches;
3797}
3798
3800{
3801 return maSheetCaches;
3802}
3803
3805{
3806 return maNameCaches;
3807}
3808
3810{
3811 return maNameCaches;
3812}
3813
3815{
3816 return maDBCaches;
3817}
3818
3820{
3821 return maDBCaches;
3822}
3823
3825{
3826 return std::for_each(maTables.begin(), maTables.end(), AccumulateOutputRanges(nTab)).getRanges();
3827}
3828
3830{
3831 return std::any_of(maTables.begin(), maTables.end(), FindIntersectingTableByColumns(nCol1, nCol2, nRow, nTab));
3832}
3833
3834bool ScDPCollection::IntersectsTableByRows( SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab ) const
3835{
3836 return std::any_of(maTables.begin(), maTables.end(), FindIntersectingTableByRows(nCol, nRow1, nRow2, nTab));
3837}
3838
3839bool ScDPCollection::HasTable( const ScRange& rRange ) const
3840{
3841 return std::any_of(maTables.begin(), maTables.end(), FindIntersectingTable(rRange));
3842}
3843
3844#if DEBUG_PIVOT_TABLE
3845
3846namespace {
3847
3848struct DumpTable
3849{
3850 void operator() (const std::unique_ptr<ScDPObject>& rObj) const
3851 {
3852 cout << "-- '" << rObj->GetName() << "'" << endl;
3853 ScDPSaveData* pSaveData = rObj->GetSaveData();
3854 if (!pSaveData)
3855 return;
3856
3857 pSaveData->Dump();
3858
3859 cout << endl; // blank line
3860 }
3861};
3862
3863}
3864
3865void ScDPCollection::DumpTables() const
3866{
3867 std::for_each(maTables.begin(), maTables.end(), DumpTable());
3868}
3869
3870#endif
3871
3873{
3874 if (maSheetCaches.remove(pCache))
3875 // sheet cache removed.
3876 return;
3877
3878 if (maNameCaches.remove(pCache))
3879 // named range cache removed.
3880 return;
3881
3882 if (maDBCaches.remove(pCache))
3883 // database cache removed.
3884 return;
3885}
3886
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 has a range name as its source.
3903 continue;
3904
3905 if (pDesc->GetSourceRange() != rSrcRange)
3906 // Different source range.
3907 continue;
3908
3909 aRefs.insert(const_cast<ScDPObject*>(&rObj));
3910 }
3911
3912 rRefs.swap(aRefs);
3913}
3914
3915void ScDPCollection::GetAllTables(std::u16string_view rSrcName, o3tl::sorted_vector<ScDPObject*>& rRefs) const
3916{
3918 for (const auto& rxTable : maTables)
3919 {
3920 const ScDPObject& rObj = *rxTable;
3921 if (!rObj.IsSheetData())
3922 // Source is not a sheet range.
3923 continue;
3924
3925 const ScSheetSourceDesc* pDesc = rObj.GetSheetDesc();
3926 if (!pDesc)
3927 continue;
3928
3929 if (!pDesc->HasRangeName())
3930 // This table probably has a sheet range as its source.
3931 continue;
3932
3933 if (pDesc->GetRangeName() != rSrcName)
3934 // Different source name.
3935 continue;
3936
3937 aRefs.insert(const_cast<ScDPObject*>(&rObj));
3938 }
3939
3940 rRefs.swap(aRefs);
3941}
3942
3944 sal_Int32 nSdbType, std::u16string_view rDBName, std::u16string_view rCommand,
3946{
3948 for (const auto& rxTable : maTables)
3949 {
3950 const ScDPObject& rObj = *rxTable;
3951 if (!rObj.IsImportData())
3952 // Source data is not a database.
3953 continue;
3954
3955 const ScImportSourceDesc* pDesc = rObj.GetImportSourceDesc();
3956 if (!pDesc)
3957 continue;
3958
3959 if (pDesc->aDBName != rDBName || pDesc->aObject != rCommand || pDesc->GetCommandType() != nSdbType)
3960 // Different database source.
3961 continue;
3962
3963 aRefs.insert(const_cast<ScDPObject*>(&rObj));
3964 }
3965
3966 rRefs.swap(aRefs);
3967}
3968
3970{
3971 if (left.mnSdbType != right.mnSdbType)
3972 return left.mnSdbType < right.mnSdbType;
3973
3974 if (left.maDBName != right.maDBName)
3975 return left.maDBName < right.maDBName;
3976
3977 return left.maCommand < right.maCommand;
3978}
3979
3980/* 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, const ILibreOfficeKitNotifier *pNotifier=nullptr)
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:361
static css::uno::Reference< css::sdbc::XRowSet > createRowSet(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand)
Definition: dpobject.cxx:3262
const ScDPCache * getCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand, const ScDPDimensionSaveData *pDimData)
Definition: dpobject.cxx:3218
bool remove(const ScDPCache *p)
Definition: dpobject.cxx:3359
void updateCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3316
ScDPCache * getExistingCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand)
Definition: dpobject.cxx:3254
bool hasCache(sal_Int32 nSdbType, const OUString &rDBName, const OUString &rCommand) const
Definition: dpobject.cxx:3211
DBCaches(ScDocument &rDoc)
Definition: dpobject.cxx:3209
Data caches for range name based source data.
Definition: dpobject.hxx:321
bool hasCache(const OUString &rName) const
Definition: dpobject.cxx:3134
ScDPCache * getExistingCache(const OUString &rName)
Definition: dpobject.cxx:3157
const ScDPCache * getCache(const OUString &rName, const ScRange &rRange, const ScDPDimensionSaveData *pDimData)
Definition: dpobject.cxx:3139
void updateCache(const OUString &rName, const ScRange &rRange, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3168
bool remove(const ScDPCache *p)
Definition: dpobject.cxx:3189
NameCaches(ScDocument &rDoc)
Definition: dpobject.cxx:3132
Stores and manages all caches from internal sheets.
Definition: dpobject.hxx:292
SC_DLLPUBLIC const std::vector< ScRange > & getAllRanges() const
Definition: dpobject.cxx:3127
SC_DLLPUBLIC size_t size() const
Definition: dpobject.cxx:3046
bool hasCache(const ScRange &rRange) const
Definition: dpobject.cxx:2946
bool remove(const ScDPCache *p)
Definition: dpobject.cxx:3113
const ScDPCache * getCache(const ScRange &rRange, const ScDPDimensionSaveData *pDimData)
Definition: dpobject.cxx:2958
SC_DLLPUBLIC ScDPCache * getExistingCache(const ScRange &rRange)
Definition: dpobject.cxx:3008
SheetCaches(ScDocument &rDoc)
Definition: dpobject.cxx:2915
void updateReference(UpdateRefMode eMode, const ScRange &r, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: dpobject.cxx:3051
void updateCache(const ScRange &rRange, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3082
bool RefsEqual(const ScDPCollection &r) const
Definition: dpobject.cxx:3666
ScDocument & mrDoc
Definition: dpobject.hxx:448
void WriteRefsTo(ScDPCollection &r) const
Definition: dpobject.cxx:3672
SC_DLLPUBLIC ScDPObject * InsertNewTable(std::unique_ptr< ScDPObject > pDPObj)
Definition: dpobject.cxx:3771
bool IntersectsTableByColumns(SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab) const
Definition: dpobject.cxx:3829
SheetCaches maSheetCaches
Definition: dpobject.hxx:450
SC_DLLPUBLIC SheetCaches & GetSheetCaches()
Definition: dpobject.cxx:3794
void FreeTable(const ScDPObject *pDPObj)
Definition: dpobject.cxx:3756
void GetAllTables(const ScRange &rSrcRange, o3tl::sorted_vector< ScDPObject * > &rRefs) const
Definition: dpobject.cxx:3887
DBCaches & GetDBCaches()
Definition: dpobject.cxx:3814
SC_DLLPUBLIC size_t GetCount() const
Definition: dpobject.cxx:3717
void RemoveCache(const ScDPCache *pCache)
Only to be called from ScDPCache::RemoveReference().
Definition: dpobject.cxx:3872
DBCaches maDBCaches
Definition: dpobject.hxx:452
void CopyToTab(SCTAB nOld, SCTAB nNew)
Definition: dpobject.cxx:3643
ScDPObject * GetByName(std::u16string_view rName) const
Definition: dpobject.cxx:3732
SC_DLLPUBLIC ScDPObject & operator[](size_t nIndex)
Definition: dpobject.cxx:3722
TranslateId ReloadCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3411
friend class ScDPCache
Definition: dpobject.hxx:285
bool IntersectsTableByRows(SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab) const
Definition: dpobject.cxx:3834
ScDPCollection(ScDocument &rDocument)
Definition: dpobject.cxx:3371
ScRangeList GetAllTableRanges(SCTAB nTab) const
Definition: dpobject.cxx:3824
void DeleteOnTab(SCTAB nTab)
Definition: dpobject.cxx:3628
TablesType maTables
Definition: dpobject.hxx:449
void UpdateReference(UpdateRefMode eUpdateRefMode, const ScRange &r, SCCOL nDx, SCROW nDy, SCTAB nDz)
Definition: dpobject.cxx:3633
OUString CreateNewName() const
Create a new name that's not yet used by any existing data pilot objects.
Definition: dpobject.cxx:3743
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject &rDPObj, const ScDPDimensionSaveData **pGroups) const
Definition: dpobject.cxx:3563
std::vector< std::unique_ptr< ScDPObject > > TablesType
Definition: dpobject.hxx:446
NameCaches & GetNameCaches()
Definition: dpobject.cxx:3804
bool ReloadGroupsInCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3475
NameCaches maNameCaches
Definition: dpobject.hxx:451
SC_DLLPUBLIC bool HasTable(const ScDPObject *pDPObj) const
Definition: dpobject.cxx:3782
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:2513
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:2825
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:2530
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:2745
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:2770
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:2644
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:2787
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:2539
void GetFieldIdsNames(css::sheet::DataPilotFieldOrientation nOrient, std::vector< tools::Long > &rIndices, std::vector< OUString > &rNames)
Definition: dpobject.cxx:2485
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:1698
std::unordered_map< OUString, size_t > DimOrderType
Definition: dpsave.hxx:237
void Dump() const
ScDPSaveDimension * DuplicateDimension(std::u16string_view rName)
Definition: dpsave.cxx:889
SC_DLLPUBLIC ScDPSaveDimension * GetDataLayoutDimension()
Definition: dpsave.cxx:870
const ScDPDimensionSaveData * GetExistingDimensionData() const
Definition: dpsave.hxx:353
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
Definition: dpsave.cxx:838
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:3112
SC_DLLPUBLIC bool RemoveFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
Definition: document.cxx:4980
SC_DLLPUBLIC bool ApplyFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
Definition: document.cxx:4970
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
Definition: document.cxx:1920
bool IsBlockEmpty(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:5288
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4684
static SC_DLLPUBLIC ::utl::TransliterationWrapper & GetTransliteration()
Definition: global.cxx:1026
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:560
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1064
::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:3969
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
OUString sName
ScGeneralFunction
the css::sheet::GeneralFunction enum is extended by constants in GeneralFunction2,...
UpdateRefMode
Definition: global.hxx:301
ScSubTotalFunc
Definition: global.hxx:860
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
@ 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:3204
Defines connection type to external data source.
Definition: dpobject.hxx:345
DBType(sal_Int32 nSdbType, OUString aDBName, OUString aCommand)
Definition: dpobject.cxx:3201
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
constexpr OUStringLiteral SC_UNO_DP_SORTING
Definition: unonames.hxx:634
constexpr OUStringLiteral SC_UNO_DP_COLGRAND
Definition: unonames.hxx:603
constexpr OUStringLiteral SC_UNO_DP_POSITION
Definition: unonames.hxx:609
constexpr OUStringLiteral SC_UNO_DP_REPEATEMPTY
Definition: unonames.hxx:621
constexpr OUStringLiteral SC_UNO_DP_ISDATALAYOUT
Definition: unonames.hxx:607
constexpr OUStringLiteral SC_UNO_DP_IGNOREEMPTY
Definition: unonames.hxx:620
constexpr OUStringLiteral SC_UNO_DP_SUBTOTAL2
Definition: unonames.hxx:615
constexpr OUStringLiteral SC_UNO_DP_LAYOUTNAME
Definition: unonames.hxx:627
constexpr OUStringLiteral SC_UNO_DP_REPEATITEMLABELS
Definition: unonames.hxx:617
constexpr OUStringLiteral SC_UNO_DP_FUNCTION2
Definition: unonames.hxx:611
constexpr OUStringLiteral SC_UNO_DP_ORIGINAL
Definition: unonames.hxx:605
constexpr OUStringLiteral SC_UNO_DP_ROWGRAND
Definition: unonames.hxx:604
constexpr OUStringLiteral SC_UNO_DP_USEDHIERARCHY
Definition: unonames.hxx:612
constexpr OUStringLiteral SC_UNO_DP_ORIENTATION
Definition: unonames.hxx:608
constexpr OUStringLiteral SC_UNO_DP_FIELD_SUBTOTALNAME
Definition: unonames.hxx:628
constexpr OUStringLiteral SC_UNO_DP_ISVISIBLE
Definition: unonames.hxx:618
constexpr OUStringLiteral SC_UNO_DP_SHOWDETAILS
Definition: unonames.hxx:619
constexpr OUStringLiteral SC_UNO_DP_SHOWEMPTY
Definition: unonames.hxx:616
constexpr OUStringLiteral SC_UNO_DP_ORIGINAL_POS
Definition: unonames.hxx:606
constexpr OUStringLiteral SC_UNO_DP_LAYOUT
Definition: unonames.hxx:636
constexpr OUStringLiteral SC_UNO_DP_REFVALUE
Definition: unonames.hxx:633
constexpr OUStringLiteral SC_UNO_DP_AUTOSHOW
Definition: unonames.hxx:635
constexpr OUStringLiteral SC_UNO_DP_FLAGS
Definition: unonames.hxx:631
sal_uInt64 left
std::unique_ptr< char[]> aBuffer
@ TABLE
Definition: xmldpimp.hxx:43
SvNumFormatType