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"
38 #include <xmloff/xmltkmap.hxx>
39 #include <xmloff/xmltoken.hxx>
40 #include <xmloff/xmlnmspe.hxx>
41 #include <xmloff/XMLEventsImportContext.hxx>
42 #include <sal/log.hxx>
44 #include <tools/urlobj.hxx>
45 #include <sax/fastattribs.hxx>
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
;
52 using ::com::sun::star::xml::sax::XAttributeList
;
55 * Determine whether this table is an external reference cache from its
56 * name. There is currently no way of determining whether a table is a
57 * regular table or an external reference cache other than examining the
58 * name itself. We should probably introduce a new boolean value for
59 * table:table element and use it instead of doing this, to make it more
60 * reliable and future-proof.
66 static bool lcl_isExternalRefCache(const OUString
& rName
, OUString
& rUrl
, OUString
& rExtTabName
)
68 // 'file:///path/to/file.ods'#MySheet
69 // 'file:///path/to/file.ods'#MySheet with space
70 // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
73 if ( rName
.toChar() != '\'' ) // initial quote
76 // #i114504# Other schemes besides "file:" are also allowed.
77 // CompareProtocolScheme is quick, only looks at the start of the string.
78 INetProtocol eProt
= INetURLObject::CompareProtocolScheme( rName
.copy(1) );
79 if ( eProt
== INetProtocol::NotValid
)
82 OUString aPrefix
= INetURLObject::GetScheme( eProt
);
83 sal_Int32 nPrefLen
= aPrefix
.getLength();
85 OUStringBuffer aUrlBuf
, aTabNameBuf
;
86 aUrlBuf
.append( aPrefix
);
87 sal_Int32 n
= rName
.getLength();
88 const sal_Unicode
* p
= rName
.getStr();
91 sal_Unicode cPrev
= 0;
92 for (sal_Int32 i
= nPrefLen
+1; i
< n
; ++i
) // start the loop after quote and prefix
94 const sal_Unicode c
= p
[i
];
103 rUrl
= aUrlBuf
.makeStringAndClear();
104 rUrl
= rUrl
.copy(0, rUrl
.getLength()-1); // remove the trailing single-quote.
111 // parsing sheet name.
112 aTabNameBuf
.append(c
);
120 if (aTabNameBuf
.isEmpty())
123 rExtTabName
= aTabNameBuf
.makeStringAndClear();
128 ScXMLExternalTabData::ScXMLExternalTabData() :
129 mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
133 ScXMLTableContext::ScXMLTableContext( ScXMLImport
& rImport
,
134 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
) :
135 ScXMLImportContext( rImport
),
137 bStartFormPage(false),
138 bPrintEntireSheet(true)
140 // get start offset in file (if available)
141 nStartOffset
= GetScImport().GetByteOffset();
143 ScXMLTabProtectionData aProtectData
;
147 if ( rAttrList
.is() )
149 for (auto &it
: *rAttrList
)
151 switch (it
.getToken())
153 case XML_ELEMENT( TABLE
, XML_NAME
):
154 sName
= it
.toString();
156 case XML_ELEMENT( TABLE
, XML_STYLE_NAME
):
157 sStyleName
= it
.toString();
159 case XML_ELEMENT( TABLE
, XML_PROTECTED
):
160 aProtectData
.mbProtected
= IsXMLToken( it
, XML_TRUE
);
162 case XML_ELEMENT( TABLE
, XML_PRINT_RANGES
):
163 sPrintRanges
= it
.toString();
165 case XML_ELEMENT( TABLE
, XML_PROTECTION_KEY
):
166 aProtectData
.maPassword
= it
.toString();
168 case XML_ELEMENT( TABLE
, XML_PROTECTION_KEY_DIGEST_ALGORITHM
):
169 aProtectData
.meHash1
= ScPassHashHelper::getHashTypeFromURI( it
.toString() );
171 case XML_ELEMENT( TABLE
, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2
):
172 case XML_ELEMENT( LO_EXT
, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2
):
173 aProtectData
.meHash2
= ScPassHashHelper::getHashTypeFromURI( it
.toString() );
175 case XML_ELEMENT( TABLE
, XML_PRINT
):
177 if ( IsXMLToken( it
, XML_FALSE
) )
178 bPrintEntireSheet
= false;
186 OUString aExtUrl
, aExtTabName
;
187 if (lcl_isExternalRefCache(sName
, aExtUrl
, aExtTabName
))
189 // This is an external ref cache table.
190 pExternalRefInfo
.reset(new ScXMLExternalTabData
);
191 ScDocument
* pDoc
= GetScImport().GetDocument();
194 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
195 pExternalRefInfo
->mnFileId
= pRefMgr
->getExternalFileId(aExtUrl
);
196 pExternalRefInfo
->mpCacheTable
= pRefMgr
->getCacheTable(pExternalRefInfo
->mnFileId
, aExtTabName
, true,
198 pExternalRefInfo
->mpCacheTable
->setWholeTableCached();
203 // This is a regular table.
204 GetScImport().GetTables().NewSheet(sName
, sStyleName
, aProtectData
);
208 ScXMLTableContext::~ScXMLTableContext()
212 SvXMLImportContextRef
ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix
,
213 const OUString
& rLName
,
214 const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttrList*/ )
216 const SvXMLTokenMap
& rTokenMap(GetScImport().GetTableElemTokenMap());
217 sal_uInt16 nToken
= rTokenMap
.Get(nPrefix
, rLName
);
218 if (pExternalRefInfo
)
220 return new SvXMLImportContext(GetImport(), nPrefix
, rLName
);
223 SvXMLImportContext
*pContext(nullptr);
227 case XML_TOK_TABLE_FORMS
:
229 GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
230 bStartFormPage
= true;
231 pContext
= xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetScImport(), nPrefix
, rLName
);
234 case XML_TOK_TABLE_EVENT_LISTENERS
:
235 case XML_TOK_TABLE_EVENT_LISTENERS_EXT
:
237 // use XEventsSupplier interface of the sheet
238 uno::Reference
<document::XEventsSupplier
> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY
);
239 pContext
= new XMLEventsImportContext( GetImport(), nPrefix
, rLName
, xSupplier
);
247 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLName
);
252 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
253 ScXMLTableContext::createFastChildContext( sal_Int32 nElement
,
254 const uno::Reference
< xml::sax::XFastAttributeList
> & xAttrList
)
256 sax_fastparser::FastAttributeList
*pAttribList
=
257 sax_fastparser::FastAttributeList::castToFastAttributeList( xAttrList
);
259 if (pExternalRefInfo
)
261 // We only care about the table-row and table-source elements for
262 // external cache data.
265 case XML_ELEMENT( TABLE
, XML_TABLE_ROW_GROUP
):
266 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_ROWS
):
267 case XML_ELEMENT( TABLE
, XML_TABLE_ROWS
):
268 // #i101319# don't discard rows in groups or header (repeat range)
269 return new ScXMLExternalRefRowsContext(
270 GetScImport(), *pExternalRefInfo
);
271 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
272 return new ScXMLExternalRefRowContext(
273 GetScImport(), pAttribList
, *pExternalRefInfo
);
274 case XML_ELEMENT( TABLE
, XML_TABLE_SOURCE
):
275 return new ScXMLExternalRefTabSourceContext(
276 GetScImport(), pAttribList
, *pExternalRefInfo
);
280 return new SvXMLImportContext( GetImport() );
283 SvXMLImportContext
*pContext(nullptr);
287 case XML_ELEMENT( TABLE
, XML_NAMED_EXPRESSIONS
):
289 SCTAB nTab
= GetScImport().GetTables().GetCurrentSheet();
290 pContext
= new ScXMLNamedExpressionsContext(
292 new ScXMLNamedExpressionsContext::SheetLocalInserter(GetScImport(), nTab
));
295 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN_GROUP
):
296 pContext
= new ScXMLTableColsContext( GetScImport(), pAttribList
,
299 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_COLUMNS
):
300 pContext
= new ScXMLTableColsContext( GetScImport(), pAttribList
,
303 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMNS
):
304 pContext
= new ScXMLTableColsContext( GetScImport(), pAttribList
,
307 case XML_ELEMENT( TABLE
, XML_TABLE_COLUMN
):
308 pContext
= new ScXMLTableColContext( GetScImport(), pAttribList
);
310 case XML_ELEMENT( TABLE
, XML_TABLE_PROTECTION
):
311 case XML_ELEMENT( LO_EXT
, XML_TABLE_PROTECTION
):
312 case XML_ELEMENT( OFFICE_EXT
, XML_TABLE_PROTECTION
):
313 pContext
= new ScXMLTableProtectionContext( GetScImport(), pAttribList
);
315 case XML_ELEMENT( TABLE
, XML_TABLE_ROW_GROUP
):
316 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
319 case XML_ELEMENT( TABLE
, XML_TABLE_HEADER_ROWS
):
320 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
323 case XML_ELEMENT( TABLE
, XML_TABLE_ROWS
):
324 pContext
= new ScXMLTableRowsContext( GetScImport(), pAttribList
,
327 case XML_ELEMENT( TABLE
, XML_TABLE_ROW
):
328 pContext
= new ScXMLTableRowContext( GetScImport(), pAttribList
);
330 case XML_ELEMENT( TABLE
, XML_TABLE_SOURCE
):
331 pContext
= new ScXMLTableSourceContext( GetScImport(), pAttribList
);
333 case XML_ELEMENT( TABLE
, XML_SCENARIO
):
334 pContext
= new ScXMLTableScenarioContext( GetScImport(), pAttribList
);
336 case XML_ELEMENT( TABLE
, XML_SHAPES
):
337 pContext
= new ScXMLTableShapesContext( GetScImport() );
339 case XML_ELEMENT( CALC_EXT
, XML_CONDITIONAL_FORMATS
):
340 pContext
= new ScXMLConditionalFormatsContext( GetScImport() );
343 pContext
= new SvXMLImportContext( GetImport() );
351 void SAL_CALL
ScXMLTableContext::endFastElement(sal_Int32
/*nElement*/)
353 ScXMLImport::MutexGuard
aMutexGuard(GetScImport());
354 ScXMLImport
& rImport
= GetScImport();
355 rImport
.GetStylesImportHelper()->EndTable();
356 ScDocument
* pDoc(rImport
.GetDocument());
360 ScMyTables
& rTables
= rImport
.GetTables();
361 SCTAB nCurTab
= rTables
.GetCurrentSheet();
362 if (!sPrintRanges
.isEmpty())
364 ScRangeList aRangeList
;
365 ScRangeStringConverter::GetRangeListFromString( aRangeList
, sPrintRanges
, pDoc
, ::formula::FormulaGrammar::CONV_OOO
);
366 size_t nCount
= aRangeList
.size();
367 for (size_t i
=0; i
< nCount
; i
++ )
369 pDoc
->AddPrintRange( nCurTab
, aRangeList
[i
] );
372 else if (!bPrintEntireSheet
)
373 // Sheet has "print entire sheet" option by default. Remove it.
374 pDoc
->ClearPrintRanges(nCurTab
);
376 ScOutlineTable
* pOutlineTable(pDoc
->GetOutlineTable(nCurTab
));
379 ScOutlineArray
& rColArray(pOutlineTable
->GetColArray());
380 size_t nDepth
= rColArray
.GetDepth();
381 for (size_t i
= 0; i
< nDepth
; ++i
)
383 size_t nCount
= rColArray
.GetCount(i
);
384 for (size_t j
= 0; j
< nCount
; ++j
)
386 const ScOutlineEntry
* pEntry
= rColArray
.GetEntry(i
, j
);
387 if (pEntry
->IsHidden())
388 rColArray
.SetVisibleBelow(i
, j
, false);
391 ScOutlineArray
& rRowArray(pOutlineTable
->GetRowArray());
392 nDepth
= rRowArray
.GetDepth();
393 for (size_t i
= 0; i
< nDepth
; ++i
)
395 size_t nCount
= rRowArray
.GetCount(i
);
396 for (size_t j
= 0; j
< nCount
; ++j
)
398 const ScOutlineEntry
* pEntry
= rRowArray
.GetEntry(i
, j
);
399 if (pEntry
->IsHidden())
400 rRowArray
.SetVisibleBelow(i
, j
, false);
404 if (rTables
.HasDrawPage())
406 if (rTables
.HasXShapes())
408 rImport
.GetShapeImport()->popGroupAndPostProcess();
409 uno::Reference
< drawing::XShapes
> xTempShapes(rTables
.GetCurrentXShapes());
410 rImport
.GetShapeImport()->endPage(xTempShapes
);
413 rImport
.GetFormImport()->endPage();
416 rTables
.DeleteTable();
417 rImport
.ProgressBarIncrement();
419 // store stream positions
420 if (!pExternalRefInfo
&& nStartOffset
>= 0 /* && nEndOffset >= 0 */)
422 ScSheetSaveData
* pSheetData
= comphelper::getUnoTunnelImplementation
<ScModelObj
>(rImport
.GetModel())->GetSheetSaveData();
423 SCTAB nTab
= rTables
.GetCurrentSheet();
424 // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
425 pSheetData
->StartStreamPos( nTab
, nStartOffset
);
429 ScXMLTableProtectionContext::ScXMLTableProtectionContext(
430 ScXMLImport
& rImport
,
431 const rtl::Reference
<sax_fastparser::FastAttributeList
>& rAttrList
) :
432 ScXMLImportContext( rImport
)
434 bool bSelectProtectedCells
= false;
435 bool bSelectUnprotectedCells
= false;
436 bool bInsertColumns
= false;
437 bool bInsertRows
= false;
438 bool bDeleteColumns
= false;
439 bool bDeleteRows
= false;
441 if ( rAttrList
.is() )
443 for (auto &aIter
: *rAttrList
)
445 sal_Int32 nToken
= aIter
.getToken();
448 case XML_ELEMENT( TABLE
, XML_SELECT_PROTECTED_CELLS
):
449 case XML_ELEMENT( OFFICE_EXT
, XML_SELECT_PROTECTED_CELLS
):
450 case XML_ELEMENT( LO_EXT
, XML_SELECT_PROTECTED_CELLS
):
451 bSelectProtectedCells
= IsXMLToken(aIter
, XML_TRUE
);
453 case XML_ELEMENT( TABLE
, XML_SELECT_UNPROTECTED_CELLS
):
454 case XML_ELEMENT( OFFICE_EXT
, XML_SELECT_UNPROTECTED_CELLS
):
455 case XML_ELEMENT( LO_EXT
, XML_SELECT_UNPROTECTED_CELLS
):
456 bSelectUnprotectedCells
= IsXMLToken(aIter
, XML_TRUE
);
458 case XML_ELEMENT( LO_EXT
, XML_INSERT_COLUMNS
):
459 bInsertColumns
= IsXMLToken(aIter
, XML_TRUE
);
461 case XML_ELEMENT( LO_EXT
, XML_INSERT_ROWS
):
462 bInsertRows
= IsXMLToken(aIter
, XML_TRUE
);
464 case XML_ELEMENT( LO_EXT
, XML_DELETE_COLUMNS
):
465 bDeleteColumns
= IsXMLToken(aIter
, XML_TRUE
);
467 case XML_ELEMENT( LO_EXT
, XML_DELETE_ROWS
):
468 bDeleteRows
= IsXMLToken(aIter
, XML_TRUE
);
471 SAL_WARN("sc", "unknown attribute: " << nToken
);
476 ScXMLTabProtectionData
& rProtectData
= GetScImport().GetTables().GetCurrentProtectionData();
477 rProtectData
.mbSelectProtectedCells
= bSelectProtectedCells
;
478 rProtectData
.mbSelectUnprotectedCells
= bSelectUnprotectedCells
;
479 rProtectData
.mbInsertColumns
= bInsertColumns
;
480 rProtectData
.mbInsertRows
= bInsertRows
;
481 rProtectData
.mbDeleteColumns
= bDeleteColumns
;
482 rProtectData
.mbDeleteRows
= bDeleteRows
;
485 ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
489 uno::Reference
< xml::sax::XFastContextHandler
> SAL_CALL
ScXMLTableProtectionContext::createFastChildContext(
490 sal_Int32
/*nElement*/, const uno::Reference
< xml::sax::XFastAttributeList
>& /*xAttrList*/ )
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */