diff options
Diffstat (limited to 'sc/source/filter/xml/XMLExportDataPilot.cxx')
-rw-r--r-- | sc/source/filter/xml/XMLExportDataPilot.cxx | 901 |
1 files changed, 901 insertions, 0 deletions
diff --git a/sc/source/filter/xml/XMLExportDataPilot.cxx b/sc/source/filter/xml/XMLExportDataPilot.cxx new file mode 100644 index 000000000..cd6f26b11 --- /dev/null +++ b/sc/source/filter/xml/XMLExportDataPilot.cxx @@ -0,0 +1,901 @@ +/* -*- 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 . + */ + +#include "XMLExportDataPilot.hxx" +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/namespacemap.hxx> +#include <sax/tools/converter.hxx> +#include <rtl/math.hxx> +#include <osl/diagnose.h> +#include "xmlexprt.hxx" +#include "XMLConverter.hxx" +#include <document.hxx> +#include <dpobject.hxx> +#include <dociter.hxx> +#include <attrib.hxx> +#include <patattr.hxx> +#include <scitems.hxx> +#include <dpsave.hxx> +#include <dpshttab.hxx> +#include <dpsdbtab.hxx> +#include <dpdimsave.hxx> +#include <dputil.hxx> +#include <rangeutl.hxx> +#include <queryentry.hxx> +#include <com/sun/star/sheet/DataImportMode.hpp> +#include <com/sun/star/sheet/DataPilotFieldReference.hpp> +#include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp> +#include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp> +#include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp> +#include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp> +#include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp> +#include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp> +#include <com/sun/star/sheet/DataPilotFieldSortMode.hpp> +#include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp> +#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> +#include <com/sun/star/sheet/GeneralFunction2.hpp> + +using namespace com::sun::star; +using namespace xmloff::token; + +ScXMLExportDataPilot::ScXMLExportDataPilot(ScXMLExport& rTempExport) + : rExport(rTempExport), + pDoc( nullptr ) +{ +} + +OUString ScXMLExportDataPilot::getDPOperatorXML( + const ScQueryOp aFilterOperator, const utl::SearchParam::SearchType eSearchType) +{ + switch (aFilterOperator) + { + case SC_EQUAL : + { + if (eSearchType == utl::SearchParam::SearchType::Regexp) + return GetXMLToken(XML_MATCH); + else + return "="; + } + case SC_NOT_EQUAL : + { + if (eSearchType == utl::SearchParam::SearchType::Regexp) + return GetXMLToken(XML_NOMATCH); + else + return "!="; + } + case SC_BOTPERC : + return GetXMLToken(XML_BOTTOM_PERCENT); + case SC_BOTVAL : + return GetXMLToken(XML_BOTTOM_VALUES); + case SC_GREATER : + return ">"; + case SC_GREATER_EQUAL : + return ">="; + case SC_LESS : + return "<"; + case SC_LESS_EQUAL : + return "<="; + case SC_TOPPERC : + return GetXMLToken(XML_TOP_PERCENT); + case SC_TOPVAL : + return GetXMLToken(XML_TOP_VALUES); + default: + OSL_FAIL("This FilterOperator is not supported."); + } + return "="; +} + +void ScXMLExportDataPilot::WriteDPCondition(const ScQueryEntry& aQueryEntry, bool bIsCaseSensitive, + utl::SearchParam::SearchType eSearchType) +{ + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, OUString::number(aQueryEntry.nField)); + if (bIsCaseSensitive) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CASE_SENSITIVE, XML_TRUE); + const ScQueryEntry::Item& rItem = aQueryEntry.GetQueryItem(); + OUString aQueryStr = rItem.maString.getString(); + if (rItem.meType == ScQueryEntry::ByString) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, aQueryStr); + } + else + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_TYPE, XML_NUMBER); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_VALUE, aQueryStr); + } + + if (aQueryEntry.IsQueryByEmpty()) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, GetXMLToken(XML_EMPTY)); + } + else if (aQueryEntry.IsQueryByNonEmpty()) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OPERATOR, GetXMLToken(XML_NOEMPTY)); + } + else + rExport.AddAttribute( + XML_NAMESPACE_TABLE, XML_OPERATOR, + getDPOperatorXML(aQueryEntry.eOp, eSearchType)); + + SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, true, true); +} + +void ScXMLExportDataPilot::WriteDPFilter(const ScQueryParam& aQueryParam) +{ + SCSIZE nQueryEntryCount = aQueryParam.GetEntryCount(); + if (nQueryEntryCount <= 0) + return; + + bool bAnd(false); + bool bOr(false); + bool bHasEntries(true); + SCSIZE nEntries(0); + SCSIZE j; + + for ( j = 0; (j < nQueryEntryCount) && bHasEntries; ++j) + { + ScQueryEntry aEntry = aQueryParam.GetEntry(j); + if (aEntry.bDoQuery) + { + if (nEntries > 0) + { + if (aEntry.eConnect == SC_AND) + bAnd = true; + else + bOr = true; + } + ++nEntries; + } + else + bHasEntries = false; + } + nQueryEntryCount = nEntries; + if (!nQueryEntryCount) + return; + + if(!((aQueryParam.nCol1 == aQueryParam.nCol2) && (aQueryParam.nRow1 == aQueryParam.nRow2) && + (static_cast<SCCOLROW>(aQueryParam.nCol1) == static_cast<SCCOLROW>(aQueryParam.nRow1)) && + (aQueryParam.nCol1 == 0) && (aQueryParam.nTab == SCTAB_MAX))) + { + ScRange aConditionRange(aQueryParam.nCol1, aQueryParam.nRow1, aQueryParam.nTab, + aQueryParam.nCol2, aQueryParam.nRow2, aQueryParam.nTab); + OUString sConditionRange; + ScRangeStringConverter::GetStringFromRange( sConditionRange, aConditionRange, pDoc, ::formula::FormulaGrammar::CONV_OOO ); + if (!sConditionRange.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CONDITION_SOURCE_RANGE_ADDRESS, sConditionRange); + } + if (!aQueryParam.bDuplicate) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_DUPLICATES, XML_FALSE); + SvXMLElementExport aElemDPF(rExport, XML_NAMESPACE_TABLE, XML_FILTER, true, true); + rExport.CheckAttrList(); + if (nQueryEntryCount == 1) + { + WriteDPCondition(aQueryParam.GetEntry(0), aQueryParam.bCaseSens, aQueryParam.eSearchType); + } + else if (bOr && !bAnd) + { + SvXMLElementExport aElemOr(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true); + for (j = 0; j < nQueryEntryCount; ++j) + { + WriteDPCondition(aQueryParam.GetEntry(j), aQueryParam.bCaseSens, aQueryParam.eSearchType); + } + } + else if (bAnd && !bOr) + { + SvXMLElementExport aElemAnd(rExport, XML_NAMESPACE_TABLE, XML_FILTER_AND, true, true); + for (j = 0; j < nQueryEntryCount; ++j) + { + WriteDPCondition(aQueryParam.GetEntry(j), aQueryParam.bCaseSens, aQueryParam.eSearchType); + } + } + else + { + SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, true, true); + ScQueryEntry aPrevFilterField(aQueryParam.GetEntry(0)); + ScQueryConnect aConnection = aQueryParam.GetEntry(1).eConnect; + bool bOpenAndElement; + OUString aName(rExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND))); + if (aConnection == SC_AND) + { + rExport.StartElement( aName, true ); + bOpenAndElement = true; + } + else + bOpenAndElement = false; + for (j = 1; j < nQueryEntryCount; ++j) + { + if (aConnection != aQueryParam.GetEntry(j).eConnect) + { + aConnection = aQueryParam.GetEntry(j).eConnect; + if (aQueryParam.GetEntry(j).eConnect == SC_AND) + { + rExport.StartElement( aName, true ); + bOpenAndElement = true; + WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.eSearchType); + aPrevFilterField = aQueryParam.GetEntry(j); + if (j == nQueryEntryCount - 1) + { + WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.eSearchType); + rExport.EndElement(aName, true); + bOpenAndElement = false; + } + } + else + { + WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.eSearchType); + aPrevFilterField = aQueryParam.GetEntry(j); + if (bOpenAndElement) + { + rExport.EndElement(aName, true); + bOpenAndElement = false; + } + if (j == nQueryEntryCount - 1) + { + WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.eSearchType); + } + } + } + else + { + WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.eSearchType); + aPrevFilterField = aQueryParam.GetEntry(j); + if (j == nQueryEntryCount - 1) + WriteDPCondition(aPrevFilterField, aQueryParam.bCaseSens, aQueryParam.eSearchType); + } + } + } +} + +void ScXMLExportDataPilot::WriteFieldReference(const ScDPSaveDimension* pDim) +{ + const sheet::DataPilotFieldReference* pRef = pDim->GetReferenceValue(); + if (pRef) + { + OUString sValueStr; + switch (pRef->ReferenceType) + { + case sheet::DataPilotFieldReferenceType::NONE : + sValueStr = GetXMLToken(XML_NONE); + break; + case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE : + sValueStr = GetXMLToken(XML_MEMBER_DIFFERENCE); + break; + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE : + sValueStr = GetXMLToken(XML_MEMBER_PERCENTAGE); + break; + case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE : + sValueStr = GetXMLToken(XML_MEMBER_PERCENTAGE_DIFFERENCE); + break; + case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL : + sValueStr = GetXMLToken(XML_RUNNING_TOTAL); + break; + case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE : + sValueStr = GetXMLToken(XML_ROW_PERCENTAGE); + break; + case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE : + sValueStr = GetXMLToken(XML_COLUMN_PERCENTAGE); + break; + case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE : + sValueStr = GetXMLToken(XML_TOTAL_PERCENTAGE); + break; + case sheet::DataPilotFieldReferenceType::INDEX : + sValueStr = GetXMLToken(XML_INDEX); + break; + } + if (!sValueStr.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TYPE, sValueStr); + + if (!pRef->ReferenceField.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NAME, pRef->ReferenceField); + + if (pRef->ReferenceItemType == sheet::DataPilotFieldReferenceItemType::NAMED) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_TYPE, XML_NAMED); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_NAME, pRef->ReferenceItemName); + } + else + { + sValueStr.clear(); + switch(pRef->ReferenceItemType) + { + case sheet::DataPilotFieldReferenceItemType::PREVIOUS : + sValueStr = GetXMLToken(XML_PREVIOUS); + break; + case sheet::DataPilotFieldReferenceItemType::NEXT : + sValueStr = GetXMLToken(XML_NEXT); + break; + } + if (!sValueStr.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_TYPE, sValueStr); + } + SvXMLElementExport aElemDPFR(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_FIELD_REFERENCE, true, true); + } + rExport.CheckAttrList(); +} + +void ScXMLExportDataPilot::WriteSortInfo(const ScDPSaveDimension* pDim) +{ + const sheet::DataPilotFieldSortInfo* pSortInfo = pDim->GetSortInfo(); + if (!pSortInfo) + return; + + if (pSortInfo->IsAscending) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_ASCENDING); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORDER, XML_DESCENDING); + + OUString sValueStr; + switch (pSortInfo->Mode) + { + case sheet::DataPilotFieldSortMode::NONE: + sValueStr = GetXMLToken(XML_NONE); + break; + case sheet::DataPilotFieldSortMode::MANUAL: + sValueStr = GetXMLToken(XML_MANUAL); + break; + case sheet::DataPilotFieldSortMode::NAME: + sValueStr = GetXMLToken(XML_NAME); + break; + case sheet::DataPilotFieldSortMode::DATA: + sValueStr = GetXMLToken(XML_DATA); + if (!pSortInfo->Field.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_FIELD, pSortInfo->Field); + break; + } + if (!sValueStr.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SORT_MODE, sValueStr); + SvXMLElementExport aElemDPLSI(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_SORT_INFO, true, true); +} + +void ScXMLExportDataPilot::WriteAutoShowInfo(const ScDPSaveDimension* pDim) +{ + const sheet::DataPilotFieldAutoShowInfo* pAutoInfo = pDim->GetAutoShowInfo(); + if (!pAutoInfo) + return; + + if (pAutoInfo->IsEnabled) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ENABLED, XML_TRUE); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ENABLED, XML_FALSE); + + OUString sValueStr; + switch (pAutoInfo->ShowItemsMode) + { + case sheet::DataPilotFieldShowItemsMode::FROM_TOP: + sValueStr = GetXMLToken(XML_FROM_TOP); + break; + case sheet::DataPilotFieldShowItemsMode::FROM_BOTTOM: + sValueStr = GetXMLToken(XML_FROM_BOTTOM); + break; + } + if (!sValueStr.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY_MEMBER_MODE, sValueStr); + + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_MEMBER_COUNT, OUString::number(pAutoInfo->ItemCount)); + + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATA_FIELD, pAutoInfo->DataField); + + SvXMLElementExport aElemDPLAI(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_DISPLAY_INFO, true, true); +} + +void ScXMLExportDataPilot::WriteLayoutInfo(const ScDPSaveDimension* pDim) +{ + const sheet::DataPilotFieldLayoutInfo* pLayoutInfo = pDim->GetLayoutInfo(); + if (!pLayoutInfo) + return; + + if (pLayoutInfo->AddEmptyLines) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ADD_EMPTY_LINES, XML_TRUE); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ADD_EMPTY_LINES, XML_FALSE); + + OUString sValueStr; + switch (pLayoutInfo->LayoutMode) + { + case sheet::DataPilotFieldLayoutMode::TABULAR_LAYOUT: + sValueStr = GetXMLToken(XML_TABULAR_LAYOUT); + break; + case sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP: + sValueStr = GetXMLToken(XML_OUTLINE_SUBTOTALS_TOP); + break; + case sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM: + sValueStr = GetXMLToken(XML_OUTLINE_SUBTOTALS_BOTTOM); + break; + } + if (!sValueStr.isEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_LAYOUT_MODE, sValueStr); + SvXMLElementExport aElemDPLLI(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_LAYOUT_INFO, true, true); +} + +void ScXMLExportDataPilot::WriteSubTotals(const ScDPSaveDimension* pDim) +{ + sal_Int32 nSubTotalCount = pDim->GetSubTotalsCount(); + std::optional<OUString> pLayoutName; + if (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + // Export display names only for 1.2 extended or later. + pLayoutName = pDim->GetSubtotalName(); + + if (nSubTotalCount <= 0) + return; + + SvXMLElementExport aElemSTs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_SUBTOTALS, true, true); + rExport.CheckAttrList(); + for (sal_Int32 nSubTotal = 0; nSubTotal < nSubTotalCount; nSubTotal++) + { + sal_Int16 nFunc = static_cast<sal_Int16>(pDim->GetSubTotalFunc(nSubTotal)); + OUString sFunction = ScXMLConverter::GetStringFromFunction(nFunc); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, sFunction); + if (pLayoutName && nFunc == sheet::GeneralFunction2::AUTO) + rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pLayoutName); + SvXMLElementExport aElemST(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_SUBTOTAL, true, true); + } +} + +void ScXMLExportDataPilot::WriteMembers(const ScDPSaveDimension* pDim) +{ + const ScDPSaveDimension::MemberList &rMembers = pDim->GetMembers(); + if (rMembers.empty()) + return; + + SvXMLElementExport aElemDPMs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_MEMBERS, true, true); + rExport.CheckAttrList(); + for (const auto& rpMember : rMembers) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rpMember->GetName()); + + if (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + // Export display names only for ODF 1.2 extended or later. + const std::optional<OUString> & pLayoutName = rpMember->GetLayoutName(); + if (pLayoutName) + rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pLayoutName); + } + + OUStringBuffer sBuffer; + ::sax::Converter::convertBool(sBuffer, rpMember->GetIsVisible()); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, sBuffer.makeStringAndClear()); + ::sax::Converter::convertBool(sBuffer, rpMember->GetShowDetails()); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SHOW_DETAILS, sBuffer.makeStringAndClear()); + SvXMLElementExport aElemDPM(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_MEMBER, true, true); + rExport.CheckAttrList(); + } +} + +void ScXMLExportDataPilot::WriteLevels(const ScDPSaveDimension* pDim) +{ + // #i114202# GetShowEmpty is only valid if HasShowEmpty is true. + if (pDim->HasShowEmpty()) + { + OUStringBuffer sBuffer; + ::sax::Converter::convertBool(sBuffer, pDim->GetShowEmpty()); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SHOW_EMPTY, sBuffer.makeStringAndClear()); + } + if (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + OUStringBuffer sBuffer; + ::sax::Converter::convertBool(sBuffer, pDim->GetRepeatItemLabels()); + rExport.AddAttribute(XML_NAMESPACE_CALC_EXT, XML_REPEAT_ITEM_LABELS, sBuffer.makeStringAndClear()); + } + SvXMLElementExport aElemDPL(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_LEVEL, true, true); + + WriteSubTotals(pDim); + WriteMembers(pDim); + WriteAutoShowInfo(pDim); + WriteSortInfo(pDim); + WriteLayoutInfo(pDim); + rExport.CheckAttrList(); +} + +void ScXMLExportDataPilot::WriteDatePart(sal_Int32 nPart) +{ + switch(nPart) + { + case css::sheet::DataPilotFieldGroupBy::SECONDS : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_SECONDS); + } + break; + case css::sheet::DataPilotFieldGroupBy::MINUTES : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_MINUTES); + } + break; + case css::sheet::DataPilotFieldGroupBy::HOURS : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_HOURS); + } + break; + case css::sheet::DataPilotFieldGroupBy::DAYS : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_DAYS); + } + break; + case css::sheet::DataPilotFieldGroupBy::MONTHS : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_MONTHS); + } + break; + case css::sheet::DataPilotFieldGroupBy::QUARTERS : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_QUARTERS); + } + break; + case css::sheet::DataPilotFieldGroupBy::YEARS : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GROUPED_BY, XML_YEARS); + } + break; + } +} + +void ScXMLExportDataPilot::WriteNumGroupInfo(const ScDPNumGroupInfo& rGroupInfo) +{ + OSL_ENSURE(rGroupInfo.mbEnable, "group dimension should be enabled"); + if (rGroupInfo.mbDateValues) + { + if (rGroupInfo.mbAutoStart) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_START, XML_AUTO); + else + { + OUStringBuffer sDate; + rExport.GetMM100UnitConverter().convertDateTime(sDate, rGroupInfo.mfStart); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_START, sDate.makeStringAndClear()); + } + if (rGroupInfo.mbAutoEnd) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_END, XML_AUTO); + else + { + OUStringBuffer sDate; + rExport.GetMM100UnitConverter().convertDateTime(sDate, rGroupInfo.mfEnd); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATE_END, sDate.makeStringAndClear()); + } + } + else + { + if (rGroupInfo.mbAutoStart) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_START, XML_AUTO); + else + { + OUString sValue( ::rtl::math::doubleToUString( rGroupInfo.mfStart, + rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', true)); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_START, sValue); + } + if (rGroupInfo.mbAutoEnd) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_END, XML_AUTO); + else + { + OUString sValue( ::rtl::math::doubleToUString( rGroupInfo.mfEnd, + rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', true)); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_END, sValue); + } + } + OUString sValue( ::rtl::math::doubleToUString( rGroupInfo.mfStep, + rtl_math_StringFormat_Automatic, + rtl_math_DecimalPlaces_Max, '.', true)); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_STEP, sValue); +} + +void ScXMLExportDataPilot::WriteGroupDimAttributes(const ScDPSaveGroupDimension* pGroupDim) +{ + if (pGroupDim) + { + OUString aSrcFieldName = ScDPUtil::getSourceDimensionName(pGroupDim->GetSourceDimName()); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SOURCE_FIELD_NAME, aSrcFieldName); + if (pGroupDim->GetDatePart()) + { + WriteDatePart(pGroupDim->GetDatePart()); + WriteNumGroupInfo(pGroupDim->GetDateInfo()); + } + } +} + +void ScXMLExportDataPilot::WriteNumGroupDim(const ScDPSaveNumGroupDimension* pNumGroupDim) +{ + if (pNumGroupDim) + { + if (pNumGroupDim->GetDatePart()) + { + WriteDatePart(pNumGroupDim->GetDatePart()); + WriteNumGroupInfo(pNumGroupDim->GetDateInfo()); + } + else + { + WriteNumGroupInfo(pNumGroupDim->GetInfo()); + } + } +} + +void ScXMLExportDataPilot::WriteGroupDimElements(const ScDPSaveDimension* pDim, const ScDPDimensionSaveData* pDimData) +{ + const ScDPSaveGroupDimension* pGroupDim = nullptr; + const ScDPSaveNumGroupDimension* pNumGroupDim = nullptr; + if (pDimData) + { + pGroupDim = pDimData->GetNamedGroupDim(pDim->GetName()); + pNumGroupDim = pDimData->GetNumGroupDim(pDim->GetName()); + OSL_ENSURE((!pGroupDim || !pNumGroupDim), "there should be no NumGroup and Group at the same field"); + if (pGroupDim) + WriteGroupDimAttributes(pGroupDim); + else if (pNumGroupDim) + WriteNumGroupDim(pNumGroupDim); + } + if (!(pGroupDim || pNumGroupDim)) + return; + + SvXMLElementExport aElemDPGs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_GROUPS, true, true); + if (!pGroupDim) + return; + + if (pGroupDim->GetDatePart()) + return; + + sal_Int32 nCount = pGroupDim->GetGroupCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + const ScDPSaveGroupItem& rGroup = pGroupDim->GetGroupByIndex( i ); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, rGroup.GetGroupName()); + SvXMLElementExport aElemDPG(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_GROUP, true, true); + sal_Int32 nElemCount = rGroup.GetElementCount(); + for(sal_Int32 j = 0; j < nElemCount; ++j) + { + const OUString* pElem = rGroup.GetElementByIndex(j); + if (pElem) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, *pElem); + SvXMLElementExport aElemDPM(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_GROUP_MEMBER, true, true); + } + } + } +} + +void ScXMLExportDataPilot::WriteDimension(const ScDPSaveDimension* pDim, const ScDPDimensionSaveData* pDimData) +{ + OUString aSrcDimName = ScDPUtil::getSourceDimensionName(pDim->GetName()); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SOURCE_FIELD_NAME, aSrcDimName); + if (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + // Export display names only for ODF 1.2 extended or later. + const std::optional<OUString> & pLayoutName = pDim->GetLayoutName(); + if (pLayoutName) + rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pLayoutName); + } + + if (pDim->IsDataLayout()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IS_DATA_LAYOUT_FIELD, XML_TRUE); + sheet::DataPilotFieldOrientation eOrientation = pDim->GetOrientation(); + OUString sValueStr = ScXMLConverter::GetStringFromOrientation(eOrientation); + if( !sValueStr.isEmpty() ) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, sValueStr ); + if (pDim->GetUsedHierarchy() != 1) + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_USED_HIERARCHY, OUString::number(pDim->GetUsedHierarchy())); + } + sValueStr = ScXMLConverter::GetStringFromFunction( static_cast<sal_Int16>(pDim->GetFunction()) ); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FUNCTION, sValueStr); + + if (eOrientation == sheet::DataPilotFieldOrientation_PAGE) + { + if (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + rExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_IGNORE_SELECTED_PAGE, "true"); + } + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SELECTED_PAGE, pDim->GetCurrentPage()); + } + + SvXMLElementExport aElemDPF(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_FIELD, true, true); + WriteLevels(pDim); + WriteFieldReference(pDim); + if( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_DATA ) + WriteGroupDimElements(pDim, pDimData); +} + +void ScXMLExportDataPilot::WriteDimensions(const ScDPSaveData* pDPSave) +{ + const ScDPSaveData::DimsType& rDimensions = pDPSave->GetDimensions(); + for (auto const& iter : rDimensions) + { + WriteDimension(iter.get(), + pDPSave->GetExistingDimensionData()); + } +} + +void ScXMLExportDataPilot::WriteGrandTotal(::xmloff::token::XMLTokenEnum eOrient, bool bVisible, const std::optional<OUString> & pGrandTotal) +{ + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DISPLAY, bVisible ? XML_TRUE : XML_FALSE); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_ORIENTATION, eOrient); + if (pGrandTotal) + rExport.AddAttribute(XML_NAMESPACE_TABLE_EXT, XML_DISPLAY_NAME, *pGrandTotal); + + SvXMLElementExport aElemGrandTotal(rExport, XML_NAMESPACE_TABLE_EXT, XML_DATA_PILOT_GRAND_TOTAL, true, true); +} + +void ScXMLExportDataPilot::WriteDataPilots() +{ + pDoc = rExport.GetDocument(); + if (!pDoc) + return; + + ScDPCollection* pDPs = pDoc->GetDPCollection(); + if (!pDPs) + return; + + size_t nDPCount = pDPs->GetCount(); + if (!nDPCount) + return; + + SvXMLElementExport aElemDPs(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_TABLES, true, true); + rExport.CheckAttrList(); + for (size_t i = 0; i < nDPCount; ++i) + { + ScDPSaveData* pDPSave = (*pDPs)[i].GetSaveData(); + if (!pDPSave) + continue; + + ScRange aOutRange((*pDPs)[i].GetOutRange()); + OUString sTargetRangeAddress; + ScRangeStringConverter::GetStringFromRange( sTargetRangeAddress, aOutRange, pDoc, ::formula::FormulaGrammar::CONV_OOO ); + ScDocAttrIterator aAttrItr(*pDoc, aOutRange.aStart.Tab(), + aOutRange.aStart.Col(), aOutRange.aStart.Row(), + aOutRange.aEnd.Col(), aOutRange.aEnd.Row()); + SCCOL nCol; + SCROW nRow1, nRow2; + OUString sOUButtonList; + const ScPatternAttr* pAttr = aAttrItr.GetNext(nCol, nRow1, nRow2); + while (pAttr) + { + const ScMergeFlagAttr& rItem = pAttr->GetItem(ATTR_MERGE_FLAG); + if (rItem.HasPivotButton()) + { + for (SCROW nButtonRow = nRow1; nButtonRow <= nRow2; ++nButtonRow) + { + ScAddress aButtonAddr(nCol, nButtonRow, aOutRange.aStart.Tab()); + ScRangeStringConverter::GetStringFromAddress( + sOUButtonList, aButtonAddr, pDoc, ::formula::FormulaGrammar::CONV_OOO, ' ', true ); + } + } + pAttr = aAttrItr.GetNext(nCol, nRow1, nRow2); + } + OUString sName((*pDPs)[i].GetName()); + OUString sApplicationData((*pDPs)[i].GetTag()); + bool bRowGrand = pDPSave->GetRowGrand(); + bool bColumnGrand = pDPSave->GetColumnGrand(); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, sName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_APPLICATION_DATA, sApplicationData); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TARGET_RANGE_ADDRESS, sTargetRangeAddress); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BUTTONS, sOUButtonList); + if (!(bRowGrand && bColumnGrand)) + { + if (bRowGrand) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GRAND_TOTAL, XML_ROW); + else if (bColumnGrand) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GRAND_TOTAL, XML_COLUMN); + else + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_GRAND_TOTAL, XML_NONE); + } + if (pDPSave->GetIgnoreEmptyRows()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IGNORE_EMPTY_ROWS, XML_TRUE); + if (pDPSave->GetRepeatIfEmpty()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_IDENTIFY_CATEGORIES, XML_TRUE); + if (!pDPSave->GetFilterButton()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SHOW_FILTER_BUTTON, XML_FALSE); + if (!pDPSave->GetDrillDown()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DRILL_DOWN_ON_DOUBLE_CLICK, XML_FALSE); + if ((*pDPs)[i].GetHeaderLayout()) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HEADER_GRID_LAYOUT, XML_TRUE); + + SvXMLElementExport aElemDP(rExport, XML_NAMESPACE_TABLE, XML_DATA_PILOT_TABLE, true, true); + + // grand total elements. + + const std::optional<OUString> & pGrandTotalName = pDPSave->GetGrandTotalName(); + if (pGrandTotalName && rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + // Use the new data-pilot-grand-total element. + if (bRowGrand && bColumnGrand) + { + WriteGrandTotal(XML_BOTH, true, pGrandTotalName); + } + else + { + WriteGrandTotal(XML_ROW, bRowGrand, pGrandTotalName); + WriteGrandTotal(XML_COLUMN, bColumnGrand, pGrandTotalName); + } + } + + rExport.CheckAttrList(); + if ((*pDPs)[i].IsSheetData()) + { + const ScSheetSourceDesc* pSheetSource = (*pDPs)[i].GetSheetDesc(); + + if (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED) + { + if (pSheetSource->HasRangeName()) + { // ODF 1.3 OFFICE-3665 + // FIXME this was wrongly exported to TABLE namespace since 2011 + // so continue doing that in ODF 1.2 extended, for now + rExport.AddAttribute( + XML_NAMESPACE_TABLE, XML_NAME, pSheetSource->GetRangeName()); + } + } + + OUString sCellRangeAddress; + ScRangeStringConverter::GetStringFromRange( + sCellRangeAddress, pSheetSource->GetSourceRange(), pDoc, + ::formula::FormulaGrammar::CONV_OOO); + + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_CELL_RANGE_ADDRESS, sCellRangeAddress); + SvXMLElementExport aElemSCR(rExport, XML_NAMESPACE_TABLE, XML_SOURCE_CELL_RANGE, true, true); + rExport.CheckAttrList(); + WriteDPFilter(pSheetSource->GetQueryParam()); + } + else if ((*pDPs)[i].IsImportData()) + { + const ScImportSourceDesc* pImpSource = (*pDPs)[i].GetImportSourceDesc(); + switch (pImpSource->nType) + { + case sheet::DataImportMode_NONE : break; + case sheet::DataImportMode_QUERY : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, pImpSource->aObject); + SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, true, true); + rExport.CheckAttrList(); + } + break; + case sheet::DataImportMode_TABLE : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_TABLE_NAME, pImpSource->aObject); + SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, true, true); + rExport.CheckAttrList(); + } + break; + case sheet::DataImportMode_SQL : + { + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, pImpSource->aObject); + if (!pImpSource->bNative) + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE); + SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, true, true); + rExport.CheckAttrList(); + } + break; + default: break; + } + } + else if ((*pDPs)[i].IsServiceData()) + { + const ScDPServiceDesc* pServSource = (*pDPs)[i].GetDPServiceDesc(); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_NAME, pServSource->aServiceName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SOURCE_NAME, pServSource->aParSource); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_OBJECT_NAME, pServSource->aParName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_USER_NAME, pServSource->aParUser); + // #i111754# leave out password attribute as long as DataPilotSource doesn't specify the content + // rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PASSWORD, OUString(pServSource->aParPass)); + SvXMLElementExport aElemSD(rExport, XML_NAMESPACE_TABLE, XML_SOURCE_SERVICE, true, true); + rExport.CheckAttrList(); + } + WriteDimensions(pDPSave); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |