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 #include "xilink.hxx"
27 #include "document.hxx"
28 #include "cell.hxx"
29 #include "scextopt.hxx"
30 #include "tablink.hxx"
31 #include "xistream.hxx"
32 #include "xihelper.hxx"
33 #include "xiname.hxx"
34 #include "excform.hxx"
35 #include "tokenarray.hxx"
36 #include "externalrefmgr.hxx"
37
38 #include <vector>
39
40 using ::std::vector;
41
42 // ============================================================================
43 // *** Helper classes ***
44 // ============================================================================
45
46 // Cached external cells ======================================================
47
48 /** Contains the address and value of an external referenced cell. */
49 class XclImpCrn : public XclImpCachedValue
50 {
51 public:
52 /** Reads a cached value and stores it with its cell address. */
53 explicit XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
54
55 const XclAddress& GetAddress() const;
56
57 private:
58 XclAddress maXclPos; /// Excel position of the cached cell.
59 };
60
61 // Sheet in an external document ==============================================
62
63 /** Contains the name and sheet index of one sheet in an external document. */
64 class XclImpSupbookTab
65 {
66 public:
67 /** Stores the sheet name and marks the sheet index as invalid.
68 The sheet index is set while creating the Calc sheet with CreateTable(). */
69 explicit XclImpSupbookTab( const String& rTabName );
70 ~XclImpSupbookTab();
71
GetTabName() const72 inline const String& GetTabName() const { return maTabName; }
73
74 /** Reads a CRN record (external referenced cell) at the specified address. */
75 void ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
76
77 void LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable);
78
79 private:
80 typedef ScfDelList< XclImpCrn > XclImpCrnList;
81
82 XclImpCrnList maCrnList; /// List of CRN records (cached cell values).
83 String maTabName; /// Name of the external sheet.
84 SCTAB mnScTab; /// New sheet index in Calc document.
85 };
86
87 // External document (SUPBOOK) ================================================
88
89 /** This class represents an external linked document (record SUPBOOK).
90 @descr Contains a list of all referenced sheets in the document. */
91 class XclImpSupbook : protected XclImpRoot
92 {
93 public:
94 /** Reads the SUPBOOK record from stream. */
95 explicit XclImpSupbook( XclImpStream& rStrm );
96
97 /** Reads an XCT record (count of following CRNs and current sheet). */
98 void ReadXct( XclImpStream& rStrm );
99 /** Reads a CRN record (external referenced cell). */
100 void ReadCrn( XclImpStream& rStrm );
101 /** Reads an EXTERNNAME record. */
102 void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
103
104 /** Returns the SUPBOOK record type. */
GetType() const105 inline XclSupbookType GetType() const { return meType; }
106
107 /** Returns the URL of the external document. */
GetXclUrl() const108 inline const String& GetXclUrl() const { return maXclUrl; }
109
110 /** Returns the external name specified by an index from the Excel document (one-based). */
111 const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const;
112 /** Tries to decode the URL to OLE or DDE link components.
113 @descr For DDE links: Decodes to application name and topic.
114 For OLE object links: Decodes to class name and document URL.
115 @return true = decoding was successful, returned strings are valid (not empty). */
116 bool GetLinkData( String& rApplic, String& rDoc ) const;
117 /** Returns the specified macro name (1-based) or an empty string on error. */
118 const String& GetMacroName( sal_uInt16 nXclNameIdx ) const;
119
120 const String& GetTabName( sal_uInt16 nXtiTab ) const;
121
122 sal_uInt16 GetTabCount() const;
123
124 void LoadCachedValues();
125
126 private:
127 typedef ScfDelList< XclImpSupbookTab > XclImpSupbookTabList;
128 typedef ScfDelList< XclImpExtName > XclImpExtNameList;
129
130 XclImpSupbookTabList maSupbTabList; /// All sheet names of the document.
131 XclImpExtNameList maExtNameList; /// All external names of the document.
132 String maXclUrl; /// URL of the external document (Excel mode).
133 String maFilterName; /// Detected filer name.
134 String maFilterOpt; /// Detected filer options.
135 XclSupbookType meType; /// Type of the supbook record.
136 sal_uInt16 mnSBTab; /// Current Excel sheet index from SUPBOOK for XCT/CRN records.
137 };
138
139 // Import link manager ========================================================
140
141 /** Contains the SUPBOOK index and sheet indexes of an external link.
142 @descr It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1),
143 therefore here occurs a sheet range. */
144 struct XclImpXti
145 {
146 sal_uInt16 mnSupbook; /// Index to SUPBOOK record.
147 sal_uInt16 mnSBTabFirst; /// Index to the first sheet of the range in the SUPBOOK.
148 sal_uInt16 mnSBTabLast; /// Index to the last sheet of the range in the SUPBOOK.
XclImpXtiXclImpXti149 inline explicit XclImpXti() : mnSupbook( SAL_MAX_UINT16 ), mnSBTabFirst( SAL_MAX_UINT16 ), mnSBTabLast( SAL_MAX_UINT16 ) {}
150 };
151
operator >>(XclImpStream & rStrm,XclImpXti & rXti)152 inline XclImpStream& operator>>( XclImpStream& rStrm, XclImpXti& rXti )
153 {
154 return rStrm >> rXti.mnSupbook >> rXti.mnSBTabFirst >> rXti.mnSBTabLast;
155 }
156
157 // ----------------------------------------------------------------------------
158
159 /** Implementation of the link manager. */
160 class XclImpLinkManagerImpl : protected XclImpRoot
161 {
162 public:
163 explicit XclImpLinkManagerImpl( const XclImpRoot& rRoot );
164
165 /** Reads the EXTERNSHEET record. */
166 void ReadExternsheet( XclImpStream& rStrm );
167 /** Reads a SUPBOOK record. */
168 void ReadSupbook( XclImpStream& rStrm );
169 /** Reads an XCT record and appends it to the current SUPBOOK. */
170 void ReadXct( XclImpStream& rStrm );
171 /** Reads a CRN record and appends it to the current SUPBOOK. */
172 void ReadCrn( XclImpStream& rStrm );
173 /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
174 void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
175
176 /** Returns true, if the specified XTI entry contains an internal reference. */
177 bool IsSelfRef( sal_uInt16 nXtiIndex ) const;
178 /** Returns the Calc sheet index range of the specified XTI entry.
179 @return true = XTI data found, returned sheet index range is valid. */
180 bool GetScTabRange(
181 SCTAB& rnFirstScTab, SCTAB& rnLastScTab,
182 sal_uInt16 nXtiIndex ) const;
183 /** Returns the specified external name or 0 on error. */
184 const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
185
186 /** Returns the absolute file URL of a supporting workbook specified by
187 the index. */
188 const String* GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
189
190 const String& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
191
192 /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
193 @descr For DDE links: Decodes to application name and topic.
194 For OLE object links: Decodes to class name and document URL.
195 @return true = decoding was successful, returned strings are valid (not empty). */
196 bool GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const;
197 /** Returns the specified macro name or an empty string on error. */
198 const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
199
200 private:
201 /** Returns the specified XTI (link entry from BIFF8 EXTERNSHEET record). */
202 const XclImpXti* GetXti( sal_uInt16 nXtiIndex ) const;
203 /** Returns the specified SUPBOOK (external document). */
204 const XclImpSupbook* GetSupbook( sal_uInt16 nXtiIndex ) const;
205 //UNUSED2009-05 /** Returns the SUPBOOK (external workbook) specified by its URL. */
206 //UNUSED2009-05 const XclImpSupbook* GetSupbook( const String& rUrl ) const;
207
208 void LoadCachedValues();
209
210 //UNUSED2009-05 /** Finds the largest range of sheet indexes in a SUPBOOK after a start sheet index.
211 //UNUSED2009-05 @param rnSBTabFirst (out-param) The first sheet index of the range in SUPBOOK is returned here.
212 //UNUSED2009-05 @param rnSBTabLast (out-param) The last sheet index of the range in SUPBOOK is returned here (inclusive).
213 //UNUSED2009-05 @param nSupbook The list index of the SUPBOOK.
214 //UNUSED2009-05 @param nSBTabStart The first allowed sheet index. Sheet ranges with an earlier start index are ignored.
215 //UNUSED2009-05 @return true = the return values are valid; false = nothing found. */
216 //UNUSED2009-05 bool FindNextTabRange(
217 //UNUSED2009-05 sal_uInt16& rnSBTabFirst, sal_uInt16& rnSBTabLast,
218 //UNUSED2009-05 sal_uInt16 nSupbook, sal_uInt16 nSBTabStart ) const;
219
220 private:
221 typedef ::std::vector< XclImpXti > XclImpXtiVector;
222 typedef ScfDelList< XclImpSupbook > XclImpSupbookList;
223
224 XclImpXtiVector maXtiList; /// List of all XTI structures.
225 XclImpSupbookList maSupbookList; /// List of external documents.
226 bool mbCreated; /// true = Calc sheets already created.
227 };
228
229 // ============================================================================
230 // *** Implementation ***
231 // ============================================================================
232
233 // Excel sheet indexes ========================================================
234
235 // original Excel sheet names -------------------------------------------------
236
AppendXclTabName(const String & rXclTabName,SCTAB nScTab)237 void XclImpTabInfo::AppendXclTabName( const String& rXclTabName, SCTAB nScTab )
238 {
239 maTabNames[ rXclTabName ] = nScTab;
240 }
241
InsertScTab(SCTAB nScTab)242 void XclImpTabInfo::InsertScTab( SCTAB nScTab )
243 {
244 for( XclTabNameMap::iterator aIt = maTabNames.begin(), aEnd = maTabNames.end(); aIt != aEnd; ++aIt )
245 if( aIt->second >= nScTab )
246 ++aIt->second;
247 }
248
GetScTabFromXclName(const String & rXclTabName) const249 SCTAB XclImpTabInfo::GetScTabFromXclName( const String& rXclTabName ) const
250 {
251 XclTabNameMap::const_iterator aIt = maTabNames.find( rXclTabName );
252 return (aIt != maTabNames.end()) ? aIt->second : SCTAB_INVALID;
253 }
254
255 // record creation order - TABID record ---------------------------------------
256
ReadTabid(XclImpStream & rStrm)257 void XclImpTabInfo::ReadTabid( XclImpStream& rStrm )
258 {
259 DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
260 if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
261 {
262 rStrm.EnableDecryption();
263 sal_Size nReadCount = rStrm.GetRecLeft() / 2;
264 DBG_ASSERT( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
265 maTabIdVec.clear();
266 maTabIdVec.reserve( nReadCount );
267 for( sal_Size nIndex = 0; rStrm.IsValid() && (nIndex < nReadCount); ++nIndex )
268 // #93471# zero index is not allowed in BIFF8, but it seems that it occurs in real life
269 maTabIdVec.push_back( rStrm.ReaduInt16() );
270 }
271 }
272
GetCurrentIndex(sal_uInt16 nCreatedId,sal_uInt16 nMaxTabId) const273 sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMaxTabId ) const
274 {
275 sal_uInt16 nReturn = 0;
276 for( ScfUInt16Vec::const_iterator aIt = maTabIdVec.begin(), aEnd = maTabIdVec.end(); aIt != aEnd; ++aIt )
277 {
278 sal_uInt16 nValue = *aIt;
279 if( nValue == nCreatedId )
280 return nReturn;
281 if( nValue <= nMaxTabId )
282 ++nReturn;
283 }
284 return 0;
285 }
286
287 // External names =============================================================
288
XclImpExtName(const XclImpSupbook & rSupbook,XclImpStream & rStrm,XclSupbookType eSubType,ExcelToSc * pFormulaConv)289 XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv )
290 {
291 sal_uInt16 nFlags;
292 sal_uInt8 nLen;
293
294 rStrm >> nFlags >> mnStorageId >> nLen ;
295 maName = rStrm.ReadUniString( nLen );
296 if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
297 {
298 if( eSubType == EXC_SBTYPE_ADDIN )
299 {
300 meType = xlExtAddIn;
301 maName = rStrm.GetRoot().GetScAddInName( maName );
302 }
303 else if ( (eSubType == EXC_SBTYPE_EUROTOOL) &&
304 maName.EqualsIgnoreCaseAscii( "EUROCONVERT" ) )
305 meType = xlExtEuroConvert;
306 else
307 {
308 meType = xlExtName;
309 ScfTools::ConvertToScDefinedName( maName );
310 }
311 }
312 else
313 {
314 meType = ::get_flagvalue( nFlags, EXC_EXTN_OLE, xlExtOLE, xlExtDDE );
315 }
316
317 if( (meType == xlExtDDE) && (rStrm.GetRecLeft() > 1) )
318 mxDdeMatrix.reset( new XclImpCachedMatrix( rStrm ) );
319
320 if (meType == xlExtName)
321 {
322 // TODO: For now, only global external names are supported. In future
323 // we should extend this to supporting per-sheet external names.
324 if (mnStorageId == 0)
325 {
326 if (pFormulaConv)
327 {
328 const ScTokenArray* pArray = NULL;
329 sal_uInt16 nFmlaLen;
330 rStrm >> nFmlaLen;
331 vector<String> aTabNames;
332 sal_uInt16 nCount = rSupbook.GetTabCount();
333 aTabNames.reserve(nCount);
334 for (sal_uInt16 i = 0; i < nCount; ++i)
335 aTabNames.push_back(rSupbook.GetTabName(i));
336
337 pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
338 if (pArray)
339 mxArray.reset(pArray->Clone());
340 }
341 }
342 }
343 }
344
~XclImpExtName()345 XclImpExtName::~XclImpExtName()
346 {
347 }
348
CreateDdeData(ScDocument & rDoc,const String & rApplic,const String & rTopic) const349 void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, const String& rTopic ) const
350 {
351 ScMatrixRef xResults;
352 if( mxDdeMatrix.get() )
353 xResults = mxDdeMatrix->CreateScMatrix();
354 rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
355 }
356
CreateExtNameData(ScDocument & rDoc,sal_uInt16 nFileId) const357 void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
358 {
359 if (!mxArray.get())
360 return;
361
362 ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
363 pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
364 }
365
HasFormulaTokens() const366 bool XclImpExtName::HasFormulaTokens() const
367 {
368 return (mxArray.get() != NULL);
369 }
370
371 // Cached external cells ======================================================
372
XclImpCrn(XclImpStream & rStrm,const XclAddress & rXclPos)373 XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
374 XclImpCachedValue( rStrm ),
375 maXclPos( rXclPos )
376 {
377 }
378
GetAddress() const379 const XclAddress& XclImpCrn::GetAddress() const
380 {
381 return maXclPos;
382 }
383
384 // Sheet in an external document ==============================================
385
XclImpSupbookTab(const String & rTabName)386 XclImpSupbookTab::XclImpSupbookTab( const String& rTabName ) :
387 maTabName( rTabName ),
388 mnScTab( SCTAB_INVALID )
389 {
390 }
391
~XclImpSupbookTab()392 XclImpSupbookTab::~XclImpSupbookTab()
393 {
394 }
395
ReadCrn(XclImpStream & rStrm,const XclAddress & rXclPos)396 void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
397 {
398 maCrnList.Append( new XclImpCrn( rStrm, rXclPos ) );
399 }
400
LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable)401 void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable)
402 {
403 if (maCrnList.Empty())
404 return;
405
406 for (XclImpCrn* p = maCrnList.First(); p; p = maCrnList.Next())
407 {
408 const XclAddress& rAddr = p->GetAddress();
409 switch (p->GetType())
410 {
411 case EXC_CACHEDVAL_BOOL:
412 {
413 bool b = p->GetBool();
414 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
415 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
416 }
417 break;
418 case EXC_CACHEDVAL_DOUBLE:
419 {
420 double f = p->GetValue();
421 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(f));
422 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
423 }
424 break;
425 case EXC_CACHEDVAL_ERROR:
426 {
427 double fError = XclTools::ErrorToDouble( p->GetXclError() );
428 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(fError));
429 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
430 }
431 break;
432 case EXC_CACHEDVAL_STRING:
433 {
434 const String& rStr = p->GetString();
435 ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(rStr));
436 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
437 }
438 break;
439 default:
440 ;
441 }
442 }
443 }
444
445 // External document (SUPBOOK) ================================================
446
XclImpSupbook(XclImpStream & rStrm)447 XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) :
448 XclImpRoot( rStrm.GetRoot() ),
449 meType( EXC_SBTYPE_UNKNOWN ),
450 mnSBTab( EXC_TAB_DELETED )
451 {
452 sal_uInt16 nSBTabCnt;
453 rStrm >> nSBTabCnt;
454
455 if( rStrm.GetRecLeft() == 2 )
456 {
457 switch( rStrm.ReaduInt16() )
458 {
459 case EXC_SUPB_SELF: meType = EXC_SBTYPE_SELF; break;
460 case EXC_SUPB_ADDIN: meType = EXC_SBTYPE_ADDIN; break;
461 default: DBG_ERRORFILE( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" );
462 }
463 return;
464 }
465
466 String aEncUrl( rStrm.ReadUniString() );
467 bool bSelf = false;
468 XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl );
469
470 if( maXclUrl.EqualsIgnoreCaseAscii( "\010EUROTOOL.XLA" ) )
471 {
472 meType = EXC_SBTYPE_EUROTOOL;
473 maSupbTabList.Append( new XclImpSupbookTab( maXclUrl ) );
474 }
475 else if( nSBTabCnt )
476 {
477 meType = EXC_SBTYPE_EXTERN;
478 for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab )
479 {
480 String aTabName( rStrm.ReadUniString() );
481 maSupbTabList.Append( new XclImpSupbookTab( aTabName ) );
482 }
483 }
484 else
485 {
486 meType = EXC_SBTYPE_SPECIAL;
487 // create dummy list entry
488 maSupbTabList.Append( new XclImpSupbookTab( maXclUrl ) );
489 }
490 }
491
ReadXct(XclImpStream & rStrm)492 void XclImpSupbook::ReadXct( XclImpStream& rStrm )
493 {
494 rStrm.Ignore( 2 );
495 rStrm >> mnSBTab;
496 }
497
ReadCrn(XclImpStream & rStrm)498 void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
499 {
500 if( XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( mnSBTab ) )
501 {
502 sal_uInt8 nXclColLast, nXclColFirst;
503 sal_uInt16 nXclRow;
504 rStrm >> nXclColLast >> nXclColFirst >> nXclRow;
505
506 for( sal_uInt8 nXclCol = nXclColFirst; (nXclCol <= nXclColLast) && (rStrm.GetRecLeft() > 1); ++nXclCol )
507 pSBTab->ReadCrn( rStrm, XclAddress( nXclCol, nXclRow ) );
508 }
509 }
510
ReadExternname(XclImpStream & rStrm,ExcelToSc * pFormulaConv)511 void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
512 {
513 maExtNameList.Append( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) );
514 }
515
GetExternName(sal_uInt16 nXclIndex) const516 const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
517 {
518 DBG_ASSERT( nXclIndex > 0, "XclImpSupbook::GetExternName - index must be >0" );
519 return (meType == EXC_SBTYPE_SELF) ? 0 : maExtNameList.GetObject( nXclIndex - 1 );
520 }
521
GetLinkData(String & rApplic,String & rTopic) const522 bool XclImpSupbook::GetLinkData( String& rApplic, String& rTopic ) const
523 {
524 return (meType == EXC_SBTYPE_SPECIAL) && XclImpUrlHelper::DecodeLink( rApplic, rTopic, maXclUrl );
525 }
526
GetMacroName(sal_uInt16 nXclNameIdx) const527 const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
528 {
529 DBG_ASSERT( nXclNameIdx > 0, "XclImpSupbook::GetMacroName - index must be >0" );
530 const XclImpName* pName = (meType == EXC_SBTYPE_SELF) ? GetNameManager().GetName( nXclNameIdx ) : 0;
531 return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_STRING;
532 }
533
GetTabName(sal_uInt16 nXtiTab) const534 const String& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const
535 {
536 if (maSupbTabList.Empty())
537 return EMPTY_STRING;
538
539 sal_uInt16 i = 0;
540 for (XclImpSupbookTab* p = maSupbTabList.First(); p; p = maSupbTabList.Next(), ++i)
541 {
542 if (i == nXtiTab)
543 return p->GetTabName();
544 }
545
546 return EMPTY_STRING;
547 }
548
GetTabCount() const549 sal_uInt16 XclImpSupbook::GetTabCount() const
550 {
551 return ulimit_cast<sal_uInt16>(maSupbTabList.Count());
552 }
553
LoadCachedValues()554 void XclImpSupbook::LoadCachedValues()
555 {
556 if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell())
557 return;
558
559 String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
560
561 ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
562 sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
563
564 sal_uInt16 nCount = static_cast< sal_uInt16 >( maSupbTabList.Count() );
565 for (sal_uInt16 i = 0; i < nCount; ++i)
566 {
567 XclImpSupbookTab* pTab = maSupbTabList.GetObject(i);
568 if (!pTab)
569 return;
570
571 const String& rTabName = pTab->GetTabName();
572 ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
573 pTab->LoadCachedValues(pCacheTable);
574 pCacheTable->setWholeTableCached();
575 }
576 }
577
578 // Import link manager ========================================================
579
XclImpLinkManagerImpl(const XclImpRoot & rRoot)580 XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot& rRoot ) :
581 XclImpRoot( rRoot ),
582 mbCreated( false )
583 {
584 }
585
ReadExternsheet(XclImpStream & rStrm)586 void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
587 {
588 sal_uInt16 nXtiCount;
589 rStrm >> nXtiCount;
590 DBG_ASSERT( static_cast< sal_Size >( nXtiCount * 6 ) == rStrm.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" );
591 nXtiCount = static_cast< sal_uInt16 >( ::std::min< sal_Size >( nXtiCount, rStrm.GetRecLeft() / 6 ) );
592
593 /* #i104057# A weird external XLS generator writes multiple EXTERNSHEET
594 records instead of only one as expected. Surprisingly, Excel seems to
595 insert the entries of the second record before the entries of the first
596 record. */
597 XclImpXtiVector aNewEntries( nXtiCount );
598 for( XclImpXtiVector::iterator aIt = aNewEntries.begin(), aEnd = aNewEntries.end(); rStrm.IsValid() && (aIt != aEnd); ++aIt )
599 rStrm >> *aIt;
600 maXtiList.insert( maXtiList.begin(), aNewEntries.begin(), aNewEntries.end() );
601
602 LoadCachedValues();
603 }
604
ReadSupbook(XclImpStream & rStrm)605 void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
606 {
607 maSupbookList.Append( new XclImpSupbook( rStrm ) );
608 }
609
ReadXct(XclImpStream & rStrm)610 void XclImpLinkManagerImpl::ReadXct( XclImpStream& rStrm )
611 {
612 if( XclImpSupbook* pSupbook = maSupbookList.Last() )
613 pSupbook->ReadXct( rStrm );
614 }
615
ReadCrn(XclImpStream & rStrm)616 void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
617 {
618 if( XclImpSupbook* pSupbook = maSupbookList.Last() )
619 pSupbook->ReadCrn( rStrm );
620 }
621
ReadExternname(XclImpStream & rStrm,ExcelToSc * pFormulaConv)622 void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
623 {
624 if( XclImpSupbook* pSupbook = maSupbookList.Last() )
625 pSupbook->ReadExternname( rStrm, pFormulaConv );
626 }
627
IsSelfRef(sal_uInt16 nXtiIndex) const628 bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
629 {
630 const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
631 return pSupbook && (pSupbook->GetType() == EXC_SBTYPE_SELF);
632 }
633
GetScTabRange(SCTAB & rnFirstScTab,SCTAB & rnLastScTab,sal_uInt16 nXtiIndex) const634 bool XclImpLinkManagerImpl::GetScTabRange(
635 SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
636 {
637 if( const XclImpXti* pXti = GetXti( nXtiIndex ) )
638 {
639 if (maSupbookList.GetObject(pXti->mnSupbook))
640 {
641 rnFirstScTab = pXti->mnSBTabFirst;
642 rnLastScTab = pXti->mnSBTabLast;
643 return true;
644 }
645 }
646 return false;
647 }
648
GetExternName(sal_uInt16 nXtiIndex,sal_uInt16 nExtName) const649 const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
650 {
651 const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
652 return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
653 }
654
GetSupbookUrl(sal_uInt16 nXtiIndex) const655 const String* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
656 {
657 const XclImpSupbook* p = GetSupbook( nXtiIndex );
658 if (!p)
659 return NULL;
660 return &p->GetXclUrl();
661 }
662
GetSupbookTabName(sal_uInt16 nXti,sal_uInt16 nXtiTab) const663 const String& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
664 {
665 const XclImpSupbook* p = GetSupbook(nXti);
666 return p ? p->GetTabName(nXtiTab) : EMPTY_STRING;
667 }
668
GetLinkData(String & rApplic,String & rTopic,sal_uInt16 nXtiIndex) const669 bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
670 {
671 const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
672 return pSupbook && pSupbook->GetLinkData( rApplic, rTopic );
673 }
674
GetMacroName(sal_uInt16 nExtSheet,sal_uInt16 nExtName) const675 const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
676 {
677 const XclImpSupbook* pSupbook = GetSupbook( nExtSheet );
678 return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_STRING;
679 }
680
GetXti(sal_uInt16 nXtiIndex) const681 const XclImpXti* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex ) const
682 {
683 return (nXtiIndex < maXtiList.size()) ? &maXtiList[ nXtiIndex ] : 0;
684 }
685
GetSupbook(sal_uInt16 nXtiIndex) const686 const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex ) const
687 {
688 const XclImpXti* pXti = GetXti( nXtiIndex );
689 return pXti ? maSupbookList.GetObject( pXti->mnSupbook ) : 0;
690 }
691
692 //UNUSED2009-05 const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) const
693 //UNUSED2009-05 {
694 //UNUSED2009-05 for( const XclImpSupbook* pSupbook = maSupbookList.First(); pSupbook; pSupbook = maSupbookList.Next() )
695 //UNUSED2009-05 if( pSupbook->GetXclUrl() == rUrl )
696 //UNUSED2009-05 return pSupbook;
697 //UNUSED2009-05 return 0;
698 //UNUSED2009-05 }
699
LoadCachedValues()700 void XclImpLinkManagerImpl::LoadCachedValues()
701 {
702 // Read all CRN records which can be accessed via XclImpSupbook, and store
703 // the cached values to the external reference manager.
704
705 sal_uInt32 nCount = maSupbookList.Count();
706 for (sal_uInt16 nSupbook = 0; nSupbook < nCount; ++nSupbook)
707 {
708 XclImpSupbook* pSupbook = maSupbookList.GetObject(nSupbook);
709 pSupbook->LoadCachedValues();
710 }
711 }
712
713 //UNUSED2009-05 bool XclImpLinkManagerImpl::FindNextTabRange(
714 //UNUSED2009-05 sal_uInt16& rnSBTabFirst, sal_uInt16& rnSBTabLast,
715 //UNUSED2009-05 sal_uInt16 nSupbook, sal_uInt16 nSBTabStart ) const
716 //UNUSED2009-05 {
717 //UNUSED2009-05 rnSBTabFirst = rnSBTabLast = EXC_NOTAB;
718 //UNUSED2009-05 for( const XclImpXti* pXti = maXtiList.First(); pXti; pXti = maXtiList.Next() )
719 //UNUSED2009-05 {
720 //UNUSED2009-05 if( (nSupbook == pXti->mnSupbook) && (nSBTabStart <= pXti->mnSBTabLast) && (pXti->mnSBTabFirst < rnSBTabFirst) )
721 //UNUSED2009-05 {
722 //UNUSED2009-05 rnSBTabFirst = ::std::max( nSBTabStart, pXti->mnSBTabFirst );
723 //UNUSED2009-05 rnSBTabLast = pXti->mnSBTabLast;
724 //UNUSED2009-05 }
725 //UNUSED2009-05 }
726 //UNUSED2009-05 return rnSBTabFirst != EXC_NOTAB;
727 //UNUSED2009-05 }
728
729 // ============================================================================
730
XclImpLinkManager(const XclImpRoot & rRoot)731 XclImpLinkManager::XclImpLinkManager( const XclImpRoot& rRoot ) :
732 XclImpRoot( rRoot ),
733 mxImpl( new XclImpLinkManagerImpl( rRoot ) )
734 {
735 }
736
~XclImpLinkManager()737 XclImpLinkManager::~XclImpLinkManager()
738 {
739 }
740
ReadExternsheet(XclImpStream & rStrm)741 void XclImpLinkManager::ReadExternsheet( XclImpStream& rStrm )
742 {
743 mxImpl->ReadExternsheet( rStrm );
744 }
745
ReadSupbook(XclImpStream & rStrm)746 void XclImpLinkManager::ReadSupbook( XclImpStream& rStrm )
747 {
748 mxImpl->ReadSupbook( rStrm );
749 }
750
ReadXct(XclImpStream & rStrm)751 void XclImpLinkManager::ReadXct( XclImpStream& rStrm )
752 {
753 mxImpl->ReadXct( rStrm );
754 }
755
ReadCrn(XclImpStream & rStrm)756 void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
757 {
758 mxImpl->ReadCrn( rStrm );
759 }
760
ReadExternname(XclImpStream & rStrm,ExcelToSc * pFormulaConv)761 void XclImpLinkManager::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
762 {
763 mxImpl->ReadExternname( rStrm, pFormulaConv );
764 }
765
IsSelfRef(sal_uInt16 nXtiIndex) const766 bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
767 {
768 return mxImpl->IsSelfRef( nXtiIndex );
769 }
770
GetScTabRange(SCTAB & rnFirstScTab,SCTAB & rnLastScTab,sal_uInt16 nXtiIndex) const771 bool XclImpLinkManager::GetScTabRange(
772 SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
773 {
774 return mxImpl->GetScTabRange( rnFirstScTab, rnLastScTab, nXtiIndex );
775 }
776
GetExternName(sal_uInt16 nXtiIndex,sal_uInt16 nExtName) const777 const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
778 {
779 return mxImpl->GetExternName( nXtiIndex, nExtName );
780 }
781
GetSupbookUrl(sal_uInt16 nXtiIndex) const782 const String* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
783 {
784 return mxImpl->GetSupbookUrl(nXtiIndex);
785 }
786
GetSupbookTabName(sal_uInt16 nXti,sal_uInt16 nXtiTab) const787 const String& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
788 {
789 return mxImpl->GetSupbookTabName(nXti, nXtiTab);
790 }
791
GetLinkData(String & rApplic,String & rTopic,sal_uInt16 nXtiIndex) const792 bool XclImpLinkManager::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
793 {
794 return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
795 }
796
GetMacroName(sal_uInt16 nExtSheet,sal_uInt16 nExtName) const797 const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
798 {
799 return mxImpl->GetMacroName( nExtSheet, nExtName );
800 }
801
802 // ============================================================================
803
804