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 "XMLConverter.hxx"
31 #include "XMLTableShapesContext.hxx"
32 #include "XMLTableSourceContext.hxx"
33 #include "XMLStylesImportHelper.hxx"
34 #include "rangeutl.hxx"
35 #include "externalrefmgr.hxx"
36 #include "sheetdata.hxx"
37 #include "xmlcondformat.hxx"
39 #include <xmloff/xmltkmap.hxx>
40 #include <xmloff/nmspmap.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include <xmloff/XMLEventsImportContext.hxx>
44 #include <tools/urlobj.hxx>
46 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
47 #include <com/sun/star/sheet/XSpreadsheets.hpp>
48 #include <com/sun/star/sheet/XSpreadsheet.hpp>
49 #include <com/sun/star/sheet/XPrintAreas.hpp>
50 #include <com/sun/star/table/CellAddress.hpp>
52 using namespace com::sun::star
;
53 using namespace xmloff::token
;
54 using ::com::sun::star::uno::Reference
;
55 using ::com::sun::star::uno::Sequence
;
56 using ::com::sun::star::uno::UNO_QUERY
;
57 using ::com::sun::star::xml::sax::XAttributeList
;
60 * Determine whether this table is an external reference cache from its
61 * name. There is currently no way of determining whether a table is a
62 * regular table or an external reference cache other than examining the
63 * name itself. We should probably introduce a new boolean value for
64 * table:table element and use it instead of doing this, to make it more
65 * reliable and future-proof.
71 static bool lcl_isExternalRefCache(const OUString
& rName
, OUString
& rUrl
, OUString
& rExtTabName
)
73 // 'file:///path/to/file.ods'#MySheet
74 // 'file:///path/to/file.ods'#MySheet with space
75 // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
78 if ( rName
.toChar() != '\'' ) // initial quote
81 // #i114504# Other schemes besides "file:" are also allowed.
82 // CompareProtocolScheme is quick, only looks at the start of the string.
83 INetProtocol eProt
= INetURLObject::CompareProtocolScheme( rName
.copy(1) );
84 if ( eProt
== INetProtocol::NotValid
)
87 OUString aPrefix
= INetURLObject::GetScheme( eProt
);
88 sal_Int32 nPrefLen
= aPrefix
.getLength();
90 OUStringBuffer aUrlBuf
, aTabNameBuf
;
91 aUrlBuf
.append( aPrefix
);
92 sal_Int32 n
= rName
.getLength();
93 const sal_Unicode
* p
= rName
.getStr();
96 sal_Unicode cPrev
= 0;
97 for (sal_Int32 i
= nPrefLen
+1; i
< n
; ++i
) // start the loop after quote and prefix
99 const sal_Unicode c
= p
[i
];
108 rUrl
= aUrlBuf
.makeStringAndClear();
109 rUrl
= rUrl
.copy(0, rUrl
.getLength()-1); // remove the trailing single-quote.
116 // parsing sheet name.
117 aTabNameBuf
.append(c
);
125 if (aTabNameBuf
.isEmpty())
128 rExtTabName
= aTabNameBuf
.makeStringAndClear();
133 ScXMLExternalTabData::ScXMLExternalTabData() :
134 mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
138 ScXMLTableContext::ScXMLTableContext( ScXMLImport
& rImport
,
140 const OUString
& rLName
,
141 const ::com::sun::star::uno::Reference
<
142 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
) :
143 SvXMLImportContext( rImport
, nPrfx
, rLName
),
145 bStartFormPage(false),
146 bPrintEntireSheet(true)
148 // get start offset in file (if available)
149 nStartOffset
= GetScImport().GetByteOffset();
151 ScXMLTabProtectionData aProtectData
;
154 sal_Int16
nAttrCount(xAttrList
.is() ? xAttrList
->getLength() : 0);
155 const SvXMLTokenMap
& rAttrTokenMap
= GetScImport().GetTableAttrTokenMap();
156 for( sal_Int16 i
=0; i
< nAttrCount
; ++i
)
158 const OUString
& sAttrName(xAttrList
->getNameByIndex( i
));
160 sal_uInt16
nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
161 sAttrName
, &aLocalName
));
162 const OUString
& sValue(xAttrList
->getValueByIndex( i
));
164 switch( rAttrTokenMap
.Get( nPrefix
, aLocalName
) )
166 case XML_TOK_TABLE_NAME
:
169 case XML_TOK_TABLE_STYLE_NAME
:
172 case XML_TOK_TABLE_PROTECTED
:
173 aProtectData
.mbProtected
= IsXMLToken(sValue
, XML_TRUE
);
175 case XML_TOK_TABLE_PRINT_RANGES
:
176 sPrintRanges
= sValue
;
178 case XML_TOK_TABLE_PASSWORD
:
179 aProtectData
.maPassword
= sValue
;
181 case XML_TOK_TABLE_PASSHASH
:
182 aProtectData
.meHash1
= ScPassHashHelper::getHashTypeFromURI(sValue
);
184 case XML_TOK_TABLE_PASSHASH_2
:
185 aProtectData
.meHash2
= ScPassHashHelper::getHashTypeFromURI(sValue
);
187 case XML_TOK_TABLE_PRINT
:
189 if (IsXMLToken(sValue
, XML_FALSE
))
190 bPrintEntireSheet
= false;
196 OUString aExtUrl
, aExtTabName
;
197 if (lcl_isExternalRefCache(sName
, aExtUrl
, aExtTabName
))
199 // This is an external ref cache table.
200 pExternalRefInfo
.reset(new ScXMLExternalTabData
);
201 pExternalRefInfo
->maFileUrl
= aExtUrl
;
202 ScDocument
* pDoc
= GetScImport().GetDocument();
205 ScExternalRefManager
* pRefMgr
= pDoc
->GetExternalRefManager();
206 pExternalRefInfo
->mnFileId
= pRefMgr
->getExternalFileId(aExtUrl
);
207 pExternalRefInfo
->mpCacheTable
= pRefMgr
->getCacheTable(pExternalRefInfo
->mnFileId
, aExtTabName
, true);
208 pExternalRefInfo
->mpCacheTable
->setWholeTableCached();
213 // This is a regular table.
214 GetScImport().GetTables().NewSheet(sName
, sStyleName
, aProtectData
);
218 ScXMLTableContext::~ScXMLTableContext()
222 SvXMLImportContext
*ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix
,
223 const OUString
& rLName
,
224 const ::com::sun::star::uno::Reference
<
225 ::com::sun::star::xml::sax::XAttributeList
>& xAttrList
)
227 const SvXMLTokenMap
& rTokenMap(GetScImport().GetTableElemTokenMap());
228 sal_uInt16 nToken
= rTokenMap
.Get(nPrefix
, rLName
);
229 if (pExternalRefInfo
.get())
231 // We only care about the table-row and table-source elements for
232 // external cache data.
235 case XML_TOK_TABLE_ROW_GROUP
:
236 case XML_TOK_TABLE_HEADER_ROWS
:
237 case XML_TOK_TABLE_ROWS
:
238 // #i101319# don't discard rows in groups or header (repeat range)
239 return new ScXMLExternalRefRowsContext(
240 GetScImport(), nPrefix
, rLName
, xAttrList
, *pExternalRefInfo
);
241 case XML_TOK_TABLE_ROW
:
242 return new ScXMLExternalRefRowContext(
243 GetScImport(), nPrefix
, rLName
, xAttrList
, *pExternalRefInfo
);
244 case XML_TOK_TABLE_SOURCE
:
245 return new ScXMLExternalRefTabSourceContext(
246 GetScImport(), nPrefix
, rLName
, xAttrList
, *pExternalRefInfo
);
251 return new SvXMLImportContext(GetImport(), nPrefix
, rLName
);
254 SvXMLImportContext
*pContext(0);
258 case XML_TOK_TABLE_NAMED_EXPRESSIONS
:
260 SCTAB nTab
= GetScImport().GetTables().GetCurrentSheet();
261 pContext
= new ScXMLNamedExpressionsContext(
262 GetScImport(), nPrefix
, rLName
, xAttrList
,
263 new ScXMLNamedExpressionsContext::SheetLocalInserter(GetScImport(), nTab
));
266 case XML_TOK_TABLE_COL_GROUP
:
267 pContext
= new ScXMLTableColsContext( GetScImport(), nPrefix
,
271 case XML_TOK_TABLE_HEADER_COLS
:
272 pContext
= new ScXMLTableColsContext( GetScImport(), nPrefix
,
276 case XML_TOK_TABLE_COLS
:
277 pContext
= new ScXMLTableColsContext( GetScImport(), nPrefix
,
281 case XML_TOK_TABLE_COL
:
282 pContext
= new ScXMLTableColContext( GetScImport(), nPrefix
,
285 case XML_TOK_TABLE_PROTECTION
:
286 case XML_TOK_TABLE_PROTECTION_EXT
:
287 pContext
= new ScXMLTableProtectionContext( GetScImport(), nPrefix
, rLName
, xAttrList
);
289 case XML_TOK_TABLE_ROW_GROUP
:
290 pContext
= new ScXMLTableRowsContext( GetScImport(), nPrefix
,
294 case XML_TOK_TABLE_HEADER_ROWS
:
295 pContext
= new ScXMLTableRowsContext( GetScImport(), nPrefix
,
299 case XML_TOK_TABLE_ROWS
:
300 pContext
= new ScXMLTableRowsContext( GetScImport(), nPrefix
,
304 case XML_TOK_TABLE_ROW
:
305 pContext
= new ScXMLTableRowContext( GetScImport(), nPrefix
,
310 case XML_TOK_TABLE_SOURCE
:
311 pContext
= new ScXMLTableSourceContext( GetScImport(), nPrefix
, rLName
, xAttrList
);
313 case XML_TOK_TABLE_SCENARIO
:
314 pContext
= new ScXMLTableScenarioContext( GetScImport(), nPrefix
, rLName
, xAttrList
);
316 case XML_TOK_TABLE_SHAPES
:
317 pContext
= new ScXMLTableShapesContext( GetScImport(), nPrefix
, rLName
, xAttrList
);
319 case XML_TOK_TABLE_FORMS
:
321 GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
322 bStartFormPage
= true;
323 pContext
= xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetScImport(), nPrefix
, rLName
);
326 case XML_TOK_TABLE_EVENT_LISTENERS
:
327 case XML_TOK_TABLE_EVENT_LISTENERS_EXT
:
329 // use XEventsSupplier interface of the sheet
330 uno::Reference
<document::XEventsSupplier
> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY
);
331 pContext
= new XMLEventsImportContext( GetImport(), nPrefix
, rLName
, xSupplier
);
334 case XML_TOK_TABLE_CONDFORMATS
:
335 pContext
= new ScXMLConditionalFormatsContext( GetScImport(), nPrefix
, rLName
);
342 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLName
);
347 void ScXMLTableContext::EndElement()
349 ScXMLImport::MutexGuard
aMutexGuard(GetScImport());
350 ScXMLImport
& rImport
= GetScImport();
351 rImport
.GetStylesImportHelper()->EndTable();
352 ScDocument
* pDoc(rImport
.GetDocument());
356 ScMyTables
& rTables
= rImport
.GetTables();
357 SCTAB nCurTab
= rTables
.GetCurrentSheet();
358 if (!sPrintRanges
.isEmpty())
360 ScRangeList aRangeList
;
361 ScRangeStringConverter::GetRangeListFromString( aRangeList
, sPrintRanges
, pDoc
, ::formula::FormulaGrammar::CONV_OOO
);
362 size_t nCount
= aRangeList
.size();
363 for (size_t i
=0; i
< nCount
; i
++ )
365 pDoc
->AddPrintRange( nCurTab
, *aRangeList
[i
] );
368 else if (!bPrintEntireSheet
)
369 // Sheet has "print entire sheet" option by default. Remove it.
370 pDoc
->ClearPrintRanges(nCurTab
);
372 ScOutlineTable
* pOutlineTable(pDoc
->GetOutlineTable(nCurTab
, false));
375 ScOutlineArray
& rColArray(pOutlineTable
->GetColArray());
376 size_t nDepth
= rColArray
.GetDepth();
377 for (size_t i
= 0; i
< nDepth
; ++i
)
379 size_t nCount
= rColArray
.GetCount(i
);
380 for (size_t j
= 0; j
< nCount
; ++j
)
382 const ScOutlineEntry
* pEntry
= rColArray
.GetEntry(i
, j
);
383 if (pEntry
->IsHidden())
384 rColArray
.SetVisibleBelow(i
, j
, false);
387 ScOutlineArray
& rRowArray(pOutlineTable
->GetRowArray());
388 nDepth
= rRowArray
.GetDepth();
389 for (size_t i
= 0; i
< nDepth
; ++i
)
391 size_t nCount
= rRowArray
.GetCount(i
);
392 for (size_t j
= 0; j
< nCount
; ++j
)
394 const ScOutlineEntry
* pEntry
= rRowArray
.GetEntry(i
, j
);
395 if (pEntry
->IsHidden())
396 rRowArray
.SetVisibleBelow(i
, j
, false);
400 if (rTables
.HasDrawPage())
402 if (rTables
.HasXShapes())
404 rImport
.GetShapeImport()->popGroupAndSort();
405 uno::Reference
< drawing::XShapes
> xTempShapes(rTables
.GetCurrentXShapes());
406 rImport
.GetShapeImport()->endPage(xTempShapes
);
409 rImport
.GetFormImport()->endPage();
412 rTables
.DeleteTable();
413 rImport
.ProgressBarIncrement(false);
415 // store stream positions
416 if (!pExternalRefInfo
.get() && nStartOffset
>= 0 /* && nEndOffset >= 0 */)
418 ScSheetSaveData
* pSheetData
= ScModelObj::getImplementation(rImport
.GetModel())->GetSheetSaveData();
419 SCTAB nTab
= rTables
.GetCurrentSheet();
420 // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
421 pSheetData
->StartStreamPos( nTab
, nStartOffset
);
425 ScXMLImport
& ScXMLTableProtectionContext::GetScImport()
427 return static_cast<ScXMLImport
&>(GetImport());
430 ScXMLTableProtectionContext::ScXMLTableProtectionContext(
431 ScXMLImport
& rImport
, sal_uInt16 nPrefix
, const OUString
& rLName
,
432 const Reference
<XAttributeList
>& xAttrList
) :
433 SvXMLImportContext( rImport
, nPrefix
, rLName
)
435 const SvXMLTokenMap
& rAttrTokenMap
= GetScImport().GetTableProtectionAttrTokenMap();
436 bool bSelectProtectedCells
= false;
437 bool bSelectUnprotectedCells
= false;
439 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
441 for (sal_Int16 i
= 0; i
< nAttrCount
; ++i
)
443 const OUString
& aAttrName
= xAttrList
->getNameByIndex(i
);
444 const OUString aValue
= xAttrList
->getValueByIndex(i
);
447 sal_uInt16 nLocalPrefix
= GetScImport().GetNamespaceMap().GetKeyByAttrName(
448 aAttrName
, &aLocalName
);
450 switch (rAttrTokenMap
.Get(nLocalPrefix
, aLocalName
))
452 case XML_TOK_TABLE_SELECT_PROTECTED_CELLS
:
453 case XML_TOK_TABLE_SELECT_PROTECTED_CELLS_EXT
:
454 bSelectProtectedCells
= IsXMLToken(aValue
, XML_TRUE
);
456 case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS
:
457 case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS_EXT
:
458 bSelectUnprotectedCells
= IsXMLToken(aValue
, XML_TRUE
);
461 SAL_WARN("sc", "unknown attribute: " << aAttrName
);
465 ScXMLTabProtectionData
& rProtectData
= GetScImport().GetTables().GetCurrentProtectionData();
466 rProtectData
.mbSelectProtectedCells
= bSelectProtectedCells
;
467 rProtectData
.mbSelectUnprotectedCells
= bSelectUnprotectedCells
;
470 ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
474 SvXMLImportContext
* ScXMLTableProtectionContext::CreateChildContext(
475 sal_uInt16
/*nPrefix*/, const OUString
& /*rLocalName*/, const Reference
<XAttributeList
>& /*xAttrList*/ )
480 void ScXMLTableProtectionContext::EndElement()
484 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */