fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / xilink.cxx
blobfce7ba4edc5c9546bc71d08b20e1238a0a4155e1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "xilink.hxx"
21 #include "document.hxx"
22 #include "formulacell.hxx"
23 #include "scextopt.hxx"
24 #include "tablink.hxx"
25 #include "xistream.hxx"
26 #include "xihelper.hxx"
27 #include "xiname.hxx"
28 #include "excform.hxx"
29 #include "tokenarray.hxx"
30 #include "externalrefmgr.hxx"
31 #include "scmatrix.hxx"
32 #include <svl/sharedstringpool.hxx>
34 #include <vector>
35 #include <boost/ptr_container/ptr_vector.hpp>
37 using ::std::vector;
39 // *** Helper classes ***
41 // Cached external cells ======================================================
43 /**
44 * Contains the address and value of an external referenced cell.
45 * Note that this is non-copyable, so cannot be used in most stl/boost containers.
47 class XclImpCrn : public XclImpCachedValue
49 public:
50 /** Reads a cached value and stores it with its cell address. */
51 explicit XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
53 const XclAddress& GetAddress() const { return maXclPos;}
55 private:
56 XclAddress maXclPos; /// Excel position of the cached cell.
59 // Sheet in an external document ==============================================
61 /** Contains the name and sheet index of one sheet in an external document. */
62 class XclImpSupbookTab
64 public:
65 /** Stores the sheet name and marks the sheet index as invalid.
66 The sheet index is set while creating the Calc sheet with CreateTable(). */
67 explicit XclImpSupbookTab( const OUString& rTabName );
68 ~XclImpSupbookTab();
70 inline const OUString& GetTabName() const { return maTabName; }
72 /** Reads a CRN record (external referenced cell) at the specified address. */
73 void ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos );
75 void LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable);
77 private:
78 typedef boost::shared_ptr< XclImpCrn > XclImpCrnRef;
79 typedef std::vector< XclImpCrnRef > XclImpCrnList;
81 XclImpCrnList maCrnList; /// List of CRN records (cached cell values).
82 OUString maTabName; /// Name of the external sheet.
85 // External document (SUPBOOK) ================================================
87 /** This class represents an external linked document (record SUPBOOK).
88 @descr Contains a list of all referenced sheets in the document. */
89 class XclImpSupbook : protected XclImpRoot
91 public:
92 /** Reads the SUPBOOK record from stream. */
93 explicit XclImpSupbook( XclImpStream& rStrm );
95 /** Reads an XCT record (count of following CRNs and current sheet). */
96 void ReadXct( XclImpStream& rStrm );
97 /** Reads a CRN record (external referenced cell). */
98 void ReadCrn( XclImpStream& rStrm );
99 /** Reads an EXTERNNAME record. */
100 void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
102 /** Returns the SUPBOOK record type. */
103 inline XclSupbookType GetType() const { return meType; }
105 /** Returns the URL of the external document. */
106 inline const OUString& GetXclUrl() const { return maXclUrl; }
108 /** Returns the external name specified by an index from the Excel document (one-based). */
109 const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const;
110 /** Tries to decode the URL to OLE or DDE link components.
111 @descr For DDE links: Decodes to application name and topic.
112 For OLE object links: Decodes to class name and document URL.
113 @return true = decoding was successful, returned strings are valid (not empty). */
114 bool GetLinkData( OUString& rApplic, OUString& rDoc ) const;
115 /** Returns the specified macro name (1-based) or an empty string on error. */
116 const OUString& GetMacroName( sal_uInt16 nXclNameIdx ) const;
118 const OUString& GetTabName( sal_uInt16 nXtiTab ) const;
120 sal_uInt16 GetTabCount() const;
122 void LoadCachedValues();
124 svl::SharedStringPool& GetSharedStringPool();
126 private:
127 typedef boost::ptr_vector< XclImpSupbookTab > XclImpSupbookTabList;
128 typedef boost::ptr_vector< XclImpExtName > XclImpExtNameList;
130 XclImpSupbookTabList maSupbTabList; /// All sheet names of the document.
131 XclImpExtNameList maExtNameList; /// All external names of the document.
132 OUString maXclUrl; /// URL of the external document (Excel mode).
133 XclSupbookType meType; /// Type of the supbook record.
134 sal_uInt16 mnSBTab; /// Current Excel sheet index from SUPBOOK for XCT/CRN records.
137 // Import link manager ========================================================
139 /** Contains the SUPBOOK index and sheet indexes of an external link.
140 @descr It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1),
141 therefore here occurs a sheet range. */
142 struct XclImpXti
144 sal_uInt16 mnSupbook; /// Index to SUPBOOK record.
145 sal_uInt16 mnSBTabFirst; /// Index to the first sheet of the range in the SUPBOOK.
146 sal_uInt16 mnSBTabLast; /// Index to the last sheet of the range in the SUPBOOK.
147 inline explicit XclImpXti() : mnSupbook( SAL_MAX_UINT16 ), mnSBTabFirst( SAL_MAX_UINT16 ), mnSBTabLast( SAL_MAX_UINT16 ) {}
150 inline XclImpStream& operator>>( XclImpStream& rStrm, XclImpXti& rXti )
152 rXti.mnSupbook = rStrm.ReaduInt16();
153 rXti.mnSBTabFirst = rStrm.ReaduInt16();
154 rXti.mnSBTabLast = rStrm.ReaduInt16();
155 return rStrm;
158 /** Implementation of the link manager. */
159 class XclImpLinkManagerImpl : protected XclImpRoot
161 public:
162 explicit XclImpLinkManagerImpl( const XclImpRoot& rRoot );
164 /** Reads the EXTERNSHEET record. */
165 void ReadExternsheet( XclImpStream& rStrm );
166 /** Reads a SUPBOOK record. */
167 void ReadSupbook( XclImpStream& rStrm );
168 /** Reads an XCT record and appends it to the current SUPBOOK. */
169 void ReadXct( XclImpStream& rStrm );
170 /** Reads a CRN record and appends it to the current SUPBOOK. */
171 void ReadCrn( XclImpStream& rStrm );
172 /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
173 void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL );
175 /** Returns true, if the specified XTI entry contains an internal reference. */
176 bool IsSelfRef( sal_uInt16 nXtiIndex ) const;
177 /** Returns the Calc sheet index range of the specified XTI entry.
178 @return true = XTI data found, returned sheet index range is valid. */
179 bool GetScTabRange(
180 SCTAB& rnFirstScTab, SCTAB& rnLastScTab,
181 sal_uInt16 nXtiIndex ) const;
182 /** Returns the specified external name or 0 on error. */
183 const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
185 /** Returns the absolute file URL of a supporting workbook specified by
186 the index. */
187 const OUString* GetSupbookUrl( sal_uInt16 nXtiIndex ) const;
189 const OUString& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const;
191 /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
192 @descr For DDE links: Decodes to application name and topic.
193 For OLE object links: Decodes to class name and document URL.
194 @return true = decoding was successful, returned strings are valid (not empty). */
195 bool GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const;
196 /** Returns the specified macro name or an empty string on error. */
197 const OUString& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
199 private:
200 /** Returns the specified XTI (link entry from BIFF8 EXTERNSHEET record). */
201 const XclImpXti* GetXti( sal_uInt16 nXtiIndex ) const;
202 /** Returns the specified SUPBOOK (external document). */
203 const XclImpSupbook* GetSupbook( sal_uInt16 nXtiIndex ) const;
205 void LoadCachedValues();
207 private:
208 typedef ::std::vector< XclImpXti > XclImpXtiVector;
209 typedef boost::ptr_vector< XclImpSupbook > XclImpSupbookList;
211 XclImpXtiVector maXtiList; /// List of all XTI structures.
212 XclImpSupbookList maSupbookList; /// List of external documents.
215 // *** Implementation ***
217 // Excel sheet indexes ========================================================
219 // original Excel sheet names -------------------------------------------------
221 void XclImpTabInfo::AppendXclTabName( const OUString& rXclTabName, SCTAB nScTab )
223 maTabNames[ rXclTabName ] = nScTab;
226 void XclImpTabInfo::InsertScTab( SCTAB nScTab )
228 for( XclTabNameMap::iterator aIt = maTabNames.begin(), aEnd = maTabNames.end(); aIt != aEnd; ++aIt )
229 if( aIt->second >= nScTab )
230 ++aIt->second;
233 SCTAB XclImpTabInfo::GetScTabFromXclName( const OUString& rXclTabName ) const
235 XclTabNameMap::const_iterator aIt = maTabNames.find( rXclTabName );
236 return (aIt != maTabNames.end()) ? aIt->second : SCTAB_INVALID;
239 // record creation order - TABID record ---------------------------------------
241 void XclImpTabInfo::ReadTabid( XclImpStream& rStrm )
243 OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
244 if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
246 rStrm.EnableDecryption();
247 sal_Size nReadCount = rStrm.GetRecLeft() / 2;
248 OSL_ENSURE( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" );
249 maTabIdVec.clear();
250 maTabIdVec.reserve( nReadCount );
251 for( sal_Size nIndex = 0; rStrm.IsValid() && (nIndex < nReadCount); ++nIndex )
252 // zero index is not allowed in BIFF8, but it seems that it occurs in real life
253 maTabIdVec.push_back( rStrm.ReaduInt16() );
257 sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMaxTabId ) const
259 sal_uInt16 nReturn = 0;
260 for( ScfUInt16Vec::const_iterator aIt = maTabIdVec.begin(), aEnd = maTabIdVec.end(); aIt != aEnd; ++aIt )
262 sal_uInt16 nValue = *aIt;
263 if( nValue == nCreatedId )
264 return nReturn;
265 if( nValue <= nMaxTabId )
266 ++nReturn;
268 return 0;
271 // External names =============================================================
273 XclImpExtName::MOper::MOper(svl::SharedStringPool& rPool, XclImpStream& rStrm) :
274 mxCached(new ScMatrix(0,0))
276 SCSIZE nLastCol = rStrm.ReaduInt8();
277 SCSIZE nLastRow = rStrm.ReaduInt16();
279 //assuming worse case scenario of nOp + one byte unistring len
280 const size_t nMinRecordSize = 2;
281 const size_t nMaxRows = rStrm.GetRecLeft() / (nMinRecordSize * (nLastCol+1));
282 if (nLastRow >= nMaxRows)
284 SAL_WARN("sc", "Parsing error: " << nMaxRows <<
285 " max possible rows, but " << nLastRow << " index claimed, truncating");
286 nLastRow = nMaxRows-1;
289 mxCached->Resize(nLastCol+1, nLastRow+1);
290 for (SCSIZE nRow = 0; nRow <= nLastRow; ++nRow)
292 for (SCSIZE nCol = 0; nCol <= nLastCol; ++nCol)
294 sal_uInt8 nOp;
295 nOp = rStrm.ReaduInt8();
296 switch (nOp)
298 case 0x01:
300 double fVal = rStrm.ReadDouble();
301 mxCached->PutDouble(fVal, nCol, nRow);
303 break;
304 case 0x02:
306 OUString aStr = rStrm.ReadUniString();
307 mxCached->PutString(rPool.intern(aStr), nCol, nRow);
309 break;
310 case 0x04:
312 bool bVal = rStrm.ReaduInt8();
313 mxCached->PutBoolean(bVal, nCol, nRow);
314 rStrm.Ignore(7);
316 break;
317 case 0x10:
319 sal_uInt8 nErr = rStrm.ReaduInt8();
320 // TODO: Map the error code from xls to calc.
321 mxCached->PutError(nErr, nCol, nRow);
322 rStrm.Ignore(7);
324 break;
325 default:
326 rStrm.Ignore(8);
332 const ScMatrix& XclImpExtName::MOper::GetCache() const
334 return *mxCached;
337 XclImpExtName::XclImpExtName( XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv )
338 : mpMOper(NULL)
339 , mnStorageId(0)
341 sal_uInt16 nFlags(0);
342 sal_uInt8 nLen(0);
344 nFlags = rStrm.ReaduInt16();
345 mnStorageId = rStrm.ReaduInt32();
346 nLen = rStrm.ReaduInt8();
347 maName = rStrm.ReadUniString( nLen );
348 if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
350 if( eSubType == EXC_SBTYPE_ADDIN )
352 meType = xlExtAddIn;
353 maName = XclImpRoot::GetScAddInName( maName );
355 else if ( (eSubType == EXC_SBTYPE_EUROTOOL) &&
356 maName.equalsIgnoreAsciiCase( "EUROCONVERT" ) )
357 meType = xlExtEuroConvert;
358 else
360 meType = xlExtName;
361 maName = ScfTools::ConvertToScDefinedName( maName );
364 else
366 meType = ::get_flagvalue( nFlags, EXC_EXTN_OLE, xlExtOLE, xlExtDDE );
369 switch (meType)
371 case xlExtDDE:
372 if (rStrm.GetRecLeft() > 1)
373 mxDdeMatrix.reset(new XclImpCachedMatrix(rStrm));
374 break;
375 case xlExtName:
376 // TODO: For now, only global external names are supported. In future
377 // we should extend this to supporting per-sheet external names.
378 if (mnStorageId == 0)
380 if (pFormulaConv)
382 const ScTokenArray* pArray = NULL;
383 sal_uInt16 nFmlaLen;
384 nFmlaLen = rStrm.ReaduInt16();
385 vector<OUString> aTabNames;
386 sal_uInt16 nCount = rSupbook.GetTabCount();
387 aTabNames.reserve(nCount);
388 for (sal_uInt16 i = 0; i < nCount; ++i)
389 aTabNames.push_back(rSupbook.GetTabName(i));
391 pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames);
392 if (pArray)
393 mxArray.reset(pArray->Clone());
396 break;
397 case xlExtOLE:
398 mpMOper = new MOper(rSupbook.GetSharedStringPool(), rStrm);
399 break;
400 default:
405 XclImpExtName::~XclImpExtName()
407 delete mpMOper;
410 void XclImpExtName::CreateDdeData( ScDocument& rDoc, const OUString& rApplic, const OUString& rTopic ) const
412 ScMatrixRef xResults;
413 if( mxDdeMatrix.get() )
414 xResults = mxDdeMatrix->CreateScMatrix(rDoc.GetSharedStringPool());
415 rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
418 void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
420 if (!mxArray.get())
421 return;
423 ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
424 pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
427 namespace {
430 * Decompose the name into sheet name and range name. An OLE link name is
431 * always formatted like this [ !Sheet1!R1C1:R5C2 ] and it always uses R1C1
432 * notation.
434 bool extractSheetAndRange(const OUString& rName, OUString& rSheet, OUString& rRange)
436 sal_Int32 n = rName.getLength();
437 const sal_Unicode* p = rName.getStr();
438 OUStringBuffer aBuf;
439 bool bInSheet = true;
440 for (sal_Int32 i = 0; i < n; ++i, ++p)
442 if (i == 0)
444 // first character must be '!'.
445 if (*p != '!')
446 return false;
447 continue;
450 if (*p == '!')
452 // sheet name to range separator.
453 if (!bInSheet)
454 return false;
455 rSheet = aBuf.makeStringAndClear();
456 bInSheet = false;
457 continue;
460 aBuf.append(*p);
463 rRange = aBuf.makeStringAndClear();
464 return true;
469 bool XclImpExtName::CreateOleData(ScDocument& rDoc, const OUString& rUrl,
470 sal_uInt16& rFileId, OUString& rTabName, ScRange& rRange) const
472 if (!mpMOper)
473 return false;
475 OUString aSheet, aRangeStr;
476 if (!extractSheetAndRange(maName, aSheet, aRangeStr))
477 return false;
479 ScRange aRange;
480 sal_uInt16 nRes = aRange.ParseAny(aRangeStr, &rDoc, formula::FormulaGrammar::CONV_XL_R1C1);
481 if ((nRes & SCA_VALID) != SCA_VALID)
482 return false;
484 if (aRange.aStart.Tab() != aRange.aEnd.Tab())
485 // We don't support multi-sheet range for this.
486 return false;
488 const ScMatrix& rCache = mpMOper->GetCache();
489 SCSIZE nC, nR;
490 rCache.GetDimensions(nC, nR);
491 if (!nC || !nR)
492 // cache matrix is empty.
493 return false;
495 ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
496 sal_uInt16 nFileId = pRefMgr->getExternalFileId(rUrl);
497 ScExternalRefCache::TableTypeRef xTab = pRefMgr->getCacheTable(nFileId, aSheet, true, NULL);
498 if (!xTab)
499 // cache table creation failed.
500 return false;
502 xTab->setWholeTableCached();
503 for (SCSIZE i = 0; i < nR; ++i)
505 for (SCSIZE j = 0; j < nC; ++j)
507 SCCOL nCol = aRange.aStart.Col() + j;
508 SCROW nRow = aRange.aStart.Row() + i;
510 ScMatrixValue aVal = rCache.Get(j, i);
511 switch (aVal.nType)
513 case SC_MATVAL_BOOLEAN:
515 bool b = aVal.GetBoolean();
516 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
517 xTab->setCell(nCol, nRow, pToken, 0, false);
519 break;
520 case SC_MATVAL_VALUE:
522 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(aVal.fVal));
523 xTab->setCell(nCol, nRow, pToken, 0, false);
525 break;
526 case SC_MATVAL_STRING:
528 const svl::SharedString aStr( aVal.GetString());
529 ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(aStr));
530 xTab->setCell(nCol, nRow, pToken, 0, false);
532 break;
533 default:
539 rFileId = nFileId;
540 rTabName = aSheet;
541 rRange = aRange;
542 return true;
545 bool XclImpExtName::HasFormulaTokens() const
547 return (mxArray.get() != NULL);
550 // Cached external cells ======================================================
552 XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
553 XclImpCachedValue( rStrm ),
554 maXclPos( rXclPos )
558 // Sheet in an external document ==============================================
560 XclImpSupbookTab::XclImpSupbookTab( const OUString& rTabName ) :
561 maTabName( rTabName )
565 XclImpSupbookTab::~XclImpSupbookTab()
569 void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
571 XclImpCrnRef crnRef( new XclImpCrn(rStrm, rXclPos) );
572 maCrnList.push_back( crnRef );
575 void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable)
577 if (maCrnList.empty())
578 return;
580 for (XclImpCrnList::iterator itCrnRef = maCrnList.begin(); itCrnRef != maCrnList.end(); ++itCrnRef)
582 const XclImpCrn* const pCrn = itCrnRef->get();
583 const XclAddress& rAddr = pCrn->GetAddress();
584 switch (pCrn->GetType())
586 case EXC_CACHEDVAL_BOOL:
588 bool b = pCrn->GetBool();
589 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0));
590 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
592 break;
593 case EXC_CACHEDVAL_DOUBLE:
595 double f = pCrn->GetValue();
596 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(f));
597 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
599 break;
600 case EXC_CACHEDVAL_ERROR:
602 double fError = XclTools::ErrorToDouble( pCrn->GetXclError() );
603 ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(fError));
604 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
606 break;
607 case EXC_CACHEDVAL_STRING:
609 const OUString& rStr = pCrn->GetString();
610 ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(rStr));
611 pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken, 0, false);
613 break;
614 default:
620 // External document (SUPBOOK) ================================================
622 XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) :
623 XclImpRoot( rStrm.GetRoot() ),
624 meType( EXC_SBTYPE_UNKNOWN ),
625 mnSBTab( EXC_TAB_DELETED )
627 sal_uInt16 nSBTabCnt;
628 nSBTabCnt = rStrm.ReaduInt16();
630 if( rStrm.GetRecLeft() == 2 )
632 switch( rStrm.ReaduInt16() )
634 case EXC_SUPB_SELF: meType = EXC_SBTYPE_SELF; break;
635 case EXC_SUPB_ADDIN: meType = EXC_SBTYPE_ADDIN; break;
636 default: OSL_FAIL( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" );
638 return;
641 OUString aEncUrl( rStrm.ReadUniString() );
642 bool bSelf = false;
643 XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl );
645 if( maXclUrl.equalsIgnoreAsciiCase( "\010EUROTOOL.XLA" ) )
647 meType = EXC_SBTYPE_EUROTOOL;
648 maSupbTabList.push_back( new XclImpSupbookTab( maXclUrl ) );
650 else if( nSBTabCnt )
652 meType = EXC_SBTYPE_EXTERN;
654 //assuming all empty strings with just len header of 0
655 const size_t nMinRecordSize = sizeof(sal_Int16);
656 const size_t nMaxRecords = rStrm.GetRecLeft() / nMinRecordSize;
657 if (nSBTabCnt > nMaxRecords)
659 SAL_WARN("sc", "Parsing error: " << nMaxRecords <<
660 " max possible entries, but " << nSBTabCnt << " claimed, truncating");
661 nSBTabCnt = nMaxRecords;
664 for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab )
666 OUString aTabName( rStrm.ReadUniString() );
667 maSupbTabList.push_back( new XclImpSupbookTab( aTabName ) );
670 else
672 meType = EXC_SBTYPE_SPECIAL;
673 // create dummy list entry
674 maSupbTabList.push_back( new XclImpSupbookTab( maXclUrl ) );
678 void XclImpSupbook::ReadXct( XclImpStream& rStrm )
680 rStrm.Ignore( 2 );
681 mnSBTab = rStrm.ReaduInt16();
684 void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
686 if (mnSBTab >= maSupbTabList.size())
687 return;
688 XclImpSupbookTab& rSbTab = maSupbTabList[mnSBTab];
689 sal_uInt8 nXclColLast, nXclColFirst;
690 sal_uInt16 nXclRow;
691 nXclColLast = rStrm.ReaduInt8();
692 nXclColFirst = rStrm.ReaduInt8();
693 nXclRow = rStrm.ReaduInt16();
695 for( sal_uInt8 nXclCol = nXclColFirst; (nXclCol <= nXclColLast) && (rStrm.GetRecLeft() > 1); ++nXclCol )
696 rSbTab.ReadCrn( rStrm, XclAddress( nXclCol, nXclRow ) );
699 void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
701 maExtNameList.push_back( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) );
704 const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
706 if (nXclIndex == 0)
708 SAL_WARN("sc", "XclImpSupbook::GetExternName - index must be >0");
709 return NULL;
711 if (meType == EXC_SBTYPE_SELF || nXclIndex > maExtNameList.size())
712 return NULL;
713 return &maExtNameList[nXclIndex-1];
716 bool XclImpSupbook::GetLinkData( OUString& rApplic, OUString& rTopic ) const
718 return (meType == EXC_SBTYPE_SPECIAL) && XclImpUrlHelper::DecodeLink( rApplic, rTopic, maXclUrl );
721 const OUString& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
723 OSL_ENSURE( nXclNameIdx > 0, "XclImpSupbook::GetMacroName - index must be >0" );
724 const XclImpName* pName = (meType == EXC_SBTYPE_SELF) ? GetNameManager().GetName( nXclNameIdx ) : 0;
725 return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_OUSTRING;
728 const OUString& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const
730 if (nXtiTab >= maSupbTabList.size())
731 return EMPTY_OUSTRING;
732 return maSupbTabList[nXtiTab].GetTabName();
735 sal_uInt16 XclImpSupbook::GetTabCount() const
737 return ulimit_cast<sal_uInt16>(maSupbTabList.size());
740 void XclImpSupbook::LoadCachedValues()
742 if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell())
743 return;
745 OUString aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
747 ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
748 sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
750 for (XclImpSupbookTabList::iterator itTab = maSupbTabList.begin(); itTab != maSupbTabList.end(); ++itTab)
752 const OUString& rTabName = itTab->GetTabName();
753 ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
754 itTab->LoadCachedValues(pCacheTable);
755 pCacheTable->setWholeTableCached();
759 svl::SharedStringPool& XclImpSupbook::GetSharedStringPool()
761 return GetDoc().GetSharedStringPool();
764 // Import link manager ========================================================
766 XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot& rRoot ) :
767 XclImpRoot( rRoot )
771 void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
773 sal_uInt16 nXtiCount;
774 nXtiCount = rStrm.ReaduInt16();
775 OSL_ENSURE( static_cast< sal_Size >( nXtiCount * 6 ) == rStrm.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" );
776 nXtiCount = static_cast< sal_uInt16 >( ::std::min< sal_Size >( nXtiCount, rStrm.GetRecLeft() / 6 ) );
778 /* #i104057# A weird external XLS generator writes multiple EXTERNSHEET
779 records instead of only one as expected. Surprisingly, Excel seems to
780 insert the entries of the second record before the entries of the first
781 record. */
782 XclImpXtiVector aNewEntries( nXtiCount );
783 for( XclImpXtiVector::iterator aIt = aNewEntries.begin(), aEnd = aNewEntries.end(); rStrm.IsValid() && (aIt != aEnd); ++aIt )
784 rStrm >> *aIt;
785 maXtiList.insert( maXtiList.begin(), aNewEntries.begin(), aNewEntries.end() );
787 LoadCachedValues();
790 void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
792 maSupbookList.push_back( new XclImpSupbook( rStrm ) );
795 void XclImpLinkManagerImpl::ReadXct( XclImpStream& rStrm )
797 if( !maSupbookList.empty() )
798 maSupbookList.back().ReadXct( rStrm );
801 void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
803 if( !maSupbookList.empty() )
804 maSupbookList.back().ReadCrn( rStrm );
807 void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
809 if( !maSupbookList.empty() )
810 maSupbookList.back().ReadExternname( rStrm, pFormulaConv );
813 bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
815 const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
816 return pSupbook && (pSupbook->GetType() == EXC_SBTYPE_SELF);
819 bool XclImpLinkManagerImpl::GetScTabRange(
820 SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
822 if( const XclImpXti* pXti = GetXti( nXtiIndex ) )
824 if (!maSupbookList.empty() && (pXti->mnSupbook < maSupbookList.size()) )
826 rnFirstScTab = pXti->mnSBTabFirst;
827 rnLastScTab = pXti->mnSBTabLast;
828 return true;
831 return false;
834 const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
836 const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
837 return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
840 const OUString* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
842 const XclImpSupbook* p = GetSupbook( nXtiIndex );
843 if (!p)
844 return NULL;
845 return &p->GetXclUrl();
848 const OUString& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
850 const XclImpSupbook* p = GetSupbook(nXti);
851 return p ? p->GetTabName(nXtiTab) : EMPTY_OUSTRING;
854 bool XclImpLinkManagerImpl::GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const
856 const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
857 return pSupbook && pSupbook->GetLinkData( rApplic, rTopic );
860 const OUString& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
862 const XclImpSupbook* pSupbook = GetSupbook( nExtSheet );
863 return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_OUSTRING;
866 const XclImpXti* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex ) const
868 return (nXtiIndex < maXtiList.size()) ? &maXtiList[ nXtiIndex ] : 0;
871 const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex ) const
873 if ( maSupbookList.empty() )
874 return NULL;
875 const XclImpXti* pXti = GetXti( nXtiIndex );
876 if (!pXti || pXti->mnSupbook >= maSupbookList.size())
877 return NULL;
878 return &(maSupbookList.at( pXti->mnSupbook ));
881 void XclImpLinkManagerImpl::LoadCachedValues()
883 // Read all CRN records which can be accessed via XclImpSupbook, and store
884 // the cached values to the external reference manager.
885 for (XclImpSupbookList::iterator itSupbook = maSupbookList.begin(); itSupbook != maSupbookList.end(); ++itSupbook)
886 itSupbook->LoadCachedValues();
889 XclImpLinkManager::XclImpLinkManager( const XclImpRoot& rRoot ) :
890 XclImpRoot( rRoot ),
891 mxImpl( new XclImpLinkManagerImpl( rRoot ) )
895 XclImpLinkManager::~XclImpLinkManager()
899 void XclImpLinkManager::ReadExternsheet( XclImpStream& rStrm )
901 mxImpl->ReadExternsheet( rStrm );
904 void XclImpLinkManager::ReadSupbook( XclImpStream& rStrm )
906 mxImpl->ReadSupbook( rStrm );
909 void XclImpLinkManager::ReadXct( XclImpStream& rStrm )
911 mxImpl->ReadXct( rStrm );
914 void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
916 mxImpl->ReadCrn( rStrm );
919 void XclImpLinkManager::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv )
921 mxImpl->ReadExternname( rStrm, pFormulaConv );
924 bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
926 return mxImpl->IsSelfRef( nXtiIndex );
929 bool XclImpLinkManager::GetScTabRange(
930 SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const
932 return mxImpl->GetScTabRange( rnFirstScTab, rnLastScTab, nXtiIndex );
935 const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const
937 return mxImpl->GetExternName( nXtiIndex, nExtName );
940 const OUString* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const
942 return mxImpl->GetSupbookUrl(nXtiIndex);
945 const OUString& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const
947 return mxImpl->GetSupbookTabName(nXti, nXtiTab);
950 bool XclImpLinkManager::GetLinkData( OUString& rApplic, OUString& rTopic, sal_uInt16 nXtiIndex ) const
952 return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
955 const OUString& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const
957 return mxImpl->GetMacroName( nExtSheet, nExtName );
960 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */