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 <quikee@gmail.com>
This commit is contained in:
Tomaž Vajngerl 2024-03-07 14:18:55 +09:00 committed by Tomaž Vajngerl
parent 2cb757db34
commit a180bf0c0f
8 changed files with 388 additions and 6 deletions

View file

@ -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 \

View file

@ -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: */

View file

@ -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: */

View file

@ -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.

View file

@ -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: */

View file

@ -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: */

View file

@ -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

View file

@ -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;
}