1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <memory>
21 #include "xmlExport.hxx"
22 #include "xmlAutoStyle.hxx"
23 #include <xmloff/ProgressBarHelper.hxx>
24 #include <xmloff/xmltoken.hxx>
25 #include <xmloff/txtimp.hxx>
26 #include <xmloff/xmlnmspe.hxx>
27 #include <xmloff/xmluconv.hxx>
28 #include <xmloff/nmspmap.hxx>
29 #include <comphelper/types.hxx>
30 #include "xmlEnums.hxx"
31 #include <xmloff/txtprmap.hxx>
32 #include <xmloff/numehelp.hxx>
33 #include "xmlHelper.hxx"
34 #include <strings.hxx>
35 #include "xmlPropertyHandler.hxx"
36 #include <sax/tools/converter.hxx>
37 #include <com/sun/star/awt/ImagePosition.hpp>
38 #include <com/sun/star/util/NumberFormat.hpp>
39 #include <com/sun/star/util/MeasureUnit.hpp>
40 #include <com/sun/star/style/ParagraphAdjust.hpp>
41 #include <com/sun/star/awt/TextAlign.hpp>
42 #include <com/sun/star/report/GroupOn.hpp>
43 #include <com/sun/star/report/XFixedText.hpp>
44 #include <com/sun/star/report/XImageControl.hpp>
45 #include <com/sun/star/report/XShape.hpp>
46 #include <com/sun/star/drawing/XShape.hpp>
47 #include <com/sun/star/drawing/XShapes.hpp>
48 #include <com/sun/star/report/XFunction.hpp>
49 #include <com/sun/star/awt/FontDescriptor.hpp>
50 #include <com/sun/star/text/TextContentAnchorType.hpp>
51 #include <com/sun/star/table/BorderLine2.hpp>
52 #include <com/sun/star/table/BorderLineStyle.hpp>
53 #include <com/sun/star/report/XFixedLine.hpp>
54 #include <RptDef.hxx>
55 #include <vcl/svapp.hxx>
56 #include <sal/macros.h>
57
58 #include <iterator>
59
60 #define DEFAULT_LINE_WIDTH 2
61
62 namespace rptxml
63 {
64 using namespace xmloff;
65 using namespace comphelper;
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::report;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::util;
70 using namespace ::com::sun::star::xml;
71
72
create(Reference<XComponentContext> const & xContext)73 Reference< XInterface > ORptExportHelper::create(Reference< XComponentContext > const & xContext)
74 {
75 return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::SETTINGS ));
76 }
77
getImplementationName_Static()78 OUString ORptExportHelper::getImplementationName_Static( )
79 {
80 return "com.sun.star.comp.report.XMLSettingsExporter";
81 }
82
getSupportedServiceNames_Static()83 Sequence< OUString > ORptExportHelper::getSupportedServiceNames_Static( )
84 {
85 Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
86 return aSupported;
87 }
88
create(Reference<XComponentContext> const & xContext)89 Reference< XInterface > ORptContentExportHelper::create(Reference< XComponentContext > const & xContext)
90 {
91 return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::CONTENT ));
92 }
93
getImplementationName_Static()94 OUString ORptContentExportHelper::getImplementationName_Static( )
95 {
96 return "com.sun.star.comp.report.XMLContentExporter";
97 }
98
getSupportedServiceNames_Static()99 Sequence< OUString > ORptContentExportHelper::getSupportedServiceNames_Static( )
100 {
101 Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
102 return aSupported;
103 }
104
105
create(Reference<XComponentContext> const & xContext)106 Reference< XInterface > ORptStylesExportHelper::create(Reference< XComponentContext > const & xContext)
107 {
108 return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::STYLES | SvXMLExportFlags::MASTERSTYLES | SvXMLExportFlags::AUTOSTYLES |
109 SvXMLExportFlags::FONTDECLS|SvXMLExportFlags::OASIS ));
110 }
111
getImplementationName_Static()112 OUString ORptStylesExportHelper::getImplementationName_Static( )
113 {
114 return "com.sun.star.comp.report.XMLStylesExporter";
115 }
116
getSupportedServiceNames_Static()117 Sequence< OUString > ORptStylesExportHelper::getSupportedServiceNames_Static( )
118 {
119 Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
120 return aSupported;
121 }
122
123
create(Reference<XComponentContext> const & xContext)124 Reference< XInterface > ORptMetaExportHelper::create(Reference< XComponentContext > const & xContext)
125 {
126 return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::META ));
127 }
128
getImplementationName_Static()129 OUString ORptMetaExportHelper::getImplementationName_Static( )
130 {
131 return "com.sun.star.comp.report.XMLMetaExporter";
132 }
133
getSupportedServiceNames_Static()134 Sequence< OUString > ORptMetaExportHelper::getSupportedServiceNames_Static( )
135 {
136 Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
137 return aSupported;
138 }
139
140
create(Reference<XComponentContext> const & xContext)141 Reference< XInterface > ODBFullExportHelper::create(Reference< XComponentContext > const & xContext)
142 {
143 return static_cast< XServiceInfo* >(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::ALL));
144 }
145
getImplementationName_Static()146 OUString ODBFullExportHelper::getImplementationName_Static( )
147 {
148 return "com.sun.star.comp.report.XMLFullExporter";
149 }
150
getSupportedServiceNames_Static()151 Sequence< OUString > ODBFullExportHelper::getSupportedServiceNames_Static( )
152 {
153 Sequence< OUString > aSupported { "com.sun.star.document.ExportFilter" };
154 return aSupported;
155 }
156
157
158 class OSpecialHandleXMLExportPropertyMapper : public SvXMLExportPropertyMapper
159 {
160 public:
OSpecialHandleXMLExportPropertyMapper(const rtl::Reference<XMLPropertySetMapper> & rMapper)161 explicit OSpecialHandleXMLExportPropertyMapper(const rtl::Reference< XMLPropertySetMapper >& rMapper) : SvXMLExportPropertyMapper(rMapper )
162 {
163 }
164 /** this method is called for every item that has the
165 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
handleSpecialItem(SvXMLAttributeList &,const XMLPropertyState &,const SvXMLUnitConverter &,const SvXMLNamespaceMap &,const::std::vector<XMLPropertyState> * =nullptr,sal_uInt32=0) const166 virtual void handleSpecialItem(
167 SvXMLAttributeList& /*rAttrList*/,
168 const XMLPropertyState& /*rProperty*/,
169 const SvXMLUnitConverter& /*rUnitConverter*/,
170 const SvXMLNamespaceMap& /*rNamespaceMap*/,
171 const ::std::vector< XMLPropertyState >* /*pProperties*/ = nullptr,
172 sal_uInt32 /*nIdx*/ = 0 ) const override
173 {
174 // nothing to do here
175 }
176 };
177
lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid & _rGrid)178 static void lcl_adjustColumnSpanOverRows(ORptExport::TSectionsGrid& _rGrid)
179 {
180 for (auto& rEntry : _rGrid)
181 {
182 ORptExport::TGrid::iterator aRowIter = rEntry.second.begin();
183 ORptExport::TGrid::const_iterator aRowEnd = rEntry.second.end();
184 for (; aRowIter != aRowEnd; ++aRowIter)
185 {
186 if ( aRowIter->first )
187 {
188 sal_Int32 nColIndex = 0;
189 for (const auto& rCell : aRowIter->second)
190 {
191 if ( rCell.nRowSpan > 1 )
192 {
193 sal_Int32 nColSpan = rCell.nColSpan;
194 for (sal_Int32 i = 1; i < rCell.nRowSpan; ++i)
195 {
196 (aRowIter+i)->second[nColIndex].nColSpan = nColSpan;
197 }
198 }
199 ++nColIndex;
200 }
201 }
202 }
203 }
204 }
205
ORptExport(const Reference<XComponentContext> & _rxContext,OUString const & implementationName,SvXMLExportFlags nExportFlag)206 ORptExport::ORptExport(const Reference< XComponentContext >& _rxContext, OUString const & implementationName, SvXMLExportFlags nExportFlag)
207 : SvXMLExport( util::MeasureUnit::MM_100TH, _rxContext, implementationName, XML_REPORT, SvXMLExportFlags::OASIS)
208 ,m_bAllreadyFilled(false)
209 {
210 setExportFlags( SvXMLExportFlags::OASIS | nExportFlag);
211 GetMM100UnitConverter().SetCoreMeasureUnit(css::util::MeasureUnit::MM_100TH);
212 GetMM100UnitConverter().SetXMLMeasureUnit(css::util::MeasureUnit::CM);
213
214 // (getExportFlags() & EXPORT_CONTENT) != 0 ? : XML_N_OOO
215 GetNamespaceMap_().Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE ), XML_NAMESPACE_OFFICE );
216 GetNamespaceMap_().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
217
218 GetNamespaceMap_().Add( GetXMLToken(XML_NP_RPT), GetXMLToken(XML_N_RPT), XML_NAMESPACE_REPORT );
219 GetNamespaceMap_().Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG_COMPAT), XML_NAMESPACE_SVG );
220 GetNamespaceMap_().Add( GetXMLToken(XML_NP_FORM), GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM );
221 GetNamespaceMap_().Add( GetXMLToken(XML_NP_DRAW), GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
222 GetNamespaceMap_().Add( GetXMLToken(XML_NP_TEXT), GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT );
223
224
225 if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS) )
226 GetNamespaceMap_().Add( GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
227
228 if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::SETTINGS) )
229 {
230 GetNamespaceMap_().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
231 }
232 if( getExportFlags() & SvXMLExportFlags::SETTINGS )
233 {
234 GetNamespaceMap_().Add( GetXMLToken(XML_NP_CONFIG), GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
235 }
236
237 if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::FONTDECLS) )
238 {
239 GetNamespaceMap_().Add( GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
240 }
241 // RDFa: needed for content and header/footer styles
242 if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
243 {
244 GetNamespaceMap_().Add( GetXMLToken(XML_NP_XHTML),GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
245 // loext, needed for paragraphs inside shapes
246 if (getDefaultVersion() > SvtSaveOptions::ODFVER_012)
247 {
248 GetNamespaceMap_().Add(
249 GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT),
250 XML_NAMESPACE_LO_EXT);
251 }
252 }
253 // GRDDL: to convert RDFa and meta.xml to RDF
254 if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
255 {
256 GetNamespaceMap_().Add( GetXMLToken(XML_NP_GRDDL),GetXMLToken(XML_N_GRDDL), XML_NAMESPACE_GRDDL );
257 }
258
259 GetNamespaceMap_().Add( GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE );
260 GetNamespaceMap_().Add( GetXMLToken(XML_NP_NUMBER), GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER );
261
262 m_sTableStyle = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME) );
263 m_sCellStyle = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_REPORT, GetXMLToken(XML_STYLE_NAME) );
264
265
266 m_xPropHdlFactory = new OXMLRptPropHdlFactory();
267 rtl::Reference < XMLPropertyHandlerFactory> xFac = new ::xmloff::OControlPropertyHandlerFactory();
268 rtl::Reference < XMLPropertySetMapper > xTableStylesPropertySetMapper1 = new XMLPropertySetMapper(OXMLHelper::GetTableStyleProps(),xFac, true);
269 rtl::Reference < XMLPropertySetMapper > xTableStylesPropertySetMapper2 = new XMLTextPropertySetMapper(TextPropMap::TABLE_DEFAULTS, true );
270 xTableStylesPropertySetMapper1->AddMapperEntry(xTableStylesPropertySetMapper2);
271
272 m_xTableStylesExportPropertySetMapper = new SvXMLExportPropertyMapper(xTableStylesPropertySetMapper1);
273
274 m_xCellStylesPropertySetMapper = OXMLHelper::GetCellStylePropertyMap( false, true);
275 m_xCellStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(m_xCellStylesPropertySetMapper);
276 m_xCellStylesExportPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(*this));
277
278 rtl::Reference < XMLPropertySetMapper > xColumnStylesPropertySetMapper = new XMLPropertySetMapper(OXMLHelper::GetColumnStyleProps(), m_xPropHdlFactory, true);
279 m_xColumnStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(xColumnStylesPropertySetMapper);
280
281 rtl::Reference < XMLPropertySetMapper > xRowStylesPropertySetMapper = new XMLPropertySetMapper(OXMLHelper::GetRowStyleProps(), m_xPropHdlFactory, true);
282 m_xRowStylesExportPropertySetMapper = new OSpecialHandleXMLExportPropertyMapper(xRowStylesPropertySetMapper);
283
284 rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
285 m_xParaPropMapper = new OSpecialHandleXMLExportPropertyMapper( xPropMapper);
286
287 const OUString& sFamily( GetXMLToken(XML_PARAGRAPH) );
288 OUString aPrefix( 'P');
289 GetAutoStylePool()->AddFamily( XML_STYLE_FAMILY_TEXT_PARAGRAPH, sFamily,
290 m_xParaPropMapper, aPrefix );
291
292 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_CELL, XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME,
293 m_xCellStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX);
294 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_COLUMN, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME,
295 m_xColumnStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX);
296 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_ROW, XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME,
297 m_xRowStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX);
298 GetAutoStylePool()->AddFamily(XML_STYLE_FAMILY_TABLE_TABLE, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_NAME,
299 m_xTableStylesExportPropertySetMapper, XML_STYLE_FAMILY_TABLE_TABLE_STYLES_PREFIX);
300 }
301
create(Reference<XComponentContext> const & xContext)302 Reference< XInterface > ORptExport::create(Reference< XComponentContext > const & xContext)
303 {
304 return *(new ORptExport(xContext, getImplementationName_Static(), SvXMLExportFlags::CONTENT | SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::FONTDECLS));
305 }
306
307
getImplementationName_Static()308 OUString ORptExport::getImplementationName_Static( )
309 {
310 return "com.sun.star.comp.report.ExportFilter";
311 }
312
313
getSupportedServiceNames_Static()314 uno::Sequence< OUString > ORptExport::getSupportedServiceNames_Static( )
315 {
316 uno::Sequence< OUString > aServices { "com.sun.star.document.ExportFilter" };
317
318 return aServices;
319 }
320
321
exportFunctions(const Reference<XIndexAccess> & _xFunctions)322 void ORptExport::exportFunctions(const Reference<XIndexAccess>& _xFunctions)
323 {
324 const sal_Int32 nCount = _xFunctions->getCount();
325 for (sal_Int32 i = 0; i< nCount; ++i)
326 {
327 uno::Reference< report::XFunction> xFunction(_xFunctions->getByIndex(i),uno::UNO_QUERY_THROW);
328 exportFunction(xFunction);
329 }
330 }
331
exportFunction(const uno::Reference<XFunction> & _xFunction)332 void ORptExport::exportFunction(const uno::Reference< XFunction>& _xFunction)
333 {
334 exportFormula(XML_FORMULA,_xFunction->getFormula());
335 beans::Optional< OUString> aInitial = _xFunction->getInitialFormula();
336 if ( aInitial.IsPresent && !aInitial.Value.isEmpty() )
337 exportFormula(XML_INITIAL_FORMULA ,aInitial.Value );
338 AddAttribute( XML_NAMESPACE_REPORT, XML_NAME , _xFunction->getName() );
339 if ( _xFunction->getPreEvaluated() )
340 AddAttribute( XML_NAMESPACE_REPORT, XML_PRE_EVALUATED , XML_TRUE );
341 if ( _xFunction->getDeepTraversing() )
342 AddAttribute( XML_NAMESPACE_REPORT, XML_DEEP_TRAVERSING , XML_TRUE );
343
344 SvXMLElementExport aFunction(*this,XML_NAMESPACE_REPORT, XML_FUNCTION, true, true);
345 }
346
exportMasterDetailFields(const Reference<XReportComponent> & _xReportComponet)347 void ORptExport::exportMasterDetailFields(const Reference<XReportComponent>& _xReportComponet)
348 {
349 const uno::Sequence< OUString> aMasterFields = _xReportComponet->getMasterFields();
350 if ( aMasterFields.hasElements() )
351 {
352 SvXMLElementExport aElement(*this,XML_NAMESPACE_REPORT, XML_MASTER_DETAIL_FIELDS, true, true);
353 const uno::Sequence< OUString> aDetailFields = _xReportComponet->getDetailFields();
354
355 OSL_ENSURE(aDetailFields.getLength() == aMasterFields.getLength(),"not equal length for master and detail fields!");
356
357 const OUString* pDetailFieldsIter = aDetailFields.getConstArray();
358 for(const OUString& rMasterField : aMasterFields)
359 {
360 AddAttribute( XML_NAMESPACE_REPORT, XML_MASTER , rMasterField );
361 if ( !pDetailFieldsIter->isEmpty() )
362 AddAttribute( XML_NAMESPACE_REPORT, XML_DETAIL , *pDetailFieldsIter );
363 SvXMLElementExport aPair(*this,XML_NAMESPACE_REPORT, XML_MASTER_DETAIL_FIELD, true, true);
364 ++pDetailFieldsIter;
365 }
366 }
367 }
368
exportReport(const Reference<XReportDefinition> & _xReportDefinition)369 void ORptExport::exportReport(const Reference<XReportDefinition>& _xReportDefinition)
370 {
371 if ( _xReportDefinition.is() )
372 {
373 exportFunctions(_xReportDefinition->getFunctions().get());
374 exportGroupsExpressionAsFunction(_xReportDefinition->getGroups());
375
376 if ( _xReportDefinition->getReportHeaderOn() )
377 {
378 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_REPORT_HEADER, true, true);
379 exportSection(_xReportDefinition->getReportHeader());
380 }
381 if ( _xReportDefinition->getPageHeaderOn() )
382 {
383 OUStringBuffer sValue;
384 sal_Int16 nRet = _xReportDefinition->getPageHeaderOption();
385 const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetReportPrintOptions();
386 if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
387 AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION,sValue.makeStringAndClear());
388
389 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_PAGE_HEADER, true, true);
390 exportSection(_xReportDefinition->getPageHeader(),true);
391 }
392
393 exportGroup(_xReportDefinition,0);
394
395 if ( _xReportDefinition->getPageFooterOn() )
396 {
397 OUStringBuffer sValue;
398 sal_Int16 nRet = _xReportDefinition->getPageFooterOption();
399 const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetReportPrintOptions();
400 if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
401 AddAttribute(XML_NAMESPACE_REPORT, XML_PAGE_PRINT_OPTION,sValue.makeStringAndClear());
402 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_PAGE_FOOTER, true, true);
403 exportSection(_xReportDefinition->getPageFooter(),true);
404 }
405 if ( _xReportDefinition->getReportFooterOn() )
406 {
407 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_REPORT_FOOTER, true, true);
408 exportSection(_xReportDefinition->getReportFooter());
409 }
410 }
411 }
412
exportComponent(const Reference<XReportComponent> & _xReportComponent)413 void ORptExport::exportComponent(const Reference<XReportComponent>& _xReportComponent)
414 {
415 OSL_ENSURE(_xReportComponent.is(),"No component interface!");
416 if ( !_xReportComponent.is() )
417 return;
418
419 AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,_xReportComponent->getName());
420
421 SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_REPORT_COMPONENT, false, false);
422 }
423
exportFormatConditions(const Reference<XReportControlModel> & _xReportElement)424 void ORptExport::exportFormatConditions(const Reference<XReportControlModel>& _xReportElement)
425 {
426 OSL_ENSURE(_xReportElement.is(),"_xReportElement is NULL -> GPF");
427 const sal_Int32 nCount = _xReportElement->getCount();
428 try
429 {
430 for (sal_Int32 i = 0; i < nCount ; ++i)
431 {
432 uno::Reference< report::XFormatCondition > xCond(_xReportElement->getByIndex(i),uno::UNO_QUERY);
433 if ( !xCond->getEnabled() )
434 AddAttribute(XML_NAMESPACE_REPORT, XML_ENABLED,XML_FALSE);
435
436 AddAttribute(XML_NAMESPACE_REPORT, XML_FORMULA,xCond->getFormula());
437
438 exportStyleName(xCond.get(),GetAttrList(),m_sCellStyle);
439 SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_FORMAT_CONDITION, true, true);
440 }
441 }
442 catch(uno::Exception&)
443 {
444 OSL_FAIL("Can not access format condition!");
445 }
446 }
447
exportReportElement(const Reference<XReportControlModel> & _xReportElement)448 void ORptExport::exportReportElement(const Reference<XReportControlModel>& _xReportElement)
449 {
450 OSL_ENSURE(_xReportElement.is(),"_xReportElement is NULL -> GPF");
451 if ( !_xReportElement->getPrintWhenGroupChange() )
452 AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_WHEN_GROUP_CHANGE, XML_FALSE );
453
454 if ( !_xReportElement->getPrintRepeatedValues() )
455 AddAttribute(XML_NAMESPACE_REPORT, XML_PRINT_REPEATED_VALUES,XML_FALSE);
456
457 SvXMLElementExport aElem(*this,XML_NAMESPACE_REPORT, XML_REPORT_ELEMENT, true, true);
458 if ( _xReportElement->getCount() )
459 {
460 exportFormatConditions(_xReportElement);
461 }
462
463 OUString sExpr = _xReportElement->getConditionalPrintExpression();
464 if ( !sExpr.isEmpty() )
465 {
466 exportFormula(XML_FORMULA,sExpr);
467 SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, true);
468 }
469
470 // only export when parent exists
471 uno::Reference< report::XSection> xParent(_xReportElement->getParent(),uno::UNO_QUERY);
472 if ( xParent.is() )
473 exportComponent(_xReportElement.get());
474 }
475
lcl_calculate(const::std::vector<sal_Int32> & _aPosX,const::std::vector<sal_Int32> & _aPosY,ORptExport::TGrid & _rColumns)476 static void lcl_calculate(const ::std::vector<sal_Int32>& _aPosX,const ::std::vector<sal_Int32>& _aPosY,ORptExport::TGrid& _rColumns)
477 {
478 sal_Int32 nCountX = _aPosX.size() - 1;
479 sal_Int32 nCountY = _aPosY.size() - 1;
480 for (sal_Int32 j = 0; j < nCountY; ++j)
481 {
482 sal_Int32 nHeight = _aPosY[j+1] - _aPosY[j];
483 if ( nHeight )
484 for (sal_Int32 i = 0; i < nCountX ; ++i)
485 {
486 _rColumns[j].second[i] = ORptExport::TCell(1,1);
487 _rColumns[j].second[i].bSet = true;
488 }
489 }
490 }
491
collectStyleNames(sal_Int32 _nFamily,const::std::vector<sal_Int32> & _aSize,std::vector<OUString> & _rStyleNames)492 void ORptExport::collectStyleNames(sal_Int32 _nFamily,const ::std::vector< sal_Int32>& _aSize, std::vector<OUString>& _rStyleNames)
493 {
494 ::std::vector< XMLPropertyState > aPropertyStates;
495 aPropertyStates.emplace_back(0);
496 ::std::vector<sal_Int32>::const_iterator aIter = _aSize.begin();
497 ::std::vector<sal_Int32>::const_iterator aIter2 = aIter + 1;
498 ::std::vector<sal_Int32>::const_iterator aEnd = _aSize.end();
499 for (;aIter2 != aEnd ; ++aIter,++aIter2)
500 {
501 sal_Int32 nValue = static_cast<sal_Int32>(*aIter2 - *aIter);
502 aPropertyStates[0].maValue <<= nValue;
503 _rStyleNames.push_back(GetAutoStylePool()->Add(_nFamily, aPropertyStates ));
504 }
505 }
506
collectStyleNames(sal_Int32 _nFamily,const::std::vector<sal_Int32> & _aSize,const::std::vector<sal_Int32> & _aSizeAutoGrow,std::vector<OUString> & _rStyleNames)507 void ORptExport::collectStyleNames(sal_Int32 _nFamily, const ::std::vector< sal_Int32>& _aSize, const ::std::vector< sal_Int32>& _aSizeAutoGrow, std::vector<OUString>& _rStyleNames)
508 {
509 ::std::vector< XMLPropertyState > aPropertyStates;
510 aPropertyStates.emplace_back(0);
511 ::std::vector<sal_Int32>::const_iterator aIter = _aSize.begin();
512 ::std::vector<sal_Int32>::const_iterator aIter2 = aIter + 1;
513 ::std::vector<sal_Int32>::const_iterator aEnd = _aSize.end();
514 for (;aIter2 != aEnd; ++aIter, ++aIter2)
515 {
516 sal_Int32 nValue = static_cast<sal_Int32>(*aIter2 - *aIter);
517 aPropertyStates[0].maValue <<= nValue;
518 // note: there cannot be 0-height rows, because a call to std::unique has removed them
519 // it cannot be predicted that the size of _aSizeAutoGrow has any relation to the size of
520 // _aSize, because of the same std::unique operation (and _aSizeAutoGrow wasn't even the same
521 // size before that), so the matching element in _aSizeAutoGrow has to be found by lookup.
522 ::std::vector<sal_Int32>::const_iterator aAutoGrow = ::std::find(_aSizeAutoGrow.begin(), _aSizeAutoGrow.end(), *aIter2);
523 bool bAutoGrow = aAutoGrow != _aSizeAutoGrow.end();
524 // the mnIndex is into the array returned by OXMLHelper::GetRowStyleProps()
525 aPropertyStates[0].mnIndex = bAutoGrow ? 1 : 0;
526 _rStyleNames.push_back(GetAutoStylePool()->Add(_nFamily, aPropertyStates));
527 }
528 }
529
exportSectionAutoStyle(const Reference<XSection> & _xProp)530 void ORptExport::exportSectionAutoStyle(const Reference<XSection>& _xProp)
531 {
532 OSL_ENSURE(_xProp != nullptr,"Section is NULL -> GPF");
533 exportAutoStyle(_xProp);
534
535 Reference<XReportDefinition> xReport = _xProp->getReportDefinition();
536 const awt::Size aSize = rptui::getStyleProperty<awt::Size>(xReport,PROPERTY_PAPERSIZE);
537 const sal_Int32 nOffset = rptui::getStyleProperty<sal_Int32>(xReport,PROPERTY_LEFTMARGIN);
538 const sal_Int32 nCount = _xProp->getCount();
539
540 ::std::vector<sal_Int32> aColumnPos;
541 aColumnPos.reserve(2*(nCount + 1));
542 aColumnPos.push_back(nOffset);
543 aColumnPos.push_back(aSize.Width - rptui::getStyleProperty<sal_Int32>(xReport,PROPERTY_RIGHTMARGIN));
544
545 ::std::vector<sal_Int32> aRowPos;
546 aRowPos.reserve(2*(nCount + 1));
547 aRowPos.push_back(0);
548 aRowPos.push_back(_xProp->getHeight());
549
550
551 ::std::vector<sal_Int32> aRowPosAutoGrow;
552 aRowPosAutoGrow.reserve(2 * (nCount + 1));
553
554
555 sal_Int32 i;
556 for (i = 0 ; i< nCount ; ++i)
557 {
558 Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
559 uno::Reference< XShape> xShape(xReportElement,uno::UNO_QUERY);
560 if ( xShape.is() )
561 continue;
562 OSL_ENSURE( xReportElement.is(),"NULL Element in Section!" );
563 if ( !xReportElement.is() )
564 continue;
565 sal_Int32 nX = xReportElement->getPositionX();
566 aColumnPos.push_back(nX);
567 Reference<XFixedLine> xFixedLine(xReportElement,uno::UNO_QUERY);
568 if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
569 {
570 sal_Int32 nWidth = static_cast<sal_Int32>(xReportElement->getWidth()*0.5);
571 nX += nWidth;
572 aColumnPos.push_back(nX);
573 nX += xReportElement->getWidth() - nWidth;
574 }
575 else
576 nX += xReportElement->getWidth();
577 aColumnPos.push_back(nX); // --nX why?
578
579 sal_Int32 nY = xReportElement->getPositionY();
580 aRowPos.push_back(nY);
581 nY += xReportElement->getHeight();
582 aRowPos.push_back(nY); // --nY why?
583 bool bAutoGrow = xReportElement->getAutoGrow();
584 if (bAutoGrow)
585 {
586 // the resulting table row ending at nY should auto-grow
587 aRowPosAutoGrow.push_back(nY);
588 }
589 }
590
591 ::std::sort(aColumnPos.begin(),aColumnPos.end(),::std::less<sal_Int32>());
592 aColumnPos.erase(::std::unique(aColumnPos.begin(),aColumnPos.end()),aColumnPos.end());
593
594 // note: the aRowPos contains top and bottom position of every report control; we now compute the
595 // top of every row in the resulting table, by sorting and eliminating unnecessary duplicate
596 // positions. (the same for the columns in the preceding lines.)
597 ::std::sort(aRowPos.begin(),aRowPos.end(),::std::less<sal_Int32>());
598 aRowPos.erase(::std::unique(aRowPos.begin(),aRowPos.end()),aRowPos.end());
599
600 TSectionsGrid::iterator aInsert = m_aSectionsGrid.emplace(
601 _xProp.get(),
602 TGrid(aRowPos.size() - 1,TGrid::value_type(false,TRow(aColumnPos.size() - 1)))
603 ).first;
604 lcl_calculate(aColumnPos,aRowPos,aInsert->second);
605
606 TGridStyleMap::iterator aPos = m_aColumnStyleNames.emplace(_xProp.get(),std::vector<OUString>()).first;
607 collectStyleNames(XML_STYLE_FAMILY_TABLE_COLUMN,aColumnPos,aPos->second);
608 aPos = m_aRowStyleNames.emplace(_xProp.get(),std::vector<OUString>()).first;
609 collectStyleNames(XML_STYLE_FAMILY_TABLE_ROW, aRowPos, aRowPosAutoGrow, aPos->second);
610
611 sal_Int32 x1 = 0;
612 sal_Int32 y1 = 0;
613 sal_Int32 x2 = 0;
614 sal_Int32 y2 = 0;
615 sal_Int32 xi = 0;
616 sal_Int32 yi = 0;
617 bool isOverlap = false;
618
619 for (i = 0 ; i< nCount ; ++i)
620 {
621 Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
622 uno::Reference< XShape> xShape(xReportElement,uno::UNO_QUERY);
623 if ( xShape.is() )
624 continue;
625 sal_Int32 nPos = xReportElement->getPositionX();
626 x1 = (::std::find(aColumnPos.begin(),aColumnPos.end(),nPos) - aColumnPos.begin());
627 Reference<XFixedLine> xFixedLine(xReportElement,uno::UNO_QUERY);
628 if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical
629 nPos += static_cast<sal_Int32>(xReportElement->getWidth()*0.5);
630 else
631 nPos += xReportElement->getWidth(); // -1 why
632 x2 = (::std::find(aColumnPos.begin(),aColumnPos.end(),nPos) - aColumnPos.begin());
633
634 nPos = xReportElement->getPositionY();
635 y1 = (::std::find(aRowPos.begin(),aRowPos.end(),nPos) - aRowPos.begin());
636 nPos += xReportElement->getHeight(); // -1 why?
637 y2 = (::std::find(aRowPos.begin(),aRowPos.end(),nPos) - aRowPos.begin());
638
639 isOverlap = false;
640 yi = y1;
641 while(yi < y2 && !isOverlap) // find overlapping controls
642 {
643 xi = x1;
644 while(xi < x2 && !isOverlap)
645 {
646 if ( aInsert->second[yi].second[xi].xElement.is() )
647 {
648 isOverlap = true;
649 }
650 ++xi;
651 }
652 ++yi;
653 }
654
655 if (!isOverlap)
656 {
657 yi = y1;
658 while(yi < y2)
659 {
660 xi = x1;
661 while(xi < x2)
662 {
663 aInsert->second[yi].second[xi] = TCell();
664 ++xi;
665 }
666 aInsert->second[yi].first = true;
667 ++yi;
668 }
669
670 if (x2 - x1 != 0 && y2 - y1 != 0)
671 {
672 sal_Int32 nColSpan = x2 - x1;
673 sal_Int32 nRowSpan = y2 - y1;
674 aInsert->second[y1].second[x1] =
675 TCell(
676 nColSpan,
677 nRowSpan,
678 xReportElement
679 );
680 }
681 }
682 }
683
684 lcl_adjustColumnSpanOverRows(m_aSectionsGrid);
685 exportReportComponentAutoStyles(_xProp);
686 }
687
exportReportComponentAutoStyles(const Reference<XSection> & _xProp)688 void ORptExport::exportReportComponentAutoStyles(const Reference<XSection>& _xProp)
689 {
690 const sal_Int32 nCount = _xProp->getCount();
691 for (sal_Int32 i = 0 ; i< nCount ; ++i)
692 {
693 const Reference<XReportComponent> xReportElement(_xProp->getByIndex(i),uno::UNO_QUERY);
694 const Reference< report::XShape > xShape(xReportElement,uno::UNO_QUERY);
695 if ( xShape.is() )
696 {
697 rtl::Reference< XMLShapeExport > xShapeExport = GetShapeExport();
698 xShapeExport->seekShapes(_xProp.get());
699 SolarMutexGuard aGuard;
700 xShapeExport->collectShapeAutoStyles(xShape.get());
701 }
702 else
703 {
704 exportAutoStyle(xReportElement.get());
705
706 Reference<XFormattedField> xFormattedField(xReportElement,uno::UNO_QUERY);
707 if ( xFormattedField.is() )
708 {
709 try
710 {
711 const sal_Int32 nFormatCount = xFormattedField->getCount();
712 for (sal_Int32 j = 0; j < nFormatCount ; ++j)
713 {
714 uno::Reference< report::XFormatCondition > xCond(xFormattedField->getByIndex(j),uno::UNO_QUERY);
715 exportAutoStyle(xCond.get(),xFormattedField);
716 }
717 }
718 catch(uno::Exception&)
719 {
720 OSL_FAIL("Can not access format condition!");
721 }
722 }
723 }
724 }
725 }
726
exportSection(const Reference<XSection> & _xSection,bool bHeader)727 void ORptExport::exportSection(const Reference<XSection>& _xSection,bool bHeader)
728 {
729 OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF");
730 OUStringBuffer sValue;
731 AddAttribute(XML_NAMESPACE_TABLE, XML_NAME,_xSection->getName());
732
733 if ( !_xSection->getVisible() )
734 AddAttribute(XML_NAMESPACE_REPORT, XML_VISIBLE,XML_FALSE);
735
736 if ( !bHeader )
737 {
738 sal_Int16 nRet = _xSection->getForceNewPage();
739 const SvXMLEnumMapEntry<sal_Int16>* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions();
740 if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
741 AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_PAGE,sValue.makeStringAndClear());
742
743 nRet = _xSection->getNewRowOrCol();
744 if ( SvXMLUnitConverter::convertEnum( sValue, nRet,aXML_EnumMap ) )
745 AddAttribute(XML_NAMESPACE_REPORT, XML_FORCE_NEW_COLUMN,sValue.makeStringAndClear());
746 if ( _xSection->getKeepTogether() )
747 AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER, XML_TRUE );
748 }
749
750 exportStyleName(_xSection.get(),GetAttrList(),m_sTableStyle);
751
752 /// TODO export as table layout
753 SvXMLElementExport aComponents(*this,XML_NAMESPACE_TABLE, XML_TABLE, true, true);
754
755 OUString sExpr = _xSection->getConditionalPrintExpression();
756 if ( !sExpr.isEmpty() )
757 {
758 exportFormula(XML_FORMULA,sExpr);
759 SvXMLElementExport aPrintExpr(*this,XML_NAMESPACE_REPORT, XML_CONDITIONAL_PRINT_EXPRESSION, true, false);
760 }
761
762 exportContainer(_xSection);
763 }
764
exportTableColumns(const Reference<XSection> & _xSection)765 void ORptExport::exportTableColumns(const Reference< XSection>& _xSection)
766 {
767 SvXMLElementExport aColumns(*this,XML_NAMESPACE_TABLE, XML_TABLE_COLUMNS, true, true);
768 TGridStyleMap::const_iterator aColFind = m_aColumnStyleNames.find(_xSection.get());
769 OSL_ENSURE(aColFind != m_aColumnStyleNames.end(),"ORptExport::exportTableColumns: Section not found in m_aColumnStyleNames!");
770 if ( aColFind == m_aColumnStyleNames.end() )
771 return;
772
773 for (auto& aCol : aColFind->second)
774 {
775 AddAttribute(m_sTableStyle, aCol);
776 SvXMLElementExport aColumn(*this,XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true);
777 }
778 }
779
exportContainer(const Reference<XSection> & _xSection)780 void ORptExport::exportContainer(const Reference< XSection>& _xSection)
781 {
782 OSL_ENSURE(_xSection.is(),"Section is NULL -> GPF");
783
784 exportTableColumns(_xSection);
785
786 TSectionsGrid::const_iterator aFind = m_aSectionsGrid.find(_xSection.get());
787 OSL_ENSURE(aFind != m_aSectionsGrid.end(),"ORptExport::exportContainer: Section not found in grid!");
788 if ( aFind == m_aSectionsGrid.end() )
789 return;
790 TGrid::const_iterator aRowIter = aFind->second.begin();
791 TGrid::const_iterator aRowEnd = aFind->second.end();
792
793 TGridStyleMap::const_iterator aRowFind = m_aRowStyleNames.find(_xSection.get());
794 auto aHeightIter = aRowFind->second.cbegin();
795 OSL_ENSURE(aRowFind->second.size() == aFind->second.size(),"Different count for rows");
796
797 bool bShapeHandled = false;
798 ::std::map<sal_Int32,sal_Int32> aRowSpan;
799 for (sal_Int32 j = 0; aRowIter != aRowEnd; ++aRowIter,++j,++aHeightIter)
800 {
801 AddAttribute( m_sTableStyle,*aHeightIter );
802 SvXMLElementExport aRow(*this,XML_NAMESPACE_TABLE, XML_TABLE_ROW, true, true);
803 if ( aRowIter->first )
804 {
805 ::std::vector< TCell >::const_iterator aColIter = aRowIter->second.begin();
806 ::std::vector< TCell >::const_iterator aColEnd = aRowIter->second.end();
807 sal_Int32 nEmptyCellColSpan = 0;
808 for (; aColIter != aColEnd; ++aColIter)
809 {
810 bool bCoveredCell = false;
811 sal_Int32 nColSpan = 0;
812 sal_Int32 nColIndex = aColIter - aRowIter->second.begin();
813 ::std::map<sal_Int32,sal_Int32>::iterator aRowSpanFind = aRowSpan.find(nColIndex);
814 if ( aRowSpanFind != aRowSpan.end() )
815 {
816 nColSpan = 1;
817 if ( !--(aRowSpanFind->second) )
818 aRowSpan.erase(aRowSpanFind);
819
820 if ( aColIter->nColSpan > 1 )
821 nColSpan += aColIter->nColSpan - 1;
822
823 bCoveredCell = true;
824 aColIter = aColIter + (aColIter->nColSpan - 1);
825 }
826 else if ( aColIter->bSet )
827 {
828 if ( nEmptyCellColSpan > 0 )
829 {
830 AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
831 bCoveredCell = true;
832 nColSpan = nEmptyCellColSpan - 1;
833 nEmptyCellColSpan = 0;
834 }
835 sal_Int32 nSpan = aColIter->nColSpan;
836 if ( nSpan > 1 )
837 {
838 AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nSpan) );
839 nColSpan = nSpan - 1;
840 bCoveredCell = true;
841 }
842 nSpan = aColIter->nRowSpan;
843 if ( nSpan > 1 )
844 {
845 AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_ROWS_SPANNED, OUString::number(nSpan) );
846 aRowSpan[nColIndex] = nSpan - 1;
847 }
848 if ( aColIter->xElement.is() )
849 exportStyleName(aColIter->xElement.get(),GetAttrList(),m_sTableStyle);
850
851 // start <table:table-cell>
852 Reference<XFormattedField> xFormattedField(aColIter->xElement,uno::UNO_QUERY);
853 if ( xFormattedField.is() )
854 {
855 sal_Int32 nFormatKey = xFormattedField->getFormatKey();
856 XMLNumberFormatAttributesExportHelper aHelper(GetNumberFormatsSupplier(),*this);
857 bool bIsStandard = false;
858 sal_Int16 nCellType = aHelper.GetCellType(nFormatKey,bIsStandard);
859 // "Standard" means "no format set, value could be anything",
860 // so don't set a format attribute in this case.
861 // P.S.: "Standard" is called "General" in some languages
862 if (!bIsStandard)
863 {
864 if ( nCellType == util::NumberFormat::TEXT )
865 aHelper.SetNumberFormatAttributes("", "");
866 else
867 aHelper.SetNumberFormatAttributes(nFormatKey, 0.0, false);
868 }
869 }
870 SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, false);
871
872 if ( aColIter->xElement.is() )
873 {
874 // start <text:p>
875 SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, true, false);
876 Reference<XServiceInfo> xElement(aColIter->xElement,uno::UNO_QUERY);
877
878 if ( !bShapeHandled )
879 {
880 bShapeHandled = true;
881 exportShapes(_xSection,false);
882 }
883 uno::Reference< XShape > xShape(xElement,uno::UNO_QUERY);
884 uno::Reference< XFixedLine > xFixedLine(xElement,uno::UNO_QUERY);
885 if ( !xShape.is() && !xFixedLine.is() )
886 {
887 Reference<XReportControlModel> xReportElement(xElement,uno::UNO_QUERY);
888 Reference<XReportDefinition> xReportDefinition(xElement,uno::UNO_QUERY);
889 Reference< XImageControl > xImage(xElement,uno::UNO_QUERY);
890 Reference<XSection> xSection(xElement,uno::UNO_QUERY);
891
892 XMLTokenEnum eToken = XML_SECTION;
893 bool bExportData = false;
894 if ( xElement->supportsService(SERVICE_FIXEDTEXT) )
895 {
896 eToken = XML_FIXED_CONTENT;
897 }
898 else if ( xElement->supportsService(SERVICE_FORMATTEDFIELD) )
899 {
900 eToken = XML_FORMATTED_TEXT;
901 bExportData = true;
902 }
903 else if ( xElement->supportsService(SERVICE_IMAGECONTROL) )
904 {
905 eToken = XML_IMAGE;
906 OUString sTargetLocation = xImage->getImageURL();
907 if ( !sTargetLocation.isEmpty() )
908 {
909 sTargetLocation = GetRelativeReference(sTargetLocation);
910 AddAttribute(XML_NAMESPACE_FORM, XML_IMAGE_DATA,sTargetLocation);
911 }
912 bExportData = true;
913 OUStringBuffer sValue;
914 const SvXMLEnumMapEntry<sal_Int16>* aXML_ImageScaleEnumMap = OXMLHelper::GetImageScaleOptions();
915 if ( SvXMLUnitConverter::convertEnum( sValue, xImage->getScaleMode(),aXML_ImageScaleEnumMap ) )
916 AddAttribute(XML_NAMESPACE_REPORT, XML_SCALE, sValue.makeStringAndClear() );
917 }
918 else if ( xReportDefinition.is() )
919 {
920 eToken = XML_SUB_DOCUMENT;
921 }
922
923 if ( bExportData )
924 {
925 const bool bPageSet = exportFormula(XML_FORMULA,xReportElement->getDataField());
926 if ( bPageSet )
927 eToken = XML_FIXED_CONTENT;
928 else if ( eToken == XML_IMAGE )
929 AddAttribute(XML_NAMESPACE_REPORT, XML_PRESERVE_IRI, xImage->getPreserveIRI() ? XML_TRUE : XML_FALSE );
930 }
931
932 {
933 // start <report:eToken>
934 SvXMLElementExport aComponents(*this,XML_NAMESPACE_REPORT, eToken, false, false);
935 if ( eToken == XML_FIXED_CONTENT )
936 exportParagraph(xReportElement);
937 if ( xReportElement.is() )
938 exportReportElement(xReportElement);
939
940 if (eToken == XML_SUB_DOCUMENT && xReportDefinition.is())
941 {
942 SvXMLElementExport aOfficeElement( *this, XML_NAMESPACE_OFFICE, XML_BODY, true, true );
943 SvXMLElementExport aElem( *this, true,
944 XML_NAMESPACE_OFFICE, XML_REPORT,
945 true, true );
946
947 exportReportAttributes(xReportDefinition);
948 exportReport(xReportDefinition);
949 }
950 else if ( xSection.is() )
951 exportSection(xSection);
952 }
953 }
954 }
955 else if ( !bShapeHandled )
956 {
957 bShapeHandled = true;
958 exportShapes(_xSection);
959 }
960 aColIter = aColIter + (aColIter->nColSpan - 1);
961 }
962 else
963 ++nEmptyCellColSpan;
964 if ( bCoveredCell )
965 {
966 for (sal_Int32 k = 0; k < nColSpan; ++k)
967 {
968 SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
969 }
970
971 }
972 }
973 if ( nEmptyCellColSpan )
974 {
975 {
976 AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
977 SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
978 if ( !bShapeHandled )
979 {
980 bShapeHandled = true;
981 exportShapes(_xSection);
982 }
983 }
984 for (sal_Int32 k = 0; k < nEmptyCellColSpan; ++k)
985 {
986 SvXMLElementExport aCoveredCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
987 }
988 }
989 }
990 else
991 { // empty rows
992 sal_Int32 nEmptyCellColSpan = aRowIter->second.size();
993 if ( nEmptyCellColSpan )
994 {
995 {
996 AddAttribute( XML_NAMESPACE_TABLE,XML_NUMBER_COLUMNS_SPANNED, OUString::number(nEmptyCellColSpan) );
997 SvXMLElementExport aCell(*this,XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true);
998 if ( !bShapeHandled )
999 {
1000 bShapeHandled = true;
1001 exportShapes(_xSection);
1002 }
1003 }
1004 for (sal_Int32 k = 1; k < nEmptyCellColSpan; ++k)
1005 {
1006 SvXMLElementExport aCoveredCell(*this,XML_NAMESPACE_TABLE, XML_COVERED_TABLE_CELL, true, true);
1007 }
1008 }
1009 }
1010 }
1011 }
1012
convertFormula(const OUString & _sFormula)1013 OUString ORptExport::convertFormula(const OUString& _sFormula)
1014 {
1015 OUString sFormula = _sFormula;
1016 if ( _sFormula == "rpt:" )
1017 sFormula.clear();
1018 return sFormula;
1019 }
1020
exportFormula(enum::xmloff::token::XMLTokenEnum eName,const OUString & _sFormula)1021 bool ORptExport::exportFormula(enum ::xmloff::token::XMLTokenEnum eName,const OUString& _sFormula)
1022 {
1023 const OUString sFieldData = convertFormula(_sFormula);
1024 sal_Int32 nPageNumberIndex = sFieldData.indexOf("PageNumber()");
1025 sal_Int32 nPageCountIndex = sFieldData.indexOf("PageCount()");
1026 bool bRet = nPageNumberIndex != -1 || nPageCountIndex != -1;
1027 if ( !bRet )
1028 AddAttribute(XML_NAMESPACE_REPORT, eName,sFieldData);
1029
1030 return bRet;
1031 }
1032
exportStyleName(XPropertySet * _xProp,SvXMLAttributeList & _rAtt,const OUString & _sName)1033 void ORptExport::exportStyleName(XPropertySet* _xProp,SvXMLAttributeList& _rAtt,const OUString& _sName)
1034 {
1035 Reference<XPropertySet> xFind(_xProp);
1036 TPropertyStyleMap::const_iterator aFind = m_aAutoStyleNames.find(xFind);
1037 if ( aFind != m_aAutoStyleNames.end() )
1038 {
1039 _rAtt.AddAttribute( _sName,
1040 aFind->second );
1041 m_aAutoStyleNames.erase(aFind);
1042 }
1043 }
1044
exportGroup(const Reference<XReportDefinition> & _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle)1045 void ORptExport::exportGroup(const Reference<XReportDefinition>& _xReportDefinition,sal_Int32 _nPos,bool _bExportAutoStyle)
1046 {
1047 if ( _xReportDefinition.is() )
1048 {
1049 Reference< XGroups > xGroups = _xReportDefinition->getGroups();
1050 if ( xGroups.is() )
1051 {
1052 sal_Int32 nCount = xGroups->getCount();
1053 if ( _nPos >= 0 && _nPos < nCount )
1054 {
1055 Reference<XGroup> xGroup(xGroups->getByIndex(_nPos),uno::UNO_QUERY);
1056 OSL_ENSURE(xGroup.is(),"No Group prepare for GPF");
1057 if ( _bExportAutoStyle )
1058 {
1059 if ( xGroup->getHeaderOn() )
1060 exportSectionAutoStyle(xGroup->getHeader());
1061 exportGroup(_xReportDefinition,_nPos+1,_bExportAutoStyle);
1062 if ( xGroup->getFooterOn() )
1063 exportSectionAutoStyle(xGroup->getFooter());
1064 }
1065 else
1066 {
1067 if ( xGroup->getSortAscending() )
1068 AddAttribute(XML_NAMESPACE_REPORT, XML_SORT_ASCENDING, XML_TRUE );
1069
1070 if ( xGroup->getStartNewColumn() )
1071 AddAttribute(XML_NAMESPACE_REPORT, XML_START_NEW_COLUMN, XML_TRUE);
1072 if ( xGroup->getResetPageNumber() )
1073 AddAttribute(XML_NAMESPACE_REPORT, XML_RESET_PAGE_NUMBER, XML_TRUE );
1074
1075 const OUString sField = xGroup->getExpression();
1076 OUString sExpression = sField;
1077 if ( !sExpression.isEmpty() )
1078 {
1079 sal_Int32 nIndex = sExpression.indexOf('"');
1080 while ( nIndex > -1 )
1081 {
1082 sExpression = sExpression.replaceAt(nIndex, 1, "\"\"");
1083 nIndex = sExpression.indexOf('"',nIndex+2);
1084 }
1085
1086 TGroupFunctionMap::const_iterator aGroupFind = m_aGroupFunctionMap.find(xGroup);
1087 if ( aGroupFind != m_aGroupFunctionMap.end() )
1088 sExpression = aGroupFind->second->getName();
1089 sExpression = "rpt:HASCHANGED(\"" + sExpression + "\")";
1090 }
1091 AddAttribute(XML_NAMESPACE_REPORT, XML_SORT_EXPRESSION, sField);
1092 AddAttribute(XML_NAMESPACE_REPORT, XML_GROUP_EXPRESSION,sExpression);
1093 sal_Int16 nRet = xGroup->getKeepTogether();
1094 OUStringBuffer sValue;
1095 const SvXMLEnumMapEntry<sal_Int16>* aXML_KeepTogetherEnumMap = OXMLHelper::GetKeepTogetherOptions();
1096 if ( SvXMLUnitConverter::convertEnum( sValue, nRet, aXML_KeepTogetherEnumMap ) )
1097 AddAttribute(XML_NAMESPACE_REPORT, XML_KEEP_TOGETHER,sValue.makeStringAndClear());
1098
1099 SvXMLElementExport aGroup(*this,XML_NAMESPACE_REPORT, XML_GROUP, true, true);
1100 exportFunctions(xGroup->getFunctions().get());
1101 if ( xGroup->getHeaderOn() )
1102 {
1103 Reference<XSection> xSection = xGroup->getHeader();
1104 if ( xSection->getRepeatSection() )
1105 AddAttribute(XML_NAMESPACE_REPORT, XML_REPEAT_SECTION,XML_TRUE );
1106 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_GROUP_HEADER, true, true);
1107 exportSection(xSection);
1108 }
1109 exportGroup(_xReportDefinition,_nPos+1,_bExportAutoStyle);
1110 if ( xGroup->getFooterOn() )
1111 {
1112 Reference<XSection> xSection = xGroup->getFooter();
1113 if ( xSection->getRepeatSection() )
1114 AddAttribute(XML_NAMESPACE_REPORT, XML_REPEAT_SECTION,XML_TRUE );
1115 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_GROUP_FOOTER, true, true);
1116 exportSection(xSection);
1117 }
1118 }
1119 }
1120 else if ( _bExportAutoStyle )
1121 {
1122 exportSectionAutoStyle(_xReportDefinition->getDetail());
1123 }
1124 else
1125 {
1126 SvXMLElementExport aGroupSection(*this,XML_NAMESPACE_REPORT, XML_DETAIL, true, true);
1127 exportSection(_xReportDefinition->getDetail());
1128 }
1129 }
1130 }
1131 }
1132
exportAutoStyle(XPropertySet * _xProp,const Reference<XFormattedField> & _xParentFormattedField)1133 void ORptExport::exportAutoStyle(XPropertySet* _xProp,const Reference<XFormattedField>& _xParentFormattedField)
1134 {
1135 const uno::Reference<report::XReportControlFormat> xFormat(_xProp,uno::UNO_QUERY);
1136 if ( xFormat.is() )
1137 {
1138 try
1139 {
1140 const awt::FontDescriptor aFont = xFormat->getFontDescriptor();
1141 OSL_ENSURE(!aFont.Name.isEmpty(),"No Font Name !");
1142 GetFontAutoStylePool()->Add(aFont.Name,aFont.StyleName,static_cast<FontFamily>(aFont.Family),
1143 static_cast<FontPitch>(aFont.Pitch),aFont.CharSet );
1144 }
1145 catch(beans::UnknownPropertyException&)
1146 {
1147 // not interested in
1148 }
1149 }
1150 const uno::Reference< report::XShape> xShape(_xProp,uno::UNO_QUERY);
1151 if ( xShape.is() )
1152 {
1153 ::std::vector< XMLPropertyState > aPropertyStates( m_xParaPropMapper->Filter(_xProp) );
1154 if ( !aPropertyStates.empty() )
1155 m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XML_STYLE_FAMILY_TEXT_PARAGRAPH, aPropertyStates ));
1156 }
1157 ::std::vector< XMLPropertyState > aPropertyStates( m_xCellStylesExportPropertySetMapper->Filter(_xProp) );
1158 Reference<XFixedLine> xFixedLine(_xProp,uno::UNO_QUERY);
1159 if ( xFixedLine.is() )
1160 {
1161 uno::Reference<beans::XPropertySet> xBorderProp = OXMLHelper::createBorderPropertySet();
1162 table::BorderLine2 aValue;
1163 aValue.Color = sal_uInt32(COL_BLACK);
1164 aValue.InnerLineWidth = aValue.LineDistance = 0;
1165 aValue.OuterLineWidth = DEFAULT_LINE_WIDTH;
1166 aValue.LineStyle = table::BorderLineStyle::SOLID;
1167 aValue.LineWidth = DEFAULT_LINE_WIDTH;
1168
1169 awt::Point aPos = xFixedLine->getPosition();
1170 awt::Size aSize = xFixedLine->getSize();
1171 sal_Int32 nSectionHeight = xFixedLine->getSection()->getHeight();
1172
1173 OUString sBorderProp;
1174 ::std::vector< OUString> aProps;
1175 if ( xFixedLine->getOrientation() == 1 ) // vertical
1176 {
1177 // check if border should be left
1178 if ( !aPos.X )
1179 {
1180 sBorderProp = PROPERTY_BORDERLEFT;
1181 aProps.emplace_back(PROPERTY_BORDERRIGHT);
1182 }
1183 else
1184 {
1185 sBorderProp = PROPERTY_BORDERRIGHT;
1186 aProps.emplace_back(PROPERTY_BORDERLEFT);
1187 }
1188 aProps.emplace_back(PROPERTY_BORDERTOP);
1189 aProps.emplace_back(PROPERTY_BORDERBOTTOM);
1190 }
1191 else // horizontal
1192 {
1193 // check if border should be bottom
1194 if ( (aPos.Y + aSize.Height) == nSectionHeight )
1195 {
1196 sBorderProp = PROPERTY_BORDERBOTTOM;
1197 aProps.emplace_back(PROPERTY_BORDERTOP);
1198 }
1199 else
1200 {
1201 sBorderProp = PROPERTY_BORDERTOP;
1202 aProps.emplace_back(PROPERTY_BORDERBOTTOM);
1203 }
1204 aProps.emplace_back(PROPERTY_BORDERRIGHT);
1205 aProps.emplace_back(PROPERTY_BORDERLEFT);
1206 }
1207
1208 xBorderProp->setPropertyValue(sBorderProp,uno::makeAny(aValue));
1209
1210 aValue.Color = aValue.OuterLineWidth = aValue.LineWidth = 0;
1211 aValue.LineStyle = table::BorderLineStyle::NONE;
1212 uno::Any aEmpty;
1213 aEmpty <<= aValue;
1214 for (auto const& it : aProps)
1215 {
1216 xBorderProp->setPropertyValue(it, aEmpty);
1217 }
1218
1219 ::std::vector< XMLPropertyState > aBorderStates(m_xCellStylesExportPropertySetMapper->Filter(xBorderProp));
1220 ::std::copy(aBorderStates.begin(),aBorderStates.end(),::std::back_inserter(aPropertyStates));
1221 }
1222 else
1223 {
1224 const Reference<XFormattedField> xFormattedField(_xProp,uno::UNO_QUERY);
1225 if ( (_xParentFormattedField.is() || xFormattedField.is()) && !aPropertyStates.empty() )
1226 {
1227 sal_Int32 nNumberFormat = 0;
1228 if ( _xParentFormattedField.is() )
1229 nNumberFormat = _xParentFormattedField->getFormatKey();
1230 else
1231 nNumberFormat = xFormattedField->getFormatKey();
1232 {
1233 sal_Int32 nStyleMapIndex = m_xCellStylesExportPropertySetMapper->getPropertySetMapper()->FindEntryIndex( CTF_RPT_NUMBERFORMAT );
1234 addDataStyle(nNumberFormat);
1235 XMLPropertyState aNumberStyleState( nStyleMapIndex, uno::makeAny( getDataStyleName(nNumberFormat) ) );
1236 auto const iter(::std::find_if(
1237 aPropertyStates.begin(), aPropertyStates.end(),
1238 [nStyleMapIndex] (XMLPropertyState const& rItem)
1239 { return rItem.mnIndex == nStyleMapIndex; } ));
1240 if (iter == aPropertyStates.end())
1241 {
1242 aPropertyStates.push_back( aNumberStyleState );
1243 }
1244 else
1245 { // there is already a property but it has the wrong type
1246 // (integer not string); TODO: can we prevent it
1247 // getting added earlier?
1248 (*iter) = aNumberStyleState;
1249 }
1250 }
1251 }
1252 }
1253
1254 if ( !aPropertyStates.empty() )
1255 m_aAutoStyleNames.emplace( _xProp,GetAutoStylePool()->Add( XML_STYLE_FAMILY_TABLE_CELL, aPropertyStates ));
1256 }
1257
exportAutoStyle(const Reference<XSection> & _xProp)1258 void ORptExport::exportAutoStyle(const Reference<XSection>& _xProp)
1259 {
1260 ::std::vector< XMLPropertyState > aPropertyStates( m_xTableStylesExportPropertySetMapper->Filter(_xProp.get()) );
1261 if ( !aPropertyStates.empty() )
1262 m_aAutoStyleNames.emplace( _xProp.get(),GetAutoStylePool()->Add( XML_STYLE_FAMILY_TABLE_TABLE, aPropertyStates ));
1263 }
1264
SetBodyAttributes()1265 void ORptExport::SetBodyAttributes()
1266 {
1267 Reference<XReportDefinition> xProp(getReportDefinition());
1268 exportReportAttributes(xProp);
1269 }
1270
exportReportAttributes(const Reference<XReportDefinition> & _xReport)1271 void ORptExport::exportReportAttributes(const Reference<XReportDefinition>& _xReport)
1272 {
1273 if ( _xReport.is() )
1274 {
1275 OUStringBuffer sValue;
1276 const SvXMLEnumMapEntry<sal_Int32>* aXML_CommnadTypeEnumMap = OXMLHelper::GetCommandTypeOptions();
1277 if ( SvXMLUnitConverter::convertEnum( sValue, _xReport->getCommandType(), aXML_CommnadTypeEnumMap ) )
1278 AddAttribute(XML_NAMESPACE_REPORT, XML_COMMAND_TYPE,sValue.makeStringAndClear());
1279
1280 OUString sComamnd = _xReport->getCommand();
1281 if ( !sComamnd.isEmpty() )
1282 AddAttribute(XML_NAMESPACE_REPORT, XML_COMMAND, sComamnd);
1283
1284 OUString sFilter( _xReport->getFilter() );
1285 if ( !sFilter.isEmpty() )
1286 AddAttribute( XML_NAMESPACE_REPORT, XML_FILTER, sFilter );
1287
1288 AddAttribute(XML_NAMESPACE_OFFICE, XML_MIMETYPE,_xReport->getMimeType());
1289
1290 bool bEscapeProcessing( _xReport->getEscapeProcessing() );
1291 if ( !bEscapeProcessing )
1292 AddAttribute( XML_NAMESPACE_REPORT, XML_ESCAPE_PROCESSING, ::xmloff::token::GetXMLToken( XML_FALSE ) );
1293
1294 OUString sName = _xReport->getCaption();
1295 if ( !sName.isEmpty() )
1296 AddAttribute(XML_NAMESPACE_OFFICE, XML_CAPTION,sName);
1297 sName = _xReport->getName();
1298 if ( !sName.isEmpty() )
1299 AddAttribute(XML_NAMESPACE_DRAW, XML_NAME,sName);
1300 }
1301 }
1302
ExportContent_()1303 void ORptExport::ExportContent_()
1304 {
1305 exportReport(getReportDefinition());
1306 }
1307
ExportMasterStyles_()1308 void ORptExport::ExportMasterStyles_()
1309 {
1310 GetPageExport()->exportMasterStyles( true );
1311 }
1312
collectComponentStyles()1313 void ORptExport::collectComponentStyles()
1314 {
1315 if ( m_bAllreadyFilled )
1316 return;
1317
1318 m_bAllreadyFilled = true;
1319 Reference<XReportDefinition> xProp(getReportDefinition());
1320 if ( xProp.is() )
1321 {
1322 uno::Reference< report::XSection> xParent(xProp->getParent(),uno::UNO_QUERY);
1323 if ( xParent.is() )
1324 exportAutoStyle(xProp.get());
1325
1326 if ( xProp->getReportHeaderOn() )
1327 exportSectionAutoStyle(xProp->getReportHeader());
1328 if ( xProp->getPageHeaderOn() )
1329 exportSectionAutoStyle(xProp->getPageHeader());
1330
1331 exportGroup(xProp,0,true);
1332
1333 if ( xProp->getPageFooterOn() )
1334 exportSectionAutoStyle(xProp->getPageFooter());
1335 if ( xProp->getReportFooterOn() )
1336 exportSectionAutoStyle(xProp->getReportFooter());
1337 }
1338 }
1339
ExportAutoStyles_()1340 void ORptExport::ExportAutoStyles_()
1341 {
1342 // there are no styles that require their own autostyles
1343 if ( getExportFlags() & SvXMLExportFlags::CONTENT )
1344 {
1345 collectComponentStyles();
1346 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_TABLE);
1347 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_COLUMN);
1348 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_ROW);
1349 GetAutoStylePool()->exportXML(XML_STYLE_FAMILY_TABLE_CELL);
1350 exportDataStyles();
1351 GetShapeExport()->exportAutoStyles();
1352 }
1353 // exported in _ExportMasterStyles
1354 if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES )
1355 GetPageExport()->collectAutoStyles( false );
1356 if( getExportFlags() & SvXMLExportFlags::MASTERSTYLES )
1357 GetPageExport()->exportAutoStyles();
1358 }
1359
ExportStyles_(bool bUsed)1360 void ORptExport::ExportStyles_(bool bUsed)
1361 {
1362 SvXMLExport::ExportStyles_(bUsed);
1363
1364 // write draw:style-name for object graphic-styles
1365 GetShapeExport()->ExportGraphicDefaults();
1366 }
1367
CreateAutoStylePool()1368 SvXMLAutoStylePoolP* ORptExport::CreateAutoStylePool()
1369 {
1370 return new OXMLAutoStylePoolP(*this);
1371 }
1372
setSourceDocument(const Reference<XComponent> & xDoc)1373 void SAL_CALL ORptExport::setSourceDocument( const Reference< XComponent >& xDoc )
1374 {
1375 m_xReportDefinition.set(xDoc,UNO_QUERY_THROW);
1376 SvXMLExport::setSourceDocument(xDoc);
1377 }
1378
ExportFontDecls_()1379 void ORptExport::ExportFontDecls_()
1380 {
1381 GetFontAutoStylePool(); // make sure the pool is created
1382 collectComponentStyles();
1383 SvXMLExport::ExportFontDecls_();
1384 }
1385
exportParagraph(const Reference<XReportControlModel> & _xReportElement)1386 void ORptExport::exportParagraph(const Reference< XReportControlModel >& _xReportElement)
1387 {
1388 OSL_PRECOND(_xReportElement.is(),"Element is null!");
1389 // start <text:p>
1390 SvXMLElementExport aParagraphContent(*this,XML_NAMESPACE_TEXT, XML_P, false, false);
1391 if ( Reference<XFormattedField>(_xReportElement,uno::UNO_QUERY).is() )
1392 {
1393 OUString sFieldData = _xReportElement->getDataField();
1394 static const char s_sPageNumber[] = "PageNumber()";
1395 static const char s_sReportPrefix[] = "rpt:";
1396 sFieldData = sFieldData.copy(strlen(s_sReportPrefix));
1397 sal_Int32 nPageNumberIndex = sFieldData.indexOf(s_sPageNumber);
1398 if ( nPageNumberIndex != -1 )
1399 {
1400 sal_Int32 nIndex = 0;
1401 do
1402 {
1403 OUString sToken = sFieldData.getToken( 0, '&', nIndex );
1404 sToken = sToken.trim();
1405 if ( !sToken.isEmpty() )
1406 {
1407 if ( sToken == s_sPageNumber )
1408 {
1409 AddAttribute(XML_NAMESPACE_TEXT, XML_SELECT_PAGE, "current" );
1410 SvXMLElementExport aPageNumber(*this,XML_NAMESPACE_TEXT, XML_PAGE_NUMBER, false, false);
1411 Characters("1");
1412 }
1413 else if ( sToken == "PageCount()" )
1414 {
1415 SvXMLElementExport aPageNumber(*this,XML_NAMESPACE_TEXT, XML_PAGE_COUNT, false, false);
1416 Characters("1");
1417 }
1418 else
1419 {
1420
1421 if ( sToken.startsWith("\"") && sToken.endsWith("\"") )
1422 sToken = sToken.copy(1,sToken.getLength()-2);
1423
1424 bool bPrevCharIsSpace = false;
1425 GetTextParagraphExport()->exportCharacterData(sToken, bPrevCharIsSpace);
1426 }
1427 }
1428 }
1429 while ( nIndex >= 0 );
1430 }
1431 }
1432 Reference< XFixedText > xFT(_xReportElement,UNO_QUERY);
1433 if ( xFT.is() )
1434 {
1435 OUString sExpr = xFT->getLabel();
1436 bool bPrevCharIsSpace = false; // FIXME this looks quite broken - does the corresponding import filter do whitespace collapsing at all?
1437 GetTextParagraphExport()->exportCharacterData(sExpr, bPrevCharIsSpace);
1438 }
1439 }
1440
CreateShapeExport()1441 XMLShapeExport* ORptExport::CreateShapeExport()
1442 {
1443 XMLShapeExport* pShapeExport = new XMLShapeExport( *this, XMLTextParagraphExport::CreateShapeExtPropMapper( *this ) );
1444 return pShapeExport;
1445 }
1446
exportShapes(const Reference<XSection> & _xSection,bool _bAddParagraph)1447 void ORptExport::exportShapes(const Reference< XSection>& _xSection,bool _bAddParagraph)
1448 {
1449 rtl::Reference< XMLShapeExport > xShapeExport = GetShapeExport();
1450 xShapeExport->seekShapes(_xSection.get());
1451 const sal_Int32 nCount = _xSection->getCount();
1452 ::std::unique_ptr<SvXMLElementExport> pParagraphContent;
1453 if ( _bAddParagraph )
1454 pParagraphContent.reset(new SvXMLElementExport(*this,XML_NAMESPACE_TEXT, XML_P, true, false));
1455
1456 awt::Point aRefPoint;
1457 aRefPoint.X = rptui::getStyleProperty<sal_Int32>(_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
1458 for (sal_Int32 i = 0; i < nCount; ++i)
1459 {
1460 uno::Reference< XShape > xShape(_xSection->getByIndex(i),uno::UNO_QUERY);
1461 if ( xShape.is() )
1462 {
1463 ::std::unique_ptr<SvXMLElementExport> pSubDocument;
1464 uno::Reference< frame::XModel> xModel(xShape->getPropertyValue("Model"),uno::UNO_QUERY);
1465 if ( xModel.is() ) // special handling for chart object
1466 {
1467 pSubDocument.reset(new SvXMLElementExport(*this,XML_NAMESPACE_REPORT, XML_SUB_DOCUMENT, false, false));
1468 exportMasterDetailFields(xShape.get());
1469 exportReportElement(xShape.get());
1470 }
1471
1472 AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, XML_PARAGRAPH );
1473 xShapeExport->exportShape(xShape.get(), SEF_DEFAULT|XMLShapeExportFlags::NO_WS,&aRefPoint);
1474 }
1475 }
1476 }
1477
exportGroupsExpressionAsFunction(const Reference<XGroups> & _xGroups)1478 void ORptExport::exportGroupsExpressionAsFunction(const Reference< XGroups>& _xGroups)
1479 {
1480 if ( _xGroups.is() )
1481 {
1482 uno::Reference< XFunctions> xFunctions = _xGroups->getReportDefinition()->getFunctions();
1483 const sal_Int32 nCount = _xGroups->getCount();
1484 for (sal_Int32 i = 0; i < nCount; ++i)
1485 {
1486 uno::Reference< XGroup> xGroup(_xGroups->getByIndex(i),uno::UNO_QUERY_THROW);
1487 const ::sal_Int16 nGroupOn = xGroup->getGroupOn();
1488 if ( nGroupOn != report::GroupOn::DEFAULT )
1489 {
1490 uno::Reference< XFunction> xFunction = xFunctions->createFunction();
1491 OUString sFunction,sPrefix,sPostfix;
1492 OUString sExpression = xGroup->getExpression();
1493 OUString sFunctionName;
1494 OUString sInitialFormula;
1495 switch(nGroupOn)
1496 {
1497 case report::GroupOn::PREFIX_CHARACTERS:
1498 sFunction = "LEFT";
1499 sPrefix = ";" + OUString::number(xGroup->getGroupInterval());
1500 break;
1501 case report::GroupOn::YEAR:
1502 sFunction = "YEAR";
1503 break;
1504 case report::GroupOn::QUARTAL:
1505 sFunction = "INT((MONTH";
1506 sPostfix = "-1)/3)+1";
1507 sFunctionName = "QUARTAL_" + sExpression;
1508 break;
1509 case report::GroupOn::MONTH:
1510 sFunction = "MONTH";
1511 break;
1512 case report::GroupOn::WEEK:
1513 sFunction = "WEEK";
1514 break;
1515 case report::GroupOn::DAY:
1516 sFunction = "DAY";
1517 break;
1518 case report::GroupOn::HOUR:
1519 sFunction = "HOUR";
1520 break;
1521 case report::GroupOn::MINUTE:
1522 sFunction = "MINUTE";
1523 break;
1524 case report::GroupOn::INTERVAL:
1525 {
1526 sFunction = "INT";
1527 uno::Reference< XFunction> xCountFunction = xFunctions->createFunction();
1528 xCountFunction->setInitialFormula(beans::Optional< OUString>(true,OUString("rpt:0")));
1529 OUString sCountName = sFunction + "_count_" + sExpression;
1530 xCountFunction->setName(sCountName);
1531 xCountFunction->setFormula( "rpt:[" + sCountName + "] + 1" );
1532 exportFunction(xCountFunction);
1533 sExpression = sCountName;
1534 // The reference to sCountName in the formula of sFunctionName refers to the *old* value
1535 // so we need to expand the formula of sCountName
1536 sPrefix = " + 1) / " + OUString::number(xGroup->getGroupInterval());
1537 sFunctionName = sFunction + "_" + sExpression;
1538 sFunction += "(";
1539 sInitialFormula = "rpt:0";
1540 }
1541 break;
1542 default:
1543 ;
1544 }
1545 if ( sFunctionName.isEmpty() )
1546 sFunctionName = sFunction + "_" + sExpression;
1547 if ( !sFunction.isEmpty() )
1548 {
1549 const sal_Unicode pReplaceChars[] = { '(',')',';',',','+','-','[',']','/','*'};
1550 for(sal_Unicode ch : pReplaceChars)
1551 sFunctionName = sFunctionName.replace(ch,'_');
1552
1553 xFunction->setName(sFunctionName);
1554 if ( !sInitialFormula.isEmpty() )
1555 xFunction->setInitialFormula(beans::Optional< OUString>(true, sInitialFormula));
1556 sFunction = "rpt:" + sFunction + "([" + sExpression + "]";
1557
1558 if ( !sPrefix.isEmpty() )
1559 sFunction += sPrefix;
1560 sFunction += ")";
1561 if ( !sPostfix.isEmpty() )
1562 sFunction += sPostfix;
1563 xFunction->setFormula(sFunction);
1564 exportFunction(xFunction);
1565 m_aGroupFunctionMap.emplace(xGroup,xFunction);
1566 }
1567 }
1568 }
1569 }
1570 }
1571
1572
1573 }// rptxml
1574
1575
1576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1577