sc/Library_scfilt.mk | 2 sc/inc/dpoutput.hxx | 8 + sc/inc/dpsave.hxx | 6 sc/inc/pivot/PivotTableFormats.hxx | 48 +++++++ sc/source/core/data/dpobject.cxx | 8 - sc/source/core/data/dpoutput.cxx | 47 +++++++ sc/source/core/data/dpsave.cxx | 18 ++ sc/source/filter/inc/PivotTableFormat.hxx | 106 ++++++++++++++++ sc/source/filter/inc/PivotTableFormatContext.hxx | 49 +++++++ sc/source/filter/inc/pivottablebuffer.hxx | 4 sc/source/filter/oox/PivotTableFormat.cxx | 148 +++++++++++++++++++++++ sc/source/filter/oox/PivotTableFormatContext.cxx | 92 ++++++++++++++ sc/source/filter/oox/pivottablebuffer.cxx | 12 + sc/source/filter/oox/pivottablefragment.cxx | 19 ++ 14 files changed, 559 insertions(+), 8 deletions(-)
New commits: commit af5bb01b9430b76ae8042b5ce6ebda65798bbb18 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Tue Mar 12 21:16:20 2024 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Thu Apr 11 17:13:20 2024 +0200 pivot: forward pivot table format data into the pivot table model The purpuse of this is to lay out the foundation for the support of pivot table formatting. This adds the code to forward the formatting information from the OOXML import into the pivot table model and uses it in a use case to set the row and column labels in the pivot table output (DPOutput). In the follow up commits the support will be extended to support more use cases with tests. Change-Id: Idf23884b32167bdbad69bc67358ccf7f14566db6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164710 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx index 9c9c068c603e..a1087d182bab 100644 --- a/sc/inc/dpoutput.hxx +++ b/sc/inc/dpoutput.hxx @@ -28,6 +28,7 @@ #include "address.hxx" #include "dptypes.hxx" +#include "pivot/PivotTableFormats.hxx" #include <memory> #include <vector> @@ -64,6 +65,8 @@ private: sal_uInt32 mnSingleNumberFormat; size_t mnRowDims; // Including empty ones. + std::unique_ptr<sc::PivotTableFormats> mpFormats; + // Output geometry related parameters sal_Int32 mnColCount; sal_Int32 mnRowCount; @@ -136,6 +139,11 @@ public: void SetHeaderLayout(bool bUseGrid); bool GetHeaderLayout() const { return mbHeaderLayout;} + void setFormats(sc::PivotTableFormats const& rPivotTableFormats) + { + mpFormats.reset(new sc::PivotTableFormats(rPivotTableFormats)); + } + static void GetDataDimensionNames( OUString& rSourceName, OUString& rGivenName, const css::uno::Reference< css::uno::XInterface>& xDim ); diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx index a54da59d57d8..ad1e393dc879 100644 --- a/sc/inc/dpsave.hxx +++ b/sc/inc/dpsave.hxx @@ -45,6 +45,7 @@ namespace com::sun::star::sheet { class ScDPDimensionSaveData; class ScDPTableData; enum class ScGeneralFunction; +namespace sc { class PivotTableFormats; } // classes to save Data Pilot settings @@ -253,6 +254,7 @@ private: * created. */ bool mbDimensionMembersBuilt; + std::unique_ptr<sc::PivotTableFormats> mpFormats; std::optional<OUString> mpGrandTotalName; mutable std::unique_ptr<DimOrderType> mpDimOrder; // dimension order for row and column dimensions, to traverse result tree. @@ -265,6 +267,10 @@ public: bool operator== ( const ScDPSaveData& r ) const; + SC_DLLPUBLIC bool hasFormats(); + SC_DLLPUBLIC sc::PivotTableFormats const& getFormats(); + SC_DLLPUBLIC void setFormats(sc::PivotTableFormats const& rPivotTableFormats); + SC_DLLPUBLIC void SetGrandTotalName(const OUString& rName); SC_DLLPUBLIC const std::optional<OUString> & GetGrandTotalName() const; diff --git a/sc/inc/pivot/PivotTableFormats.hxx b/sc/inc/pivot/PivotTableFormats.hxx new file mode 100644 index 000000000000..09f181e7e178 --- /dev/null +++ b/sc/inc/pivot/PivotTableFormats.hxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +#pragma once + +#include <memory> +#include <vector> +#include <rtl/ustring.hxx> + +namespace sc +{ +struct PivotTableFormat +{ + sal_Int32 nField; + sal_Int32 nDataIndex; + OUString aStyleName; + + PivotTableFormat(sal_Int32 _nField, sal_Int32 _nDataIndex, OUString _aStyleName) + : nField(_nField) + , nDataIndex(_nDataIndex) + , aStyleName(_aStyleName) + { + } +}; + +class PivotTableFormats +{ + std::vector<PivotTableFormat> maFormats; + +public: + void add(sal_Int32 nField, sal_Int32 nDataIndex, OUString const& rStyle) + { + maFormats.emplace_back(nField, nDataIndex, rStyle); + } + + size_t size() { return maFormats.size(); } + + std::vector<PivotTableFormat> const& getVector() { return maFormats; } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 63b7021de95c..3f98a5fcc40c 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -526,8 +526,12 @@ void ScDPObject::CreateOutput() return; bool bFilterButton = IsSheetData() && mpSaveData && mpSaveData->GetFilterButton(); - mpOutput.reset( new ScDPOutput(mpDocument, mxSource, maOutputRange.aStart, bFilterButton, mpSaveData ? mpSaveData->GetExpandCollapse() : false ) ); - mpOutput->SetHeaderLayout ( mbHeaderLayout ); + bool bExpandCollapse = mpSaveData ? mpSaveData->GetExpandCollapse() : false; + + mpOutput.reset(new ScDPOutput(mpDocument, mxSource, maOutputRange.aStart, bFilterButton, bExpandCollapse)); + mpOutput->SetHeaderLayout(mbHeaderLayout); + if (mpSaveData->hasFormats()) + mpOutput->setFormats(mpSaveData->getFormats()); sal_Int32 nOldRows = mnHeaderRows; mnHeaderRows = mpOutput->GetHeaderRows(); diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index c269e00a3438..d88a320aeac0 100644 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -763,6 +763,21 @@ void ScDPOutput::DataCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const sheet::Data // SubTotal formatting is controlled by headers } +namespace +{ +void lclApplyStyle(ScDocument* pDoc, SCTAB nTab, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, + OUString const& rStyleName) +{ + ScStyleSheetPool* pStlPool = pDoc->GetStyleSheetPool(); + ScStyleSheet* pStyle = static_cast<ScStyleSheet*>(pStlPool->Find(rStyleName, SfxStyleFamily::Para)); + if (pStyle) + { + pDoc->ApplyStyleAreaTab(nCol1, nRow1, nCol2, nRow2, nTab, *pStyle); + } +} +} + void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const sheet::MemberResult& rData, bool bColHeader, tools::Long nLevel ) { @@ -1060,12 +1075,16 @@ void ScDPOutput::Output() MultiFieldCell(nHdrCol, mnTabStartRow, nTab, false /* bRowField */); SCROW nRowPos = mnMemberStartRow + static_cast<SCROW>(nField); //TODO: check for overflow + tools::Long nDimension = mpColFields[nField].mnDim; const uno::Sequence<sheet::MemberResult> rSequence = mpColFields[nField].maResult; const sheet::MemberResult* pArray = rSequence.getConstArray(); tools::Long nThisColCount = rSequence.getLength(); OSL_ENSURE(nThisColCount == mnColCount, "count mismatch"); //TODO: ??? + tools::Long nColumnIndex = -1; for (tools::Long nCol=0; nCol<nThisColCount; nCol++) { + if (!(pArray[nCol].Flags & sheet::MemberResultFlags::CONTINUE)) + nColumnIndex++; SCCOL nColPos = mnDataStartCol + static_cast<SCCOL>(nCol); //TODO: check for overflow HeaderCell( nColPos, nRowPos, nTab, pArray[nCol], true, nField ); if ( ( pArray[nCol].Flags & sheet::MemberResultFlags::HASMEMBER ) && @@ -1094,6 +1113,18 @@ void ScDPOutput::Output() else if ( pArray[nCol].Flags & sheet::MemberResultFlags::SUBTOTAL ) outputimp.AddCol( nColPos ); + // Apply format + if (mpFormats) + { + for (auto& aFormat : mpFormats->getVector()) + { + if (aFormat.nField == nDimension && aFormat.nDataIndex == nColumnIndex) + { + lclApplyStyle(mpDocument, nTab, nColPos, nRowPos, nColPos, mnDataStartRow - 1, aFormat.aStyleName); + } + } + } + // Apply the same number format as in data source. mpDocument->ApplyAttr(nColPos, nRowPos, nTab, SfxUInt32Item(ATTR_VALUE_FORMAT, mpColFields[nField].mnSrcNumFmt)); } @@ -1118,12 +1149,16 @@ void ScDPOutput::Output() MultiFieldCell(nHdrCol, nHdrRow, nTab, true /* bRowField */); SCCOL nColPos = mnMemberStartCol + static_cast<SCCOL>(nFieldColOffset); //TODO: check for overflow + tools::Long nDimension = mpRowFields[nField].mnDim; const uno::Sequence<sheet::MemberResult> rSequence = mpRowFields[nField].maResult; const sheet::MemberResult* pArray = rSequence.getConstArray(); sal_Int32 nThisRowCount = rSequence.getLength(); OSL_ENSURE(nThisRowCount == mnRowCount, "count mismatch"); //TODO: ??? + tools::Long nRowIndex = -1; for (sal_Int32 nRow=0; nRow<nThisRowCount; nRow++) { + if (!(pArray[nRow].Flags & sheet::MemberResultFlags::CONTINUE)) + nRowIndex++; const sheet::MemberResult& rData = pArray[nRow]; const bool bHasMember = (rData.Flags & sheet::MemberResultFlags::HASMEMBER); const bool bSubtotal = (rData.Flags & sheet::MemberResultFlags::SUBTOTAL); @@ -1174,6 +1209,18 @@ void ScDPOutput::Output() else if ( bSubtotal ) outputimp.AddRow( nRowPos ); + // Apply format + if (mpFormats) + { + for (auto& aFormat : mpFormats->getVector()) + { + if (aFormat.nField == nDimension && aFormat.nDataIndex == nRowIndex) + { + lclApplyStyle(mpDocument, nTab, nColPos, nRowPos, mnDataStartCol - 1, nRowPos, aFormat.aStyleName); + } + } + } + // Apply the same number format as in data source. mpDocument->ApplyAttr(nColPos, nRowPos, nTab, SfxUInt32Item(ATTR_VALUE_FORMAT, mpRowFields[nField].mnSrcNumFmt)); } diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx index a872a6385475..ed888eebd737 100644 --- a/sc/source/core/data/dpsave.cxx +++ b/sc/source/core/data/dpsave.cxx @@ -25,6 +25,7 @@ #include <dputil.hxx> #include <generalfunction.hxx> #include <dptabdat.hxx> +#include <pivot/PivotTableFormats.hxx> #include <sal/types.h> #include <sal/log.hxx> @@ -712,6 +713,8 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& rOther) { if (rOther.mpDimensionData) mpDimensionData.reset(new ScDPDimensionSaveData(*rOther.mpDimensionData)); + if (rOther.mpFormats) + mpFormats.reset(new sc::PivotTableFormats(*rOther.mpFormats)); for (auto const& rOtherSaveDimension : rOther.m_DimList) { @@ -764,6 +767,21 @@ ScDPSaveData::~ScDPSaveData() { } +void ScDPSaveData::setFormats(sc::PivotTableFormats const& rPivotTableFormats) +{ + mpFormats.reset(new sc::PivotTableFormats(rPivotTableFormats)); +} + +bool ScDPSaveData::hasFormats() +{ + return bool(mpFormats); +} + +sc::PivotTableFormats const& ScDPSaveData::getFormats() +{ + return *mpFormats; +} + void ScDPSaveData::SetGrandTotalName(const OUString& rName) { mpGrandTotalName = rName; diff --git a/sc/source/filter/inc/PivotTableFormat.hxx b/sc/source/filter/inc/PivotTableFormat.hxx index fffaf1a572df..204dea566def 100644 --- a/sc/source/filter/inc/PivotTableFormat.hxx +++ b/sc/source/filter/inc/PivotTableFormat.hxx @@ -56,16 +56,21 @@ private: std::vector<std::shared_ptr<PivotTableReference>> maReferences; + // Other + PivotTable& mrPivotTable; + public: - explicit PivotTableFormat(const PivotTable& rPivotTable); + explicit PivotTableFormat(PivotTable& rPivotTable); void importPivotArea(const oox::AttributeList& rAttribs); void importFormat(const oox::AttributeList& rAttribs); PivotTableReference& createReference(); + void finalizeImport(); }; class PivotTableReference : public WorkbookHelper { - //PivotTableFormat const& mrFormat; +public: + PivotTableFormat const& mrFormat; std::optional<sal_uInt32> mnField; std::optional<sal_uInt32> mnCount; diff --git a/sc/source/filter/oox/PivotTableFormat.cxx b/sc/source/filter/oox/PivotTableFormat.cxx index 7447b352745a..1f76d5159a7d 100644 --- a/sc/source/filter/oox/PivotTableFormat.cxx +++ b/sc/source/filter/oox/PivotTableFormat.cxx @@ -11,11 +11,15 @@ #include <pivottablebuffer.hxx> #include <oox/token/properties.hxx> #include <oox/token/tokens.hxx> +#include <pivot/PivotTableFormats.hxx> +#include <dpsave.hxx> +#include <dpobject.hxx> namespace oox::xls { -PivotTableFormat::PivotTableFormat(const PivotTable& rPivotTable) +PivotTableFormat::PivotTableFormat(PivotTable& rPivotTable) : WorkbookHelper(rPivotTable) + , mrPivotTable(rPivotTable) { } @@ -69,6 +73,34 @@ void PivotTableFormat::importPivotArea(const oox::AttributeList& rAttribs) mnFieldPosition = rAttribs.getUnsigned(XML_field); } +void PivotTableFormat::finalizeImport() +{ + OUString const& rDxfStyle = getStyles().createDxfStyle(mnDxfId); + + ScDPObject* pDPObj = mrPivotTable.getDPObject(); + ScDPSaveData* pSaveData = pDPObj->GetSaveData(); + + sc::PivotTableFormats aFormats; + + if (pSaveData->hasFormats()) + aFormats = pSaveData->getFormats(); + + // Resolve references - TODO + for (auto const& pReference : maReferences) + { + if (pReference->mnField && pReference->mbSelected) + { + auto nField = *pReference->mnField; + for (auto index : pReference->maFieldItemsIndices) + { + aFormats.add(nField, index, rDxfStyle); + } + } + } + + pSaveData->setFormats(aFormats); +} + PivotTableReference& PivotTableFormat::createReference() { auto xReference = std::make_shared<PivotTableReference>(*this); @@ -78,6 +110,7 @@ PivotTableReference& PivotTableFormat::createReference() PivotTableReference::PivotTableReference(const PivotTableFormat& rFormat) : WorkbookHelper(rFormat) + , mrFormat(rFormat) { } void PivotTableReference::importReference(const oox::AttributeList& rAttribs) diff --git a/sc/source/filter/oox/pivottablebuffer.cxx b/sc/source/filter/oox/pivottablebuffer.cxx index e5c315fa9cdb..072dde626848 100644 --- a/sc/source/filter/oox/pivottablebuffer.cxx +++ b/sc/source/filter/oox/pivottablebuffer.cxx @@ -1337,8 +1337,8 @@ void PivotTable::finalizeImport() maFilters.forEachMem( &PivotTableFilter::finalizeImport ); // formats - //for (auto& pFormat : maFormats) - // pFormat->finalizeImport(); + for (auto& pFormat : maFormats) + pFormat->finalizeImport(); // calculate base position of table CellAddress aPos( maLocationModel.maRange.aStart.Tab(), maLocationModel.maRange.aStart.Col(), maLocationModel.maRange.aStart.Row() ); commit a180bf0c0f805462c2ba84abcdcc89c59d1e50fa Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Thu Mar 7 14:18:55 2024 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Thu Apr 11 17:13:14 2024 +0200 pivot: Import Pivot Table "formats" element(s) This reads the "formats" element that is a subelement of OOXML "pivotTableDefinition" element and is used to define the custom cell format of a pivot table output. Change-Id: Ice0d489d78860ef04388c59810d9f97c5cdb983e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164708 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk index 65794a9bc879..e4936656676e 100644 --- a/sc/Library_scfilt.mk +++ b/sc/Library_scfilt.mk @@ -196,6 +196,8 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\ sc/source/filter/oox/pivotcachefragment \ sc/source/filter/oox/pivottablebuffer \ sc/source/filter/oox/pivottablefragment \ + sc/source/filter/oox/PivotTableFormat \ + sc/source/filter/oox/PivotTableFormatContext \ sc/source/filter/oox/querytablebuffer \ sc/source/filter/oox/querytablefragment \ sc/source/filter/oox/revisionfragment \ diff --git a/sc/source/filter/inc/PivotTableFormat.hxx b/sc/source/filter/inc/PivotTableFormat.hxx new file mode 100644 index 000000000000..fffaf1a572df --- /dev/null +++ b/sc/source/filter/inc/PivotTableFormat.hxx @@ -0,0 +1,101 @@ +/* -*- 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/. + */ + +#pragma once + +#include "workbookhelper.hxx" + +#include <memory> +#include <vector> +#include <optional> +#include <oox/helper/attributelist.hxx> + +namespace oox::xls +{ +class PivotTable; +class PivotTableFormat; +class PivotTableReference; + +enum class PivotAreaType +{ + None, + Normal, + Data, + All, + Origin, + Button, + TopRight +}; + +class PivotTableFormat : public WorkbookHelper +{ +public: + // DXF + sal_Int32 mnDxfId = -1; + +private: + // PivotArea + std::optional<sal_Int32> mnField; + PivotAreaType meType = PivotAreaType::Normal; + bool mbDataOnly = true; + bool mbLabelOnly = false; + bool mbGrandRow = false; + bool mbGrandCol = false; + bool mbCacheIndex = false; + bool mbOutline = true; + std::optional<OUString> msOffset; + bool mbCollapsedLevelsAreSubtotals = false; + // TODO Axis + std::optional<sal_uInt32> mnFieldPosition; + + std::vector<std::shared_ptr<PivotTableReference>> maReferences; + +public: + explicit PivotTableFormat(const PivotTable& rPivotTable); + void importPivotArea(const oox::AttributeList& rAttribs); + void importFormat(const oox::AttributeList& rAttribs); + PivotTableReference& createReference(); +}; + +class PivotTableReference : public WorkbookHelper +{ + //PivotTableFormat const& mrFormat; + + std::optional<sal_uInt32> mnField; + std::optional<sal_uInt32> mnCount; + bool mbSelected = true; + bool mbByPosition = false; + bool mbRelative = false; + bool mbDefaultSubtotal = false; + bool mbSumSubtotal = false; + bool mbCountASubtotal = false; + bool mbAvgSubtotal = false; + bool mbMaxSubtotal = false; + bool mbMinSubtotal = false; + bool mbProductSubtotal = false; + bool mbCountSubtotal = false; + bool mbStdDevSubtotal = false; + bool mbStdDevPSubtotal = false; + bool mbVarSubtotal = false; + bool mbVarPSubtotal = false; + + std::vector<sal_uInt32> maFieldItemsIndices; + +public: + explicit PivotTableReference(const PivotTableFormat& rFormat); + + void importReference(const oox::AttributeList& rAttribs); + void addFieldItem(const oox::AttributeList& rAttribs); +}; + +typedef std::vector<std::shared_ptr<PivotTableFormat>> PivotTableFormatVector; + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/PivotTableFormatContext.hxx b/sc/source/filter/inc/PivotTableFormatContext.hxx new file mode 100644 index 000000000000..6eee45806726 --- /dev/null +++ b/sc/source/filter/inc/PivotTableFormatContext.hxx @@ -0,0 +1,49 @@ +/* -*- 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/. + */ + +#pragma once + +#include "excelhandlers.hxx" +#include "worksheethelper.hxx" + +namespace oox::xls +{ +class PivotTableFormat; +class PivotTableReference; + +class PivotTableFormatContext : public WorksheetContextBase +{ +public: + explicit PivotTableFormatContext(WorksheetFragmentBase& rFragment, PivotTableFormat& rFormat); + + oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; + void onStartElement(const AttributeList& rAttribs) override; + +private: + PivotTableFormat& mrFormat; +}; + +class PivotTableReferenceContext : public WorksheetContextBase +{ +public: + explicit PivotTableReferenceContext(PivotTableFormatContext& rFragment, + PivotTableReference& rReference); + + oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, + const AttributeList& rAttribs) override; + void onStartElement(const AttributeList& rAttribs) override; + +private: + PivotTableReference& mrReference; +}; + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/inc/pivottablebuffer.hxx b/sc/source/filter/inc/pivottablebuffer.hxx index a4ba60022dea..2c032277e90e 100644 --- a/sc/source/filter/inc/pivottablebuffer.hxx +++ b/sc/source/filter/inc/pivottablebuffer.hxx @@ -20,6 +20,7 @@ #pragma once #include "pivotcachebuffer.hxx" +#include "PivotTableFormat.hxx" #include "stylesbuffer.hxx" #include <rtl/ref.hxx> @@ -318,6 +319,8 @@ public: PivotTableField& createTableField(); /** Creates and returns a new pivot table filter. */ PivotTableFilter& createTableFilter(); + /** Creates and returns a new pivot table format. */ + PivotTableFormat& createFormat(); /** Inserts the pivot table into the sheet. */ void finalizeImport(); /** Finalizes all fields, finds field names and creates grouping fields. */ @@ -377,6 +380,7 @@ private: PageFieldVector maPageFields; /// Settings for all fields in page dimension. DataFieldVector maDataFields; /// Settings for all fields in data area. PivotTableFilterVector maFilters; /// All field filters. + PivotTableFormatVector maFormats; PTDefinitionModel maDefModel; /// Global pivot table settings. PTLocationModel maLocationModel; /// Location settings of the pivot table. PivotCache* mpPivotCache; /// The pivot cache this table is based on. diff --git a/sc/source/filter/oox/PivotTableFormat.cxx b/sc/source/filter/oox/PivotTableFormat.cxx new file mode 100644 index 000000000000..7447b352745a --- /dev/null +++ b/sc/source/filter/oox/PivotTableFormat.cxx @@ -0,0 +1,115 @@ +/* -*- 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/. + */ + +#include <PivotTableFormat.hxx> +#include <pivottablebuffer.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokens.hxx> + +namespace oox::xls +{ +PivotTableFormat::PivotTableFormat(const PivotTable& rPivotTable) + : WorkbookHelper(rPivotTable) +{ +} + +void PivotTableFormat::importFormat(const oox::AttributeList& rAttribs) +{ + mnDxfId = rAttribs.getInteger(XML_dxfId, -1); +} + +void PivotTableFormat::importPivotArea(const oox::AttributeList& rAttribs) +{ + mnField = rAttribs.getInteger(XML_field); + + auto oType = rAttribs.getToken(XML_type); + if (oType) + { + switch (*oType) + { + case XML_none: + meType = PivotAreaType::None; + break; + case XML_data: + meType = PivotAreaType::Data; + break; + case XML_all: + meType = PivotAreaType::All; + break; + case XML_origin: + meType = PivotAreaType::Origin; + break; + case XML_button: + meType = PivotAreaType::Button; + break; + case XML_topRight: + meType = PivotAreaType::TopRight; + break; + default: + case XML_normal: + meType = PivotAreaType::Normal; + break; + } + } + + mbDataOnly = rAttribs.getBool(XML_dataOnly, true); + mbLabelOnly = rAttribs.getBool(XML_labelOnly, false); + mbGrandRow = rAttribs.getBool(XML_grandRow, false); + mbGrandCol = rAttribs.getBool(XML_grandCol, false); + mbCacheIndex = rAttribs.getBool(XML_cacheIndex, false); + mbOutline = rAttribs.getBool(XML_cacheIndex, true); + msOffset = rAttribs.getXString(XML_offset); + mbCollapsedLevelsAreSubtotals = rAttribs.getBool(XML_collapsedLevelsAreSubtotals, false); + mnFieldPosition = rAttribs.getUnsigned(XML_field); +} + +PivotTableReference& PivotTableFormat::createReference() +{ + auto xReference = std::make_shared<PivotTableReference>(*this); + maReferences.push_back(xReference); + return *xReference; +} + +PivotTableReference::PivotTableReference(const PivotTableFormat& rFormat) + : WorkbookHelper(rFormat) +{ +} +void PivotTableReference::importReference(const oox::AttributeList& rAttribs) +{ + mnField = rAttribs.getUnsigned(XML_field); + mnCount = rAttribs.getUnsigned(XML_count); + mbSelected = rAttribs.getBool(XML_selected, true); + mbByPosition = rAttribs.getBool(XML_byPosition, false); + mbRelative = rAttribs.getBool(XML_relative, false); + mbDefaultSubtotal = rAttribs.getBool(XML_defaultSubtotal, false); + mbSumSubtotal = rAttribs.getBool(XML_sumSubtotal, false); + mbCountASubtotal = rAttribs.getBool(XML_countASubtotal, false); + mbAvgSubtotal = rAttribs.getBool(XML_avgSubtotal, false); + mbMaxSubtotal = rAttribs.getBool(XML_maxSubtotal, false); + mbMinSubtotal = rAttribs.getBool(XML_minSubtotal, false); + mbProductSubtotal = rAttribs.getBool(XML_productSubtotal, false); + mbCountSubtotal = rAttribs.getBool(XML_countSubtotal, false); + mbStdDevSubtotal = rAttribs.getBool(XML_stdDevSubtotal, false); + mbStdDevPSubtotal = rAttribs.getBool(XML_stdDevPSubtotal, false); + mbVarSubtotal = rAttribs.getBool(XML_varSubtotal, false); + mbVarPSubtotal = rAttribs.getBool(XML_varPSubtotal, false); +} + +void PivotTableReference::addFieldItem(const oox::AttributeList& rAttribs) +{ + auto oSharedItemsIndex = rAttribs.getUnsigned(XML_v); // XML_v - shared items index + if (oSharedItemsIndex) + { + maFieldItemsIndices.push_back(*oSharedItemsIndex); + } +} + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/oox/PivotTableFormatContext.cxx b/sc/source/filter/oox/PivotTableFormatContext.cxx new file mode 100644 index 000000000000..75893ea1022c --- /dev/null +++ b/sc/source/filter/oox/PivotTableFormatContext.cxx @@ -0,0 +1,92 @@ +/* -*- 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/. + */ + +#include <PivotTableFormatContext.hxx> + +#include <pivottablefragment.hxx> +#include <pivottablebuffer.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/helper/attributelist.hxx> + +namespace oox::xls +{ +PivotTableFormatContext::PivotTableFormatContext(WorksheetFragmentBase& rFragment, + PivotTableFormat& rFormat) + : WorksheetContextBase(rFragment) + , mrFormat(rFormat) +{ +} + +oox::core::ContextHandlerRef +PivotTableFormatContext::onCreateContext(sal_Int32 nElement, const AttributeList& /*rAttribs*/) +{ + switch (getCurrentElement()) + { + case XLS_TOKEN(format): + if (nElement == XLS_TOKEN(pivotArea)) + return this; + break; + case XLS_TOKEN(pivotArea): + if (nElement == XLS_TOKEN(references)) + return this; + break; + case XLS_TOKEN(references): + if (nElement == XLS_TOKEN(reference)) + return new PivotTableReferenceContext(*this, mrFormat.createReference()); + break; + } + return nullptr; +} + +void PivotTableFormatContext::onStartElement(const AttributeList& rAttribs) +{ + if (isRootElement()) + { + mrFormat.importFormat(rAttribs); + } + else if (isCurrentElement(XLS_TOKEN(pivotArea))) + { + mrFormat.importPivotArea(rAttribs); + } +} + +PivotTableReferenceContext::PivotTableReferenceContext(PivotTableFormatContext& rFragment, + PivotTableReference& rReference) + : WorksheetContextBase(rFragment) + , mrReference(rReference) +{ +} +oox::core::ContextHandlerRef +PivotTableReferenceContext::onCreateContext(sal_Int32 nElement, const AttributeList& /*rAttribs*/) +{ + switch (getCurrentElement()) + { + case XLS_TOKEN(reference): + if (nElement == XLS_TOKEN(x)) + return this; + break; + } + return nullptr; +} + +void PivotTableReferenceContext::onStartElement(const AttributeList& rAttribs) +{ + if (isRootElement()) + { + mrReference.importReference(rAttribs); + } + else if (isCurrentElement(XLS_TOKEN(x))) + { + mrReference.addFieldItem(rAttribs); + } +} + +} // namespace oox::xls + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/oox/pivottablebuffer.cxx b/sc/source/filter/oox/pivottablebuffer.cxx index f434780d2756..e5c315fa9cdb 100644 --- a/sc/source/filter/oox/pivottablebuffer.cxx +++ b/sc/source/filter/oox/pivottablebuffer.cxx @@ -60,6 +60,7 @@ #include <document.hxx> #include <documentimport.hxx> #include <workbooksettings.hxx> +#include <PivotTableFormat.hxx> namespace oox::xls { @@ -1234,6 +1235,13 @@ PivotTableFilter& PivotTable::createTableFilter() return *xTableFilter; } +PivotTableFormat& PivotTable::createFormat() +{ + PivotTableFormatVector::value_type xFormat = std::make_shared<PivotTableFormat>(*this); + maFormats.push_back(xFormat); + return *xFormat; +} + void PivotTable::finalizeImport() { if( !getAddressConverter().validateCellRange( maLocationModel.maRange, true, true ) ) @@ -1328,6 +1336,10 @@ void PivotTable::finalizeImport() // filters maFilters.forEachMem( &PivotTableFilter::finalizeImport ); + // formats + //for (auto& pFormat : maFormats) + // pFormat->finalizeImport(); + // calculate base position of table CellAddress aPos( maLocationModel.maRange.aStart.Tab(), maLocationModel.maRange.aStart.Col(), maLocationModel.maRange.aStart.Row() ); /* If page fields exist, include them into the destination diff --git a/sc/source/filter/oox/pivottablefragment.cxx b/sc/source/filter/oox/pivottablefragment.cxx index 76d2abdcde36..d173e6bf0fa3 100644 --- a/sc/source/filter/oox/pivottablefragment.cxx +++ b/sc/source/filter/oox/pivottablefragment.cxx @@ -19,6 +19,7 @@ #include <pivottablefragment.hxx> #include <pivottablebuffer.hxx> +#include <PivotTableFormatContext.hxx> #include <biffhelper.hxx> #include <oox/token/namespaces.hxx> @@ -174,12 +175,14 @@ ContextHandlerRef PivotTableFragment::onCreateContext( sal_Int32 nElement, const switch( nElement ) { case XLS_TOKEN( location ): mrPivotTable.importLocation( rAttribs, getSheetIndex() ); break; - case XLS_TOKEN( pivotFields ): return this; - case XLS_TOKEN( rowFields ): return this; - case XLS_TOKEN( colFields ): return this; - case XLS_TOKEN( pageFields ): return this; - case XLS_TOKEN( dataFields ): return this; - case XLS_TOKEN( filters ): return this; + case XLS_TOKEN(pivotFields): + case XLS_TOKEN(rowFields): + case XLS_TOKEN(colFields): + case XLS_TOKEN(pageFields): + case XLS_TOKEN(dataFields): + case XLS_TOKEN(filters): + case XLS_TOKEN(formats): + return this; case XLS_TOKEN(pivotTableStyleInfo): mrPivotTable.putToInteropGrabBag("pivotTableStyleInfo", rAttribs); break; @@ -204,6 +207,10 @@ ContextHandlerRef PivotTableFragment::onCreateContext( sal_Int32 nElement, const case XLS_TOKEN( filters ): if( nElement == XLS_TOKEN( filter ) ) return new PivotTableFilterContext( *this, mrPivotTable.createTableFilter() ); break; + case XLS_TOKEN(formats): + if (nElement == XLS_TOKEN(format)) + return new PivotTableFormatContext(*this, mrPivotTable.createFormat()); + break; } return nullptr; }