1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 // INCLUDE ---------------------------------------------------------------
30
31 #include "xmltabi.hxx"
32 #include "xmlimprt.hxx"
33 #include "xmlrowi.hxx"
34 #include "xmlcoli.hxx"
35 #include "xmlsceni.hxx"
36 #include "xmlexternaltabi.hxx"
37 #include "document.hxx"
38 #include "docuno.hxx"
39 #include "olinetab.hxx"
40 #include "XMLConverter.hxx"
41 #include "XMLTableShapesContext.hxx"
42 #include "XMLTableSourceContext.hxx"
43 #include "XMLStylesImportHelper.hxx"
44 #include "rangeutl.hxx"
45 #include "externalrefmgr.hxx"
46 #include "sheetdata.hxx"
47 #include "xmlnexpi.hxx"
48
49 #include <xmloff/xmltkmap.hxx>
50 #include <xmloff/nmspmap.hxx>
51 #include <xmloff/formsimp.hxx>
52 #include <xmloff/xmltoken.hxx>
53 #include <xmloff/XMLEventsImportContext.hxx>
54
55 #include <tools/urlobj.hxx>
56
57 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
58 #include <com/sun/star/sheet/XSpreadsheets.hpp>
59 #include <com/sun/star/sheet/XSpreadsheet.hpp>
60 #include <com/sun/star/sheet/XPrintAreas.hpp>
61 #include <com/sun/star/table/CellAddress.hpp>
62
63 using namespace com::sun::star;
64 using namespace xmloff::token;
65
66 /**
67 * Determine whether this table is an external reference cache from its
68 * name. There is currently no way of determining whether a table is a
69 * regular table or an external reference cache other than examining the
70 * name itself. We should probably introduce a new boolean value for
71 * table:table element and use it instead of doing this, to make it more
72 * reliable and future-proof.
73 *
74 * @param rName
75 *
76 * @return
77 */
lcl_isExternalRefCache(const rtl::OUString & rName,rtl::OUString & rUrl,rtl::OUString & rExtTabName)78 static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rUrl, rtl::OUString& rExtTabName)
79 {
80 // 'file:///path/to/file.ods'#MySheet
81 // 'file:///path/to/file.ods'#MySheet with space
82 // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
83 // That's allowed.)
84
85 if ( rName.toChar() != '\'' ) // initial quote
86 return false;
87
88 // #i114504# Other schemes besides "file:" are also allowed.
89 // CompareProtocolScheme is quick, only looks at the start of the string.
90 INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.copy(1) );
91 if ( eProt == INET_PROT_NOT_VALID )
92 return false;
93
94 rtl::OUString aPrefix = INetURLObject::GetScheme( eProt );
95 sal_Int32 nPrefLen = aPrefix.getLength();
96
97 rtl::OUStringBuffer aUrlBuf, aTabNameBuf;
98 aUrlBuf.append( aPrefix );
99 sal_Int32 n = rName.getLength();
100 const sal_Unicode* p = rName.getStr();
101
102 bool bInUrl = true;
103 sal_Unicode cPrev = 0;
104 for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix
105 {
106 const sal_Unicode c = p[i];
107 if (bInUrl)
108 {
109 // parsing file URL
110 if (c == '#')
111 {
112 if (cPrev != '\'')
113 return false;
114
115 rUrl = aUrlBuf.makeStringAndClear();
116 rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
117 bInUrl = false;
118 }
119 else
120 aUrlBuf.append(c);
121 }
122 else
123 // parsing sheet name.
124 aTabNameBuf.append(c);
125
126 cPrev = c;
127 }
128
129 if (bInUrl)
130 return false;
131
132 if (aTabNameBuf.getLength() == 0)
133 return false;
134
135 rExtTabName = aTabNameBuf.makeStringAndClear();
136
137 return true;
138 }
139
ScXMLExternalTabData()140 ScXMLExternalTabData::ScXMLExternalTabData() :
141 mpCacheTable(), mnRow(0), mnCol(0), mnFileId(0)
142 {
143 }
144
145 //------------------------------------------------------------------
146
ScXMLTableContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,const sal_Bool bTempIsSubTable,const sal_Int32 nSpannedCols)147 ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
148 sal_uInt16 nPrfx,
149 const ::rtl::OUString& rLName,
150 const ::com::sun::star::uno::Reference<
151 ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
152 const sal_Bool bTempIsSubTable,
153 const sal_Int32 nSpannedCols) :
154 SvXMLImportContext( rImport, nPrfx, rLName ),
155 pExternalRefInfo(NULL),
156 nStartOffset(-1),
157 bStartFormPage(sal_False),
158 bPrintEntireSheet(sal_True)
159 {
160 // get start offset in file (if available)
161 nStartOffset = GetScImport().GetByteOffset();
162
163 if (!bTempIsSubTable)
164 {
165 sal_Bool bProtection(sal_False);
166 rtl::OUString sName;
167 rtl::OUString sStyleName;
168 rtl::OUString sPassword;
169 sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
170 const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
171 for( sal_Int16 i=0; i < nAttrCount; ++i )
172 {
173 const rtl::OUString& sAttrName(xAttrList->getNameByIndex( i ));
174 rtl::OUString aLocalName;
175 sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
176 sAttrName, &aLocalName ));
177 const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
178
179 switch( rAttrTokenMap.Get( nPrefix, aLocalName ) )
180 {
181 case XML_TOK_TABLE_NAME:
182 sName = sValue;
183 break;
184 case XML_TOK_TABLE_STYLE_NAME:
185 sStyleName = sValue;
186 break;
187 case XML_TOK_TABLE_PROTECTION:
188 bProtection = IsXMLToken(sValue, XML_TRUE);
189 break;
190 case XML_TOK_TABLE_PRINT_RANGES:
191 sPrintRanges = sValue;
192 break;
193 case XML_TOK_TABLE_PASSWORD:
194 sPassword = sValue;
195 break;
196 case XML_TOK_TABLE_PRINT:
197 {
198 if (IsXMLToken(sValue, XML_FALSE))
199 bPrintEntireSheet = sal_False;
200 }
201 break;
202 }
203 }
204
205 rtl::OUString aExtUrl, aExtTabName;
206 if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
207 {
208 // This is an external ref cache table.
209 pExternalRefInfo.reset(new ScXMLExternalTabData);
210 pExternalRefInfo->maFileUrl = aExtUrl;
211 ScDocument* pDoc = GetScImport().GetDocument();
212 if (pDoc)
213 {
214 ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
215 pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
216 pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true);
217 pExternalRefInfo->mpCacheTable->setWholeTableCached();
218 }
219 }
220 else
221 {
222 // This is a regular table.
223 GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
224 }
225 }
226 else
227 {
228 GetScImport().GetTables().NewTable(nSpannedCols);
229 }
230 }
231
~ScXMLTableContext()232 ScXMLTableContext::~ScXMLTableContext()
233 {
234 }
235
CreateChildContext(sal_uInt16 nPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList)236 SvXMLImportContext *ScXMLTableContext::CreateChildContext( sal_uInt16 nPrefix,
237 const ::rtl::OUString& rLName,
238 const ::com::sun::star::uno::Reference<
239 ::com::sun::star::xml::sax::XAttributeList>& xAttrList )
240 {
241 const SvXMLTokenMap& rTokenMap(GetScImport().GetTableElemTokenMap());
242 sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLName);
243 if (pExternalRefInfo.get())
244 {
245 // We only care about the table-row and table-source elements for
246 // external cache data.
247 switch (nToken)
248 {
249 case XML_TOK_TABLE_ROW_GROUP:
250 case XML_TOK_TABLE_HEADER_ROWS:
251 case XML_TOK_TABLE_ROWS:
252 // #i101319# don't discard rows in groups or header (repeat range)
253 return new ScXMLExternalRefRowsContext(
254 GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
255 case XML_TOK_TABLE_ROW:
256 return new ScXMLExternalRefRowContext(
257 GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
258 case XML_TOK_TABLE_SOURCE:
259 return new ScXMLExternalRefTabSourceContext(
260 GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
261 default:
262 ;
263 }
264
265 return new SvXMLImportContext(GetImport(), nPrefix, rLName);
266 }
267
268 SvXMLImportContext *pContext(0);
269
270 switch (nToken)
271 {
272 case XML_TOK_TABLE_COL_GROUP:
273 pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
274 rLName, xAttrList,
275 sal_False, sal_True );
276 break;
277 case XML_TOK_TABLE_HEADER_COLS:
278 pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
279 rLName, xAttrList,
280 sal_True, sal_False );
281 break;
282 case XML_TOK_TABLE_COLS:
283 pContext = new ScXMLTableColsContext( GetScImport(), nPrefix,
284 rLName, xAttrList,
285 sal_False, sal_False );
286 break;
287 case XML_TOK_TABLE_COL:
288 pContext = new ScXMLTableColContext( GetScImport(), nPrefix,
289 rLName, xAttrList );
290 break;
291 case XML_TOK_TABLE_ROW_GROUP:
292 pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
293 rLName, xAttrList,
294 sal_False, sal_True );
295 break;
296 case XML_TOK_TABLE_HEADER_ROWS:
297 pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
298 rLName, xAttrList,
299 sal_True, sal_False );
300 break;
301 case XML_TOK_TABLE_ROWS:
302 pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
303 rLName, xAttrList,
304 sal_False, sal_False );
305 break;
306 case XML_TOK_TABLE_ROW:
307 pContext = new ScXMLTableRowContext( GetScImport(), nPrefix,
308 rLName, xAttrList//,
309 //this
310 );
311 break;
312 case XML_TOK_TABLE_SOURCE:
313 pContext = new ScXMLTableSourceContext( GetScImport(), nPrefix, rLName, xAttrList);
314 break;
315 case XML_TOK_TABLE_SCENARIO:
316 pContext = new ScXMLTableScenarioContext( GetScImport(), nPrefix, rLName, xAttrList);
317 break;
318 case XML_TOK_TABLE_SHAPES:
319 pContext = new ScXMLTableShapesContext( GetScImport(), nPrefix, rLName, xAttrList);
320 break;
321 case XML_TOK_TABLE_FORMS:
322 {
323 GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
324 bStartFormPage = sal_True;
325 pContext = GetScImport().GetFormImport()->createOfficeFormsContext( GetScImport(), nPrefix, rLName );
326 }
327 break;
328 case XML_TOK_TABLE_NAMED_EXPRESSIONS:
329 {
330 SCTAB nCurrentSheet = static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet());
331 pContext = new ScXMLNamedExpressionsContext ( GetScImport(), nPrefix, rLName, xAttrList );//worksheetname
332 static_cast<ScXMLNamedExpressionsContext*>(pContext)->SetScope( nCurrentSheet );
333 }
334 break;
335 case XML_TOK_TABLE_EVENT_LISTENERS:
336 case XML_TOK_TABLE_EVENT_LISTENERS_EXT:
337 {
338 // use XEventsSupplier interface of the sheet
339 uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
340 pContext = new XMLEventsImportContext( GetImport(), nPrefix, rLName, xSupplier );
341 }
342 break;
343 default:
344 ;
345 }
346
347 if( !pContext )
348 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLName );
349
350 return pContext;
351 }
352
EndElement()353 void ScXMLTableContext::EndElement()
354 {
355 // get end offset in file (if available)
356 // sal_Int32 nEndOffset = GetScImport().GetByteOffset();
357
358 GetScImport().LockSolarMutex();
359 GetScImport().GetStylesImportHelper()->EndTable();
360 ScDocument* pDoc(GetScImport().GetDocument());
361 if (pDoc)
362 {
363 if (sPrintRanges.getLength())
364 {
365 uno::Reference< sheet::XPrintAreas > xPrintAreas( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
366 if( xPrintAreas.is() )
367 {
368 uno::Sequence< table::CellRangeAddress > aRangeList;
369 ScRangeStringConverter::GetRangeListFromString( aRangeList, sPrintRanges, pDoc, ::formula::FormulaGrammar::CONV_OOO );
370 xPrintAreas->setPrintAreas( aRangeList );
371 }
372 }
373 else if (bPrintEntireSheet) pDoc->SetPrintEntireSheet(static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet()));
374
375 ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(static_cast<SCTAB>(GetScImport().GetTables().GetCurrentSheet()), sal_False));
376 if (pOutlineTable)
377 {
378 ScOutlineArray* pColArray(pOutlineTable->GetColArray());
379 sal_Int32 nDepth(pColArray->GetDepth());
380 sal_Int32 i;
381 for (i = 0; i < nDepth; ++i)
382 {
383 sal_Int32 nCount(pColArray->GetCount(static_cast<sal_uInt16>(i)));
384 for (sal_Int32 j = 0; j < nCount; ++j)
385 {
386 ScOutlineEntry* pEntry(pColArray->GetEntry(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j)));
387 if (pEntry->IsHidden())
388 pColArray->SetVisibleBelow(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j), sal_False);
389 }
390 }
391 ScOutlineArray* pRowArray(pOutlineTable->GetRowArray());
392 nDepth = pRowArray->GetDepth();
393 for (i = 0; i < nDepth; ++i)
394 {
395 sal_Int32 nCount(pRowArray->GetCount(static_cast<sal_uInt16>(i)));
396 for (sal_Int32 j = 0; j < nCount; ++j)
397 {
398 ScOutlineEntry* pEntry(pRowArray->GetEntry(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j)));
399 if (pEntry->IsHidden())
400 pRowArray->SetVisibleBelow(static_cast<sal_uInt16>(i), static_cast<sal_uInt16>(j), sal_False);
401 }
402 }
403 }
404 if (GetScImport().GetTables().HasDrawPage())
405 {
406 if (GetScImport().GetTables().HasXShapes())
407 {
408 GetScImport().GetShapeImport()->popGroupAndSort();
409 uno::Reference < drawing::XShapes > xTempShapes(GetScImport().GetTables().GetCurrentXShapes());
410 GetScImport().GetShapeImport()->endPage(xTempShapes);
411 }
412 if (bStartFormPage)
413 GetScImport().GetFormImport()->endPage();
414 }
415
416 GetScImport().GetTables().DeleteTable();
417 GetScImport().ProgressBarIncrement(sal_False);
418
419 // store stream positions
420 if (!pExternalRefInfo.get() && nStartOffset >= 0 /* && nEndOffset >= 0 */)
421 {
422 ScSheetSaveData* pSheetData = ScModelObj::getImplementation(GetScImport().GetModel())->GetSheetSaveData();
423 sal_Int32 nTab = GetScImport().GetTables().GetCurrentSheet();
424 // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
425 pSheetData->StartStreamPos( nTab, nStartOffset );
426 }
427 }
428 GetScImport().UnlockSolarMutex();
429 }
430
431