diff options
-rw-r--r-- | sc/inc/pivot/PivotTableFormats.hxx | 14 | ||||
-rw-r--r-- | sc/qa/unit/PivotTableFormatsImportExport.cxx | 14 | ||||
-rw-r--r-- | sc/source/filter/excel/xepivotxml.cxx | 65 | ||||
-rw-r--r-- | sc/source/filter/excel/xestyle.cxx | 115 | ||||
-rw-r--r-- | sc/source/filter/inc/PivotTableFormat.hxx | 5 | ||||
-rw-r--r-- | sc/source/filter/inc/xepivotxml.hxx | 1 | ||||
-rw-r--r-- | sc/source/filter/inc/xestyle.hxx | 8 | ||||
-rw-r--r-- | sc/source/filter/oox/PivotTableFormat.cxx | 15 |
8 files changed, 184 insertions, 53 deletions
diff --git a/sc/inc/pivot/PivotTableFormats.hxx b/sc/inc/pivot/PivotTableFormats.hxx index 2665c088625c..3a4d12e16479 100644 --- a/sc/inc/pivot/PivotTableFormats.hxx +++ b/sc/inc/pivot/PivotTableFormats.hxx @@ -28,6 +28,7 @@ enum class FormatType /** Information to make a selection in the pivot table. */ struct Selection { + bool bSelected = false; sal_Int32 nField = 0; sal_uInt32 nDataIndex = 0; }; @@ -38,8 +39,17 @@ struct Selection struct PivotTableFormat { FormatType eType = FormatType::None; + + bool bDataOnly = true; + bool bLabelOnly = false; + bool bSelected = false; + bool bOutline = false; + std::optional<sal_uInt32> oFieldPosition = std::nullopt; + std::vector<Selection> aSelections; std::shared_ptr<ScPatternAttr> pPattern; + + std::vector<Selection> const& getSelections() const { return aSelections; } }; /** A holder for a collection of PivotTableFormat */ @@ -50,9 +60,9 @@ class PivotTableFormats public: void add(PivotTableFormat const& rPivotTableFormat) { maFormats.push_back(rPivotTableFormat); } - size_t size() { return maFormats.size(); } + size_t size() const { return maFormats.size(); } - std::vector<PivotTableFormat> const& getVector() { return maFormats; } + std::vector<PivotTableFormat> const& getVector() const { return maFormats; } }; } diff --git a/sc/qa/unit/PivotTableFormatsImportExport.cxx b/sc/qa/unit/PivotTableFormatsImportExport.cxx index 3cffe8cbc510..401e190b34f5 100644 --- a/sc/qa/unit/PivotTableFormatsImportExport.cxx +++ b/sc/qa/unit/PivotTableFormatsImportExport.cxx @@ -73,6 +73,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_1_DataFieldInRow_RowLabelColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, @@ -85,6 +87,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc( "xlsx/pivot-table/PivotTableCellFormatsTest_2_DataFieldInRow_ColumnLabelColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, @@ -98,6 +102,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc( "xlsx/pivot-table/PivotTableCellFormatsTest_3_DataFieldInColumn_ColumnLabelColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, @@ -110,6 +116,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc("xlsx/pivot-table/PivotTableCellFormatsTest_4_DataFieldInColumn_DataColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, @@ -124,6 +132,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc("xlsx/pivot-table//" "PivotTableCellFormatsTest_5_DataFieldInColumnAndTwoRowFields_DataColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, @@ -137,6 +147,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc( "xlsx/pivot-table//PivotTableCellFormatsTest_6_SingleDataFieldInColumn_DataColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, @@ -154,6 +166,8 @@ CPPUNIT_TEST_FIXTURE(ScPivotTableFormatsImportExport, createScDoc( "xlsx/pivot-table//PivotTableCellFormatsTest_7_TwoRowTwoColumnFields_DataColor.xlsx"); assertDocument(*getScDoc()); + saveAndReload("Calc Office Open XML"); + assertDocument(*getScDoc()); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx index 633499eadb5e..81f1c71f30a6 100644 --- a/sc/source/filter/excel/xepivotxml.cxx +++ b/sc/source/filter/excel/xepivotxml.cxx @@ -9,6 +9,7 @@ #include <xepivotxml.hxx> #include <dpcache.hxx> +#include <pivot/PivotTableFormats.hxx> #include <dpdimsave.hxx> #include <dpitemdata.hxx> #include <dpobject.hxx> @@ -27,6 +28,7 @@ #include <sal/log.hxx> #include <sax/tools/converter.hxx> #include <sax/fastattribs.hxx> +#include <sax/fshelper.hxx> #include <svl/numformat.hxx> #include <com/sun/star/beans/XPropertySet.hpp> @@ -1181,6 +1183,9 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP pPivotStrm->endElement(XML_dataFields); } + // <formats> + savePivotTableFormats(rStrm, rDPObj); + // Now add style info (use grab bag, or just a set which is default on Excel 2007 through 2016) if (const auto [bHas, aVal] = rDPObj.GetInteropGrabBagValue("pivotTableStyleInfo"); bHas) WriteGrabBagItemToStream(rStrm, XML_pivotTableStyleInfo, aVal); @@ -1202,6 +1207,66 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP pPivotStrm->endElement(XML_pivotTableDefinition); } +void XclExpXmlPivotTables::savePivotTableFormats(XclExpXmlStream& rStream, ScDPObject const& rDPObject) +{ + sax_fastparser::FSHelperPtr& pPivotStream = rStream.GetCurrentStream(); + + ScDPSaveData* pSaveData = rDPObject.GetSaveData(); + if (pSaveData && pSaveData->hasFormats()) + { + sc::PivotTableFormats const& rFormats = pSaveData->getFormats(); + if (rFormats.size() > 0) + { + pPivotStream->startElement(XML_formats, XML_count, OString::number(rFormats.size())); + + for (auto const& rFormat : rFormats.getVector()) + { + if (!rFormat.pPattern) + continue; + + sal_Int32 nDxf = GetDxfs().GetDxfIdForPattern(rFormat.pPattern.get()); + if (nDxf == -1) + continue; + + pPivotStream->startElement(XML_format, XML_dxfId, OString::number(nDxf)); + { + auto pAttributeList = sax_fastparser::FastSerializerHelper::createAttrList(); + if (!rFormat.bDataOnly) // default is true + pAttributeList->add(XML_dataOnly, "0"); + if (rFormat.bLabelOnly) // default is false + pAttributeList->add(XML_labelOnly, "1"); + if (!rFormat.bOutline) // default is true + pAttributeList->add(XML_outline, "0"); + if (rFormat.oFieldPosition) + pAttributeList->add(XML_fieldPosition, OString::number(*rFormat.oFieldPosition)); + pPivotStream->startElement(XML_pivotArea, pAttributeList); + } + pPivotStream->startElement(XML_references, XML_count, OString::number(rFormat.aSelections.size())); + for (sc::Selection const& rSelection : rFormat.getSelections()) + { + { + auto pRefAttributeList = sax_fastparser::FastSerializerHelper::createAttrList(); + pRefAttributeList->add(XML_field, OString::number(sal_uInt32(rSelection.nField))); + pRefAttributeList->add(XML_count, "1"); + if (!rSelection.bSelected) // default is true + pRefAttributeList->add(XML_selected, "0"); + pPivotStream->startElement(XML_reference, pRefAttributeList); + } + + pPivotStream->singleElement(XML_x, XML_v, OString::number(rSelection.nDataIndex)); + + pPivotStream->endElement(XML_reference); + } + pPivotStream->endElement(XML_references); + pPivotStream->endElement(XML_pivotArea); + + pPivotStream->endElement(XML_format); + } + pPivotStream->endElement(XML_formats); + } + } +} + void XclExpXmlPivotTables::AppendTable( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId ) { maTables.emplace_back(pTable, nCacheId, nPivotId); diff --git a/sc/source/filter/excel/xestyle.cxx b/sc/source/filter/excel/xestyle.cxx index 6ee407c369f9..057bee7b30f4 100644 --- a/sc/source/filter/excel/xestyle.cxx +++ b/sc/source/filter/excel/xestyle.cxx @@ -50,6 +50,9 @@ #include <dbdata.hxx> #include <filterentries.hxx> #include <export/ExportTools.hxx> +#include <dpobject.hxx> +#include <dpsave.hxx> +#include <pivot/PivotTableFormats.hxx> #include <o3tl/safeint.hxx> #include <oox/export/utils.hxx> @@ -3070,7 +3073,6 @@ XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot ) xFormatter->FillKeywordTableForExcel( *mpKeywordTable ); SCTAB nTables = rRoot.GetDoc().GetTableCount(); - sal_Int32 nDxfId = 0; for(SCTAB nTab = 0; nTab < nTables; ++nTab) { // Color filters @@ -3089,21 +3091,21 @@ XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot ) // Does not matter it is text color or cell background color for (auto& rColor : aFilterEntries.getBackgroundColors()) { - if (!maColorToDxfId.emplace(rColor, nDxfId).second) + if (!maColorToDxfId.emplace(rColor, mnDxfId).second) continue; std::unique_ptr<XclExpCellArea> pExpCellArea(new XclExpCellArea(rColor, 0)); maDxf.push_back(std::make_unique<XclExpDxf>(rRoot, std::move(pExpCellArea))); - nDxfId++; + mnDxfId++; } for (auto& rColor : aFilterEntries.getTextColors()) { - if (!maColorToDxfId.emplace(rColor, nDxfId).second) + if (!maColorToDxfId.emplace(rColor, mnDxfId).second) continue; std::unique_ptr<XclExpCellArea> pExpCellArea(new XclExpCellArea(rColor, 0)); maDxf.push_back(std::make_unique<XclExpDxf>(rRoot, std::move(pExpCellArea))); - nDxfId++; + mnDxfId++; } } } @@ -3137,57 +3139,74 @@ XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot ) aStyleName = pEntry->GetStyleName(); } - if (maStyleNameToDxfId.emplace(aStyleName, nDxfId).second) + if (maStyleNameToDxfId.emplace(aStyleName, mnDxfId).second) { SfxStyleSheetBase* pStyle = rRoot.GetDoc().GetStyleSheetPool()->Find(aStyleName, SfxStyleFamily::Para); if(!pStyle) continue; SfxItemSet& rSet = pStyle->GetItemSet(); - - std::unique_ptr<XclExpCellBorder> pBorder(new XclExpCellBorder); - if (!pBorder->FillFromItemSet( rSet, GetPalette(), GetBiff()) ) - { - pBorder.reset(); - } - - std::unique_ptr<XclExpCellAlign> pAlign(new XclExpCellAlign); - if (!pAlign->FillFromItemSet(rRoot, rSet, false, GetBiff())) - { - pAlign.reset(); - } - - std::unique_ptr<XclExpCellProt> pCellProt(new XclExpCellProt); - if (!pCellProt->FillFromItemSet( rSet )) - { - pCellProt.reset(); - } - - std::unique_ptr<XclExpColor> pColor(new XclExpColor); - if(!pColor->FillFromItemSet( rSet )) - { - pColor.reset(); - } - - std::unique_ptr<XclExpDxfFont> pFont(new XclExpDxfFont(rRoot, rSet)); - - std::unique_ptr<XclExpNumFmt> pNumFormat; - if( const SfxUInt32Item *pPoolItem = rSet.GetItemIfSet( ATTR_VALUE_FORMAT ) ) - { - sal_uInt32 nScNumFmt = pPoolItem->GetValue(); - sal_Int32 nXclNumFmt = GetRoot().GetNumFmtBuffer().Insert(nScNumFmt); - pNumFormat.reset(new XclExpNumFmt( nScNumFmt, nXclNumFmt, GetNumberFormatCode( *this, nScNumFmt, xFormatter.get(), mpKeywordTable.get() ))); - } - - maDxf.push_back(std::make_unique<XclExpDxf>( rRoot, std::move(pAlign), std::move(pBorder), - std::move(pFont), std::move(pNumFormat), std::move(pCellProt), std::move(pColor) )); - ++nDxfId; + fillDxfFrom(rSet, xFormatter); + mnDxfId++; } } } } } + + ScDPCollection* pCollection = rRoot.GetDoc().GetDPCollection(); + for (size_t nIndex = 0; nIndex < pCollection->GetCount(); nIndex++) + { + const ScDPObject& rObject = (*pCollection)[nIndex]; + ScDPSaveData* pSaveData = rObject.GetSaveData(); + if (pSaveData && pSaveData->hasFormats()) + { + sc::PivotTableFormats const& rFormats = pSaveData->getFormats(); + for (sc::PivotTableFormat const& rFormat : rFormats.getVector()) + { + if (!rFormat.pPattern) + continue; + + SfxItemSet& rItemSet = rFormat.pPattern->GetItemSet(); + fillDxfFrom(rItemSet, xFormatter); + maPatternToDxfId.emplace(rFormat.pPattern.get(), mnDxfId); + mnDxfId++; + } + } + } +} + +void XclExpDxfs::fillDxfFrom(SfxItemSet& rItemSet, SvNumberFormatterPtr& xFormatter) +{ + std::unique_ptr<XclExpCellBorder> pBorder(new XclExpCellBorder); + if (!pBorder->FillFromItemSet(rItemSet, GetPalette(), GetBiff())) + pBorder.reset(); + + std::unique_ptr<XclExpCellAlign> pAlign(new XclExpCellAlign); + if (!pAlign->FillFromItemSet(GetRoot(), rItemSet, false, GetBiff())) + pAlign.reset(); + + std::unique_ptr<XclExpCellProt> pCellProtection(new XclExpCellProt); + if (!pCellProtection->FillFromItemSet(rItemSet)) + pCellProtection.reset(); + + std::unique_ptr<XclExpColor> pColor(new XclExpColor); + if (!pColor->FillFromItemSet(rItemSet)) + pColor.reset(); + + std::unique_ptr<XclExpDxfFont> pFont(new XclExpDxfFont(GetRoot(), rItemSet)); + + std::unique_ptr<XclExpNumFmt> pNumberFormat; + if (const SfxUInt32Item* pPoolItem = rItemSet.GetItemIfSet(ATTR_VALUE_FORMAT)) + { + sal_uInt32 nScNumberFormat = pPoolItem->GetValue(); + sal_Int32 nXclNumberFormat = GetRoot().GetNumFmtBuffer().Insert(nScNumberFormat); + pNumberFormat.reset(new XclExpNumFmt(nScNumberFormat, nXclNumberFormat, GetNumberFormatCode(*this, nScNumberFormat, xFormatter.get(), mpKeywordTable.get()))); + } + + maDxf.push_back(std::make_unique<XclExpDxf>(GetRoot(), std::move(pAlign), std::move(pBorder), + std::move(pFont), std::move(pNumberFormat), std::move(pCellProtection), std::move(pColor))); } sal_Int32 XclExpDxfs::GetDxfId( const OUString& rStyleName ) const @@ -3206,6 +3225,14 @@ sal_Int32 XclExpDxfs::GetDxfByColor(Color aColor) const return -1; } +sal_Int32 XclExpDxfs::GetDxfIdForPattern(ScPatternAttr* pPattern) const +{ + auto iterator = maPatternToDxfId.find(pPattern); + if (iterator != maPatternToDxfId.end()) + return iterator->second; + return -1; +} + void XclExpDxfs::addColor(Color aColor) { maColorToDxfId.emplace(aColor, maDxf.size()); diff --git a/sc/source/filter/inc/PivotTableFormat.hxx b/sc/source/filter/inc/PivotTableFormat.hxx index 204dea566def..3a7b56cf423b 100644 --- a/sc/source/filter/inc/PivotTableFormat.hxx +++ b/sc/source/filter/inc/PivotTableFormat.hxx @@ -43,16 +43,17 @@ private: // PivotArea std::optional<sal_Int32> mnField; PivotAreaType meType = PivotAreaType::Normal; + std::optional<sal_uInt32> moField = std::nullopt; bool mbDataOnly = true; bool mbLabelOnly = false; bool mbGrandRow = false; bool mbGrandCol = false; bool mbCacheIndex = false; bool mbOutline = true; - std::optional<OUString> msOffset; + std::optional<OUString> moOffset = std::nullopt; bool mbCollapsedLevelsAreSubtotals = false; // TODO Axis - std::optional<sal_uInt32> mnFieldPosition; + std::optional<sal_uInt32> moFieldPosition = std::nullopt; std::vector<std::shared_ptr<PivotTableReference>> maReferences; diff --git a/sc/source/filter/inc/xepivotxml.hxx b/sc/source/filter/inc/xepivotxml.hxx index 30fb25a30f48..5e02ba214b78 100644 --- a/sc/source/filter/inc/xepivotxml.hxx +++ b/sc/source/filter/inc/xepivotxml.hxx @@ -66,6 +66,7 @@ public: private: void SavePivotTableXml(XclExpXmlStream& rStrm, const ScDPObject& rObj, sal_Int32 nCacheId); + void savePivotTableFormats(XclExpXmlStream& rStrm, ScDPObject const& rDPObject); }; class XclExpXmlPivotTableManager : protected XclExpRoot diff --git a/sc/source/filter/inc/xestyle.hxx b/sc/source/filter/inc/xestyle.hxx index dd290af06825..740c892dcb68 100644 --- a/sc/source/filter/inc/xestyle.hxx +++ b/sc/source/filter/inc/xestyle.hxx @@ -758,9 +758,10 @@ private: class XclExpDxfs : public XclExpRecordBase, protected XclExpRoot { public: - XclExpDxfs( const XclExpRoot& rRoot ); + XclExpDxfs(const XclExpRoot& rRoot); sal_Int32 GetDxfId(const OUString& rName) const; + sal_Int32 GetDxfIdForPattern(ScPatternAttr* pPattern) const; sal_Int32 GetDxfByColor(Color aColor) const; void addColor(Color aColor); @@ -769,10 +770,15 @@ public: private: typedef std::vector< std::unique_ptr<XclExpDxf> > DxfContainer; + sal_Int32 mnDxfId = 0; std::map<OUString, sal_Int32> maStyleNameToDxfId; std::map<Color, sal_Int32> maColorToDxfId; + std::map<ScPatternAttr*, sal_Int32> maPatternToDxfId; DxfContainer maDxf; std::unique_ptr<NfKeywordTable> mpKeywordTable; /// Replacement table. + + void fillDxfFrom(SfxItemSet& rItemSet, SvNumberFormatterPtr& xFormatter); + }; class XclExpXmlStyleSheet : public XclExpRecordBase, protected XclExpRoot diff --git a/sc/source/filter/oox/PivotTableFormat.cxx b/sc/source/filter/oox/PivotTableFormat.cxx index 9b16087400d2..156fe9983a6e 100644 --- a/sc/source/filter/oox/PivotTableFormat.cxx +++ b/sc/source/filter/oox/PivotTableFormat.cxx @@ -62,15 +62,16 @@ void PivotTableFormat::importPivotArea(const oox::AttributeList& rAttribs) } } + moField = rAttribs.getUnsigned(XML_field); 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); + mbOutline = rAttribs.getBool(XML_outline, true); + moOffset = rAttribs.getXString(XML_offset); mbCollapsedLevelsAreSubtotals = rAttribs.getBool(XML_collapsedLevelsAreSubtotals, false); - mnFieldPosition = rAttribs.getUnsigned(XML_field); + moFieldPosition = rAttribs.getUnsigned(XML_fieldPosition); } void PivotTableFormat::finalizeImport() @@ -95,13 +96,19 @@ void PivotTableFormat::finalizeImport() else if (mbLabelOnly) aFormat.eType = sc::FormatType::Label; + aFormat.bDataOnly = mbDataOnly; + aFormat.bLabelOnly = mbLabelOnly; + aFormat.bOutline = mbOutline; + aFormat.oFieldPosition = moFieldPosition; + aFormat.pPattern = pPattern; for (auto& rReference : maReferences) { if (rReference->mnField) { aFormat.aSelections.push_back( - sc::Selection{ .nField = sal_Int32(*rReference->mnField), + sc::Selection{ .bSelected = rReference->mbSelected, + .nField = sal_Int32(*rReference->mnField), .nDataIndex = rReference->maFieldItemsIndices[0] }); } } |