/* -*- 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 #include "xmlExport.hxx" #include "xmlAutoStyle.hxx" #include #include #include #include #include #include #include "xmlHelper.hxx" #include #include "xmlPropertyHandler.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 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 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 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 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 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 const&) { return cppu::acquire(new ORptExport(context, "com.sun.star.comp.report.ExportFilter", SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS)); } void ORptExport::exportFunctions(const Reference& _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) { 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) { 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* 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* 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) { 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& _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& _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& _aPosX,const ::std::vector& _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& _rStyleNames) { ::std::vector::const_iterator aIter = _aSize.begin(); ::std::vector::const_iterator aIter2 = aIter + 1; ::std::vector::const_iterator aEnd = _aSize.end(); for (;aIter2 != aEnd ; ++aIter,++aIter2) { ::std::vector< XMLPropertyState > aPropertyStates(1, 0); sal_Int32 nValue = static_cast(*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& _rStyleNames) { ::std::vector::const_iterator aIter = _aSize.begin(); ::std::vector::const_iterator aIter2 = aIter + 1; ::std::vector::const_iterator aEnd = _aSize.end(); for (;aIter2 != aEnd; ++aIter, ++aIter2) { ::std::vector< XMLPropertyState > aPropertyStates(1, 0); sal_Int32 nValue = static_cast(*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::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& _xProp) { OSL_ENSURE(_xProp != nullptr,"Section is NULL -> GPF"); exportAutoStyle(_xProp); Reference xReport = _xProp->getReportDefinition(); const awt::Size aSize = rptui::getStyleProperty(xReport,PROPERTY_PAPERSIZE); const sal_Int32 nOffset = rptui::getStyleProperty(xReport,PROPERTY_LEFTMARGIN); const sal_Int32 nCount = _xProp->getCount(); ::std::vector aColumnPos; aColumnPos.reserve(2*(nCount + 1)); aColumnPos.push_back(nOffset); aColumnPos.push_back(aSize.Width - rptui::getStyleProperty(xReport,PROPERTY_RIGHTMARGIN)); ::std::vector aRowPos; aRowPos.reserve(2*(nCount + 1)); aRowPos.push_back(0); aRowPos.push_back(_xProp->getHeight()); ::std::vector aRowPosAutoGrow; aRowPosAutoGrow.reserve(2 * (nCount + 1)); sal_Int32 i; for (i = 0 ; i< nCount ; ++i) { Reference 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(xReportElement,uno::UNO_QUERY); if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical { sal_Int32 nWidth = static_cast(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()); 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()); 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()).first; collectStyleNames(XmlStyleFamily::TABLE_COLUMN,aColumnPos,aPos->second); aPos = m_aRowStyleNames.emplace(_xProp.get(),std::vector()).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 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(xReportElement,uno::UNO_QUERY); if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical nPos += static_cast(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& _xProp) { const sal_Int32 nCount = _xProp->getCount(); for (sal_Int32 i = 0 ; i< nCount ; ++i) { const Reference 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(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,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* 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 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::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 Reference 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 SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, true, false); Reference 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 xReportElement(xElement,uno::UNO_QUERY); Reference xReportDefinition(xElement,uno::UNO_QUERY); Reference< XImageControl > xImage(xElement,uno::UNO_QUERY); Reference 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* 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 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 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,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(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* 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 = 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 = 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& _xParentFormattedField) { const uno::Reference 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(aFont.Family), static_cast(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 aPropertyStates(m_xParaPropMapper->Filter(*this, _xProp)); if ( !aPropertyStates.empty() ) m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XmlStyleFamily::TEXT_PARAGRAPH, std::move(aPropertyStates) )); } ::std::vector aPropertyStates(m_xCellStylesExportPropertySetMapper->Filter(*this, _xProp)); Reference xFixedLine(_xProp,uno::UNO_QUERY); if ( xFixedLine.is() ) { uno::Reference 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 aBorderStates(m_xCellStylesExportPropertySetMapper->Filter(*this, xBorderProp)); aPropertyStates.insert( aPropertyStates.end(), aBorderStates.begin(), aBorderStates.end() ); } else { const Reference 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& _xProp) { ::std::vector 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 xProp(getReportDefinition()); exportReportAttributes(xProp); } void ORptExport::exportReportAttributes(const Reference& _xReport) { if ( !_xReport.is() ) return; OUStringBuffer sValue; const SvXMLEnumMapEntry* 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 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 SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, false, false); if ( Reference(_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 pParagraphContent; if ( _bAddParagraph ) pParagraphContent.reset(new SvXMLElementExport(*this,XML_NAMESPACE_TEXT, XML_P, true, false)); awt::Point aRefPoint; aRefPoint.X = rptui::getStyleProperty(_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 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: */