summaryrefslogtreecommitdiffstats
path: root/reportdesign/source/filter/xml/xmlExport.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'reportdesign/source/filter/xml/xmlExport.cxx')
-rw-r--r--reportdesign/source/filter/xml/xmlExport.cxx1537
1 files changed, 1537 insertions, 0 deletions
diff --git a/reportdesign/source/filter/xml/xmlExport.cxx b/reportdesign/source/filter/xml/xmlExport.cxx
new file mode 100644
index 000000000..7472b549e
--- /dev/null
+++ b/reportdesign/source/filter/xml/xmlExport.cxx
@@ -0,0 +1,1537 @@
+/* -*- 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 <memory>
+#include "xmlExport.hxx"
+#include "xmlAutoStyle.hxx"
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/numehelp.hxx>
+#include "xmlHelper.hxx"
+#include <strings.hxx>
+#include "xmlPropertyHandler.hxx"
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/report/GroupOn.hpp>
+#include <com/sun/star/report/XFixedText.hpp>
+#include <com/sun/star/report/XImageControl.hpp>
+#include <com/sun/star/report/XShape.hpp>
+#include <com/sun/star/report/XFunction.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/table/BorderLineStyle.hpp>
+#include <com/sun/star/report/XFixedLine.hpp>
+#include <RptDef.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/diagnose.h>
+#include <tools/color.hxx>
+#include <o3tl/string_view.hxx>
+
+#define DEFAULT_LINE_WIDTH 2
+
+namespace rptxml
+{
+ using namespace xmloff;
+ using namespace comphelper;
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::report;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::xml;
+
+
+ /** Exports only settings
+ * \ingroup reportdesign_source_filter_xml
+ *
+ */
+ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+ reportdesign_ORptExportHelper_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+ {
+ return cppu::acquire(new ORptExport(context,
+ "com.sun.star.comp.report.XMLSettingsExporter",
+ SvXMLExportFlags::SETTINGS ));
+ }
+
+ /** Exports only content
+ * \ingroup reportdesign_source_filter_xml
+ *
+ */
+ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+ reportdesign_ORptContentExportHelper_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+ {
+ return cppu::acquire(new ORptExport(context,
+ "com.sun.star.comp.report.XMLContentExporter",
+ SvXMLExportFlags::CONTENT ));
+ }
+
+ /** Exports only styles
+ * \ingroup reportdesign_source_filter_xml
+ *
+ */
+ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+ reportdesign_ORptStylesExportHelper_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+ {
+ return cppu::acquire(new ORptExport(context,
+ "com.sun.star.comp.report.XMLStylesExporter",
+ SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::AUTOSTYLES |
+ SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS ));
+ }
+
+ /** Exports only meta data
+ * \ingroup reportdesign_source_filter_xml
+ *
+ */
+ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+ reportdesign_ORptMetaExportHelper_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+ {
+ return cppu::acquire(new ORptExport(context,
+ "com.sun.star.comp.report.XMLMetaExporter",
+ SvXMLExportFlags::META ));
+ }
+
+ /** Exports all
+ * \ingroup reportdesign_source_filter_xml
+ *
+ */
+ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+ reportdesign_ODBFullExportHelper_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+ {
+ return cppu::acquire(new ORptExport(context,
+ "com.sun.star.comp.report.XMLFullExporter",
+ SvXMLExportFlags::ALL));
+ }
+
+ namespace {
+
+ class OSpecialHandleXMLExportPropertyMapper : public SvXMLExportPropertyMapper
+ {
+ public:
+ explicit OSpecialHandleXMLExportPropertyMapper(const rtl::Reference< XMLPropertySetMapper >& rMapper) : SvXMLExportPropertyMapper(rMapper )
+ {
+ }
+ /** this method is called for every item that has the
+ MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
+ virtual void handleSpecialItem(
+ SvXMLAttributeList& /*rAttrList*/,
+ const XMLPropertyState& /*rProperty*/,
+ const SvXMLUnitConverter& /*rUnitConverter*/,
+ const SvXMLNamespaceMap& /*rNamespaceMap*/,
+ const ::std::vector< XMLPropertyState >* /*pProperties*/ = nullptr,
+ sal_uInt32 /*nIdx*/ = 0 ) const override
+ {
+ // nothing to do here
+ }
+ };
+
+ }
+
+static void lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid& _rGrid)
+{
+ for (auto& rEntry : _rGrid)
+ {
+ ORptExport::TGrid::iterator aRowIter = rEntry.second.begin();
+ ORptExport::TGrid::const_iterator aRowEnd = rEntry.second.end();
+ for (; aRowIter != aRowEnd; ++aRowIter)
+ {
+ if ( aRowIter->first )
+ {
+ sal_Int32 nColIndex = 0;
+ for (const auto& rCell : aRowIter->second)
+ {
+ if ( rCell.nRowSpan > 1 )
+ {
+ sal_Int32 nColSpan = rCell.nColSpan;
+ for (sal_Int32 i = 1; i < rCell.nRowSpan; ++i)
+ {
+ (aRowIter+i)->second[nColIndex].nColSpan = nColSpan;
+ }
+ }
+ ++nColIndex;
+ }
+ }
+ }
+ }
+}
+
+ORptExport::ORptExport(const Reference< XComponentContext >& _rxContext, OUString const & implementationName, SvXMLExportFlags nExportFlag)
+: SvXMLExport( _rxContext, implementationName, util::MeasureUnit::MM_100TH, XML_REPORT, SvXMLExportFlags::OASIS)
+,m_bAllreadyFilled(false)
+{
+ setExportFlags( SvXMLExportFlags::OASIS | nExportFlag);
+ GetMM100UnitConverter().SetCoreMeasureUnit(css::util::MeasureUnit::MM_100TH);
+ GetMM100UnitConverter().SetXMLMeasureUnit(css::util::MeasureUnit::CM);
+
+ // (getExportFlags() & EXPORT_CONTENT) != 0 ? : XML_N_OOO
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE ), XML_NAMESPACE_OFFICE );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
+
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_RPT), GetXMLToken(XML_N_RPT), XML_NAMESPACE_REPORT );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG_COMPAT), XML_NAMESPACE_SVG );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_FORM), GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_DRAW), GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_TEXT), GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT );
+
+
+ if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS) )
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
+
+ if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::SETTINGS) )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
+ }
+ if( getExportFlags() & SvXMLExportFlags::SETTINGS )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_CONFIG), GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
+ }
+
+ if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::FONTDECLS) )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
+ }
+ // RDFa: needed for content and header/footer styles
+ if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_XHTML),GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
+ // loext, needed for paragraphs inside shapes
+ if (getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ GetNamespaceMap_().Add(
+ GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT),
+ XML_NAMESPACE_LO_EXT);
+ }
+ }
+ // GRDDL: to convert RDFa and meta.xml to RDF
+ if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
+ {
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_GRDDL),GetXMLToken(XML_N_GRDDL), XML_NAMESPACE_GRDDL );
+ }
+
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE );
+ GetNamespaceMap_().Add( GetXMLToken(XML_NP_NUMBER), GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER );
+
+ m_sTableStyle = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME) );
+ m_sCellStyle = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_REPORT, GetXMLToken(XML_STYLE_NAME) );
+
+
+ m_xPropHdlFactory = new OXMLRptPropHdlFactory();
+ rtl::Reference < XMLPropertyHandlerFactory> xFac = new ::xmloff::OControlPropertyHandlerFactory();
+ rtl::Reference < XMLPropertySetMapper > xTableStylesPropertySetMapper1 = new XMLPropertySetMapper(OXMLHelper::GetTableStyleProps(),xFac, true);
+ rtl::Reference < XMLPropertySetMapper > xTableStylesPropertySetMapper2 = new XMLTextPropertySetMapper(TextPropMap::TABLE_DEFAULTS, true );
+ xTableStylesPropertySetMapper1->AddMapperEntry(xTableStylesPropertySetMapper2);
+
+ m_xTableStylesExportPropertySetMapper = new SvXMLExportPropertyMapper(xTableStylesPropertySetMapper1);
+
+ m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylePropertyMap( false, true);
+ m_xCellStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(m_xCellStylesPropertySetMapper);
+ m_xCellStylesExportPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));
+
+ rtl::Reference < XMLPropertySetMapper > xColumnStylesPropertySetMapper = new XMLPropertySetMapper(OXMLHelper::GetColumnStyleProps(), m_xPropHdlFactory, true);
+ m_xColumnStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(xColumnStylesPropertySetMapper);
+
+ rtl::Reference < XMLPropertySetMapper > xRowStylesPropertySetMapper = new XMLPropertySetMapper(OXMLHelper::GetRowStyleProps(), m_xPropHdlFactory, true);
+ m_xRowStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(xRowStylesPropertySetMapper);
+
+ rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
+ m_xParaPropMapper = new OSpecialHandleXMLExportPropertyMapper( xPropMapper);
+
+ const OUString& sFamily( GetXMLToken(XML_PARAGRAPH) );
+ GetAutoStylePool()->AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
+ m_xParaPropMapper, "P" );
+
+ GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
+ m_xCellStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX);
+ GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
+ m_xColumnStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
+ GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
+ m_xRowStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
+ GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
+ m_xTableStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+reportdesign_ORptExport_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ORptExport(context,
+ "com.sun.star.comp.report.ExportFilter",
+ SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS));
+}
+
+
+void ORptExport::exportFunctions(const Reference<XIndexAccess>& _xFunctions)
+{
+ const sal_Int32 nCount = _xFunctions->getCount();
+ for (sal_Int32 i = 0; i< nCount; ++i)
+ {
+ uno::Reference< report::XFunction> xFunction(_xFunctions->getByIndex(i),uno::UNO_QUERY_THROW);
+ exportFunction(xFunction);
+ }
+}
+
+void ORptExport::exportFunction(const uno::Reference< XFunction>& _xFunction)
+{
+ exportFormula(XML_FORMULA,_xFunction->getFormula());
+ beans::Optional< OUString> aInitial = _xFunction->getInitialFormula();
+ if ( aInitial.IsPresent && !aInitial.Value.isEmpty() )
+ exportFormula(XML_INITIAL_FORMULA ,aInitial.Value );
+ AddAttribute( XML_NAMESPACE_REPORT, XML_NAME , _xFunction->getName() );
+ if ( _xFunction->getPreEvaluated() )
+ AddAttribute( XML_NAMESPACE_REPORT, XML_PRE_EVALUATED , XML_TRUE );
+ if ( _xFunction->getDeepTraversing() )
+ AddAttribute( XML_NAMESPACE_REPORT, XML_DEEP_TRAVERSING , XML_TRUE );
+
+ SvXMLElementExport aFunction(*this,XML_NAMESPACE_REPORT, XML_FUNCTION, true, true);
+}
+
+void ORptExport::exportMasterDetailFields(const Reference<XReportComponent>& _xReportComponent)
+{
+ const uno::Sequence< OUString> aMasterFields = _xReportComponent->getMasterFields();
+ if ( !aMasterFields.hasElements() )
+ return;
+
+ SvXMLElementExport aElement(*this,XML_NAMESPACE_REPORT, XML_MASTER_DETAIL_FIELDS, true, true);
+ const uno::Sequence< OUString> aDetailFields = _xReportComponent->getDetailFields();
+
+ OSL_ENSURE(aDetailFields.getLength() == aMasterFields.getLength(),"not equal length for master and detail fields!");
+
+ const OUString* pDetailFieldsIter = aDetailFields.getConstArray();
+ for(const OUString& rMasterField : aMasterFields)
+ {
+ AddAttribute( XML_NAMESPACE_REPORT, XML_MASTER , rMasterField );
+ if ( !pDetailFieldsIter->isEmpty() )
+ AddAttribute( XML_NAMESPACE_REPORT, XML_DETAIL , *pDetailFieldsIter );
+ SvXMLElementExport aPair(*this,XML_NAMESPACE_REPORT, XML_MASTER_DETAIL_FIELD, true, true);
+ ++pDetailFieldsIter;
+ }
+}
+
+void ORptExport::exportReport(const Reference<XReportDefinition>& _xReportDefinition)
+{
+ if ( !_xReportDefinition.is() )
+ return;
+
+ exportFunctions(_xReportDefinition->getFunctions());
+ exportGroupsExpressionAsFunction(_xReportDefinition->getGroups());
+
+ if ( _xReportDefinition->getReportHeaderOn() )
+ {
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_REPORT_HEADER, true, true);
+ exportSection(_xReportDefinition->getReportHeader());
+ }
+ if ( _xReportDefinition->getPageHeaderOn() )
+ {
+ OUStringBuffer sValue;
+ sal_Int16 nRet = _xReportDefinition->getPageHeaderOption();
+ const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetReportPrintOptions();
+ if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION,sValue.makeStringAndClear());
+
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_PAGE_HEADER, true, true);
+ exportSection(_xReportDefinition->getPageHeader(),true);
+ }
+
+ exportGroup(_xReportDefinition,0);
+
+ if ( _xReportDefinition->getPageFooterOn() )
+ {
+ OUStringBuffer sValue;
+ sal_Int16 nRet = _xReportDefinition->getPageFooterOption();
+ const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetReportPrintOptions();
+ if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION,sValue.makeStringAndClear());
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_PAGE_FOOTER, true, true);
+ exportSection(_xReportDefinition->getPageFooter(),true);
+ }
+ if ( _xReportDefinition->getReportFooterOn() )
+ {
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_REPORT_FOOTER, true, true);
+ exportSection(_xReportDefinition->getReportFooter());
+ }
+}
+
+void ORptExport::exportComponent(const Reference<XReportComponent>& _xReportComponent)
+{
+ OSL_ENSURE(_xReportComponent.is(),"No component interface!");
+ if ( !_xReportComponent.is() )
+ return;
+
+ AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,_xReportComponent->getName());
+
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_REPORT_COMPONENT, false, false);
+}
+
+void ORptExport::exportFormatConditions(const Reference<XReportControlModel>& _xReportElement)
+{
+ OSL_ENSURE(_xReportElement.is(),"_xReportElement is NULL -> GPF");
+ const sal_Int32 nCount = _xReportElement->getCount();
+ try
+ {
+ for (sal_Int32 i = 0; i < nCount ; ++i)
+ {
+ uno::Reference< report::XFormatCondition > xCond(_xReportElement->getByIndex(i),uno::UNO_QUERY);
+ if ( !xCond->getEnabled() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_ENABLED,XML_FALSE);
+
+ AddAttribute(XML_NAMESPACE_REPORT, XML_FORMULA,xCond->getFormula());
+
+ exportStyleName(xCond.get(),GetAttrList(),m_sCellStyle);
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_FORMAT_CONDITION, true, true);
+ }
+ }
+ catch(uno::Exception&)
+ {
+ OSL_FAIL("Can not access format condition!");
+ }
+}
+
+void ORptExport::exportReportElement(const Reference<XReportControlModel>& _xReportElement)
+{
+ OSL_ENSURE(_xReportElement.is(),"_xReportElement is NULL -> GPF");
+ if ( !_xReportElement->getPrintWhenGroupChange() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_WHEN_GROUP_CHANGE, XML_FALSE );
+
+ if ( !_xReportElement->getPrintRepeatedValues() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_REPEATED_VALUES,XML_FALSE);
+
+ SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_REPORT_ELEMENT, true, true);
+ if ( _xReportElement->getCount() )
+ {
+ exportFormatConditions(_xReportElement);
+ }
+
+ OUString sExpr = _xReportElement->getConditionalPrintExpression();
+ if ( !sExpr.isEmpty() )
+ {
+ exportFormula(XML_FORMULA,sExpr);
+ SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, true);
+ }
+
+ // only export when parent exists
+ uno::Reference< report::XSection> xParent(_xReportElement->getParent(),uno::UNO_QUERY);
+ if ( xParent.is() )
+ exportComponent(_xReportElement);
+}
+
+static void lcl_calculate(const ::std::vector<sal_Int32>& _aPosX,const ::std::vector<sal_Int32>& _aPosY,ORptExport::TGrid& _rColumns)
+{
+ sal_Int32 nCountX = _aPosX.size() - 1;
+ sal_Int32 nCountY = _aPosY.size() - 1;
+ for (sal_Int32 j = 0; j < nCountY; ++j)
+ {
+ sal_Int32 nHeight = _aPosY[j+1] - _aPosY[j];
+ if ( nHeight )
+ for (sal_Int32 i = 0; i < nCountX ; ++i)
+ {
+ _rColumns[j].second[i] = ORptExport::TCell(1,1);
+ _rColumns[j].second[i].bSet = true;
+ }
+ }
+}
+
+void ORptExport::collectStyleNames(XmlStyleFamily _nFamily,const ::std::vector< sal_Int32>& _aSize, std::vector<OUString>& _rStyleNames)
+{
+ ::std::vector<sal_Int32>::const_iterator aIter = _aSize.begin();
+ ::std::vector<sal_Int32>::const_iterator aIter2 = aIter + 1;
+ ::std::vector<sal_Int32>::const_iterator aEnd = _aSize.end();
+ for (;aIter2 != aEnd ; ++aIter,++aIter2)
+ {
+ ::std::vector< XMLPropertyState > aPropertyStates(1, 0);
+ sal_Int32 nValue = static_cast<sal_Int32>(*aIter2 - *aIter);
+ aPropertyStates[0].maValue <<= nValue;
+ _rStyleNames.push_back(GetAutoStylePool()->Add(_nFamily, std::move(aPropertyStates) ));
+ }
+}
+
+void ORptExport::collectStyleNames(XmlStyleFamily _nFamily, const ::std::vector< sal_Int32>& _aSize, const ::std::vector< sal_Int32>& _aSizeAutoGrow, std::vector<OUString>& _rStyleNames)
+{
+ ::std::vector<sal_Int32>::const_iterator aIter = _aSize.begin();
+ ::std::vector<sal_Int32>::const_iterator aIter2 = aIter + 1;
+ ::std::vector<sal_Int32>::const_iterator aEnd = _aSize.end();
+ for (;aIter2 != aEnd; ++aIter, ++aIter2)
+ {
+ ::std::vector< XMLPropertyState > aPropertyStates(1, 0);
+ sal_Int32 nValue = static_cast<sal_Int32>(*aIter2 - *aIter);
+ aPropertyStates[0].maValue <<= nValue;
+ // note: there cannot be 0-height rows, because a call to std::unique has removed them
+ // it cannot be predicted that the size of _aSizeAutoGrow has any relation to the size of
+ // _aSize, because of the same std::unique operation (and _aSizeAutoGrow wasn't even the same
+ // size before that), so the matching element in _aSizeAutoGrow has to be found by lookup.
+ ::std::vector<sal_Int32>::const_iterator aAutoGrow = ::std::find(_aSizeAutoGrow.begin(), _aSizeAutoGrow.end(), *aIter2);
+ bool bAutoGrow = aAutoGrow != _aSizeAutoGrow.end();
+ // the mnIndex is into the array returned by OXMLHelper::GetRowStyleProps()
+ aPropertyStates[0].mnIndex = bAutoGrow ? 1 : 0;
+ _rStyleNames.push_back(GetAutoStylePool()->Add(_nFamily, std::move(aPropertyStates)));
+ }
+}
+
+void ORptExport::exportSectionAutoStyle(const Reference<XSection>& _xProp)
+{
+ OSL_ENSURE(_xProp != nullptr,"Section is NULL -> GPF");
+ exportAutoStyle(_xProp);
+
+ Reference<XReportDefinition> xReport = _xProp->getReportDefinition();
+ const awt::Size aSize = rptui::getStyleProperty<awt::Size>(xReport,PROPERTY_PAPERSIZE);
+ const sal_Int32 nOffset = rptui::getStyleProperty<sal_Int32>(xReport,PROPERTY_LEFTMARGIN);
+ const sal_Int32 nCount = _xProp->getCount();
+
+ ::std::vector<sal_Int32> aColumnPos;
+ aColumnPos.reserve(2*(nCount + 1));
+ aColumnPos.push_back(nOffset);
+ aColumnPos.push_back(aSize.Width - rptui::getStyleProperty<sal_Int32>(xReport,PROPERTY_RIGHTMARGIN));
+
+ ::std::vector<sal_Int32> aRowPos;
+ aRowPos.reserve(2*(nCount + 1));
+ aRowPos.push_back(0);
+ aRowPos.push_back(_xProp->getHeight());
+
+
+ ::std::vector<sal_Int32> aRowPosAutoGrow;
+ aRowPosAutoGrow.reserve(2 * (nCount + 1));
+
+
+ sal_Int32 i;
+ for (i = 0 ; i< nCount ; ++i)
+ {
+ Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
+ uno::Reference< XShape> xShape(xReportElement,uno::UNO_QUERY);
+ if ( xShape.is() )
+ continue;
+ OSL_ENSURE( xReportElement.is(),"NULL Element in Section!" );
+ if ( !xReportElement.is() )
+ continue;
+ sal_Int32 nX = xReportElement->getPositionX();
+ aColumnPos.push_back(nX);
+ Reference<XFixedLine> xFixedLine(xReportElement,uno::UNO_QUERY);
+ if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
+ {
+ sal_Int32 nWidth = static_cast<sal_Int32>(xReportElement->getWidth()*0.5);
+ nX += nWidth;
+ aColumnPos.push_back(nX);
+ nX += xReportElement->getWidth() - nWidth;
+ }
+ else
+ nX += xReportElement->getWidth();
+ aColumnPos.push_back(nX); // --nX why?
+
+ sal_Int32 nY = xReportElement->getPositionY();
+ aRowPos.push_back(nY);
+ nY += xReportElement->getHeight();
+ aRowPos.push_back(nY); // --nY why?
+ bool bAutoGrow = xReportElement->getAutoGrow();
+ if (bAutoGrow)
+ {
+ // the resulting table row ending at nY should auto-grow
+ aRowPosAutoGrow.push_back(nY);
+ }
+ }
+
+ ::std::sort(aColumnPos.begin(),aColumnPos.end(),::std::less<sal_Int32>());
+ aColumnPos.erase(::std::unique(aColumnPos.begin(),aColumnPos.end()),aColumnPos.end());
+
+ // note: the aRowPos contains top and bottom position of every report control; we now compute the
+ // top of every row in the resulting table, by sorting and eliminating unnecessary duplicate
+ // positions. (the same for the columns in the preceding lines.)
+ ::std::sort(aRowPos.begin(),aRowPos.end(),::std::less<sal_Int32>());
+ aRowPos.erase(::std::unique(aRowPos.begin(),aRowPos.end()),aRowPos.end());
+
+ TSectionsGrid::iterator aInsert = m_aSectionsGrid.emplace(
+ _xProp.get(),
+ TGrid(aRowPos.size() - 1,TGrid::value_type(false,TRow(aColumnPos.size() - 1)))
+ ).first;
+ lcl_calculate(aColumnPos,aRowPos,aInsert->second);
+
+ TGridStyleMap::iterator aPos = m_aColumnStyleNames.emplace(_xProp.get(),std::vector<OUString>()).first;
+ collectStyleNames(XmlStyleFamily::TABLE_COLUMN,aColumnPos,aPos->second);
+ aPos = m_aRowStyleNames.emplace(_xProp.get(),std::vector<OUString>()).first;
+ collectStyleNames(XmlStyleFamily::TABLE_ROW, aRowPos, aRowPosAutoGrow, aPos->second);
+
+ sal_Int32 x1 = 0;
+ sal_Int32 y1 = 0;
+ sal_Int32 x2 = 0;
+ sal_Int32 y2 = 0;
+ sal_Int32 xi = 0;
+ sal_Int32 yi = 0;
+ bool isOverlap = false;
+
+ for (i = 0 ; i< nCount ; ++i)
+ {
+ Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
+ uno::Reference< XShape> xShape(xReportElement,uno::UNO_QUERY);
+ if ( xShape.is() )
+ continue;
+ sal_Int32 nPos = xReportElement->getPositionX();
+ x1 = (::std::find(aColumnPos.begin(),aColumnPos.end(),nPos) - aColumnPos.begin());
+ Reference<XFixedLine> xFixedLine(xReportElement,uno::UNO_QUERY);
+ if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
+ nPos += static_cast<sal_Int32>(xReportElement->getWidth()*0.5);
+ else
+ nPos += xReportElement->getWidth(); // -1 why
+ x2 = (::std::find(aColumnPos.begin(),aColumnPos.end(),nPos) - aColumnPos.begin());
+
+ nPos = xReportElement->getPositionY();
+ y1 = (::std::find(aRowPos.begin(),aRowPos.end(),nPos) - aRowPos.begin());
+ nPos += xReportElement->getHeight(); // -1 why?
+ y2 = (::std::find(aRowPos.begin(),aRowPos.end(),nPos) - aRowPos.begin());
+
+ isOverlap = false;
+ yi = y1;
+ while(yi < y2 && !isOverlap) // find overlapping controls
+ {
+ xi = x1;
+ while(xi < x2 && !isOverlap)
+ {
+ if ( aInsert->second[yi].second[xi].xElement.is() )
+ {
+ isOverlap = true;
+ }
+ ++xi;
+ }
+ ++yi;
+ }
+
+ if (!isOverlap)
+ {
+ yi = y1;
+ while(yi < y2)
+ {
+ xi = x1;
+ while(xi < x2)
+ {
+ aInsert->second[yi].second[xi] = TCell();
+ ++xi;
+ }
+ aInsert->second[yi].first = true;
+ ++yi;
+ }
+
+ if (x2 - x1 != 0 && y2 - y1 != 0)
+ {
+ sal_Int32 nColSpan = x2 - x1;
+ sal_Int32 nRowSpan = y2 - y1;
+ aInsert->second[y1].second[x1] =
+ TCell(
+ nColSpan,
+ nRowSpan,
+ xReportElement
+ );
+ }
+ }
+ }
+
+ lcl_adjustColumnSpanOverRows(m_aSectionsGrid);
+ exportReportComponentAutoStyles(_xProp);
+}
+
+void ORptExport::exportReportComponentAutoStyles(const Reference<XSection>& _xProp)
+{
+ const sal_Int32 nCount = _xProp->getCount();
+ for (sal_Int32 i = 0 ; i< nCount ; ++i)
+ {
+ const Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
+ const Reference< report::XShape > xShape(xReportElement,uno::UNO_QUERY);
+ if ( xShape.is() )
+ {
+ rtl::Reference< XMLShapeExport > xShapeExport = GetShapeExport();
+ xShapeExport->seekShapes(_xProp);
+ SolarMutexGuard aGuard;
+ xShapeExport->collectShapeAutoStyles(xShape);
+ }
+ else
+ {
+ exportAutoStyle(xReportElement.get());
+
+ Reference<XFormattedField> xFormattedField(xReportElement,uno::UNO_QUERY);
+ if ( xFormattedField.is() )
+ {
+ try
+ {
+ const sal_Int32 nFormatCount = xFormattedField->getCount();
+ for (sal_Int32 j = 0; j < nFormatCount ; ++j)
+ {
+ uno::Reference< report::XFormatCondition > xCond(xFormattedField->getByIndex(j),uno::UNO_QUERY);
+ exportAutoStyle(xCond.get(),xFormattedField);
+ }
+ }
+ catch(uno::Exception&)
+ {
+ OSL_FAIL("Can not access format condition!");
+ }
+ }
+ }
+ }
+}
+
+void ORptExport::exportSection(const Reference<XSection>& _xSection,bool bHeader)
+{
+ OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF");
+ AddAttribute(XML_NAMESPACE_TABLE, XML_NAME,_xSection->getName());
+
+ if ( !_xSection->getVisible() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_VISIBLE,XML_FALSE);
+
+ if ( !bHeader )
+ {
+ OUStringBuffer sValue;
+ sal_Int16 nRet = _xSection->getForceNewPage();
+ const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions();
+ if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_PAGE,sValue.makeStringAndClear());
+
+ nRet = _xSection->getNewRowOrCol();
+ if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_COLUMN,sValue.makeStringAndClear());
+ if ( _xSection->getKeepTogether() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER, XML_TRUE );
+ }
+
+ exportStyleName(_xSection.get(),GetAttrList(),m_sTableStyle);
+
+ /// TODO export as table layout
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_TABLE, XML_TABLE, true, true);
+
+ OUString sExpr = _xSection->getConditionalPrintExpression();
+ if ( !sExpr.isEmpty() )
+ {
+ exportFormula(XML_FORMULA,sExpr);
+ SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, false);
+ }
+
+ exportContainer(_xSection);
+}
+
+void ORptExport::exportTableColumns(const Reference< XSection>& _xSection)
+{
+ SvXMLElementExport aColumns(*this,XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, true, true);
+ TGridStyleMap::const_iterator aColFind = m_aColumnStyleNames.find(_xSection);
+ OSL_ENSURE(aColFind != m_aColumnStyleNames.end(),"ORptExport::exportTableColumns: Section not found in m_aColumnStyleNames!");
+ if ( aColFind == m_aColumnStyleNames.end() )
+ return;
+
+ for (auto& aCol : aColFind->second)
+ {
+ AddAttribute(m_sTableStyle, aCol);
+ SvXMLElementExport aColumn(*this,XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true);
+ }
+}
+
+void ORptExport::exportContainer(const Reference< XSection>& _xSection)
+{
+ OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF");
+
+ exportTableColumns(_xSection);
+
+ TSectionsGrid::const_iterator aFind = m_aSectionsGrid.find(_xSection);
+ OSL_ENSURE(aFind != m_aSectionsGrid.end(),"ORptExport::exportContainer: Section not found in grid!");
+ if ( aFind == m_aSectionsGrid.end() )
+ return;
+ TGrid::const_iterator aRowIter = aFind->second.begin();
+ TGrid::const_iterator aRowEnd = aFind->second.end();
+
+ TGridStyleMap::const_iterator aRowFind = m_aRowStyleNames.find(_xSection);
+ auto aHeightIter = aRowFind->second.cbegin();
+ OSL_ENSURE(aRowFind->second.size() == aFind->second.size(),"Different count for rows");
+
+ bool bShapeHandled = false;
+ ::std::map<sal_Int32,sal_Int32> aRowSpan;
+ for (sal_Int32 j = 0; aRowIter != aRowEnd; ++aRowIter,++j,++aHeightIter)
+ {
+ AddAttribute( m_sTableStyle,*aHeightIter );
+ SvXMLElementExport aRow(*this,XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
+ if ( aRowIter->first )
+ {
+ ::std::vector< TCell >::const_iterator aColIter = aRowIter->second.begin();
+ ::std::vector< TCell >::const_iterator aColEnd = aRowIter->second.end();
+ sal_Int32 nEmptyCellColSpan = 0;
+ for (; aColIter != aColEnd; ++aColIter)
+ {
+ bool bCoveredCell = false;
+ sal_Int32 nColSpan = 0;
+ sal_Int32 nColIndex = aColIter - aRowIter->second.begin();
+ ::std::map<sal_Int32,sal_Int32>::iterator aRowSpanFind = aRowSpan.find(nColIndex);
+ if ( aRowSpanFind != aRowSpan.end() )
+ {
+ nColSpan = 1;
+ if ( !--(aRowSpanFind->second) )
+ aRowSpan.erase(aRowSpanFind);
+
+ if ( aColIter->nColSpan > 1 )
+ nColSpan += aColIter->nColSpan - 1;
+
+ bCoveredCell = true;
+ aColIter = aColIter + (aColIter->nColSpan - 1);
+ }
+ else if ( aColIter->bSet )
+ {
+ if ( nEmptyCellColSpan > 0 )
+ {
+ AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
+ bCoveredCell = true;
+ nColSpan = nEmptyCellColSpan - 1;
+ nEmptyCellColSpan = 0;
+ }
+ sal_Int32 nSpan = aColIter->nColSpan;
+ if ( nSpan > 1 )
+ {
+ AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nSpan) );
+ nColSpan = nSpan - 1;
+ bCoveredCell = true;
+ }
+ nSpan = aColIter->nRowSpan;
+ if ( nSpan > 1 )
+ {
+ AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_ROWS_SPANNED, OUString::number(nSpan) );
+ aRowSpan[nColIndex] = nSpan - 1;
+ }
+ if ( aColIter->xElement.is() )
+ exportStyleName(aColIter->xElement.get(),GetAttrList(),m_sTableStyle);
+
+ // start <table:table-cell>
+ Reference<XFormattedField> xFormattedField(aColIter->xElement,uno::UNO_QUERY);
+ if ( xFormattedField.is() )
+ {
+ sal_Int32 nFormatKey = xFormattedField->getFormatKey();
+ XMLNumberFormatAttributesExportHelper aHelper(GetNumberFormatsSupplier(),*this);
+ bool bIsStandard = false;
+ sal_Int16 nCellType = aHelper.GetCellType(nFormatKey,bIsStandard);
+ // "Standard" means "no format set, value could be anything",
+ // so don't set a format attribute in this case.
+ // P.S.: "Standard" is called "General" in some languages
+ if (!bIsStandard)
+ {
+ if ( nCellType == util::NumberFormat::TEXT )
+ aHelper.SetNumberFormatAttributes("", u"");
+ else
+ aHelper.SetNumberFormatAttributes(nFormatKey, 0.0, false);
+ }
+ }
+ SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, false);
+
+ if ( aColIter->xElement.is() )
+ {
+ // start <text:p>
+ SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, true, false);
+ Reference<XServiceInfo> xElement(aColIter->xElement,uno::UNO_QUERY);
+
+ if ( !bShapeHandled )
+ {
+ bShapeHandled = true;
+ exportShapes(_xSection,false);
+ }
+ uno::Reference< XShape > xShape(xElement,uno::UNO_QUERY);
+ uno::Reference< XFixedLine > xFixedLine(xElement,uno::UNO_QUERY);
+ if ( !xShape.is() && !xFixedLine.is() )
+ {
+ Reference<XReportControlModel> xReportElement(xElement,uno::UNO_QUERY);
+ Reference<XReportDefinition> xReportDefinition(xElement,uno::UNO_QUERY);
+ Reference< XImageControl > xImage(xElement,uno::UNO_QUERY);
+ Reference<XSection> xSection(xElement,uno::UNO_QUERY);
+
+ XMLTokenEnum eToken = XML_SECTION;
+ bool bExportData = false;
+ if ( xElement->supportsService(SERVICE_FIXEDTEXT) )
+ {
+ eToken = XML_FIXED_CONTENT;
+ }
+ else if ( xElement->supportsService(SERVICE_FORMATTEDFIELD) )
+ {
+ eToken = XML_FORMATTED_TEXT;
+ bExportData = true;
+ }
+ else if ( xElement->supportsService(SERVICE_IMAGECONTROL) )
+ {
+ eToken = XML_IMAGE;
+ OUString sTargetLocation = xImage->getImageURL();
+ if ( !sTargetLocation.isEmpty() )
+ {
+ sTargetLocation = GetRelativeReference(sTargetLocation);
+ AddAttribute(XML_NAMESPACE_FORM, XML_IMAGE_DATA,sTargetLocation);
+ }
+ bExportData = true;
+ OUStringBuffer sValue;
+ const SvXMLEnumMapEntry<sal_Int16>* aXML_ImageScaleEnumMap = OXMLHelper::GetImageScaleOptions();
+ if ( SvXMLUnitConverter::convertEnum( sValue, xImage->getScaleMode(),aXML_ImageScaleEnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_SCALE, sValue.makeStringAndClear() );
+ }
+ else if ( xReportDefinition.is() )
+ {
+ eToken = XML_SUB_DOCUMENT;
+ }
+
+ if ( bExportData )
+ {
+ const bool bPageSet = exportFormula(XML_FORMULA,xReportElement->getDataField());
+ if ( bPageSet )
+ eToken = XML_FIXED_CONTENT;
+ else if ( eToken == XML_IMAGE )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_PRESERVE_IRI, xImage->getPreserveIRI() ? XML_TRUE : XML_FALSE );
+ }
+
+ {
+ // start <report:eToken>
+ SvXMLElementExport aComponents(*this,XML_NAMESPACE_REPORT, eToken, false, false);
+ if ( eToken == XML_FIXED_CONTENT )
+ exportParagraph(xReportElement);
+ if ( xReportElement.is() )
+ exportReportElement(xReportElement);
+
+ if (eToken == XML_SUB_DOCUMENT && xReportDefinition.is())
+ {
+ SvXMLElementExport aOfficeElement( *this, XML_NAMESPACE_OFFICE, XML_BODY, true, true );
+ SvXMLElementExport aElem( *this, true,
+ XML_NAMESPACE_OFFICE, XML_REPORT,
+ true, true );
+
+ exportReportAttributes(xReportDefinition);
+ exportReport(xReportDefinition);
+ }
+ else if ( xSection.is() )
+ exportSection(xSection);
+ }
+ }
+ }
+ else if ( !bShapeHandled )
+ {
+ bShapeHandled = true;
+ exportShapes(_xSection);
+ }
+ aColIter = aColIter + (aColIter->nColSpan - 1);
+ }
+ else
+ ++nEmptyCellColSpan;
+ if ( bCoveredCell )
+ {
+ for (sal_Int32 k = 0; k < nColSpan; ++k)
+ {
+ SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
+ }
+
+ }
+ }
+ if ( nEmptyCellColSpan )
+ {
+ {
+ AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
+ SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
+ if ( !bShapeHandled )
+ {
+ bShapeHandled = true;
+ exportShapes(_xSection);
+ }
+ }
+ for (sal_Int32 k = 0; k < nEmptyCellColSpan; ++k)
+ {
+ SvXMLElementExport aCoveredCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
+ }
+ }
+ }
+ else
+ { // empty rows
+ sal_Int32 nEmptyCellColSpan = aRowIter->second.size();
+ if ( nEmptyCellColSpan )
+ {
+ {
+ AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
+ SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
+ if ( !bShapeHandled )
+ {
+ bShapeHandled = true;
+ exportShapes(_xSection);
+ }
+ }
+ for (sal_Int32 k = 1; k < nEmptyCellColSpan; ++k)
+ {
+ SvXMLElementExport aCoveredCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
+ }
+ }
+ }
+ }
+}
+
+OUString ORptExport::convertFormula(const OUString& _sFormula)
+{
+ OUString sFormula = _sFormula;
+ if ( _sFormula == "rpt:" )
+ sFormula.clear();
+ return sFormula;
+}
+
+bool ORptExport::exportFormula(enum ::xmloff::token::XMLTokenEnum eName,const OUString& _sFormula)
+{
+ const OUString sFieldData = convertFormula(_sFormula);
+ sal_Int32 nPageNumberIndex = sFieldData.indexOf("PageNumber()");
+ sal_Int32 nPageCountIndex = sFieldData.indexOf("PageCount()");
+ bool bRet = nPageNumberIndex != -1 || nPageCountIndex != -1;
+ if ( !bRet )
+ AddAttribute(XML_NAMESPACE_REPORT, eName,sFieldData);
+
+ return bRet;
+}
+
+void ORptExport::exportStyleName(XPropertySet* _xProp,SvXMLAttributeList& _rAtt,const OUString& _sName)
+{
+ Reference<XPropertySet> xFind(_xProp);
+ TPropertyStyleMap::const_iterator aFind = m_aAutoStyleNames.find(xFind);
+ if ( aFind != m_aAutoStyleNames.end() )
+ {
+ _rAtt.AddAttribute( _sName,
+ aFind->second );
+ m_aAutoStyleNames.erase(aFind);
+ }
+}
+
+void ORptExport::exportGroup(const Reference<XReportDefinition>& _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle)
+{
+ if ( !_xReportDefinition.is() )
+ return;
+
+ Reference< XGroups > xGroups = _xReportDefinition->getGroups();
+ if ( !xGroups.is() )
+ return;
+
+ sal_Int32 nCount = xGroups->getCount();
+ if ( _nPos >= 0 && _nPos < nCount )
+ {
+ Reference<XGroup> xGroup(xGroups->getByIndex(_nPos),uno::UNO_QUERY);
+ OSL_ENSURE(xGroup.is(),"No Group prepare for GPF");
+ if ( _bExportAutoStyle )
+ {
+ if ( xGroup->getHeaderOn() )
+ exportSectionAutoStyle(xGroup->getHeader());
+ exportGroup(_xReportDefinition,_nPos+1,_bExportAutoStyle);
+ if ( xGroup->getFooterOn() )
+ exportSectionAutoStyle(xGroup->getFooter());
+ }
+ else
+ {
+ if ( xGroup->getSortAscending() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_SORT_ASCENDING, XML_TRUE );
+
+ if ( xGroup->getStartNewColumn() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_START_NEW_COLUMN, XML_TRUE);
+ if ( xGroup->getResetPageNumber() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_RESET_PAGE_NUMBER, XML_TRUE );
+
+ const OUString sField = xGroup->getExpression();
+ OUString sExpression = sField;
+ if ( !sExpression.isEmpty() )
+ {
+ sal_Int32 nIndex = sExpression.indexOf('"');
+ while ( nIndex > -1 )
+ {
+ sExpression = sExpression.replaceAt(nIndex, 1, u"\"\"");
+ nIndex = sExpression.indexOf('"',nIndex+2);
+ }
+
+ TGroupFunctionMap::const_iterator aGroupFind = m_aGroupFunctionMap.find(xGroup);
+ if ( aGroupFind != m_aGroupFunctionMap.end() )
+ sExpression = aGroupFind->second->getName();
+ sExpression = "rpt:HASCHANGED(\"" + sExpression + "\")";
+ }
+ AddAttribute(XML_NAMESPACE_REPORT, XML_SORT_EXPRESSION, sField);
+ AddAttribute(XML_NAMESPACE_REPORT, XML_GROUP_EXPRESSION,sExpression);
+ sal_Int16 nRet = xGroup->getKeepTogether();
+ OUStringBuffer sValue;
+ const SvXMLEnumMapEntry<sal_Int16>* aXML_KeepTogetherEnumMap = OXMLHelper::GetKeepTogetherOptions();
+ if ( SvXMLUnitConverter::convertEnum( sValue, nRet, aXML_KeepTogetherEnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER,sValue.makeStringAndClear());
+
+ SvXMLElementExport aGroup(*this,XML_NAMESPACE_REPORT, XML_GROUP, true, true);
+ exportFunctions(xGroup->getFunctions());
+ if ( xGroup->getHeaderOn() )
+ {
+ Reference<XSection> xSection = xGroup->getHeader();
+ if ( xSection->getRepeatSection() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_REPEAT_SECTION,XML_TRUE );
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_GROUP_HEADER, true, true);
+ exportSection(xSection);
+ }
+ exportGroup(_xReportDefinition,_nPos+1,_bExportAutoStyle);
+ if ( xGroup->getFooterOn() )
+ {
+ Reference<XSection> xSection = xGroup->getFooter();
+ if ( xSection->getRepeatSection() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_REPEAT_SECTION,XML_TRUE );
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_GROUP_FOOTER, true, true);
+ exportSection(xSection);
+ }
+ }
+ }
+ else if ( _bExportAutoStyle )
+ {
+ exportSectionAutoStyle(_xReportDefinition->getDetail());
+ }
+ else
+ {
+ SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_DETAIL, true, true);
+ exportSection(_xReportDefinition->getDetail());
+ }
+}
+
+void ORptExport::exportAutoStyle(XPropertySet* _xProp,const Reference<XFormattedField>& _xParentFormattedField)
+{
+ const uno::Reference<report::XReportControlFormat> xFormat(_xProp,uno::UNO_QUERY);
+ if ( xFormat.is() )
+ {
+ try
+ {
+ const awt::FontDescriptor aFont = xFormat->getFontDescriptor();
+ OSL_ENSURE(!aFont.Name.isEmpty(),"No Font Name !");
+ GetFontAutoStylePool()->Add(aFont.Name,aFont.StyleName,static_cast<FontFamily>(aFont.Family),
+ static_cast<FontPitch>(aFont.Pitch),aFont.CharSet );
+ }
+ catch(beans::UnknownPropertyException&)
+ {
+ // not interested in
+ }
+ }
+ const uno::Reference< report::XShape> xShape(_xProp,uno::UNO_QUERY);
+ if ( xShape.is() )
+ {
+ ::std::vector<XMLPropertyState> aPropertyStates(m_xParaPropMapper->Filter(*this, _xProp));
+ if ( !aPropertyStates.empty() )
+ m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XmlStyleFamily::TEXT_PARAGRAPH, std::move(aPropertyStates) ));
+ }
+ ::std::vector<XMLPropertyState> aPropertyStates(m_xCellStylesExportPropertySetMapper->Filter(*this, _xProp));
+ Reference<XFixedLine> xFixedLine(_xProp,uno::UNO_QUERY);
+ if ( xFixedLine.is() )
+ {
+ uno::Reference<beans::XPropertySet> xBorderProp = OXMLHelper::createBorderPropertySet();
+ table::BorderLine2 aValue;
+ aValue.Color = sal_uInt32(COL_BLACK);
+ aValue.InnerLineWidth = aValue.LineDistance = 0;
+ aValue.OuterLineWidth = DEFAULT_LINE_WIDTH;
+ aValue.LineStyle = table::BorderLineStyle::SOLID;
+ aValue.LineWidth = DEFAULT_LINE_WIDTH;
+
+ awt::Point aPos = xFixedLine->getPosition();
+ awt::Size aSize = xFixedLine->getSize();
+ sal_Int32 nSectionHeight = xFixedLine->getSection()->getHeight();
+
+ OUString sBorderProp;
+ ::std::vector< OUString> aProps;
+ if ( xFixedLine->getOrientation() == 1 ) // vertical
+ {
+ // check if border should be left
+ if ( !aPos.X )
+ {
+ sBorderProp = PROPERTY_BORDERLEFT;
+ aProps.emplace_back(PROPERTY_BORDERRIGHT);
+ }
+ else
+ {
+ sBorderProp = PROPERTY_BORDERRIGHT;
+ aProps.emplace_back(PROPERTY_BORDERLEFT);
+ }
+ aProps.emplace_back(PROPERTY_BORDERTOP);
+ aProps.emplace_back(PROPERTY_BORDERBOTTOM);
+ }
+ else // horizontal
+ {
+ // check if border should be bottom
+ if ( (aPos.Y + aSize.Height) == nSectionHeight )
+ {
+ sBorderProp = PROPERTY_BORDERBOTTOM;
+ aProps.emplace_back(PROPERTY_BORDERTOP);
+ }
+ else
+ {
+ sBorderProp = PROPERTY_BORDERTOP;
+ aProps.emplace_back(PROPERTY_BORDERBOTTOM);
+ }
+ aProps.emplace_back(PROPERTY_BORDERRIGHT);
+ aProps.emplace_back(PROPERTY_BORDERLEFT);
+ }
+
+ xBorderProp->setPropertyValue(sBorderProp,uno::Any(aValue));
+
+ aValue.Color = aValue.OuterLineWidth = aValue.LineWidth = 0;
+ aValue.LineStyle = table::BorderLineStyle::NONE;
+ uno::Any aEmpty;
+ aEmpty <<= aValue;
+ for (auto const& it : aProps)
+ {
+ xBorderProp->setPropertyValue(it, aEmpty);
+ }
+
+ ::std::vector<XMLPropertyState> aBorderStates(m_xCellStylesExportPropertySetMapper->Filter(*this, xBorderProp));
+ aPropertyStates.insert( aPropertyStates.end(), aBorderStates.begin(), aBorderStates.end() );
+ }
+ else
+ {
+ const Reference<XFormattedField> xFormattedField(_xProp,uno::UNO_QUERY);
+ if ( (_xParentFormattedField.is() || xFormattedField.is()) && !aPropertyStates.empty() )
+ {
+ sal_Int32 nNumberFormat = 0;
+ if ( _xParentFormattedField.is() )
+ nNumberFormat = _xParentFormattedField->getFormatKey();
+ else
+ nNumberFormat = xFormattedField->getFormatKey();
+ {
+ sal_Int32 nStyleMapIndex = m_xCellStylesExportPropertySetMapper->getPropertySetMapper()->FindEntryIndex( CTF_RPT_NUMBERFORMAT );
+ addDataStyle(nNumberFormat);
+ XMLPropertyState aNumberStyleState( nStyleMapIndex, uno::Any( getDataStyleName(nNumberFormat) ) );
+ auto const iter(::std::find_if(
+ aPropertyStates.begin(), aPropertyStates.end(),
+ [nStyleMapIndex] (XMLPropertyState const& rItem)
+ { return rItem.mnIndex == nStyleMapIndex; } ));
+ if (iter == aPropertyStates.end())
+ {
+ aPropertyStates.push_back( aNumberStyleState );
+ }
+ else
+ { // there is already a property but it has the wrong type
+ // (integer not string); TODO: can we prevent it
+ // getting added earlier?
+ (*iter) = aNumberStyleState;
+ }
+ }
+ }
+ }
+
+ if ( !aPropertyStates.empty() )
+ m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XmlStyleFamily::TABLE_CELL, std::move(aPropertyStates) ));
+}
+
+void ORptExport::exportAutoStyle(const Reference<XSection>& _xProp)
+{
+ ::std::vector<XMLPropertyState> aPropertyStates(m_xTableStylesExportPropertySetMapper->Filter(*this, _xProp));
+ if ( !aPropertyStates.empty() )
+ m_aAutoStyleNames.emplace( _xProp.get(),GetAutoStylePool()->Add( XmlStyleFamily::TABLE_TABLE, std::move(aPropertyStates) ));
+}
+
+void ORptExport::SetBodyAttributes()
+{
+ Reference<XReportDefinition> xProp(getReportDefinition());
+ exportReportAttributes(xProp);
+}
+
+void ORptExport::exportReportAttributes(const Reference<XReportDefinition>& _xReport)
+{
+ if ( !_xReport.is() )
+ return;
+
+ OUStringBuffer sValue;
+ const SvXMLEnumMapEntry<sal_Int32>* aXML_CommandTypeEnumMap = OXMLHelper::GetCommandTypeOptions();
+ if ( SvXMLUnitConverter::convertEnum( sValue, _xReport->getCommandType(), aXML_CommandTypeEnumMap ) )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_COMMAND_TYPE,sValue.makeStringAndClear());
+
+ OUString sCommand = _xReport->getCommand();
+ if ( !sCommand.isEmpty() )
+ AddAttribute(XML_NAMESPACE_REPORT, XML_COMMAND, sCommand);
+
+ OUString sFilter( _xReport->getFilter() );
+ if ( !sFilter.isEmpty() )
+ AddAttribute( XML_NAMESPACE_REPORT, XML_FILTER, sFilter );
+
+ AddAttribute(XML_NAMESPACE_OFFICE, XML_MIMETYPE,_xReport->getMimeType());
+
+ bool bEscapeProcessing( _xReport->getEscapeProcessing() );
+ if ( !bEscapeProcessing )
+ AddAttribute( XML_NAMESPACE_REPORT, XML_ESCAPE_PROCESSING, ::xmloff::token::GetXMLToken( XML_FALSE ) );
+
+ OUString sName = _xReport->getCaption();
+ if ( !sName.isEmpty() )
+ AddAttribute(XML_NAMESPACE_OFFICE, XML_CAPTION,sName);
+ sName = _xReport->getName();
+ if ( !sName.isEmpty() )
+ AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,sName);
+}
+
+void ORptExport::ExportContent_()
+{
+ exportReport(getReportDefinition());
+}
+
+void ORptExport::ExportMasterStyles_()
+{
+ GetPageExport()->exportMasterStyles( true );
+}
+
+void ORptExport::collectComponentStyles()
+{
+ if ( m_bAllreadyFilled )
+ return;
+
+ m_bAllreadyFilled = true;
+ Reference<XReportDefinition> xProp(getReportDefinition());
+ if ( !xProp.is() )
+ return;
+
+ uno::Reference< report::XSection> xParent(xProp->getParent(),uno::UNO_QUERY);
+ if ( xParent.is() )
+ exportAutoStyle(xProp.get());
+
+ if ( xProp->getReportHeaderOn() )
+ exportSectionAutoStyle(xProp->getReportHeader());
+ if ( xProp->getPageHeaderOn() )
+ exportSectionAutoStyle(xProp->getPageHeader());
+
+ exportGroup(xProp,0,true);
+
+ if ( xProp->getPageFooterOn() )
+ exportSectionAutoStyle(xProp->getPageFooter());
+ if ( xProp->getReportFooterOn() )
+ exportSectionAutoStyle(xProp->getReportFooter());
+}
+
+void ORptExport::ExportAutoStyles_()
+{
+ // there are no styles that require their own autostyles
+ if ( getExportFlags() & SvXMLExportFlags::CONTENT )
+ {
+ collectComponentStyles();
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_TABLE);
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_COLUMN);
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_ROW);
+ GetAutoStylePool()->exportXML(XmlStyleFamily::TABLE_CELL);
+ exportDataStyles();
+ GetShapeExport()->exportAutoStyles();
+ }
+ // exported in _ExportMasterStyles
+ if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES )
+ GetPageExport()->collectAutoStyles( false );
+ if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES )
+ GetPageExport()->exportAutoStyles();
+}
+
+void ORptExport::ExportStyles_(bool bUsed)
+{
+ SvXMLExport::ExportStyles_(bUsed);
+
+ // write draw:style-name for object graphic-styles
+ GetShapeExport()->ExportGraphicDefaults();
+}
+
+SvXMLAutoStylePoolP* ORptExport::CreateAutoStylePool()
+{
+ return new OXMLAutoStylePoolP(*this);
+}
+
+void SAL_CALL ORptExport::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ m_xReportDefinition.set(xDoc,UNO_QUERY_THROW);
+ SvXMLExport::setSourceDocument(xDoc);
+}
+
+void ORptExport::ExportFontDecls_()
+{
+ GetFontAutoStylePool(); // make sure the pool is created
+ collectComponentStyles();
+ SvXMLExport::ExportFontDecls_();
+}
+
+void ORptExport::exportParagraph(const Reference< XReportControlModel >& _xReportElement)
+{
+ OSL_PRECOND(_xReportElement.is(),"Element is null!");
+ // start <text:p>
+ SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, false, false);
+ if ( Reference<XFormattedField>(_xReportElement,uno::UNO_QUERY).is() )
+ {
+ OUString sFieldData = _xReportElement->getDataField();
+ static const sal_Unicode s_sPageNumber[] = u"PageNumber()";
+ static const char s_sReportPrefix[] = "rpt:";
+ sFieldData = sFieldData.copy(strlen(s_sReportPrefix));
+ sal_Int32 nPageNumberIndex = sFieldData.indexOf(s_sPageNumber);
+ if ( nPageNumberIndex != -1 )
+ {
+ sal_Int32 nIndex = 0;
+ do
+ {
+ std::u16string_view sToken = o3tl::getToken(sFieldData, 0, '&', nIndex );
+ sToken = o3tl::trim(sToken);
+ if ( !sToken.empty() )
+ {
+ if ( sToken == s_sPageNumber )
+ {
+ AddAttribute(XML_NAMESPACE_TEXT, XML_SELECT_PAGE, "current" );
+ SvXMLElementExport aPageNumber(*this,XML_NAMESPACE_TEXT, XML_PAGE_NUMBER, false, false);
+ Characters("1");
+ }
+ else if ( sToken == u"PageCount()" )
+ {
+ SvXMLElementExport aPageNumber(*this,XML_NAMESPACE_TEXT, XML_PAGE_COUNT, false, false);
+ Characters("1");
+ }
+ else
+ {
+
+ if ( o3tl::starts_with(sToken, u"\"") && o3tl::ends_with(sToken, u"\"") )
+ sToken = sToken.substr(1, sToken.size() - 2);
+
+ bool bPrevCharIsSpace = false;
+ GetTextParagraphExport()->exportCharacterData(OUString(sToken), bPrevCharIsSpace);
+ }
+ }
+ }
+ while ( nIndex >= 0 );
+ }
+ }
+ Reference< XFixedText > xFT(_xReportElement,UNO_QUERY);
+ if ( xFT.is() )
+ {
+ OUString sExpr = xFT->getLabel();
+ bool bPrevCharIsSpace = false; // FIXME this looks quite broken - does the corresponding import filter do whitespace collapsing at all?
+ GetTextParagraphExport()->exportCharacterData(sExpr, bPrevCharIsSpace);
+ }
+}
+
+XMLShapeExport* ORptExport::CreateShapeExport()
+{
+ XMLShapeExport* pShapeExport = new XMLShapeExport( *this, XMLTextParagraphExport::CreateShapeExtPropMapper( *this ) );
+ return pShapeExport;
+}
+
+void ORptExport::exportShapes(const Reference< XSection>& _xSection,bool _bAddParagraph)
+{
+ rtl::Reference< XMLShapeExport > xShapeExport = GetShapeExport();
+ xShapeExport->seekShapes(_xSection);
+ const sal_Int32 nCount = _xSection->getCount();
+ ::std::unique_ptr<SvXMLElementExport> pParagraphContent;
+ if ( _bAddParagraph )
+ pParagraphContent.reset(new SvXMLElementExport(*this,XML_NAMESPACE_TEXT, XML_P, true, false));
+
+ awt::Point aRefPoint;
+ aRefPoint.X = rptui::getStyleProperty<sal_Int32>(_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference< XShape > xShape(_xSection->getByIndex(i),uno::UNO_QUERY);
+ if ( xShape.is() )
+ {
+ ::std::unique_ptr<SvXMLElementExport> pSubDocument;
+ uno::Reference< frame::XModel> xModel(xShape->getPropertyValue("Model"),uno::UNO_QUERY);
+ if ( xModel.is() ) // special handling for chart object
+ {
+ pSubDocument.reset(new SvXMLElementExport(*this,XML_NAMESPACE_REPORT, XML_SUB_DOCUMENT, false, false));
+ exportMasterDetailFields(xShape);
+ exportReportElement(xShape);
+ }
+
+ AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, XML_PARAGRAPH );
+ xShapeExport->exportShape(xShape, SEF_DEFAULT|XMLShapeExportFlags::NO_WS,&aRefPoint);
+ }
+ }
+}
+
+void ORptExport::exportGroupsExpressionAsFunction(const Reference< XGroups>& _xGroups)
+{
+ if ( !_xGroups.is() )
+ return;
+
+ uno::Reference< XFunctions> xFunctions = _xGroups->getReportDefinition()->getFunctions();
+ const sal_Int32 nCount = _xGroups->getCount();
+ for (sal_Int32 i = 0; i < nCount; ++i)
+ {
+ uno::Reference< XGroup> xGroup(_xGroups->getByIndex(i),uno::UNO_QUERY_THROW);
+ const ::sal_Int16 nGroupOn = xGroup->getGroupOn();
+ if ( nGroupOn != report::GroupOn::DEFAULT )
+ {
+ uno::Reference< XFunction> xFunction = xFunctions->createFunction();
+ OUString sFunction,sPrefix,sPostfix;
+ OUString sExpression = xGroup->getExpression();
+ OUString sFunctionName;
+ OUString sInitialFormula;
+ switch(nGroupOn)
+ {
+ case report::GroupOn::PREFIX_CHARACTERS:
+ sFunction = "LEFT";
+ sPrefix = ";" + OUString::number(xGroup->getGroupInterval());
+ break;
+ case report::GroupOn::YEAR:
+ sFunction = "YEAR";
+ break;
+ case report::GroupOn::QUARTAL:
+ sFunction = "INT((MONTH";
+ sPostfix = "-1)/3)+1";
+ sFunctionName = "QUARTAL_" + sExpression;
+ break;
+ case report::GroupOn::MONTH:
+ sFunction = "MONTH";
+ break;
+ case report::GroupOn::WEEK:
+ sFunction = "WEEK";
+ break;
+ case report::GroupOn::DAY:
+ sFunction = "DAY";
+ break;
+ case report::GroupOn::HOUR:
+ sFunction = "HOUR";
+ break;
+ case report::GroupOn::MINUTE:
+ sFunction = "MINUTE";
+ break;
+ case report::GroupOn::INTERVAL:
+ {
+ sFunction = "INT";
+ uno::Reference< XFunction> xCountFunction = xFunctions->createFunction();
+ xCountFunction->setInitialFormula(beans::Optional< OUString>(true,OUString("rpt:0")));
+ OUString sCountName = sFunction + "_count_" + sExpression;
+ xCountFunction->setName(sCountName);
+ xCountFunction->setFormula( "rpt:[" + sCountName + "] + 1" );
+ exportFunction(xCountFunction);
+ sExpression = sCountName;
+ // The reference to sCountName in the formula of sFunctionName refers to the *old* value
+ // so we need to expand the formula of sCountName
+ sPrefix = " + 1) / " + OUString::number(xGroup->getGroupInterval());
+ sFunctionName = sFunction + "_" + sExpression;
+ sFunction += "(";
+ sInitialFormula = "rpt:0";
+ }
+ break;
+ default:
+ ;
+ }
+ if ( sFunctionName.isEmpty() )
+ sFunctionName = sFunction + "_" + sExpression;
+ if ( !sFunction.isEmpty() )
+ {
+ const sal_Unicode pReplaceChars[] = { '(',')',';',',','+','-','[',']','/','*'};
+ for(sal_Unicode ch : pReplaceChars)
+ sFunctionName = sFunctionName.replace(ch,'_');
+
+ xFunction->setName(sFunctionName);
+ if ( !sInitialFormula.isEmpty() )
+ xFunction->setInitialFormula(beans::Optional< OUString>(true, sInitialFormula));
+ sFunction = "rpt:" + sFunction + "([" + sExpression + "]";
+
+ if ( !sPrefix.isEmpty() )
+ sFunction += sPrefix;
+ sFunction += ")";
+ if ( !sPostfix.isEmpty() )
+ sFunction += sPostfix;
+ xFunction->setFormula(sFunction);
+ exportFunction(xFunction);
+ m_aGroupFunctionMap.emplace(xGroup,xFunction);
+ }
+ }
+ }
+}
+
+
+}// rptxml
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */