1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <xmloff/table/XMLTableExport.hxx>
22 #include <sal/config.h>
23 #include <sal/log.hxx>
25 #include <rtl/ustring.hxx>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
28 #include <com/sun/star/text/XText.hpp>
29 #include <com/sun/star/table/XCellRange.hpp>
30 #include <com/sun/star/table/XColumnRowRange.hpp>
31 #include <com/sun/star/table/XMergeableCell.hpp>
32 #include <com/sun/star/style/XStyle.hpp>
33 #include <com/sun/star/beans/XPropertyState.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <comphelper/diagnose_ex.hxx>
39 #include <xmloff/xmlnamespace.hxx>
40 #include <xmloff/xmlprmap.hxx>
41 #include <xmloff/xmlexppr.hxx>
42 #include <xmloff/xmlexp.hxx>
43 #include <xmloff/xmltypes.hxx>
44 #include <xmlsdtypes.hxx>
45 #include <xmloff/maptype.hxx>
46 #include <xmloff/prhdlfac.hxx>
47 #include <xmloff/txtprmap.hxx>
49 #include <xmlprop.hxx>
51 using namespace ::xmloff::token
;
52 using namespace ::com::sun::star::uno
;
53 using namespace ::com::sun::star::lang
;
54 using namespace ::com::sun::star::table
;
55 using namespace ::com::sun::star::beans
;
56 using namespace ::com::sun::star::container
;
57 using namespace ::com::sun::star::text
;
58 using namespace ::com::sun::star::style
;
60 #define MAP_(name,prefix,token,type,context) { name, prefix, token, type, context, SvtSaveOptions::ODFSVER_010, false }
61 #define CMAP(name,prefix,token,type,context) MAP_(name,prefix,token,type|XML_TYPE_PROP_TABLE_COLUMN,context)
62 #define RMAP(name,prefix,token,type,context) MAP_(name,prefix,token,type|XML_TYPE_PROP_TABLE_ROW,context)
63 #define CELLMAP(name,prefix,token,type,context) MAP_(name,prefix,token,type|XML_TYPE_PROP_TABLE_CELL,context)
64 #define MAP_END { nullptr }
66 const XMLPropertyMapEntry
* getColumnPropertiesMap()
68 static const XMLPropertyMapEntry aXMLColumnProperties
[] =
70 CMAP( PROP_Width
, XML_NAMESPACE_STYLE
, XML_COLUMN_WIDTH
, XML_TYPE_MEASURE
, 0 ),
71 CMAP( PROP_OptimalWidth
, XML_NAMESPACE_STYLE
, XML_USE_OPTIMAL_COLUMN_WIDTH
, XML_TYPE_BOOL
, 0 ),
75 return &aXMLColumnProperties
[0];
78 const XMLPropertyMapEntry
* getRowPropertiesMap()
80 static const XMLPropertyMapEntry aXMLRowProperties
[] =
82 RMAP( PROP_Height
, XML_NAMESPACE_STYLE
, XML_ROW_HEIGHT
, XML_TYPE_MEASURE
, 0 ),
83 RMAP( PROP_MinHeight
, XML_NAMESPACE_STYLE
, XML_MIN_ROW_HEIGHT
, XML_TYPE_MEASURE
, 0 ),
84 RMAP( PROP_OptimalHeight
, XML_NAMESPACE_STYLE
, XML_USE_OPTIMAL_ROW_HEIGHT
, XML_TYPE_BOOL
, 0 ),
88 return &aXMLRowProperties
[0];
91 const XMLPropertyMapEntry
* getCellPropertiesMap()
93 static const XMLPropertyMapEntry aXMLCellProperties
[] =
95 CELLMAP( PROP_RotateAngle
, XML_NAMESPACE_STYLE
, XML_ROTATION_ANGLE
, XML_SD_TYPE_CELL_ROTATION_ANGLE
, 0),
96 CELLMAP( PROP_TextVerticalAdjust
, XML_NAMESPACE_STYLE
, XML_VERTICAL_ALIGN
, XML_SD_TYPE_VERTICAL_ALIGN
|MID_FLAG_SPECIAL_ITEM_EXPORT
, 0),
97 CELLMAP( PROP_BackColor
, XML_NAMESPACE_FO
, XML_BACKGROUND_COLOR
, XML_TYPE_COLORTRANSPARENT
|MID_FLAG_SPECIAL_ITEM
, 0),
98 CELLMAP( PROP_LeftBorder
, XML_NAMESPACE_FO
, XML_BORDER
, XML_TYPE_BORDER
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARALLBORDER
),
99 CELLMAP( PROP_LeftBorder
, XML_NAMESPACE_FO
, XML_BORDER_LEFT
, XML_TYPE_BORDER
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARLEFTBORDER
),
100 CELLMAP( PROP_RightBorder
, XML_NAMESPACE_FO
, XML_BORDER_RIGHT
, XML_TYPE_BORDER
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARRIGHTBORDER
),
101 CELLMAP( PROP_TopBorder
, XML_NAMESPACE_FO
, XML_BORDER_TOP
, XML_TYPE_BORDER
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARTOPBORDER
),
102 CELLMAP( PROP_BottomBorder
, XML_NAMESPACE_FO
, XML_BORDER_BOTTOM
, XML_TYPE_BORDER
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARBOTTOMBORDER
),
103 CELLMAP( PROP_TextLeftDistance
, XML_NAMESPACE_FO
, XML_PADDING
, XML_TYPE_MEASURE
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARALLBORDERDISTANCE
),
104 CELLMAP( PROP_TextLeftDistance
, XML_NAMESPACE_FO
, XML_PADDING_LEFT
, XML_TYPE_MEASURE
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARLEFTBORDERDISTANCE
),
105 CELLMAP( PROP_TextRightDistance
, XML_NAMESPACE_FO
, XML_PADDING_RIGHT
, XML_TYPE_MEASURE
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARRIGHTBORDERDISTANCE
),
106 CELLMAP( PROP_TextUpperDistance
, XML_NAMESPACE_FO
, XML_PADDING_TOP
, XML_TYPE_MEASURE
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARTOPBORDERDISTANCE
),
107 CELLMAP( PROP_TextLowerDistance
, XML_NAMESPACE_FO
, XML_PADDING_BOTTOM
, XML_TYPE_MEASURE
|MID_FLAG_SPECIAL_ITEM_EXPORT
, CTF_CHARBOTTOMBORDERDISTANCE
),
111 return &aXMLCellProperties
[0];
116 class StringStatisticHelper
119 std::map
< OUString
, sal_Int32
> mStats
;
122 void add( const OUString
& rStyleName
);
123 void clear() { mStats
.clear(); }
125 sal_Int32
getModeString( /* out */ OUString
& rModeString
);
130 void StringStatisticHelper::add( const OUString
& rStyleName
)
132 std::map
< OUString
, sal_Int32
>::iterator
iter( mStats
.find( rStyleName
) );
133 if( iter
== mStats
.end() )
135 mStats
[rStyleName
] = 1;
143 sal_Int32
StringStatisticHelper::getModeString( OUString
& rStyleName
)
146 for( const auto& rStatsEntry
: mStats
)
148 if( rStatsEntry
.second
> nMax
)
150 rStyleName
= rStatsEntry
.first
;
151 nMax
= rStatsEntry
.second
;
160 class XMLCellExportPropertyMapper
: public SvXMLExportPropertyMapper
163 using SvXMLExportPropertyMapper::SvXMLExportPropertyMapper
;
164 /** this method is called for every item that has the
165 MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
166 virtual void handleSpecialItem(comphelper::AttributeList
&, const XMLPropertyState
&, const SvXMLUnitConverter
&,
167 const SvXMLNamespaceMap
&, const std::vector
<XMLPropertyState
>*, sal_uInt32
) const override
169 // the SpecialItem NumberFormat must not be handled by this method
175 XMLTableExport::XMLTableExport(SvXMLExport
& rExp
, const rtl::Reference
< SvXMLExportPropertyMapper
>& xExportPropertyMapper
, const rtl::Reference
< XMLPropertyHandlerFactory
>& xFactoryRef
)
177 , mbExportTables( false )
180 Reference
< XMultiServiceFactory
> xFac( rExp
.GetModel(), UNO_QUERY
);
183 const Sequence
< OUString
> sSNS( xFac
->getAvailableServiceNames() );
184 const OUString
* pSNS
= std::find_if(sSNS
.begin(), sSNS
.end(),
185 [](const OUString
& rSNS
) {
186 return rSNS
== "com.sun.star.drawing.TableShape"
187 || rSNS
== "com.sun.star.style.TableStyle"; });
188 if (pSNS
!= sSNS
.end())
190 mbExportTables
= true;
191 mbWriter
= (*pSNS
== "com.sun.star.style.TableStyle");
194 catch(const Exception
&)
200 mxCellExportPropertySetMapper
= new XMLCellExportPropertyMapper(new XMLTextPropertySetMapper(TextPropMap::CELL
, true));
204 mxCellExportPropertySetMapper
= xExportPropertyMapper
;
205 mxCellExportPropertySetMapper
->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(rExp
));
206 mxCellExportPropertySetMapper
->ChainExportMapper(new XMLCellExportPropertyMapper(new XMLPropertySetMapper(getCellPropertiesMap(), xFactoryRef
, true)));
209 mxRowExportPropertySetMapper
= new SvXMLExportPropertyMapper( new XMLPropertySetMapper( getRowPropertiesMap(), xFactoryRef
, true ) );
210 mxColumnExportPropertySetMapper
= new SvXMLExportPropertyMapper( new XMLPropertySetMapper( getColumnPropertiesMap(), xFactoryRef
, true ) );
212 mrExport
.GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_COLUMN
,
213 OUString(XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_NAME
),
214 mxColumnExportPropertySetMapper
.get(),
215 OUString(XML_STYLE_FAMILY_TABLE_COLUMN_STYLES_PREFIX
));
216 mrExport
.GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_ROW
,
217 OUString(XML_STYLE_FAMILY_TABLE_ROW_STYLES_NAME
),
218 mxRowExportPropertySetMapper
.get(),
219 OUString(XML_STYLE_FAMILY_TABLE_ROW_STYLES_PREFIX
));
220 mrExport
.GetAutoStylePool()->AddFamily(XmlStyleFamily::TABLE_CELL
,
221 OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME
),
222 mxCellExportPropertySetMapper
.get(),
223 OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX
));
226 XMLTableExport::~XMLTableExport ()
230 static bool has_states( const std::vector
< XMLPropertyState
>& xPropStates
)
232 return std::any_of(xPropStates
.cbegin(), xPropStates
.cend(),
233 [](const XMLPropertyState
& rPropertyState
) { return rPropertyState
.mnIndex
!= -1; });
236 void XMLTableExport::collectTableAutoStyles(const Reference
< XColumnRowRange
>& xColumnRowRange
)
238 if( !mbExportTables
)
241 auto xTableInfo
= std::make_shared
<XMLTableInfo
>();
242 maTableInfoMap
[xColumnRowRange
] = xTableInfo
;
246 Reference
< XIndexAccess
> xIndexAccessCols( xColumnRowRange
->getColumns(), UNO_QUERY_THROW
);
247 const sal_Int32 nColumnCount
= xIndexAccessCols
->getCount();
248 for( sal_Int32 nColumn
= 0; nColumn
< nColumnCount
; ++nColumn
) try
250 Reference
< XPropertySet
> xPropSet( xIndexAccessCols
->getByIndex(nColumn
) , UNO_QUERY_THROW
);
251 std::vector
<XMLPropertyState
> aPropStates(mxColumnExportPropertySetMapper
->Filter(mrExport
, xPropSet
));
253 if( has_states( aPropStates
) )
255 const OUString
sStyleName( mrExport
.GetAutoStylePool()->Add(XmlStyleFamily::TABLE_COLUMN
, std::move(aPropStates
)) );
256 Reference
< XInterface
> xKey( xPropSet
, UNO_QUERY
);
257 xTableInfo
->maColumnStyleMap
[xKey
] = sStyleName
;
260 catch(const Exception
&)
262 TOOLS_WARN_EXCEPTION("xmloff.table", "exception during column style collection!");
265 Reference
< XIndexAccess
> xIndexAccessRows( xColumnRowRange
->getRows(), UNO_QUERY_THROW
);
266 const sal_Int32 nRowCount
= xIndexAccessRows
->getCount();
267 xTableInfo
->maDefaultRowCellStyles
.resize(nRowCount
);
269 StringStatisticHelper aStringStatistic
;
271 for( sal_Int32 nRow
= 0; nRow
< nRowCount
; ++nRow
)
274 Reference
< XPropertySet
> xPropSet( xIndexAccessRows
->getByIndex(nRow
) , UNO_QUERY_THROW
);
275 std::vector
<XMLPropertyState
> aRowPropStates(mxRowExportPropertySetMapper
->Filter(mrExport
, xPropSet
));
277 if( has_states( aRowPropStates
) )
279 const OUString
sStyleName( mrExport
.GetAutoStylePool()->Add(XmlStyleFamily::TABLE_ROW
, std::move(aRowPropStates
)) );
280 Reference
< XInterface
> xKey( xPropSet
, UNO_QUERY
);
281 xTableInfo
->maRowStyleMap
[xKey
] = sStyleName
;
284 // get the current row
285 Reference
< XCellRange
> xCellRange( xPropSet
, UNO_QUERY_THROW
);
286 for ( sal_Int32 nColumn
= 0; nColumn
< nColumnCount
; ++nColumn
)
288 // get current cell, remarks row index is 0, because we get the range for each row separate
289 Reference
< XPropertySet
> xCellSet( xCellRange
->getCellByPosition(nColumn
, 0), UNO_QUERY_THROW
);
292 OUString sParentStyleName
;
293 Reference
< XPropertySetInfo
> xPropertySetInfo( xCellSet
->getPropertySetInfo() );
294 if( xPropertySetInfo
.is() && xPropertySetInfo
->hasPropertyByName("Style") )
296 Reference
< XStyle
> xStyle( xCellSet
->getPropertyValue("Style"), UNO_QUERY
);
298 sParentStyleName
= xStyle
->getName();
301 // create auto style, if needed
303 std::vector
<XMLPropertyState
> aCellPropStates(mxCellExportPropertySetMapper
->Filter(mrExport
, xCellSet
));
304 if( has_states( aCellPropStates
) )
305 sStyleName
= mrExport
.GetAutoStylePool()->Add(XmlStyleFamily::TABLE_CELL
, std::move(aCellPropStates
));
307 sStyleName
= sParentStyleName
;
309 if( !sStyleName
.isEmpty() )
311 Reference
< XInterface
> xKey( xCellSet
, UNO_QUERY
);
312 xTableInfo
->maCellStyleMap
[xKey
] = sStyleName
;
315 // create auto style for text
316 Reference
< XText
> xText(xCellSet
, UNO_QUERY
);
317 if(xText
.is() && !xText
->getString().isEmpty())
318 GetExport().GetTextParagraphExport()->collectTextAutoStyles( xText
);
320 aStringStatistic
.add( sStyleName
);
323 OUString sDefaultCellStyle
;
324 if( aStringStatistic
.getModeString( sDefaultCellStyle
) > 1 )
325 xTableInfo
->maDefaultRowCellStyles
[nRow
] = sDefaultCellStyle
;
327 aStringStatistic
.clear();
329 catch(const Exception
&)
331 TOOLS_WARN_EXCEPTION("xmloff.table", "exception during column style collection!");
334 catch(const Exception
&)
336 TOOLS_WARN_EXCEPTION("xmloff.table", "exception caught!");
340 void XMLTableExport::exportTable( const Reference
< XColumnRowRange
>& xColumnRowRange
)
342 if( !mbExportTables
)
347 std::shared_ptr
< XMLTableInfo
> xTableInfo( maTableInfoMap
[xColumnRowRange
] );
349 // get row and column count
350 Reference
< XIndexAccess
> xIndexAccess( xColumnRowRange
->getRows(), UNO_QUERY_THROW
);
351 Reference
< XIndexAccess
> xIndexAccessCols( xColumnRowRange
->getColumns(), UNO_QUERY_THROW
);
353 const sal_Int32 rowCount
= xIndexAccess
->getCount();
354 const sal_Int32 columnCount
= xIndexAccessCols
->getCount();
356 SvXMLElementExport
tableElement( mrExport
, XML_NAMESPACE_TABLE
, XML_TABLE
, true, true );
358 // export table columns
359 ExportTableColumns( xIndexAccessCols
, xTableInfo
);
361 // start iterating rows and columns
362 for ( sal_Int32 rowIndex
= 0; rowIndex
< rowCount
; rowIndex
++ )
364 // get the current row
365 Reference
< XCellRange
> xCellRange( xIndexAccess
->getByIndex(rowIndex
), UNO_QUERY_THROW
);
367 OUString sDefaultCellStyle
;
372 Reference
< XInterface
> xKey( xCellRange
, UNO_QUERY
);
373 const OUString
sStyleName( xTableInfo
->maRowStyleMap
[xKey
] );
374 if( !sStyleName
.isEmpty() )
375 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, sStyleName
);
377 sDefaultCellStyle
= xTableInfo
->maDefaultRowCellStyles
[rowIndex
];
378 if( !sDefaultCellStyle
.isEmpty() )
379 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_DEFAULT_CELL_STYLE_NAME
, sDefaultCellStyle
);
383 SvXMLElementExport
tableRowElement( mrExport
, XML_NAMESPACE_TABLE
, XML_TABLE_ROW
, true, true );
385 for ( sal_Int32 columnIndex
= 0; columnIndex
< columnCount
; columnIndex
++ )
387 // get current cell, remarks row index is 0, because we get the range for each row separate
388 Reference
< XCell
> xCell( xCellRange
->getCellByPosition(columnIndex
, 0), UNO_SET_THROW
);
390 // use XMergeableCell interface from offapi
391 Reference
< XMergeableCell
> xMergeableCell( xCell
, UNO_QUERY_THROW
);
394 ExportCell( xCell
, xTableInfo
, sDefaultCellStyle
);
398 catch(const Exception
&)
400 TOOLS_WARN_EXCEPTION("xmloff.table", "" );
404 // Export the table columns
406 void XMLTableExport::ExportTableColumns( const Reference
< XIndexAccess
>& xtableColumnsIndexAccess
, const std::shared_ptr
< XMLTableInfo
>& rTableInfo
)
408 const sal_Int32 nColumnCount
= xtableColumnsIndexAccess
->getCount();
409 for( sal_Int32 nColumn
= 0; nColumn
< nColumnCount
; ++nColumn
)
411 Reference
< XPropertySet
> xColumnProperties( xtableColumnsIndexAccess
->getByIndex(nColumn
) , UNO_QUERY
);
412 if ( xColumnProperties
.is() )
417 Reference
< XInterface
> xKey( xColumnProperties
, UNO_QUERY
);
418 const OUString
sStyleName( rTableInfo
->maColumnStyleMap
[xKey
] );
419 if( !sStyleName
.isEmpty() )
420 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, sStyleName
);
423 // TODO: all columns first have to be checked if someone
424 // have identical properties. If yes, attr table:number-columns-repeated
425 // has to be written.
426 SvXMLElementExport
tableColumnElement( mrExport
, XML_NAMESPACE_TABLE
, XML_TABLE_COLUMN
, true, true );
431 // ODF export for a table cell.
433 void XMLTableExport::ExportCell( const Reference
< XCell
>& xCell
, const std::shared_ptr
< XMLTableInfo
>& rTableInfo
, std::u16string_view rDefaultCellStyle
)
435 bool bIsMerged
= false;
436 sal_Int32 nRowSpan
= 0;
437 sal_Int32 nColSpan
= 0;
444 Reference
< XInterface
> xKey( xCell
, UNO_QUERY
);
445 const OUString
sStyleName( rTableInfo
->maCellStyleMap
[xKey
] );
446 if( !sStyleName
.isEmpty() && (sStyleName
!= rDefaultCellStyle
) )
447 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, sStyleName
);
450 Reference
< XMergeableCell
> xMerge( xCell
, UNO_QUERY
);
453 bIsMerged
= xMerge
->isMerged();
454 nRowSpan
= xMerge
->getRowSpan();
455 nColSpan
= xMerge
->getColumnSpan();
457 SAL_WARN_IF( (nRowSpan
< 1) || (nColSpan
< 1), "xmloff", "xmloff::XMLTableExport::ExportCell(), illegal row or col span < 1?" );
459 catch (const Exception
&)
461 TOOLS_WARN_EXCEPTION("xmloff.table", "exception while exporting a table cell");
464 // table:number-columns-repeated
467 // table:number-columns-spanned
469 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_NUMBER_COLUMNS_SPANNED
, OUString::number( nColSpan
) );
471 // table:number-rows-spanned
473 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_NUMBER_ROWS_SPANNED
, OUString::number( nRowSpan
) );
475 // <table:table-cell> or <table:covered-table-cell>
476 SvXMLElementExport
tableCellElement( mrExport
, XML_NAMESPACE_TABLE
, bIsMerged
? XML_COVERED_TABLE_CELL
: XML_TABLE_CELL
, true, true );
478 // export cells text content
479 ImpExportText( xCell
);
482 // ODF export of the text contents of a table cell.
483 // Remarks: Up to now we only export text contents!
484 // TODO: Check against nested tables...
486 void XMLTableExport::ImpExportText( const Reference
< XCell
>& xCell
)
488 Reference
< XText
> xText( xCell
, UNO_QUERY
);
489 if( xText
.is() && !xText
->getString().isEmpty())
490 mrExport
.GetTextParagraphExport()->exportText( xText
);
493 void XMLTableExport::exportTableStyles()
495 if( !mbExportTables
)
498 rtl::Reference
<XMLStyleExport
> aStEx
;
499 OUString sCellStyleName
;
502 sCellStyleName
= "CellStyles";
503 aStEx
.set(new XMLCellStyleExport(mrExport
));
507 // write graphic family styles
508 sCellStyleName
= "cell";
509 aStEx
.set(new XMLStyleExport(mrExport
, mrExport
.GetAutoStylePool().get()));
512 aStEx
->exportStyleFamily(sCellStyleName
, OUString(XML_STYLE_FAMILY_TABLE_CELL_STYLES_NAME
), mxCellExportPropertySetMapper
, true, XmlStyleFamily::TABLE_CELL
);
514 exportTableTemplates();
517 // Export the collected automatic styles
519 void XMLTableExport::exportAutoStyles()
521 if( !mbExportTables
)
524 mrExport
.GetAutoStylePool()->exportXML( XmlStyleFamily::TABLE_COLUMN
);
525 mrExport
.GetAutoStylePool()->exportXML( XmlStyleFamily::TABLE_ROW
);
526 mrExport
.GetAutoStylePool()->exportXML( XmlStyleFamily::TABLE_CELL
);
529 const TableStyleElement
* getTableStyleMap()
531 static const struct TableStyleElement gTableStyleElements
[] =
533 { XML_FIRST_ROW
, OUString("first-row") },
534 { XML_LAST_ROW
, OUString("last-row") },
535 { XML_FIRST_COLUMN
, OUString("first-column") },
536 { XML_LAST_COLUMN
, OUString("last-column") },
537 { XML_BODY
, OUString("body") },
538 { XML_EVEN_ROWS
, OUString("even-rows") },
539 { XML_ODD_ROWS
, OUString("odd-rows") },
540 { XML_EVEN_COLUMNS
, OUString("even-columns") },
541 { XML_ODD_COLUMNS
, OUString("odd-columns") },
542 { XML_BACKGROUND
, OUString("background") },
543 { XML_TOKEN_END
, OUString() }
546 return &gTableStyleElements
[0];
549 const TableStyleElement
* getWriterSpecificTableStyleMap()
551 static const struct TableStyleElement gWriterSpecificTableStyleElements
[] =
553 { XML_FIRST_ROW_EVEN_COLUMN
, OUString("first-row-even-column") },
554 { XML_LAST_ROW_EVEN_COLUMN
, OUString("last-row-even-column") },
555 { XML_FIRST_ROW_END_COLUMN
, OUString("first-row-end-column") },
556 { XML_FIRST_ROW_START_COLUMN
, OUString("first-row-start-column") },
557 { XML_LAST_ROW_END_COLUMN
, OUString("last-row-end-column") },
558 { XML_LAST_ROW_START_COLUMN
, OUString("last-row-start-column") },
559 { XML_TOKEN_END
, OUString() }
562 return &gWriterSpecificTableStyleElements
[0];
565 static const TableStyleElement
* getWriterSpecificTableStyleAttributes()
567 static const struct TableStyleElement gWriterSpecifitTableStyleAttributes
[] =
569 { XML_FIRST_ROW_END_COLUMN
, OUString("FirstRowEndColumn") },
570 { XML_FIRST_ROW_START_COLUMN
, OUString("FirstRowStartColumn") },
571 { XML_LAST_ROW_END_COLUMN
, OUString("LastRowEndColumn") },
572 { XML_LAST_ROW_START_COLUMN
, OUString("LastRowStartColumn") },
573 { XML_TOKEN_END
, OUString() }
576 return &gWriterSpecifitTableStyleAttributes
[0];
579 void XMLTableExport::exportTableTemplates()
581 if( !mbExportTables
)
586 Reference
< XStyleFamiliesSupplier
> xFamiliesSupp( mrExport
.GetModel(), UNO_QUERY_THROW
);
587 Reference
< XNameAccess
> xFamilies( xFamiliesSupp
->getStyleFamilies() );
588 OUString sFamilyName
;
590 sFamilyName
= "TableStyles";
592 sFamilyName
= "table";
594 Reference
< XIndexAccess
> xTableFamily( xFamilies
->getByName( sFamilyName
), UNO_QUERY_THROW
);
596 for( sal_Int32 nIndex
= 0; nIndex
< xTableFamily
->getCount(); nIndex
++ ) try
598 SvtSaveOptions::ODFSaneDefaultVersion eVersion
= mrExport
.getSaneDefaultVersion();
600 Reference
< XStyle
> xTableStyle( xTableFamily
->getByIndex( nIndex
), UNO_QUERY_THROW
);
601 Reference
<XPropertySet
> xTableStylePropSet( xTableStyle
, UNO_QUERY_THROW
);
602 bool bPhysical
= false;
606 xTableStylePropSet
->getPropertyValue("IsPhysical") >>= bPhysical
;
608 catch(const Exception
&)
612 if (!xTableStyle
->isInUse() && !bPhysical
)
615 const TableStyleElement
* pElements
;
618 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_NAME
, xTableStyle
->getName());
619 pElements
= getWriterSpecificTableStyleAttributes();
620 while(pElements
->meElement
!= XML_TOKEN_END
)
625 xTableStylePropSet
->getPropertyValue(pElements
->msStyleName
) >>= sVal
;
626 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, pElements
->meElement
, sVal
);
628 catch(const Exception
&)
630 TOOLS_WARN_EXCEPTION("xmloff", "XMLTableExport::exportTableTemplates(), export Writer specific attributes, exception caught!");
637 // checks if any of the extended version of ODF are set
638 if (eVersion
== SvtSaveOptions::ODFSVER_012_EXT_COMPAT
)
640 // tdf#106780 historically this wrong attribute was used
641 // for the name; write it if extended because LO < 5.3 can
642 // read only text:style-name, not the correct table:name
643 mrExport
.AddAttribute(XML_NAMESPACE_TEXT
, XML_STYLE_NAME
, xTableStyle
->getName());
645 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_NAME
, xTableStyle
->getName());
648 SvXMLElementExport
tableTemplate( mrExport
, XML_NAMESPACE_TABLE
, XML_TABLE_TEMPLATE
, true, true );
650 Reference
< XNameAccess
> xStyleNames( xTableStyle
, UNO_QUERY_THROW
);
651 pElements
= getTableStyleMap();
652 while( pElements
->meElement
!= XML_TOKEN_END
)
656 Reference
< XStyle
> xStyle( xStyleNames
->getByName( pElements
->msStyleName
), UNO_QUERY
);
659 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, GetExport().EncodeStyleName( xStyle
->getName() ) );
660 SvXMLElementExport
element( mrExport
, XML_NAMESPACE_TABLE
, pElements
->meElement
, true, true );
663 catch(const Exception
&)
665 TOOLS_WARN_EXCEPTION("xmloff.table", "");
671 if (mbWriter
&& ((eVersion
& SvtSaveOptions::ODFSVER_EXTENDED
) != 0))
673 pElements
= getWriterSpecificTableStyleMap();
674 while(pElements
->meElement
!= XML_TOKEN_END
)
678 Reference
<XStyle
> xStyle(xStyleNames
->getByName(pElements
->msStyleName
), UNO_QUERY
);
681 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_STYLE_NAME
, GetExport().EncodeStyleName(xStyle
->getName()));
682 SvXMLElementExport
element(mrExport
, XML_NAMESPACE_LO_EXT
, pElements
->meElement
, true, true);
685 catch(const Exception
&)
687 TOOLS_WARN_EXCEPTION("xmloff", "XMLTableExport::exportTableTemplates(), export Writer specific styles, exception caught!");
693 catch(const Exception
&)
695 TOOLS_WARN_EXCEPTION("xmloff", "XMLTableExport::exportTableDesigns(), exception caught while exporting a table design!");
698 catch(const Exception
&)
700 TOOLS_WARN_EXCEPTION("xmloff", "XMLTableExport::exportTableDesigns()");
704 void XMLCellStyleExport::exportStyleContent(const Reference
<XStyle
>& /*rStyle*/)
708 void XMLCellStyleExport::exportStyleAttributes(const Reference
<XStyle
>& rStyle
)
710 Reference
<XPropertySet
> xPropSet(rStyle
, UNO_QUERY
);
714 Reference
<XPropertySetInfo
> xPropSetInfo(xPropSet
->getPropertySetInfo());
715 static const OUStringLiteral
sNumberFormat(u
"NumberFormat");
716 if (xPropSetInfo
->hasPropertyByName(sNumberFormat
))
718 Reference
<XPropertyState
> xPropState(xPropSet
, UNO_QUERY
);
719 if (xPropState
.is() && (PropertyState_DIRECT_VALUE
==
720 xPropState
->getPropertyState(sNumberFormat
)))
722 sal_Int32 nNumberFormat
= 0;
723 if (xPropSet
->getPropertyValue(sNumberFormat
) >>= nNumberFormat
)
724 GetExport().AddAttribute(XML_NAMESPACE_STYLE
, XML_DATA_STYLE_NAME
,
725 GetExport().getDataStyleName(nNumberFormat
));
730 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */