24 #include <unonames.hxx>
31 #include <osl/diagnose.h>
34 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
35 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
36 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
37 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
38 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
39 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
40 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
41 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
42 #include <com/sun/star/sheet/XMembersSupplier.hpp>
43 #include <com/sun/star/container/XNamed.hpp>
44 #include <com/sun/star/util/XCloneable.hpp>
47 #include <unordered_map>
52 using ::std::unique_ptr;
54 #define SC_DPSAVEMODE_DONTKNOW 2
57 const OUString& rName,
bool bValue )
61 xProp->setPropertyValue( rName,
uno::Any( bValue ) );
73 mpLayoutName( r.mpLayoutName ),
74 nVisibleMode( r.nVisibleMode ),
75 nShowDetailsMode( r.nShowDetailsMode )
135 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY );
136 OSL_ENSURE( xMembProp.is(),
"no properties at member" );
137 if ( !xMembProp.is() )
153 if ( nPosition >= 0 )
161 std::string aIndent(nIndent*4,
' ');
162 cout << aIndent <<
"* member name: '" <<
aName <<
"'" <<
endl;
164 cout << aIndent <<
" + layout name: ";
171 cout << aIndent <<
" + visibility: ";
183 bIsDataLayout( bDataLayout ),
185 nOrientation(
sheet::DataPilotFieldOrientation_HIDDEN ),
187 nUsedHierarchy( -1 ),
189 bRepeatItemLabels( false ),
190 bSubTotalDefault( true )
196 mpLayoutName( r.mpLayoutName ),
197 mpSubtotalName( r.mpSubtotalName ),
198 bIsDataLayout( r.bIsDataLayout ),
199 bDupFlag( r.bDupFlag ),
200 nOrientation( r.nOrientation ),
201 nFunction( r.nFunction ),
202 nUsedHierarchy( r.nUsedHierarchy ),
203 nShowEmptyMode( r.nShowEmptyMode ),
204 bRepeatItemLabels( r.bRepeatItemLabels ),
205 bSubTotalDefault( r.bSubTotalDefault ),
206 maSubTotalFuncs( r.maSubTotalFuncs )
210 const OUString& rName = pMem->
GetName();
211 std::unique_ptr<ScDPSaveMember> pNew(
new ScDPSaveMember( *pMem ));
294 const OUString & rName = pMember->GetName();
296 auto tmp = pMember.get();
304 aExisting->second = std::move(pMember);
371 if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
374 const std::optional<OUString> & pLayoutName = pMem->GetLayoutName();
375 return pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName);
381 mpLayoutName = rName;
391 mpLayoutName.reset();
405 pSortInfo.reset(
new sheet::DataPilotFieldSortInfo(*pNew) );
413 pAutoShowInfo.reset(
new sheet::DataPilotFieldAutoShowInfo(*pNew) );
421 pLayoutInfo.reset(
new sheet::DataPilotFieldLayoutInfo(*pNew) );
433 bool bVisible = !pPage || pMem->GetName() == *pPage;
434 pMem->SetIsVisible(bVisible);
443 return (*it)->GetName();
452 return res->second.get();
460 return res->second.get();
463 maMemberHash[rName] = std::unique_ptr<ScDPSaveMember>(pNew);
479 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY );
480 OSL_ENSURE( xDimProp.is(),
"no properties at dimension" );
485 sheet::DataPilotFieldOrientation eOrient =
nOrientation;
488 sal_Int16 eFunc =
static_cast<sal_Int16
>(
nFunction);
517 uno::Reference<container::XIndexAccess> xHiers;
518 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY );
519 if ( xHierSupp.is() )
521 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
523 nHierCount = xHiers->getCount();
526 bool bHasHiddenMember =
false;
528 for (
tools::Long nHier=0; nHier<nHierCount; nHier++)
531 uno::Reference<container::XIndexAccess> xLevels;
532 uno::Reference<sheet::XLevelsSupplier> xLevSupp(xHiers->getByIndex(nHier), uno::UNO_QUERY);
535 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels();
537 nLevCount = xLevels->getCount();
542 uno::Reference<uno::XInterface> xLevel(xLevels->getByIndex(nLev), uno::UNO_QUERY);
543 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY );
544 OSL_ENSURE( xLevProp.is(),
"no properties at level" );
575 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY );
576 if ( xMembSupp.is() )
578 uno::Reference<sheet::XMembersAccess> xMembers = xMembSupp->getMembers();
581 sal_Int32 nPosition = -1;
587 if (!pMember->GetIsVisible())
588 bHasHiddenMember =
true;
589 OUString aMemberName = pMember->GetName();
590 if ( xMembers->hasByName( aMemberName ) )
592 uno::Reference<uno::XInterface> xMemberInt(
593 xMembers->getByName(aMemberName), uno::UNO_QUERY);
594 pMember->WriteToSource( xMemberInt, nPosition );
596 if ( nPosition >= 0 )
615 const OUString& rMemName = pMem->GetName();
616 auto itr = rData.find(rMemName);
617 if (itr != rData.end())
618 pMem->SetIsVisible(itr->second);
625 [](
const ScDPSaveMember* pMem) {
return !pMem->GetIsVisible(); });
633 if (rMembers.count(pMem->GetName()))
636 aNew.push_back(pMem);
644 maMemberList.swap(aNew);
651 static const char* pOrientNames[] = {
"hidden",
"column",
"row",
"page",
"data" };
652 std::string aIndent(nIndent*4,
' ');
654 cout << aIndent <<
"* dimension name: '" <<
aName <<
"'" << endl;
656 cout << aIndent <<
" + orientation: ";
663 cout << aIndent <<
" + layout name: ";
665 cout <<
"'" << *mpLayoutName <<
"'";
670 cout << aIndent <<
" + subtotal name: ";
677 cout << aIndent <<
" + is data layout: " << (
bIsDataLayout ?
"yes" :
"no") << endl;
678 cout << aIndent <<
" + is duplicate: " << (
bDupFlag ?
"yes" :
"no") << endl;
682 pMem->Dump(nIndent+1);
695 bFilterButton( true ),
697 mbDimensionMembersBuilt(false)
702 nColumnGrandMode( r.nColumnGrandMode ),
703 nRowGrandMode( r.nRowGrandMode ),
704 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
705 nRepeatEmptyMode( r.nRepeatEmptyMode ),
706 bFilterButton( r.bFilterButton ),
707 bDrillDown( r.bDrillDown ),
708 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
709 mpGrandTotalName(r.mpGrandTotalName)
716 m_DimList.push_back(std::make_unique<ScDPSaveDimension>(*it));
777 class DimOrderInserter
785 size_t nRank = mrNames.size();
786 mrNames.emplace(pDim->
GetName(), nRank);
797 std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
801 std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(*
mpDimOrder));
802 std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(*
mpDimOrder));
808 sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims)
const
810 std::vector<const ScDPSaveDimension*> aDims;
817 aDims.push_back(&rDim);
829 m_DimList.push_back(std::unique_ptr<ScDPSaveDimension>(pDim));
838 if (iter->GetName() == rName && !iter->IsDataLayout() )
849 if (iter->GetName() == rName && !iter->IsDataLayout() )
859 if (iter->GetName() == rName && !iter->IsDataLayout() )
879 if ( iter->IsDataLayout() )
901 [&rName](
const std::unique_ptr<ScDPSaveDimension>& rxDim) {
902 return rxDim->GetName() == rName && !rxDim->IsDataLayout(); });
924 [&nOrientation](
const std::unique_ptr<ScDPSaveDimension>& rxDim) {
925 return rxDim->GetOrientation() == nOrientation && !rxDim->IsDataLayout(); });
936 if (iter->GetOrientation() == eOrientation && !iter->IsDataLayout())
948 if (iter->GetOrientation() == sheet::DataPilotFieldOrientation_DATA)
962 [&pDim](
const std::unique_ptr<ScDPSaveDimension>& rxDim) {
return pDim == rxDim.get(); });
973 [&nOrient, &nNew](
const std::unique_ptr<ScDPSaveDimension>& rxDim) {
974 if (rxDim->GetOrientation() == nOrient )
979 m_DimList.insert(iterInsert, std::unique_ptr<ScDPSaveDimension>(pDim));
1015 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1018 for (
tools::Long nIntDim=0; nIntDim<nIntCount; nIntDim++)
1020 uno::Reference<beans::XPropertySet> xDimProp(xIntDims->getByIndex(nIntDim), uno::UNO_QUERY);
1035 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY );
1036 SAL_WARN_IF( !xSourceProp.is(),
"sc.core",
"no properties at source" );
1037 if ( xSourceProp.is() )
1051 catch(uno::Exception&)
1057 if (pGrandTotalName)
1067 SAL_INFO(
"sc.core",
"ScDPSaveData::WriteToSource");
1071 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
1077 OUString
aName = rxDim->GetName();
1082 bool bData = rxDim->IsDataLayout();
1086 bool bFound =
false;
1087 for (
tools::Long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++)
1089 uno::Reference<uno::XInterface> xIntDim(xIntDims->getByIndex(nIntDim),
1093 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY );
1094 if ( xDimProp.is() )
1103 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY );
1104 if (xDimName.is() && xDimName->getName() == aCoreName)
1110 if (rxDim->GetDupFlag())
1112 uno::Reference<util::XCloneable> xCloneable(xIntDim, uno::UNO_QUERY);
1113 SAL_WARN_IF(!xCloneable.is(),
"sc.core",
"cannot clone dimension");
1114 if (xCloneable.is())
1116 uno::Reference<util::XCloneable> xNew = xCloneable->createClone();
1117 uno::Reference<container::XNamed> xNewName(xNew, uno::UNO_QUERY);
1120 xNewName->setName(aName);
1121 rxDim->WriteToSource(xNew);
1126 rxDim->WriteToSource( xIntDim );
1129 SAL_WARN_IF(!bFound,
"sc.core",
"WriteToSource: Dimension not found: " + aName +
".");
1132 if ( xSourceProp.is() )
1142 catch(uno::Exception
const &)
1152 if (iter->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !iter->IsDataLayout())
1172 while ( pExistingGroup )
1181 pDeletedNames->push_back(aGroupDimName);
1184 pExistingGroup =
pDimensionData->GetGroupDimForBase(rSrcDimName);
1186 if ( pExistingGroup && pExistingGroup->
GetGroupDimName() == aGroupDimName )
1189 OSL_FAIL(
"couldn't remove group dimension");
1190 pExistingGroup =
nullptr;
1216 typedef std::unordered_map<OUString, tools::Long> NameIndexMap;
1222 NameIndexMap::const_iterator itrEnd = aMap.end();
1226 const OUString& rDimName = iter->GetName();
1227 if (rDimName.isEmpty())
1231 NameIndexMap::const_iterator itr = aMap.find(rDimName);
1238 size_t nMemberCount = rMembers.size();
1239 for (
size_t j = 0; j < nMemberCount; ++j)
1243 if (iter->GetExistingMemberByName(aMemName))
1247 unique_ptr<ScDPSaveMember> pNewMember(
new ScDPSaveMember(aMemName));
1248 pNewMember->SetIsVisible(
true);
1249 iter->AddMember(std::move(pNewMember));
1258 typedef std::unordered_map<OUString, tools::Long> NameIndexMap;
1266 NameIndexMap::const_iterator itMapEnd = aMap.end();
1270 const OUString& rDimName = it->GetName();
1271 if (rDimName.isEmpty())
1275 NameIndexMap::const_iterator itMap = aMap.find(rDimName);
1276 if (itMap == itMapEnd)
1283 size_t nMemberCount = rMembers.size();
1284 for (
size_t j = 0; j < nMemberCount; ++j)
1288 aMemNames.insert(aMemName);
1291 it->RemoveObsoleteMembers(aMemNames);
1304 #if DUMP_PIVOT_TABLE
1333 OUString aCoreName = rName;
1357 m_DimList.push_back(std::unique_ptr<ScDPSaveDimension>(pNew));
SC_DLLPUBLIC bool HasInvisibleMember(std::u16string_view rDimName) const
Check whether a dimension has one or more invisible members.
SC_DLLPUBLIC void SetRepeatIfEmpty(bool bSet)
const OUString & GetGroupDimName() const
static SC_DLLPUBLIC OUString createDuplicateDimensionName(const OUString &rOriginal, size_t nDupCount)
#define SC_UNO_DP_FIELD_SUBTOTALNAME
void WriteToSource(const css::uno::Reference< css::uno::XInterface > &xMember, sal_Int32 nPosition)
const std::optional< OUString > & GetLayoutName() const
#define SC_UNO_DP_IGNOREEMPTY
void BuildAllDimensionMembers(ScDPTableData *pData)
css::sheet::DataPilotFieldOrientation nOrientation
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
ScDPSaveMember * GetMemberByName(const OUString &rName)
Get a member object by its name.
void SetOrientation(css::sheet::DataPilotFieldOrientation nNew)
#define SC_UNO_DP_REFVALUE
bool operator==(const ScDPSaveMember &r) const
SC_DLLPUBLIC const std::optional< OUString > & GetGrandTotalName() const
std::unique_ptr< DimOrderType > mpDimOrder
void RemoveObsoleteMembers(const MemberSetType &rMembers)
bool IsMemberNameInUse(const OUString &rName) const
std::optional< OUString > mpLayoutName
css::sheet::DataPilotFieldOrientation GetOrientation() const
void CheckDuplicateName(ScDPSaveDimension &rDim)
std::unique_ptr< css::sheet::DataPilotFieldSortInfo > pSortInfo
sal_uInt16 nShowDetailsMode
std::unordered_map< OUString, std::unique_ptr< ScDPSaveMember > > maMemberHash
SC_DLLPUBLIC ScDPDimensionSaveData * GetDimensionData()
#define SC_UNO_DP_COLGRAND
#define SC_UNO_DP_SORTING
static void lcl_SetBoolProperty(const uno::Reference< beans::XPropertySet > &xProp, const OUString &rName, bool bValue)
#define SC_UNO_DP_REPEATEMPTY
ScDPSaveMember * GetExistingMemberByName(const OUString &rName)
#define SC_UNO_DP_POSITION
virtual const std::vector< SCROW > & GetColumnEntries(sal_Int32 nColumn)
void SetName(const OUString &rNew)
void AddDimension(ScDPSaveDimension *pDim)
bool HasInvisibleMember() const
SC_DLLPUBLIC void SetIsVisible(bool bSet)
#define SC_UNO_DP_GRANDTOTAL_NAME
std::unordered_set< OUString > MemberSetType
ScDPSaveData & operator=(const ScDPSaveData &r)
exports com.sun.star. sheet
std::optional< OUString > mpGrandTotalName
SC_DLLPUBLIC void GetAllDimensionsByOrientation(css::sheet::DataPilotFieldOrientation eOrientation, std::vector< const ScDPSaveDimension * > &rDims) const
Get all dimensions in a given orientation.
virtual const ScDPItemData * GetMemberById(sal_Int32 nDim, sal_Int32 nId)
#define SC_UNO_DP_LAYOUTNAME
HashMap_OWString_Interface aMap
ScGeneralFunction nFunction
void RemoveDimensionByName(const OUString &rName)
bool operator==(const ScDPSaveDimension &r) const
bool operator==(const ScDPSaveData &r) const
const DimOrderType & GetDimensionSortOrder() const
Get sort order map to sort row and column dimensions in order of appearance.
const OUString & GetName() const
void SetMemberPosition(const OUString &rName, sal_Int32 nNewPos)
bool HasShowEmpty() const
std::unordered_map< OUString, size_t > DimOrderType
void SetFunction(ScGeneralFunction nNew)
std::vector< ScDPSaveMember * > MemberList
#define SC_UNO_DP_REPEATITEMLABELS
ScDPSaveDimension * GetInnermostDimension(css::sheet::DataPilotFieldOrientation nOrientation)
void SetLayoutName(const OUString &rName)
std::unique_ptr< ScDPDimensionSaveData > pDimensionData
keep track of number of duplicates in each name.
void SyncAllDimensionMembers(ScDPTableData *pData)
ScDPSaveDimension * GetFirstDimension(css::sheet::DataPilotFieldOrientation eOrientation)
SC_DLLPUBLIC tools::Long GetDataDimensionCount() const
#define TOOLS_WARN_EXCEPTION(area, stream)
void RemoveDuplicateNameCount(const OUString &rName)
SC_DLLPUBLIC ScDPSaveDimension * GetNewDimensionByName(const OUString &rName)
When assigning a string value, you can also assign an interned string whose life-cycle is managed by ...
#define SC_UNO_DP_FUNCTION2
void SetCurrentPage(const OUString *pPage)
DupNameCountType maDupNameCounts
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
ScDPSaveDimension * AppendNewDimension(const OUString &rName, bool bDataLayout)
Append a new original dimension.
SC_DLLPUBLIC ScDPSaveDimension * GetExistingDataLayoutDimension() const
virtual OUString getDimensionName(sal_Int32 nColumn)=0
SC_DLLPUBLIC void SetLayoutName(const OUString &rName)
static SC_DLLPUBLIC OUString getSourceDimensionName(const OUString &rName)
void SetUsedHierarchy(tools::Long nNew)
void SetName(const OUString &rNew)
static bool GetBoolProperty(const css::uno::Reference< css::beans::XPropertySet > &xProp, const OUString &rName, bool bDefault=false)
SC_DLLPUBLIC ~ScDPSaveData()
static bool isDuplicateDimension(const OUString &rName)
SC_DLLPUBLIC void SetIgnoreEmptyRows(bool bSet)
sal_uInt16 nIgnoreEmptyMode
#define SC_UNO_DP_AUTOSHOW
SC_DLLPUBLIC ScDPSaveDimension * GetExistingDimensionByName(std::u16string_view rName) const
void SetDupFlag(bool bSet)
void Dump(int nIndent=0) const
OUString GetCurrentPage() const
SC_DLLPUBLIC void SetFilterButton(bool bSet)
#define SC_UNO_DP_HAS_HIDDEN_MEMBER
ScDPSaveDimension * DuplicateDimension(std::u16string_view rName)
static void SetOptionalPropertyValue(const css::uno::Reference< css::beans::XPropertySet > &rPropSet, const char *pPropName, const css::uno::Any &rVal)
sal_uInt16 nColumnGrandMode
void SetReferenceValue(const css::sheet::DataPilotFieldReference *pNew)
const std::optional< OUString > & GetSubtotalName() const
bool ContainerUniquePtrEquals(C< std::unique_ptr< T >, Etc... > const &lhs, C< std::unique_ptr< T >, Etc... > const &rhs)
void SetPosition(ScDPSaveDimension *pDim, tools::Long nNew)
bool mbDimensionMembersBuilt
if true, all dimensions already have all of their member instances created.
SC_DLLPUBLIC void SetShowDetails(bool bSet)
#define SC_UNO_DP_ROWGRAND
std::optional< OUString > mpSubtotalName
#define SC_UNO_DP_ORIENTATION
void SetAutoShowInfo(const css::sheet::DataPilotFieldAutoShowInfo *pNew)
SC_DLLPUBLIC void SetGrandTotalName(const OUString &rName)
SC_DLLPUBLIC void SetDrillDown(bool bSet)
#define SC_UNO_DP_SHOWEMPTY
Base class that abstracts different data source types of a datapilot table.
#define SC_DPSAVEMODE_DONTKNOW
SC_DLLPUBLIC bool HasIsVisible() const
tools::Long nUsedHierarchy
sal_uInt16 nShowEmptyMode
sal_uInt16 nRepeatEmptyMode
std::unique_ptr< css::sheet::DataPilotFieldReference > pReferenceValue
void SetRepeatItemLabels(bool bSet)
#define SC_UNO_DP_USEDHIERARCHY
#define SAL_WARN_IF(condition, area, stream)
void UpdateMemberVisibility(const std::unordered_map< OUString, bool > &rData)
void SetSubtotalName(const OUString &rName)
std::unique_ptr< css::sheet::DataPilotFieldLayoutInfo > pLayoutInfo
SvStream & endl(SvStream &rStr)
ScGeneralFunction
the css::sheet::GeneralFunction enum is extended by constants in GeneralFunction2, which causes some type-safety issues.
#define SAL_INFO(area, stream)
const OUString & GetName() const
#define SC_UNO_DP_ISVISIBLE
void WriteToSource(const css::uno::Reference< css::uno::XInterface > &xDim)
std::unique_ptr< css::sheet::DataPilotFieldAutoShowInfo > pAutoShowInfo
Represents a new group dimension whose dimension ID is higher than the highest source dimension ID...
void RemoveSubtotalName()
bool bSubTotalDefault
at level
Sequence< sal_Int8 > aSeq
void SetShowEmpty(bool bSet)
SC_DLLPUBLIC void SetColumnGrand(bool bSet)
OUString GetFormattedString(sal_Int32 nDim, const ScDPItemData &rItem, bool bLocaleIndependent) const
SC_DLLPUBLIC void SetRowGrand(bool bSet)
void WriteToSource(const css::uno::Reference< css::sheet::XDimensionsSupplier > &xSource)
void Dump(int nIndent=0) const
#define SC_UNO_DP_SHOWDETAILS
bool bRepeatItemLabels
at level
ScDPSaveDimension(const OUString &rName, bool bDataLayout)
#define SC_UNO_DP_ISDATALAYOUT
SC_DLLPUBLIC const std::optional< OUString > & GetLayoutName() const
void RemoveAllGroupDimensions(const OUString &rSrcDimName, std::vector< OUString > *pDeletedNames=nullptr)
std::optional< OUString > mpLayoutName
#define SC_UNO_DP_SUBTOTAL2
void SetSubTotals(std::vector< ScGeneralFunction > const &rFuncs)
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
static void lcl_ResetOrient(const uno::Reference< sheet::XDimensionsSupplier > &xSource)
void SetLayoutInfo(const css::sheet::DataPilotFieldLayoutInfo *pNew)
SC_DLLPUBLIC ScDPSaveDimension * GetDataLayoutDimension()
ScDPSaveMember(const OUString &rName)
std::vector< ScGeneralFunction > maSubTotalFuncs
at level
void AddMember(std::unique_ptr< ScDPSaveMember > pMember)
void SetSortInfo(const css::sheet::DataPilotFieldSortInfo *pNew)
SC_DLLPUBLIC ScDPSaveData()
virtual sal_Int32 GetColumnCount()=0
use (new) typed collection instead of ScStrCollection or separate Str and ValueCollection ...
SC_DLLPUBLIC bool HasShowDetails() const