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 "xmltabi.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmlrowi.hxx"
23 #include "xmlcoli.hxx"
24 #include "xmlsceni.hxx"
25 #include "xmlexternaltabi.hxx"
26 #include "xmlnexpi.hxx"
27 #include <document.hxx>
29 #include <olinetab.hxx>
30 #include "XMLTableShapesContext.hxx"
31 #include "XMLTableSourceContext.hxx"
32 #include "XMLStylesImportHelper.hxx"
33 #include <rangeutl.hxx>
34 #include <externalrefmgr.hxx>
35 #include <sheetdata.hxx>
36 #include "xmlcondformat.hxx"
37 #include "SparklineGroupsImportContext.hxx"
39 #include <xmloff/xmltoken.hxx>
40 #include <xmloff/xmlnamespace.hxx>
41 #include <xmloff/XMLEventsImportContext.hxx>
43 #include <tools/urlobj.hxx>
44 #include <sax/fastattribs.hxx>
45 #include <com/sun/star/sheet/XSpreadsheet.hpp>
46 #include <comphelper/servicehelper.hxx>
48 using namespace com::sun::star
;
49 using namespace xmloff::token
;
50 using ::com::sun::star::uno::Reference
;
51 using ::com::sun::star::uno::UNO_QUERY
;
54 * Determine whether this table is an external reference cache from its
55 * name. There is currently no way of determining whether a table is a
56 * regular table or an external reference cache other than examining the
57 * name itself. We should probably introduce a new boolean value for
58 * table:table element and use it instead of doing this, to make it more
59 * reliable and future-proof.
65 static bool lcl_isExternalRefCache(const OUString
& rName
, OUString
& rUrl
, OUString
& rExtTabName
)
67 // 'file:///path/to/file.ods'#MySheet
68 // 'file:///path/to/file.ods'#MySheet with space
69 // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
72 if ( rName
.toChar() != '\'' ) // initial quote
75 // #i114504# Other schemes besides "file:" are also allowed.
76 // CompareProtocolScheme is quick, only looks at the start of the string.
77 INetProtocol eProt
= INetURLObject::CompareProtocolScheme( rName
.subView(1) );
78 if ( eProt
== INetProtocol::NotValid
)
81 OUString aPrefix
= INetURLObject::GetScheme( eProt
);
82 sal_Int32 nPrefLen
= aPrefix
.getLength();
84 OUStringBuffer aUrlBuf
, aTabNameBuf
;
85 aUrlBuf
.append( aPrefix
);
86 sal_Int32 n
= rName
.getLength();
87 const sal_Unicode
* p
= rName
.getStr();
90 sal_Unicode cPrev
= 0;
91 for (sal_Int32 i
= nPrefLen
+1; i
< n
; ++i
) // start the loop after quote and prefix
93 const sal_Unicode c
= p
[i
];
102 rUrl
= aUrlBuf
.makeStringAndClear();
103 rUrl
= rUrl
.copy(0, rUrl
.getLength()-1); // remove the trailing single-quote.
110 // parsing sheet name.
111 aTabNameBuf
.append(c
);
119 if (aTabNameBuf
.isEmpty())
122 rExtTabName
= aTabNameBuf
.makeStringAndClear();
127 ScXMLExternalTabData::ScXMLExternalTabData() :
128 mnRow(0), mnCol(0), mnFileId(0)
132 ScXMLTableContext::ScXMLTableContext( ScXMLImport
& rImport
,
133 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
) :
134 ScXMLImportContext( rImport
),
136 bStartFormPage(false),
137 bPrintEntireSheet(true)
139 // get start offset in file (if available)
140 nStartOffset
= GetScImport().GetByteOffset();
142 ScXMLTabProtectionData aProtectData
;
146 if ( rAttrList
.is() )
148 for (auto &it
: *rAttrList
)
150 switch (it
.getToken())
152 case XML_ELEMENT( TABLE
, XML_NAME
):
153 sName
= it
.toString();
155 case XML_ELEMENT( TABLE
, XML_STYLE_NAME
):
156 sStyleName
= it
.toString();
158 case XML_ELEMENT( TABLE
, XML_PROTECTED
):
159 aProtectData
.mbProtected
= IsXMLToken( it
, XML_TRUE
);
161 case XML_ELEMENT( TABLE
, XML_PRINT_RANGES
):
162 sPrintRanges
= it
.toString();
164 case XML_ELEMENT( TABLE
, XML_PROTECTION_KEY
):
165 aProtectData
.maPassword
= it
.toString();
167 case XML_ELEMENT( TABLE
, XML_PROTECTION_KEY_DIGEST_ALGORITHM
):
168 aProtectData
.meHash1
= ScPassHashHelper::getHashTypeFromURI( it
.toString() );
170 case XML_ELEMENT( TABLE
, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2
):
171 case XML_ELEMENT( LO_EXT
, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2
):
172 aProtectData
.meHash2
= ScPassHashHelper::getHashTypeFromURI( it
.toString() );
174 case XML_ELEMENT( TABLE
, XML_PRINT
):
176 if ( IsXMLToken( it
, XML_FALSE
) )
177 bPrintEntireSheet
= false;
185 OUString aExtUrl
, aExtTabName
;
186 if (lcl_isExternalRefCache(sName
, aExtUrl
, aExtTabName
))
188 // This is an external ref cache table.
189 pExternalRefInfo
.reset(new ScXMLExternalTabData
);
190 ScDocument
* pDoc
= GetScImport().GetDocument();
193 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
194 pExternalRefInfo
->mnFileId
= pRefMgr
->getExternalFileId(aExtUrl
);
195 pExternalRefInfo
->mpCacheTable
= pRefMgr
->getCacheTable(pExternalRefInfo
->mnFileId
, aExtTabName
, true,
197 pExternalRefInfo
->mpCacheTable
->setWholeTableCached();
202 // This is a regular table.
203 GetScImport().GetTables().NewSheet(sName
, sStyleName
, aProtectData
);
207 ScXMLTableContext::~ScXMLTableContext()
211 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
212 ScXMLTableContext::createFastChildContext( sal_Int32 nElement
,
213 const uno::Reference
< xml::sax::XFastAttributeList
> & xAttrList
)
215 sax_fastparser::FastAttributeList
*pAttribList
=
216 &sax_fastparser::castToFastAttributeList( xAttrList
);
218 if (pExternalRefInfo
)
220 // We only care about the table-row and table-source elements for
221 // external cache data.
224 case XML_ELEMENT( TABLE
, XML_TABLE_ROW_GROUP
):
225 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_ROWS
):
226 case XML_ELEMENT( TABLE
, XML_TABLE_ROWS
):
227 // #i101319# don't discard rows in groups or header (repeat range)
228 return new ScXMLExternalRefRowsContext(
229 GetScImport(), *pExternalRefInfo
);
230 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
231 return new ScXMLExternalRefRowContext(
232 GetScImport(), pAttribList
, *pExternalRefInfo
);
233 case XML_ELEMENT( TABLE
, XML_TABLE_SOURCE
):
234 return new ScXMLExternalRefTabSourceContext(
235 GetScImport(), pAttribList
, *pExternalRefInfo
);
242 SvXMLImportContext
*pContext(nullptr);
246 case XML_ELEMENT( TABLE
, XML_NAMED_EXPRESSIONS
):
248 SCTAB nTab
= GetScImport().GetTables().GetCurrentSheet();
249 pContext
= new ScXMLNamedExpressionsContext(
251 std::make_shared
<ScXMLNamedExpressionsContext::SheetLocalInserter
>(GetScImport(), nTab
));
254 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN_GROUP
):
255 pContext
= new ScXMLTableColsContext( GetScImport(), pAttribList
,
258 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_COLUMNS
):
259 pContext
= new ScXMLTableColsContext( GetScImport(), pAttribList
,
262 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMNS
):
263 pContext
= new ScXMLTableColsContext( GetScImport(), pAttribList
,
266 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN
):
267 pContext
= new ScXMLTableColContext( GetScImport(), pAttribList
);
269 case XML_ELEMENT( TABLE
, XML_TABLE_PROTECTION
):
270 case XML_ELEMENT( LO_EXT
, XML_TABLE_PROTECTION
):
271 case XML_ELEMENT( OFFICE_EXT
, XML_TABLE_PROTECTION
):
272 pContext
= new ScXMLTableProtectionContext( GetScImport(), pAttribList
);
274 case XML_ELEMENT( TABLE
, XML_TABLE_ROW_GROUP
):
275 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
278 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_ROWS
):
279 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
282 case XML_ELEMENT( TABLE
, XML_TABLE_ROWS
):
283 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
286 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
287 pContext
= new ScXMLTableRowContext( GetScImport(), pAttribList
);
289 case XML_ELEMENT( TABLE
, XML_TABLE_SOURCE
):
290 pContext
= new ScXMLTableSourceContext( GetScImport(), pAttribList
);
292 case XML_ELEMENT( TABLE
, XML_SCENARIO
):
293 pContext
= new ScXMLTableScenarioContext( GetScImport(), pAttribList
);
295 case XML_ELEMENT( TABLE
, XML_SHAPES
):
296 pContext
= new ScXMLTableShapesContext( GetScImport() );
298 case XML_ELEMENT( CALC_EXT
, XML_CONDITIONAL_FORMATS
):
299 pContext
= new ScXMLConditionalFormatsContext( GetScImport() );
301 case XML_ELEMENT(CALC_EXT
, XML_SPARKLINE_GROUPS
):
302 pContext
= new sc::SparklineGroupsImportContext(GetScImport());
304 case XML_ELEMENT(OFFICE
, XML_EVENT_LISTENERS
):
305 case XML_ELEMENT(OFFICE_EXT
, XML_EVENT_LISTENERS
):
307 // use XEventsSupplier interface of the sheet
308 uno::Reference
<document::XEventsSupplier
> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY
);
309 pContext
= new XMLEventsImportContext( GetImport(), xSupplier
);
312 case XML_ELEMENT(OFFICE
, XML_FORMS
):
314 GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
315 bStartFormPage
= true;
316 pContext
= xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetScImport() );
320 XMLOFF_WARN_UNKNOWN_ELEMENT("sc", nElement
);
327 void SAL_CALL
ScXMLTableContext::endFastElement(sal_Int32
/*nElement*/)
329 ScXMLImport::MutexGuard
aMutexGuard(GetScImport());
330 ScXMLImport
& rImport
= GetScImport();
331 rImport
.GetStylesImportHelper()->EndTable();
332 ScDocument
* pDoc(rImport
.GetDocument());
336 ScMyTables
& rTables
= rImport
.GetTables();
337 SCTAB nCurTab
= rTables
.GetCurrentSheet();
338 // tdf#51022 process only print ranges of internal sheets
339 if (!pExternalRefInfo
)
341 if (!sPrintRanges
.isEmpty())
343 ScRangeList aRangeList
;
344 ScRangeStringConverter::GetRangeListFromString(aRangeList
, sPrintRanges
, *pDoc
, ::formula::FormulaGrammar::CONV_OOO
);
345 size_t nCount
= aRangeList
.size();
346 for (size_t i
= 0; i
< nCount
; i
++)
348 pDoc
->AddPrintRange(nCurTab
, aRangeList
[i
]);
351 else if (!bPrintEntireSheet
)
352 // Sheet has "print entire sheet" option by default. Remove it.
353 pDoc
->ClearPrintRanges(nCurTab
);
356 ScOutlineTable
* pOutlineTable(pDoc
->GetOutlineTable(nCurTab
));
359 ScOutlineArray
& rColArray(pOutlineTable
->GetColArray());
360 size_t nDepth
= rColArray
.GetDepth();
361 for (size_t i
= 0; i
< nDepth
; ++i
)
363 size_t nCount
= rColArray
.GetCount(i
);
364 for (size_t j
= 0; j
< nCount
; ++j
)
366 const ScOutlineEntry
* pEntry
= rColArray
.GetEntry(i
, j
);
367 if (pEntry
->IsHidden())
368 rColArray
.SetVisibleBelow(i
, j
, false);
371 ScOutlineArray
& rRowArray(pOutlineTable
->GetRowArray());
372 nDepth
= rRowArray
.GetDepth();
373 for (size_t i
= 0; i
< nDepth
; ++i
)
375 size_t nCount
= rRowArray
.GetCount(i
);
376 for (size_t j
= 0; j
< nCount
; ++j
)
378 const ScOutlineEntry
* pEntry
= rRowArray
.GetEntry(i
, j
);
379 if (pEntry
->IsHidden())
380 rRowArray
.SetVisibleBelow(i
, j
, false);
384 if (rTables
.HasDrawPage())
386 if (rTables
.HasXShapes())
388 rImport
.GetShapeImport()->popGroupAndPostProcess();
389 uno::Reference
< drawing::XShapes
> xTempShapes(rTables
.GetCurrentXShapes());
390 rImport
.GetShapeImport()->endPage(xTempShapes
);
393 rImport
.GetFormImport()->endPage();
396 rTables
.DeleteTable();
397 rImport
.ProgressBarIncrement();
399 // store stream positions
400 if (!pExternalRefInfo
&& nStartOffset
>= 0 /* && nEndOffset >= 0 */)
402 ScSheetSaveData
* pSheetData
= rImport
.GetScModel()->GetSheetSaveData();
403 SCTAB nTab
= rTables
.GetCurrentSheet();
404 // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
405 pSheetData
->StartStreamPos( nTab
, nStartOffset
);
409 ScXMLTableProtectionContext::ScXMLTableProtectionContext(
410 ScXMLImport
& rImport
,
411 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
) :
412 ScXMLImportContext( rImport
)
414 bool bSelectProtectedCells
= false;
415 bool bSelectUnprotectedCells
= false;
416 bool bInsertColumns
= false;
417 bool bInsertRows
= false;
418 bool bDeleteColumns
= false;
419 bool bDeleteRows
= false;
420 bool bUseAutoFilter
= false;
421 bool bUsePivot
= false;
423 if ( rAttrList
.is() )
425 for (auto &aIter
: *rAttrList
)
427 sal_Int32 nToken
= aIter
.getToken();
430 case XML_ELEMENT( TABLE
, XML_SELECT_PROTECTED_CELLS
):
431 case XML_ELEMENT( OFFICE_EXT
, XML_SELECT_PROTECTED_CELLS
):
432 case XML_ELEMENT( LO_EXT
, XML_SELECT_PROTECTED_CELLS
):
433 bSelectProtectedCells
= IsXMLToken(aIter
, XML_TRUE
);
435 case XML_ELEMENT( TABLE
, XML_SELECT_UNPROTECTED_CELLS
):
436 case XML_ELEMENT( OFFICE_EXT
, XML_SELECT_UNPROTECTED_CELLS
):
437 case XML_ELEMENT( LO_EXT
, XML_SELECT_UNPROTECTED_CELLS
):
438 bSelectUnprotectedCells
= IsXMLToken(aIter
, XML_TRUE
);
440 case XML_ELEMENT( LO_EXT
, XML_INSERT_COLUMNS
):
441 bInsertColumns
= IsXMLToken(aIter
, XML_TRUE
);
443 case XML_ELEMENT( LO_EXT
, XML_INSERT_ROWS
):
444 bInsertRows
= IsXMLToken(aIter
, XML_TRUE
);
446 case XML_ELEMENT( LO_EXT
, XML_DELETE_COLUMNS
):
447 bDeleteColumns
= IsXMLToken(aIter
, XML_TRUE
);
449 case XML_ELEMENT( LO_EXT
, XML_DELETE_ROWS
):
450 bDeleteRows
= IsXMLToken(aIter
, XML_TRUE
);
452 case XML_ELEMENT( LO_EXT
, XML_USE_AUTOFILTER
):
453 bUseAutoFilter
= IsXMLToken(aIter
, XML_TRUE
);
455 case XML_ELEMENT( LO_EXT
, XML_USE_PIVOT
):
456 bUsePivot
= IsXMLToken(aIter
, XML_TRUE
);
459 XMLOFF_WARN_UNKNOWN("sc", aIter
);
464 ScXMLTabProtectionData
& rProtectData
= GetScImport().GetTables().GetCurrentProtectionData();
465 rProtectData
.mbSelectProtectedCells
= bSelectProtectedCells
;
466 rProtectData
.mbSelectUnprotectedCells
= bSelectUnprotectedCells
;
467 rProtectData
.mbInsertColumns
= bInsertColumns
;
468 rProtectData
.mbInsertRows
= bInsertRows
;
469 rProtectData
.mbDeleteColumns
= bDeleteColumns
;
470 rProtectData
.mbDeleteRows
= bDeleteRows
;
471 rProtectData
.mbUseAutoFilter
= bUseAutoFilter
;
472 rProtectData
.mbUsePivot
= bUsePivot
;
475 ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */