office-gobmx/sc/inc/dpobject.hxx
Tamás Zolnai 7c429ddca6 tdf#112278: Pivot table: filtering of non-string fields is not exported to XLS
It is needed to use the right string representation of field value.
During export this representation is available directly, next to
the actual value. During import we can use the number format attached
to the corresponding pivot field.

Change-Id: Ie8f731f6c72d7f55f43c318e52d63dc4e993d9c0
Reviewed-on: https://gerrit.libreoffice.org/42069
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com>
2017-09-09 12:13:53 +02:00

437 lines
16 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_SC_INC_DPOBJECT_HXX
#define INCLUDED_SC_INC_DPOBJECT_HXX
#include "scdllapi.h"
#include "global.hxx"
#include "address.hxx"
#include "dpoutput.hxx"
#include "dptypes.hxx"
#include "pivot.hxx"
#include "calcmacros.hxx"
#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
#include <memory>
#include <set>
#include <vector>
#include <map>
namespace com { namespace sun { namespace star {
namespace container {
class XIndexAccess;
}
namespace sdbc {
class XRowSet;
}
namespace sheet {
class XMembersAccess;
struct DataPilotTablePositionData;
struct DataPilotTableHeaderData;
struct DataPilotFieldFilter;
}
}}}
namespace tools { class Rectangle; }
class ScDPSaveData;
class ScDPOutput;
struct ScPivotParam;
struct ScImportSourceDesc;
class ScSheetSourceDesc;
struct ScPivotField;
class ScDPTableData;
class ScDPDimensionSaveData;
class ScRangeList;
struct ScDPServiceDesc
{
OUString aServiceName;
OUString aParSource;
OUString aParName;
OUString aParUser;
OUString aParPass;
ScDPServiceDesc( const OUString& rServ, const OUString& rSrc, const OUString& rNam,
const OUString& rUser, const OUString& rPass );
bool operator== ( const ScDPServiceDesc& rOther ) const;
};
class SC_DLLPUBLIC ScDPObject
{
private:
ScDocument* pDoc;
// settings
ScDPSaveData* pSaveData;
OUString aTableName;
OUString aTableTag;
ScRange aOutRange;
ScSheetSourceDesc* pSheetDesc; // for sheet data
ScImportSourceDesc* pImpDesc; // for database data
ScDPServiceDesc* pServDesc; // for external service
std::shared_ptr<ScDPTableData> mpTableData;
// cached data
css::uno::Reference<css::sheet::XDimensionsSupplier> xSource;
ScDPOutput* pOutput;
long nHeaderRows; // page fields plus filter button
bool mbHeaderLayout:1; // true : grid, false : standard
bool bAllowMove:1;
bool bSettingsChanged:1;
bool mbEnableGetPivotData:1;
SAL_DLLPRIVATE ScDPTableData* GetTableData();
SAL_DLLPRIVATE void CreateObjects();
SAL_DLLPRIVATE void CreateOutput();
SAL_DLLPRIVATE void ClearSource();
SAL_DLLPRIVATE bool FillLabelDataForDimension(
const css::uno::Reference< css::container::XIndexAccess>& xDims,
sal_Int32 nDim, ScDPLabelData& rLabelData);
public:
ScDPObject(ScDocument* pD);
ScDPObject(const ScDPObject& r);
~ScDPObject();
ScDPObject& operator= (const ScDPObject& r);
void EnableGetPivotData(bool b);
void SetAllowMove(bool bSet);
void InvalidateData();
void Clear();
void ClearTableData();
void ReloadGroupTableData();
void Output( const ScAddress& rPos );
ScRange GetNewOutputRange( bool& rOverflow );
ScRange GetOutputRangeByType( sal_Int32 nType );
ScRange GetOutputRangeByType( sal_Int32 nType ) const;
void SetSaveData(const ScDPSaveData& rData);
ScDPSaveData* GetSaveData() const { return pSaveData; }
void SetOutRange(const ScRange& rRange);
const ScRange& GetOutRange() const;
void SetHeaderLayout(bool bUseGrid);
bool GetHeaderLayout() const { return mbHeaderLayout;}
void SetSheetDesc(const ScSheetSourceDesc& rDesc);
void SetImportDesc(const ScImportSourceDesc& rDesc);
void SetServiceData(const ScDPServiceDesc& rDesc);
void WriteSourceDataTo( ScDPObject& rDest ) const;
void WriteTempDataTo( ScDPObject& rDest ) const;
const ScSheetSourceDesc* GetSheetDesc() const { return pSheetDesc; }
const ScImportSourceDesc* GetImportSourceDesc() const { return pImpDesc; }
const ScDPServiceDesc* GetDPServiceDesc() const { return pServDesc; }
css::uno::Reference<css::sheet::XDimensionsSupplier> const & GetSource();
bool IsSheetData() const;
bool IsImportData() const { return(pImpDesc != nullptr); }
bool IsServiceData() const { return(pServDesc != nullptr); }
void SetName(const OUString& rNew);
const OUString& GetName() const { return aTableName; }
void SetTag(const OUString& rNew);
const OUString& GetTag() const { return aTableTag; }
/**
* Data description cell displays the description of a data dimension if
* and only if there is only one data dimension. It's usually located at
* the upper-left corner of the table output.
*/
bool IsDataDescriptionCell(const ScAddress& rPos);
bool IsDimNameInUse(const OUString& rName) const;
OUString GetDimName( long nDim, bool& rIsDataLayout, sal_Int32* pFlags = nullptr );
bool IsDuplicated( long nDim );
long GetDimCount();
void GetHeaderPositionData(const ScAddress& rPos, css::sheet::DataPilotTableHeaderData& rData);
long GetHeaderDim( const ScAddress& rPos, css::sheet::DataPilotFieldOrientation& rOrient );
bool GetHeaderDrag( const ScAddress& rPos, bool bMouseLeft, bool bMouseTop,
long nDragDim,
tools::Rectangle& rPosRect, css::sheet::DataPilotFieldOrientation& rOrient, long& rDimPos );
bool IsFilterButton( const ScAddress& rPos );
OUString GetFormattedString( const OUString& rDimName, const double fValue );
double GetPivotData(
const OUString& rDataFieldName,
std::vector<css::sheet::DataPilotFieldFilter>& rFilters);
bool ParseFilters(
OUString& rDataFieldName,
std::vector<css::sheet::DataPilotFieldFilter>& rFilters,
std::vector<sal_Int16>& rFilterFuncs,
const OUString& rFilterList );
void GetMemberResultNames(ScDPUniqueStringSet& rNames, long nDimension);
void ToggleDetails(const css::sheet::DataPilotTableHeaderData& rElemDesc, ScDPObject* pDestObj);
void FillOldParam(ScPivotParam& rParam) const;
void FillLabelData(sal_Int32 nDim, ScDPLabelData& Labels);
void FillLabelData(ScPivotParam& rParam);
bool GetHierarchiesNA( sal_Int32 nDim, css::uno::Reference< css::container::XNameAccess >& xHiers );
void GetHierarchies( sal_Int32 nDim, css::uno::Sequence< OUString >& rHiers );
sal_Int32 GetUsedHierarchy( sal_Int32 nDim );
bool GetMembersNA( sal_Int32 nDim, css::uno::Reference< css::sheet::XMembersAccess >& xMembers );
bool GetMembersNA( sal_Int32 nDim, sal_Int32 nHier, css::uno::Reference< css::sheet::XMembersAccess >& xMembers );
bool GetMemberNames( sal_Int32 nDim, css::uno::Sequence< OUString >& rNames );
bool GetMembers( sal_Int32 nDim, sal_Int32 nHier, ::std::vector<ScDPLabelData::Member>& rMembers );
void UpdateReference( UpdateRefMode eUpdateRefMode,
const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz );
bool RefsEqual( const ScDPObject& r ) const;
void WriteRefsTo( ScDPObject& r ) const;
void GetPositionData(const ScAddress& rPos, css::sheet::DataPilotTablePositionData& rPosData);
bool GetDataFieldPositionData(const ScAddress& rPos,
css::uno::Sequence<
css::sheet::DataPilotFieldFilter >& rFilters);
void GetDrillDownData(const ScAddress& rPos,
css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& rTableData);
// apply drop-down attribute, initialize nHeaderRows, without accessing the source
// (button attribute must be present)
void RefreshAfterLoad();
void BuildAllDimensionMembers();
/**
* Remove in the save data entries for members that don't exist anymore.
* This is called during pivot table refresh.
*/
bool SyncAllDimensionMembers();
static bool HasRegisteredSources();
static std::vector<OUString> GetRegisteredSources();
static css::uno::Reference<css::sheet::XDimensionsSupplier>
CreateSource( const ScDPServiceDesc& rDesc );
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 );
static bool IsOrientationAllowed( css::sheet::DataPilotFieldOrientation nOrient, sal_Int32 nDimFlags );
#if DUMP_PIVOT_TABLE
void Dump() const;
void DumpCache() const;
#endif
};
class ScDPCollection
{
friend class ScDPCache;
public:
/**
* Stores and manages all caches from internal sheets.
*/
class SheetCaches
{
friend class ScDPCollection;
typedef std::map<size_t, std::unique_ptr<ScDPCache>> CachesType;
typedef std::vector<ScRange> RangeIndexType;
CachesType m_Caches;
RangeIndexType maRanges;
ScDocument* mpDoc;
public:
SheetCaches(ScDocument* pDoc);
bool hasCache(const ScRange& rRange) const;
const ScDPCache* getCache(const ScRange& rRange, const ScDPDimensionSaveData* pDimData);
SC_DLLPUBLIC size_t size() const;
void updateReference(
UpdateRefMode eMode, const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz);
SC_DLLPUBLIC ScDPCache* getExistingCache(const ScRange& rRange);
SC_DLLPUBLIC const ScDPCache* getExistingCache(const ScRange& rRange) const;
void updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs);
bool remove(const ScDPCache* p);
SC_DLLPUBLIC const std::vector<ScRange>& getAllRanges() const;
};
/**
* Data caches for range name based source data.
*/
class NameCaches
{
friend class ScDPCollection;
typedef ::std::map<OUString, std::unique_ptr<ScDPCache>> CachesType;
CachesType m_Caches;
ScDocument* mpDoc;
public:
NameCaches(ScDocument* pDoc);
bool hasCache(const OUString& rName) const;
const ScDPCache* getCache(
const OUString& rName, const ScRange& rRange, const ScDPDimensionSaveData* pDimData);
size_t size() const;
private:
ScDPCache* getExistingCache(const OUString& rName);
void updateCache(
const OUString& rName, const ScRange& rRange, std::set<ScDPObject*>& rRefs);
bool remove(const ScDPCache* p);
};
/**
* Defines connection type to external data source. Used as a key to look
* up database cache.
*/
struct DBType
{
sal_Int32 mnSdbType;
OUString maDBName;
OUString maCommand;
DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand);
struct less
{
bool operator() (const DBType& left, const DBType& right) const;
};
};
/**
* Data caches for external database sources.
*/
class DBCaches
{
friend class ScDPCollection;
typedef ::std::map<DBType, std::unique_ptr<ScDPCache>, DBType::less> CachesType;
CachesType m_Caches;
ScDocument* mpDoc;
public:
DBCaches(ScDocument* pDoc);
bool hasCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) const;
const ScDPCache* getCache(
sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
const ScDPDimensionSaveData* pDimData);
private:
ScDPCache* getExistingCache(
sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand);
static css::uno::Reference<css::sdbc::XRowSet> createRowSet(
sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand);
void updateCache(
sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
std::set<ScDPObject*>& rRefs);
bool remove(const ScDPCache* p);
};
ScDPCollection(ScDocument* pDocument);
ScDPCollection(const ScDPCollection& r);
~ScDPCollection();
const char* ReloadCache(const ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs);
bool ReloadGroupsInCache(const ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs);
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject& rDPObj, const ScDPDimensionSaveData** pGroups) const;
SC_DLLPUBLIC size_t GetCount() const;
SC_DLLPUBLIC ScDPObject& operator[](size_t nIndex);
SC_DLLPUBLIC const ScDPObject& operator[](size_t nIndex) const;
ScDPObject* GetByName(const OUString& rName) const;
void DeleteOnTab( SCTAB nTab );
void UpdateReference( UpdateRefMode eUpdateRefMode,
const ScRange& r, SCCOL nDx, SCROW nDy, SCTAB nDz );
void CopyToTab( SCTAB nOld, SCTAB nNew );
bool RefsEqual( const ScDPCollection& r ) const;
void WriteRefsTo( ScDPCollection& r ) const;
/**
* Create a new name that's not yet used by any existing data pilot
* objects. All data pilot names are 'DataPilot' + <num>
*
* @return new name for data pilot object.
*/
OUString CreateNewName() const;
void FreeTable(const ScDPObject* pDPObj);
SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj);
SC_DLLPUBLIC bool HasTable(const ScDPObject* pDPObj) const;
SC_DLLPUBLIC SheetCaches& GetSheetCaches();
SC_DLLPUBLIC const SheetCaches& GetSheetCaches() const;
NameCaches& GetNameCaches();
SC_DLLPUBLIC const NameCaches& GetNameCaches() const;
DBCaches& GetDBCaches();
SC_DLLPUBLIC const DBCaches& GetDBCaches() const;
ScRangeList GetAllTableRanges( SCTAB nTab ) const;
bool IntersectsTableByColumns( SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab ) const;
bool IntersectsTableByRows( SCCOL nCol, SCROW nRow1, SCROW nRow2, SCTAB nTab ) const;
bool HasTable( const ScRange& rRange ) const;
#if DEBUG_PIVOT_TABLE
void DumpTables() const;
#endif
private:
/** Only to be called from ScDPCache::RemoveReference(). */
void RemoveCache(const ScDPCache* pCache);
void GetAllTables(const ScRange& rSrcRange, std::set<ScDPObject*>& rRefs) const;
void GetAllTables(const OUString& rSrcName, std::set<ScDPObject*>& rRefs) const;
void GetAllTables(
sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand,
std::set<ScDPObject*>& rRefs) const;
private:
typedef std::vector< std::unique_ptr<ScDPObject> > TablesType;
ScDocument* mpDoc;
TablesType maTables;
SheetCaches maSheetCaches;
NameCaches maNameCaches;
DBCaches maDBCaches;
};
bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right);
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */