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 "xmlrowi.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmlcelli.hxx"
23 #include "xmlstyli.hxx"
24 #include "xmlstyle.hxx"
25 #include <document.hxx>
27 #include <olinetab.hxx>
28 #include <sheetdata.hxx>
29 #include <documentimport.hxx>
30 #include <unonames.hxx>
32 #include <comphelper/extract.hxx>
33 #include <comphelper/configuration.hxx>
34 #include <xmloff/xmlnamespace.hxx>
35 #include <xmloff/families.hxx>
36 #include <xmloff/xmltoken.hxx>
37 #include <sax/fastattribs.hxx>
38 #include <com/sun/star/sheet/XSpreadsheet.hpp>
39 #include <com/sun/star/table/XColumnRowRange.hpp>
40 #include <com/sun/star/sheet/XPrintAreas.hpp>
41 #include <comphelper/servicehelper.hxx>
42 #include <osl/diagnose.h>
44 constexpr OUStringLiteral SC_ISFILTERED
= u
"IsFiltered";
46 using namespace com::sun::star
;
47 using namespace xmloff::token
;
49 ScXMLTableRowContext::ScXMLTableRowContext( ScXMLImport
& rImport
,
50 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
) :
51 ScXMLImportContext( rImport
),
52 sVisibility(GetXMLToken(XML_VISIBLE
)),
56 OUString sCellStyleName
;
59 for (auto &it
: *rAttrList
)
61 switch (it
.getToken())
63 case XML_ELEMENT( TABLE
, XML_STYLE_NAME
):
65 sStyleName
= it
.toString();
68 case XML_ELEMENT( TABLE
, XML_VISIBILITY
):
70 sVisibility
= it
.toString();
73 case XML_ELEMENT( TABLE
, XML_NUMBER_ROWS_REPEATED
):
75 if (ScDocument
* pDoc
= rImport
.GetDocument())
77 nRepeatedRows
= std::max( it
.toInt32(), sal_Int32(1) );
78 nRepeatedRows
= std::min( nRepeatedRows
, pDoc
->GetSheetLimits().GetMaxRowCount() );
79 if (comphelper::IsFuzzing())
80 nRepeatedRows
= std::min(nRepeatedRows
, sal_Int32(1024));
84 case XML_ELEMENT( TABLE
, XML_DEFAULT_CELL_STYLE_NAME
):
86 sCellStyleName
= it
.toString();
89 /*case XML_ELEMENT( TABLE, XML_USE_OPTIMAL_HEIGHT ):
91 sOptimalHeight = it.toString();
98 GetScImport().GetTables().AddRow();
99 GetScImport().GetTables().SetRowStyle(sCellStyleName
);
102 ScXMLTableRowContext::~ScXMLTableRowContext()
106 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
107 ScXMLTableRowContext::createFastChildContext( sal_Int32 nElement
,
108 const uno::Reference
< xml::sax::XFastAttributeList
> & xAttrList
)
110 SvXMLImportContext
*pContext(nullptr);
111 sax_fastparser::FastAttributeList
*pAttribList
=
112 &sax_fastparser::castToFastAttributeList( xAttrList
);
116 case XML_ELEMENT( TABLE
, XML_TABLE_CELL
):
117 // if( IsInsertCellPossible() )
120 pContext
= new ScXMLTableRowCellContext( GetScImport(),
121 pAttribList
, false, static_cast<SCROW
>(nRepeatedRows
)
126 case XML_ELEMENT( TABLE
, XML_COVERED_TABLE_CELL
):
127 // if( IsInsertCellPossible() )
130 pContext
= new ScXMLTableRowCellContext( GetScImport(),
131 pAttribList
, true, static_cast<SCROW
>(nRepeatedRows
)
141 void SAL_CALL
ScXMLTableRowContext::endFastElement(sal_Int32
/*nElement*/)
143 ScXMLImport
& rXMLImport(GetScImport());
144 ScDocument
* pDoc(rXMLImport
.GetDocument());
148 if (!bHasCell
&& nRepeatedRows
> 1)
150 for (sal_Int32 i
= 0; i
< nRepeatedRows
- 1; ++i
) //one row is always added
151 GetScImport().GetTables().AddRow();
152 OSL_FAIL("it seems here is a nonvalid file; possible missing of table:table-cell element");
154 SCTAB nSheet
= rXMLImport
.GetTables().GetCurrentSheet();
155 sal_Int32
nCurrentRow(rXMLImport
.GetTables().GetCurrentRow());
156 uno::Reference
<sheet::XSpreadsheet
> xSheet(rXMLImport
.GetTables().GetCurrentXSheet());
160 sal_Int32
nFirstRow(nCurrentRow
- nRepeatedRows
+ 1);
161 if (nFirstRow
> pDoc
->MaxRow())
162 nFirstRow
= pDoc
->MaxRow();
163 if (nCurrentRow
> pDoc
->MaxRow())
164 nCurrentRow
= pDoc
->MaxRow();
165 uno::Reference
<table::XCellRange
> xCellRange(xSheet
->getCellRangeByPosition(0, nFirstRow
, 0, nCurrentRow
));
166 if (!xCellRange
.is())
169 uno::Reference
<table::XColumnRowRange
> xColumnRowRange (xCellRange
, uno::UNO_QUERY
);
170 if (!xColumnRowRange
.is())
173 uno::Reference
<beans::XPropertySet
> xRowProperties(xColumnRowRange
->getRows(), uno::UNO_QUERY
);
174 if (!xRowProperties
.is())
177 XMLTableStyleContext
* ptmpStyle
= nullptr;
179 if (!sStyleName
.isEmpty())
181 XMLTableStylesContext
*pStyles(static_cast<XMLTableStylesContext
*>(rXMLImport
.GetAutoStyles()));
184 XMLTableStyleContext
* pStyle(const_cast<XMLTableStyleContext
*>(static_cast<const XMLTableStyleContext
*>(pStyles
->FindStyleChildContext(
185 XmlStyleFamily::TABLE_ROW
, sStyleName
, true))));
188 pStyle
->FillPropertySet(xRowProperties
);
190 if ( nSheet
!= pStyle
->GetLastSheet() )
192 ScSheetSaveData
* pSheetData
= rXMLImport
.GetScModel()->GetSheetSaveData();
193 pSheetData
->AddRowStyle( sStyleName
, ScAddress( 0, static_cast<SCROW
>(nFirstRow
), nSheet
) );
194 pStyle
->SetLastSheet(nSheet
);
197 // for later checking of optimal row height
202 bool bVisible (true);
203 bool bFiltered (false);
204 if (IsXMLToken(sVisibility
, XML_COLLAPSE
))
208 else if (IsXMLToken(sVisibility
, XML_FILTER
))
215 rXMLImport
.GetDoc().setRowsVisible(nSheet
, nFirstRow
, nCurrentRow
, false);
218 xRowProperties
->setPropertyValue(SC_ISFILTERED
, uno::Any(bFiltered
));
220 uno::Any any
= xRowProperties
->getPropertyValue(SC_UNONAME_OHEIGHT
);
221 bool bOptionalHeight
= false;
222 any
>>= bOptionalHeight
;
225 // Save this row for later height update, only if we have no already optimal row heights
226 // If we have already optimal row heights, recalc only the first 200 row in case of optimal document loading
227 std::vector
<ScDocRowHeightUpdater::TabRanges
>& rRecalcRanges
= rXMLImport
.GetRecalcRowRanges();
228 while (static_cast<SCTAB
>(rRecalcRanges
.size()) <= nSheet
)
230 rRecalcRanges
.emplace_back(0, pDoc
->MaxRow());
232 rRecalcRanges
.at(nSheet
).mnTab
= nSheet
;
234 // check that, we already have valid optimal row heights
235 if (nCurrentRow
> 200 && ptmpStyle
&& !ptmpStyle
->FindProperty(CTF_SC_ROWHEIGHT
))
237 XMLPropertyState
* pOptimalHeight
= ptmpStyle
->FindProperty(CTF_SC_ROWOPTIMALHEIGHT
);
238 if (pOptimalHeight
&& ::cppu::any2bool(pOptimalHeight
->maValue
))
240 rRecalcRanges
.at(nSheet
).maRanges
.setFalse(nFirstRow
, nCurrentRow
);
244 rRecalcRanges
.at(nSheet
).maRanges
.setTrue(nFirstRow
, nCurrentRow
);
249 rRecalcRanges
.at(nSheet
).maRanges
.setTrue(nFirstRow
, nCurrentRow
);
254 ScXMLTableRowsContext::ScXMLTableRowsContext( ScXMLImport
& rImport
,
255 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
256 const bool bTempHeader
,
257 const bool bTempGroup
) :
258 ScXMLImportContext( rImport
),
261 bHeader(bTempHeader
),
265 // don't have any attributes
268 ScAddress aAddr
= rImport
.GetTables().GetCurrentCellPos();
269 nHeaderStartRow
= aAddr
.Row();
274 nGroupStartRow
= rImport
.GetTables().GetCurrentRow();
276 if ( rAttrList
.is() )
278 auto aIter( rAttrList
->find( XML_ELEMENT( TABLE
, XML_DISPLAY
) ) );
279 if (aIter
!= rAttrList
->end())
280 bGroupDisplay
= IsXMLToken( aIter
, XML_TRUE
);
285 ScXMLTableRowsContext::~ScXMLTableRowsContext()
289 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
290 ScXMLTableRowsContext::createFastChildContext( sal_Int32 nElement
,
291 const uno::Reference
< xml::sax::XFastAttributeList
> & xAttrList
)
293 SvXMLImportContext
*pContext(nullptr);
294 sax_fastparser::FastAttributeList
*pAttribList
=
295 &sax_fastparser::castToFastAttributeList( xAttrList
);
299 case XML_ELEMENT( TABLE
, XML_TABLE_ROW_GROUP
):
300 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
303 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_ROWS
):
304 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
307 case XML_ELEMENT( TABLE
, XML_TABLE_ROWS
):
308 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
311 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
312 pContext
= new ScXMLTableRowContext( GetScImport(), pAttribList
);
319 void SAL_CALL
ScXMLTableRowsContext::endFastElement(sal_Int32
/*nElement*/)
321 ScXMLImport
& rXMLImport(GetScImport());
324 SCROW nHeaderEndRow
= rXMLImport
.GetTables().GetCurrentRow();
325 if (nHeaderStartRow
<= nHeaderEndRow
)
327 uno::Reference
<sheet::XPrintAreas
> xPrintAreas (rXMLImport
.GetTables().GetCurrentXSheet(), uno::UNO_QUERY
);
328 if (xPrintAreas
.is())
330 if (!xPrintAreas
->getPrintTitleRows())
332 xPrintAreas
->setPrintTitleRows(true);
333 table::CellRangeAddress aRowHeaderRange
;
334 aRowHeaderRange
.StartRow
= nHeaderStartRow
;
335 aRowHeaderRange
.EndRow
= nHeaderEndRow
;
336 xPrintAreas
->setTitleRows(aRowHeaderRange
);
340 table::CellRangeAddress
aRowHeaderRange(xPrintAreas
->getTitleRows());
341 aRowHeaderRange
.EndRow
= nHeaderEndRow
;
342 xPrintAreas
->setTitleRows(aRowHeaderRange
);
349 SCROW nGroupEndRow
= rXMLImport
.GetTables().GetCurrentRow();
350 SCTAB
nSheet(rXMLImport
.GetTables().GetCurrentSheet());
351 if (nGroupStartRow
<= nGroupEndRow
)
353 ScDocument
* pDoc(GetScImport().GetDocument());
356 ScXMLImport::MutexGuard
aGuard(GetScImport());
357 ScOutlineTable
* pOutlineTable(pDoc
->GetOutlineTable(nSheet
, true));
358 ScOutlineArray
& rRowArray(pOutlineTable
->GetRowArray());
360 rRowArray
.Insert(nGroupStartRow
, nGroupEndRow
, bResized
, !bGroupDisplay
);
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */