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 <unotools/configmgr.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 nRepeatedRows
= std::max( it
.toInt32(), sal_Int32(1) );
76 nRepeatedRows
= std::min( nRepeatedRows
, rImport
.GetDocument()->GetSheetLimits().GetMaxRowCount() );
77 if (utl::ConfigManager::IsFuzzing())
78 nRepeatedRows
= std::min(nRepeatedRows
, sal_Int32(1024));
81 case XML_ELEMENT( TABLE
, XML_DEFAULT_CELL_STYLE_NAME
):
83 sCellStyleName
= it
.toString();
86 /*case XML_ELEMENT( TABLE, XML_USE_OPTIMAL_HEIGHT ):
88 sOptimalHeight = it.toString();
95 GetScImport().GetTables().AddRow();
96 GetScImport().GetTables().SetRowStyle(sCellStyleName
);
99 ScXMLTableRowContext::~ScXMLTableRowContext()
103 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
104 ScXMLTableRowContext::createFastChildContext( sal_Int32 nElement
,
105 const uno::Reference
< xml::sax::XFastAttributeList
> & xAttrList
)
107 SvXMLImportContext
*pContext(nullptr);
108 sax_fastparser::FastAttributeList
*pAttribList
=
109 &sax_fastparser::castToFastAttributeList( xAttrList
);
113 case XML_ELEMENT( TABLE
, XML_TABLE_CELL
):
114 // if( IsInsertCellPossible() )
117 pContext
= new ScXMLTableRowCellContext( GetScImport(),
118 pAttribList
, false, static_cast<SCROW
>(nRepeatedRows
)
123 case XML_ELEMENT( TABLE
, XML_COVERED_TABLE_CELL
):
124 // if( IsInsertCellPossible() )
127 pContext
= new ScXMLTableRowCellContext( GetScImport(),
128 pAttribList
, true, static_cast<SCROW
>(nRepeatedRows
)
138 void SAL_CALL
ScXMLTableRowContext::endFastElement(sal_Int32
/*nElement*/)
140 ScXMLImport
& rXMLImport(GetScImport());
141 ScDocument
* pDoc(rXMLImport
.GetDocument());
142 if (!bHasCell
&& nRepeatedRows
> 1)
144 for (sal_Int32 i
= 0; i
< nRepeatedRows
- 1; ++i
) //one row is always added
145 GetScImport().GetTables().AddRow();
146 OSL_FAIL("it seems here is a nonvalid file; possible missing of table:table-cell element");
148 SCTAB nSheet
= rXMLImport
.GetTables().GetCurrentSheet();
149 sal_Int32
nCurrentRow(rXMLImport
.GetTables().GetCurrentRow());
150 uno::Reference
<sheet::XSpreadsheet
> xSheet(rXMLImport
.GetTables().GetCurrentXSheet());
154 sal_Int32
nFirstRow(nCurrentRow
- nRepeatedRows
+ 1);
155 if (nFirstRow
> pDoc
->MaxRow())
156 nFirstRow
= pDoc
->MaxRow();
157 if (nCurrentRow
> pDoc
->MaxRow())
158 nCurrentRow
= pDoc
->MaxRow();
159 uno::Reference
<table::XCellRange
> xCellRange(xSheet
->getCellRangeByPosition(0, nFirstRow
, 0, nCurrentRow
));
160 if (!xCellRange
.is())
163 uno::Reference
<table::XColumnRowRange
> xColumnRowRange (xCellRange
, uno::UNO_QUERY
);
164 if (!xColumnRowRange
.is())
167 uno::Reference
<beans::XPropertySet
> xRowProperties(xColumnRowRange
->getRows(), uno::UNO_QUERY
);
168 if (!xRowProperties
.is())
171 XMLTableStyleContext
* ptmpStyle
= nullptr;
173 if (!sStyleName
.isEmpty())
175 XMLTableStylesContext
*pStyles(static_cast<XMLTableStylesContext
*>(rXMLImport
.GetAutoStyles()));
178 XMLTableStyleContext
* pStyle(const_cast<XMLTableStyleContext
*>(static_cast<const XMLTableStyleContext
*>(pStyles
->FindStyleChildContext(
179 XmlStyleFamily::TABLE_ROW
, sStyleName
, true))));
182 pStyle
->FillPropertySet(xRowProperties
);
184 if ( nSheet
!= pStyle
->GetLastSheet() )
186 ScSheetSaveData
* pSheetData
= comphelper::getFromUnoTunnel
<ScModelObj
>(rXMLImport
.GetModel())->GetSheetSaveData();
187 pSheetData
->AddRowStyle( sStyleName
, ScAddress( 0, static_cast<SCROW
>(nFirstRow
), nSheet
) );
188 pStyle
->SetLastSheet(nSheet
);
191 // for later checking of optimal row height
196 bool bVisible (true);
197 bool bFiltered (false);
198 if (IsXMLToken(sVisibility
, XML_COLLAPSE
))
202 else if (IsXMLToken(sVisibility
, XML_FILTER
))
209 rXMLImport
.GetDoc().setRowsVisible(nSheet
, nFirstRow
, nCurrentRow
, false);
212 xRowProperties
->setPropertyValue(SC_ISFILTERED
, uno::Any(bFiltered
));
214 uno::Any any
= xRowProperties
->getPropertyValue(SC_UNONAME_OHEIGHT
);
215 bool bOptionalHeight
= false;
216 any
>>= bOptionalHeight
;
219 // Save this row for later height update, only if we have no already optimal row heights
220 // If we have already optimal row heights, recalc only the first 200 row in case of optimal document loading
221 std::vector
<ScDocRowHeightUpdater::TabRanges
>& rRecalcRanges
= rXMLImport
.GetRecalcRowRanges();
222 while (static_cast<SCTAB
>(rRecalcRanges
.size()) <= nSheet
)
224 rRecalcRanges
.emplace_back(0, pDoc
->MaxRow());
226 rRecalcRanges
.at(nSheet
).mnTab
= nSheet
;
228 // check that, we already have valid optimal row heights
229 if (nCurrentRow
> 200 && ptmpStyle
&& !ptmpStyle
->FindProperty(CTF_SC_ROWHEIGHT
))
231 XMLPropertyState
* pOptimalHeight
= ptmpStyle
->FindProperty(CTF_SC_ROWOPTIMALHEIGHT
);
232 if (pOptimalHeight
&& ::cppu::any2bool(pOptimalHeight
->maValue
))
234 rRecalcRanges
.at(nSheet
).maRanges
.setFalse(nFirstRow
, nCurrentRow
);
238 rRecalcRanges
.at(nSheet
).maRanges
.setTrue(nFirstRow
, nCurrentRow
);
243 rRecalcRanges
.at(nSheet
).maRanges
.setTrue(nFirstRow
, nCurrentRow
);
248 ScXMLTableRowsContext::ScXMLTableRowsContext( ScXMLImport
& rImport
,
249 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
,
250 const bool bTempHeader
,
251 const bool bTempGroup
) :
252 ScXMLImportContext( rImport
),
255 bHeader(bTempHeader
),
259 // don't have any attributes
262 ScAddress aAddr
= rImport
.GetTables().GetCurrentCellPos();
263 nHeaderStartRow
= aAddr
.Row();
268 nGroupStartRow
= rImport
.GetTables().GetCurrentRow();
270 if ( rAttrList
.is() )
272 auto aIter( rAttrList
->find( XML_ELEMENT( TABLE
, XML_DISPLAY
) ) );
273 if (aIter
!= rAttrList
->end())
274 bGroupDisplay
= IsXMLToken( aIter
, XML_TRUE
);
279 ScXMLTableRowsContext::~ScXMLTableRowsContext()
283 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
284 ScXMLTableRowsContext::createFastChildContext( sal_Int32 nElement
,
285 const uno::Reference
< xml::sax::XFastAttributeList
> & xAttrList
)
287 SvXMLImportContext
*pContext(nullptr);
288 sax_fastparser::FastAttributeList
*pAttribList
=
289 &sax_fastparser::castToFastAttributeList( xAttrList
);
293 case XML_ELEMENT( TABLE
, XML_TABLE_ROW_GROUP
):
294 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
297 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_ROWS
):
298 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
301 case XML_ELEMENT( TABLE
, XML_TABLE_ROWS
):
302 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
305 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
306 pContext
= new ScXMLTableRowContext( GetScImport(), pAttribList
);
313 void SAL_CALL
ScXMLTableRowsContext::endFastElement(sal_Int32
/*nElement*/)
315 ScXMLImport
& rXMLImport(GetScImport());
318 SCROW nHeaderEndRow
= rXMLImport
.GetTables().GetCurrentRow();
319 if (nHeaderStartRow
<= nHeaderEndRow
)
321 uno::Reference
<sheet::XPrintAreas
> xPrintAreas (rXMLImport
.GetTables().GetCurrentXSheet(), uno::UNO_QUERY
);
322 if (xPrintAreas
.is())
324 if (!xPrintAreas
->getPrintTitleRows())
326 xPrintAreas
->setPrintTitleRows(true);
327 table::CellRangeAddress aRowHeaderRange
;
328 aRowHeaderRange
.StartRow
= nHeaderStartRow
;
329 aRowHeaderRange
.EndRow
= nHeaderEndRow
;
330 xPrintAreas
->setTitleRows(aRowHeaderRange
);
334 table::CellRangeAddress
aRowHeaderRange(xPrintAreas
->getTitleRows());
335 aRowHeaderRange
.EndRow
= nHeaderEndRow
;
336 xPrintAreas
->setTitleRows(aRowHeaderRange
);
343 SCROW nGroupEndRow
= rXMLImport
.GetTables().GetCurrentRow();
344 SCTAB
nSheet(rXMLImport
.GetTables().GetCurrentSheet());
345 if (nGroupStartRow
<= nGroupEndRow
)
347 ScDocument
* pDoc(GetScImport().GetDocument());
350 ScXMLImport::MutexGuard
aGuard(GetScImport());
351 ScOutlineTable
* pOutlineTable(pDoc
->GetOutlineTable(nSheet
, true));
352 ScOutlineArray
& rRowArray(pOutlineTable
->GetRowArray());
354 rRowArray
.Insert(nGroupStartRow
, nGroupEndRow
, bResized
, !bGroupDisplay
);
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */