diff options
Diffstat (limited to 'sc/source/filter/excel/xilink.cxx')
-rw-r--r-- | sc/source/filter/excel/xilink.cxx | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx new file mode 100644 index 000000000000..dc2234570ea6 --- /dev/null +++ b/sc/source/filter/excel/xilink.cxx @@ -0,0 +1,807 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "xilink.hxx" +#include "document.hxx" +#include "cell.hxx" +#include "scextopt.hxx" +#include "tablink.hxx" +#include "xistream.hxx" +#include "xihelper.hxx" +#include "xiname.hxx" +#include "excform.hxx" +#include "tokenarray.hxx" +#include "externalrefmgr.hxx" + +#include <vector> + +using ::std::vector; + +// ============================================================================ +// *** Helper classes *** +// ============================================================================ + +// Cached external cells ====================================================== + +/** Contains the address and value of an external referenced cell. */ +class XclImpCrn : public XclImpCachedValue +{ +public: + /** Reads a cached value and stores it with its cell address. */ + explicit XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ); + + const XclAddress& GetAddress() const; + +private: + XclAddress maXclPos; /// Excel position of the cached cell. +}; + +// Sheet in an external document ============================================== + +/** Contains the name and sheet index of one sheet in an external document. */ +class XclImpSupbookTab +{ +public: + /** Stores the sheet name and marks the sheet index as invalid. + The sheet index is set while creating the Calc sheet with CreateTable(). */ + explicit XclImpSupbookTab( const String& rTabName ); + ~XclImpSupbookTab(); + + inline const String& GetTabName() const { return maTabName; } + + /** Reads a CRN record (external referenced cell) at the specified address. */ + void ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos ); + + void LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable); + +private: + typedef ScfDelList< XclImpCrn > XclImpCrnList; + + XclImpCrnList maCrnList; /// List of CRN records (cached cell values). + String maTabName; /// Name of the external sheet. + SCTAB mnScTab; /// New sheet index in Calc document. +}; + +// External document (SUPBOOK) ================================================ + +/** This class represents an external linked document (record SUPBOOK). + @descr Contains a list of all referenced sheets in the document. */ +class XclImpSupbook : protected XclImpRoot +{ +public: + /** Reads the SUPBOOK record from stream. */ + explicit XclImpSupbook( XclImpStream& rStrm ); + + /** Reads an XCT record (count of following CRNs and current sheet). */ + void ReadXct( XclImpStream& rStrm ); + /** Reads a CRN record (external referenced cell). */ + void ReadCrn( XclImpStream& rStrm ); + /** Reads an EXTERNNAME record. */ + void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL ); + + /** Returns the SUPBOOK record type. */ + inline XclSupbookType GetType() const { return meType; } + + /** Returns the URL of the external document. */ + inline const String& GetXclUrl() const { return maXclUrl; } + + /** Returns the external name specified by an index from the Excel document (one-based). */ + const XclImpExtName* GetExternName( sal_uInt16 nXclIndex ) const; + /** Tries to decode the URL to OLE or DDE link components. + @descr For DDE links: Decodes to application name and topic. + For OLE object links: Decodes to class name and document URL. + @return true = decoding was successful, returned strings are valid (not empty). */ + bool GetLinkData( String& rApplic, String& rDoc ) const; + /** Returns the specified macro name (1-based) or an empty string on error. */ + const String& GetMacroName( sal_uInt16 nXclNameIdx ) const; + + const String& GetTabName( sal_uInt16 nXtiTab ) const; + + sal_uInt16 GetTabCount() const; + + void LoadCachedValues(); + +private: + typedef ScfDelList< XclImpSupbookTab > XclImpSupbookTabList; + typedef ScfDelList< XclImpExtName > XclImpExtNameList; + + XclImpSupbookTabList maSupbTabList; /// All sheet names of the document. + XclImpExtNameList maExtNameList; /// All external names of the document. + String maXclUrl; /// URL of the external document (Excel mode). + String maFilterName; /// Detected filer name. + String maFilterOpt; /// Detected filer options. + XclSupbookType meType; /// Type of the supbook record. + sal_uInt16 mnSBTab; /// Current Excel sheet index from SUPBOOK for XCT/CRN records. +}; + +// Import link manager ======================================================== + +/** Contains the SUPBOOK index and sheet indexes of an external link. + @descr It is possible to enter a formula like =SUM(Sheet1:Sheet3!A1), + therefore here occurs a sheet range. */ +struct XclImpXti +{ + sal_uInt16 mnSupbook; /// Index to SUPBOOK record. + sal_uInt16 mnSBTabFirst; /// Index to the first sheet of the range in the SUPBOOK. + sal_uInt16 mnSBTabLast; /// Index to the last sheet of the range in the SUPBOOK. + inline explicit XclImpXti() : mnSupbook( SAL_MAX_UINT16 ), mnSBTabFirst( SAL_MAX_UINT16 ), mnSBTabLast( SAL_MAX_UINT16 ) {} +}; + +inline XclImpStream& operator>>( XclImpStream& rStrm, XclImpXti& rXti ) +{ + return rStrm >> rXti.mnSupbook >> rXti.mnSBTabFirst >> rXti.mnSBTabLast; +} + +// ---------------------------------------------------------------------------- + +/** Implementation of the link manager. */ +class XclImpLinkManagerImpl : protected XclImpRoot +{ +public: + explicit XclImpLinkManagerImpl( const XclImpRoot& rRoot ); + + /** Reads the EXTERNSHEET record. */ + void ReadExternsheet( XclImpStream& rStrm ); + /** Reads a SUPBOOK record. */ + void ReadSupbook( XclImpStream& rStrm ); + /** Reads an XCT record and appends it to the current SUPBOOK. */ + void ReadXct( XclImpStream& rStrm ); + /** Reads a CRN record and appends it to the current SUPBOOK. */ + void ReadCrn( XclImpStream& rStrm ); + /** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */ + void ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv = NULL ); + + /** Returns true, if the specified XTI entry contains an internal reference. */ + bool IsSelfRef( sal_uInt16 nXtiIndex ) const; + /** Returns the Calc sheet index range of the specified XTI entry. + @return true = XTI data found, returned sheet index range is valid. */ + bool GetScTabRange( + SCTAB& rnFirstScTab, SCTAB& rnLastScTab, + sal_uInt16 nXtiIndex ) const; + /** Returns the specified external name or 0 on error. */ + const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const; + + /** Returns the absolute file URL of a supporting workbook specified by + the index. */ + const String* GetSupbookUrl( sal_uInt16 nXtiIndex ) const; + + const String& GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const; + + /** Tries to decode the URL of the specified XTI entry to OLE or DDE link components. + @descr For DDE links: Decodes to application name and topic. + For OLE object links: Decodes to class name and document URL. + @return true = decoding was successful, returned strings are valid (not empty). */ + bool GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const; + /** Returns the specified macro name or an empty string on error. */ + const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const; + +private: + /** Returns the specified XTI (link entry from BIFF8 EXTERNSHEET record). */ + const XclImpXti* GetXti( sal_uInt16 nXtiIndex ) const; + /** Returns the specified SUPBOOK (external document). */ + const XclImpSupbook* GetSupbook( sal_uInt16 nXtiIndex ) const; +//UNUSED2009-05 /** Returns the SUPBOOK (external workbook) specified by its URL. */ +//UNUSED2009-05 const XclImpSupbook* GetSupbook( const String& rUrl ) const; + + void LoadCachedValues(); + +//UNUSED2009-05 /** Finds the largest range of sheet indexes in a SUPBOOK after a start sheet index. +//UNUSED2009-05 @param rnSBTabFirst (out-param) The first sheet index of the range in SUPBOOK is returned here. +//UNUSED2009-05 @param rnSBTabLast (out-param) The last sheet index of the range in SUPBOOK is returned here (inclusive). +//UNUSED2009-05 @param nSupbook The list index of the SUPBOOK. +//UNUSED2009-05 @param nSBTabStart The first allowed sheet index. Sheet ranges with an earlier start index are ignored. +//UNUSED2009-05 @return true = the return values are valid; false = nothing found. */ +//UNUSED2009-05 bool FindNextTabRange( +//UNUSED2009-05 sal_uInt16& rnSBTabFirst, sal_uInt16& rnSBTabLast, +//UNUSED2009-05 sal_uInt16 nSupbook, sal_uInt16 nSBTabStart ) const; + +private: + typedef ::std::vector< XclImpXti > XclImpXtiVector; + typedef ScfDelList< XclImpSupbook > XclImpSupbookList; + + XclImpXtiVector maXtiList; /// List of all XTI structures. + XclImpSupbookList maSupbookList; /// List of external documents. + bool mbCreated; /// true = Calc sheets already created. +}; + +// ============================================================================ +// *** Implementation *** +// ============================================================================ + +// Excel sheet indexes ======================================================== + +// original Excel sheet names ------------------------------------------------- + +void XclImpTabInfo::AppendXclTabName( const String& rXclTabName, SCTAB nScTab ) +{ + maTabNames[ rXclTabName ] = nScTab; +} + +void XclImpTabInfo::InsertScTab( SCTAB nScTab ) +{ + for( XclTabNameMap::iterator aIt = maTabNames.begin(), aEnd = maTabNames.end(); aIt != aEnd; ++aIt ) + if( aIt->second >= nScTab ) + ++aIt->second; +} + +SCTAB XclImpTabInfo::GetScTabFromXclName( const String& rXclTabName ) const +{ + XclTabNameMap::const_iterator aIt = maTabNames.find( rXclTabName ); + return (aIt != maTabNames.end()) ? aIt->second : SCTAB_INVALID; +} + +// record creation order - TABID record --------------------------------------- + +void XclImpTabInfo::ReadTabid( XclImpStream& rStrm ) +{ + DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 ); + if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 ) + { + rStrm.EnableDecryption(); + sal_Size nReadCount = rStrm.GetRecLeft() / 2; + DBG_ASSERT( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" ); + maTabIdVec.clear(); + maTabIdVec.reserve( nReadCount ); + for( sal_Size nIndex = 0; rStrm.IsValid() && (nIndex < nReadCount); ++nIndex ) + // #93471# zero index is not allowed in BIFF8, but it seems that it occurs in real life + maTabIdVec.push_back( rStrm.ReaduInt16() ); + } +} + +sal_uInt16 XclImpTabInfo::GetCurrentIndex( sal_uInt16 nCreatedId, sal_uInt16 nMaxTabId ) const +{ + sal_uInt16 nReturn = 0; + for( ScfUInt16Vec::const_iterator aIt = maTabIdVec.begin(), aEnd = maTabIdVec.end(); aIt != aEnd; ++aIt ) + { + sal_uInt16 nValue = *aIt; + if( nValue == nCreatedId ) + return nReturn; + if( nValue <= nMaxTabId ) + ++nReturn; + } + return 0; +} + +// External names ============================================================= + +XclImpExtName::XclImpExtName( const XclImpSupbook& rSupbook, XclImpStream& rStrm, XclSupbookType eSubType, ExcelToSc* pFormulaConv ) +{ + sal_uInt16 nFlags; + sal_uInt8 nLen; + + rStrm >> nFlags >> mnStorageId >> nLen ; + maName = rStrm.ReadUniString( nLen ); + if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) ) + { + if( eSubType == EXC_SBTYPE_ADDIN ) + { + meType = xlExtAddIn; + maName = rStrm.GetRoot().GetScAddInName( maName ); + } + else if ( (eSubType == EXC_SBTYPE_EUROTOOL) && + maName.EqualsIgnoreCaseAscii( "EUROCONVERT" ) ) + meType = xlExtEuroConvert; + else + { + meType = xlExtName; + ScfTools::ConvertToScDefinedName( maName ); + } + } + else + { + meType = ::get_flagvalue( nFlags, EXC_EXTN_OLE, xlExtOLE, xlExtDDE ); + } + + if( (meType == xlExtDDE) && (rStrm.GetRecLeft() > 1) ) + mxDdeMatrix.reset( new XclImpCachedMatrix( rStrm ) ); + + if (meType == xlExtName) + { + // TODO: For now, only global external names are supported. In future + // we should extend this to supporting per-sheet external names. + if (mnStorageId == 0) + { + if (pFormulaConv) + { + const ScTokenArray* pArray = NULL; + sal_uInt16 nFmlaLen; + rStrm >> nFmlaLen; + vector<String> aTabNames; + sal_uInt16 nCount = rSupbook.GetTabCount(); + aTabNames.reserve(nCount); + for (sal_uInt16 i = 0; i < nCount; ++i) + aTabNames.push_back(rSupbook.GetTabName(i)); + + pFormulaConv->ConvertExternName(pArray, rStrm, nFmlaLen, rSupbook.GetXclUrl(), aTabNames); + if (pArray) + mxArray.reset(pArray->Clone()); + } + } + } +} + +XclImpExtName::~XclImpExtName() +{ +} + +void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, const String& rTopic ) const +{ + ScMatrixRef xResults; + if( mxDdeMatrix.get() ) + xResults = mxDdeMatrix->CreateScMatrix(); + rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults ); +} + +void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const +{ + if (!mxArray.get()) + return; + + ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager(); + pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray); +} + +bool XclImpExtName::HasFormulaTokens() const +{ + return (mxArray.get() != NULL); +} + +// Cached external cells ====================================================== + +XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) : + XclImpCachedValue( rStrm ), + maXclPos( rXclPos ) +{ +} + +const XclAddress& XclImpCrn::GetAddress() const +{ + return maXclPos; +} + +// Sheet in an external document ============================================== + +XclImpSupbookTab::XclImpSupbookTab( const String& rTabName ) : + maTabName( rTabName ), + mnScTab( SCTAB_INVALID ) +{ +} + +XclImpSupbookTab::~XclImpSupbookTab() +{ +} + +void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) +{ + maCrnList.Append( new XclImpCrn( rStrm, rXclPos ) ); +} + +void XclImpSupbookTab::LoadCachedValues(ScExternalRefCache::TableTypeRef pCacheTable) +{ + if (maCrnList.Empty()) + return; + + for (XclImpCrn* p = maCrnList.First(); p; p = maCrnList.Next()) + { + const XclAddress& rAddr = p->GetAddress(); + switch (p->GetType()) + { + case EXC_CACHEDVAL_BOOL: + { + bool b = p->GetBool(); + ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(b ? 1.0 : 0.0)); + pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken); + } + break; + case EXC_CACHEDVAL_DOUBLE: + { + double f = p->GetValue(); + ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(f)); + pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken); + } + break; + case EXC_CACHEDVAL_ERROR: + { + double fError = XclTools::ErrorToDouble( p->GetXclError() ); + ScExternalRefCache::TokenRef pToken(new formula::FormulaDoubleToken(fError)); + pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken); + } + break; + case EXC_CACHEDVAL_STRING: + { + const String& rStr = p->GetString(); + ScExternalRefCache::TokenRef pToken(new formula::FormulaStringToken(rStr)); + pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken); + } + break; + default: + ; + } + } +} + +// External document (SUPBOOK) ================================================ + +XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) : + XclImpRoot( rStrm.GetRoot() ), + meType( EXC_SBTYPE_UNKNOWN ), + mnSBTab( EXC_TAB_DELETED ) +{ + sal_uInt16 nSBTabCnt; + rStrm >> nSBTabCnt; + + if( rStrm.GetRecLeft() == 2 ) + { + switch( rStrm.ReaduInt16() ) + { + case EXC_SUPB_SELF: meType = EXC_SBTYPE_SELF; break; + case EXC_SUPB_ADDIN: meType = EXC_SBTYPE_ADDIN; break; + default: DBG_ERRORFILE( "XclImpSupbook::XclImpSupbook - unknown special SUPBOOK type" ); + } + return; + } + + String aEncUrl( rStrm.ReadUniString() ); + bool bSelf = false; + XclImpUrlHelper::DecodeUrl( maXclUrl, bSelf, GetRoot(), aEncUrl ); + + if( maXclUrl.EqualsIgnoreCaseAscii( "\010EUROTOOL.XLA" ) ) + { + meType = EXC_SBTYPE_EUROTOOL; + maSupbTabList.Append( new XclImpSupbookTab( maXclUrl ) ); + } + else if( nSBTabCnt ) + { + meType = EXC_SBTYPE_EXTERN; + for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab ) + { + String aTabName( rStrm.ReadUniString() ); + maSupbTabList.Append( new XclImpSupbookTab( aTabName ) ); + } + } + else + { + meType = EXC_SBTYPE_SPECIAL; + // create dummy list entry + maSupbTabList.Append( new XclImpSupbookTab( maXclUrl ) ); + } +} + +void XclImpSupbook::ReadXct( XclImpStream& rStrm ) +{ + rStrm.Ignore( 2 ); + rStrm >> mnSBTab; +} + +void XclImpSupbook::ReadCrn( XclImpStream& rStrm ) +{ + if( XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( mnSBTab ) ) + { + sal_uInt8 nXclColLast, nXclColFirst; + sal_uInt16 nXclRow; + rStrm >> nXclColLast >> nXclColFirst >> nXclRow; + + for( sal_uInt8 nXclCol = nXclColFirst; (nXclCol <= nXclColLast) && (rStrm.GetRecLeft() > 1); ++nXclCol ) + pSBTab->ReadCrn( rStrm, XclAddress( nXclCol, nXclRow ) ); + } +} + +void XclImpSupbook::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv ) +{ + maExtNameList.Append( new XclImpExtName( *this, rStrm, meType, pFormulaConv ) ); +} + +const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const +{ + DBG_ASSERT( nXclIndex > 0, "XclImpSupbook::GetExternName - index must be >0" ); + return (meType == EXC_SBTYPE_SELF) ? 0 : maExtNameList.GetObject( nXclIndex - 1 ); +} + +bool XclImpSupbook::GetLinkData( String& rApplic, String& rTopic ) const +{ + return (meType == EXC_SBTYPE_SPECIAL) && XclImpUrlHelper::DecodeLink( rApplic, rTopic, maXclUrl ); +} + +const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const +{ + DBG_ASSERT( nXclNameIdx > 0, "XclImpSupbook::GetMacroName - index must be >0" ); + const XclImpName* pName = (meType == EXC_SBTYPE_SELF) ? GetNameManager().GetName( nXclNameIdx ) : 0; + return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_STRING; +} + +const String& XclImpSupbook::GetTabName( sal_uInt16 nXtiTab ) const +{ + if (maSupbTabList.Empty()) + return EMPTY_STRING; + + sal_uInt16 i = 0; + for (XclImpSupbookTab* p = maSupbTabList.First(); p; p = maSupbTabList.Next(), ++i) + { + if (i == nXtiTab) + return p->GetTabName(); + } + + return EMPTY_STRING; +} + +sal_uInt16 XclImpSupbook::GetTabCount() const +{ + return ulimit_cast<sal_uInt16>(maSupbTabList.Count()); +} + +void XclImpSupbook::LoadCachedValues() +{ + if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0 || !GetDocShell()) + return; + + String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) ); + + ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager(); + sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl); + + sal_uInt16 nCount = static_cast< sal_uInt16 >( maSupbTabList.Count() ); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + XclImpSupbookTab* pTab = maSupbTabList.GetObject(i); + if (!pTab) + return; + + const String& rTabName = pTab->GetTabName(); + ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true); + pTab->LoadCachedValues(pCacheTable); + pCacheTable->setWholeTableCached(); + } +} + +// Import link manager ======================================================== + +XclImpLinkManagerImpl::XclImpLinkManagerImpl( const XclImpRoot& rRoot ) : + XclImpRoot( rRoot ), + mbCreated( false ) +{ +} + +void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm ) +{ + sal_uInt16 nXtiCount; + rStrm >> nXtiCount; + DBG_ASSERT( static_cast< sal_Size >( nXtiCount * 6 ) == rStrm.GetRecLeft(), "XclImpLinkManagerImpl::ReadExternsheet - invalid count" ); + nXtiCount = static_cast< sal_uInt16 >( ::std::min< sal_Size >( nXtiCount, rStrm.GetRecLeft() / 6 ) ); + + /* #i104057# A weird external XLS generator writes multiple EXTERNSHEET + records instead of only one as expected. Surprisingly, Excel seems to + insert the entries of the second record before the entries of the first + record. */ + XclImpXtiVector aNewEntries( nXtiCount ); + for( XclImpXtiVector::iterator aIt = aNewEntries.begin(), aEnd = aNewEntries.end(); rStrm.IsValid() && (aIt != aEnd); ++aIt ) + rStrm >> *aIt; + maXtiList.insert( maXtiList.begin(), aNewEntries.begin(), aNewEntries.end() ); + + LoadCachedValues(); +} + +void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm ) +{ + maSupbookList.Append( new XclImpSupbook( rStrm ) ); +} + +void XclImpLinkManagerImpl::ReadXct( XclImpStream& rStrm ) +{ + if( XclImpSupbook* pSupbook = maSupbookList.Last() ) + pSupbook->ReadXct( rStrm ); +} + +void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm ) +{ + if( XclImpSupbook* pSupbook = maSupbookList.Last() ) + pSupbook->ReadCrn( rStrm ); +} + +void XclImpLinkManagerImpl::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv ) +{ + if( XclImpSupbook* pSupbook = maSupbookList.Last() ) + pSupbook->ReadExternname( rStrm, pFormulaConv ); +} + +bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const +{ + const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex ); + return pSupbook && (pSupbook->GetType() == EXC_SBTYPE_SELF); +} + +bool XclImpLinkManagerImpl::GetScTabRange( + SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const +{ + if( const XclImpXti* pXti = GetXti( nXtiIndex ) ) + { + if (maSupbookList.GetObject(pXti->mnSupbook)) + { + rnFirstScTab = pXti->mnSBTabFirst; + rnLastScTab = pXti->mnSBTabLast; + return true; + } + } + return false; +} + +const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const +{ + const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex ); + return pSupbook ? pSupbook->GetExternName( nExtName ) : 0; +} + +const String* XclImpLinkManagerImpl::GetSupbookUrl( sal_uInt16 nXtiIndex ) const +{ + const XclImpSupbook* p = GetSupbook( nXtiIndex ); + if (!p) + return NULL; + return &p->GetXclUrl(); +} + +const String& XclImpLinkManagerImpl::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const +{ + const XclImpSupbook* p = GetSupbook(nXti); + return p ? p->GetTabName(nXtiTab) : EMPTY_STRING; +} + +bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const +{ + const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex ); + return pSupbook && pSupbook->GetLinkData( rApplic, rTopic ); +} + +const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const +{ + const XclImpSupbook* pSupbook = GetSupbook( nExtSheet ); + return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_STRING; +} + +const XclImpXti* XclImpLinkManagerImpl::GetXti( sal_uInt16 nXtiIndex ) const +{ + return (nXtiIndex < maXtiList.size()) ? &maXtiList[ nXtiIndex ] : 0; +} + +const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt16 nXtiIndex ) const +{ + const XclImpXti* pXti = GetXti( nXtiIndex ); + return pXti ? maSupbookList.GetObject( pXti->mnSupbook ) : 0; +} + +//UNUSED2009-05 const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) const +//UNUSED2009-05 { +//UNUSED2009-05 for( const XclImpSupbook* pSupbook = maSupbookList.First(); pSupbook; pSupbook = maSupbookList.Next() ) +//UNUSED2009-05 if( pSupbook->GetXclUrl() == rUrl ) +//UNUSED2009-05 return pSupbook; +//UNUSED2009-05 return 0; +//UNUSED2009-05 } + +void XclImpLinkManagerImpl::LoadCachedValues() +{ + // Read all CRN records which can be accessed via XclImpSupbook, and store + // the cached values to the external reference manager. + + sal_uInt32 nCount = maSupbookList.Count(); + for (sal_uInt16 nSupbook = 0; nSupbook < nCount; ++nSupbook) + { + XclImpSupbook* pSupbook = maSupbookList.GetObject(nSupbook); + pSupbook->LoadCachedValues(); + } +} + +//UNUSED2009-05 bool XclImpLinkManagerImpl::FindNextTabRange( +//UNUSED2009-05 sal_uInt16& rnSBTabFirst, sal_uInt16& rnSBTabLast, +//UNUSED2009-05 sal_uInt16 nSupbook, sal_uInt16 nSBTabStart ) const +//UNUSED2009-05 { +//UNUSED2009-05 rnSBTabFirst = rnSBTabLast = EXC_NOTAB; +//UNUSED2009-05 for( const XclImpXti* pXti = maXtiList.First(); pXti; pXti = maXtiList.Next() ) +//UNUSED2009-05 { +//UNUSED2009-05 if( (nSupbook == pXti->mnSupbook) && (nSBTabStart <= pXti->mnSBTabLast) && (pXti->mnSBTabFirst < rnSBTabFirst) ) +//UNUSED2009-05 { +//UNUSED2009-05 rnSBTabFirst = ::std::max( nSBTabStart, pXti->mnSBTabFirst ); +//UNUSED2009-05 rnSBTabLast = pXti->mnSBTabLast; +//UNUSED2009-05 } +//UNUSED2009-05 } +//UNUSED2009-05 return rnSBTabFirst != EXC_NOTAB; +//UNUSED2009-05 } + +// ============================================================================ + +XclImpLinkManager::XclImpLinkManager( const XclImpRoot& rRoot ) : + XclImpRoot( rRoot ), + mxImpl( new XclImpLinkManagerImpl( rRoot ) ) +{ +} + +XclImpLinkManager::~XclImpLinkManager() +{ +} + +void XclImpLinkManager::ReadExternsheet( XclImpStream& rStrm ) +{ + mxImpl->ReadExternsheet( rStrm ); +} + +void XclImpLinkManager::ReadSupbook( XclImpStream& rStrm ) +{ + mxImpl->ReadSupbook( rStrm ); +} + +void XclImpLinkManager::ReadXct( XclImpStream& rStrm ) +{ + mxImpl->ReadXct( rStrm ); +} + +void XclImpLinkManager::ReadCrn( XclImpStream& rStrm ) +{ + mxImpl->ReadCrn( rStrm ); +} + +void XclImpLinkManager::ReadExternname( XclImpStream& rStrm, ExcelToSc* pFormulaConv ) +{ + mxImpl->ReadExternname( rStrm, pFormulaConv ); +} + +bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const +{ + return mxImpl->IsSelfRef( nXtiIndex ); +} + +bool XclImpLinkManager::GetScTabRange( + SCTAB& rnFirstScTab, SCTAB& rnLastScTab, sal_uInt16 nXtiIndex ) const +{ + return mxImpl->GetScTabRange( rnFirstScTab, rnLastScTab, nXtiIndex ); +} + +const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const +{ + return mxImpl->GetExternName( nXtiIndex, nExtName ); +} + +const String* XclImpLinkManager::GetSupbookUrl( sal_uInt16 nXtiIndex ) const +{ + return mxImpl->GetSupbookUrl(nXtiIndex); +} + +const String& XclImpLinkManager::GetSupbookTabName( sal_uInt16 nXti, sal_uInt16 nXtiTab ) const +{ + return mxImpl->GetSupbookTabName(nXti, nXtiTab); +} + +bool XclImpLinkManager::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const +{ + return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex ); +} + +const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const +{ + return mxImpl->GetMacroName( nExtSheet, nExtName ); +} + +// ============================================================================ + |