summaryrefslogtreecommitdiff
path: root/oox/source/xls/externallinkbuffer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/xls/externallinkbuffer.cxx')
-rw-r--r--oox/source/xls/externallinkbuffer.cxx1143
1 files changed, 1143 insertions, 0 deletions
diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx
new file mode 100644
index 000000000000..04fcd2f84648
--- /dev/null
+++ b/oox/source/xls/externallinkbuffer.cxx
@@ -0,0 +1,1143 @@
+/*************************************************************************
+ *
+ * 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.
+ *
+ ************************************************************************/
+
+#include "oox/xls/externallinkbuffer.hxx"
+#include <rtl/strbuf.hxx>
+#include <com/sun/star/sheet/ComplexReference.hpp>
+#include <com/sun/star/sheet/DDELinkInfo.hpp>
+#include <com/sun/star/sheet/ExternalLinkType.hpp>
+#include <com/sun/star/sheet/ExternalReference.hpp>
+#include <com/sun/star/sheet/ReferenceFlags.hpp>
+#include <com/sun/star/sheet/SingleReference.hpp>
+#include <com/sun/star/sheet/XDDELinks.hpp>
+#include <com/sun/star/sheet/XDDELink.hpp>
+#include <com/sun/star/sheet/XDDELinkResults.hpp>
+#include <com/sun/star/sheet/XExternalDocLink.hpp>
+#include <com/sun/star/sheet/XExternalDocLinks.hpp>
+#include "oox/helper/attributelist.hxx"
+#include "oox/core/filterbase.hxx"
+#include "oox/xls/addressconverter.hxx"
+#include "oox/xls/biffinputstream.hxx"
+#include "oox/xls/excelhandlers.hxx"
+#include "oox/xls/formulaparser.hxx"
+#include "oox/xls/worksheetbuffer.hxx"
+
+using ::rtl::OString;
+using ::rtl::OStringBuffer;
+using ::rtl::OStringToOUString;
+using ::rtl::OUString;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::table::CellAddress;
+using ::com::sun::star::sheet::ComplexReference;
+using ::com::sun::star::sheet::DDEItemInfo;
+using ::com::sun::star::sheet::DDELinkInfo;
+using ::com::sun::star::sheet::ExternalLinkInfo;
+using ::com::sun::star::sheet::ExternalReference;
+using ::com::sun::star::sheet::SingleReference;
+using ::com::sun::star::sheet::XDDELinks;
+using ::com::sun::star::sheet::XDDELinkResults;
+using ::com::sun::star::sheet::XExternalDocLinks;
+using ::com::sun::star::sheet::XExternalSheetCache;
+using ::oox::core::Relation;
+using ::oox::core::Relations;
+
+namespace oox {
+namespace xls {
+
+// ============================================================================
+
+namespace {
+
+const sal_uInt16 OOBIN_EXTERNALBOOK_BOOK = 0;
+const sal_uInt16 OOBIN_EXTERNALBOOK_DDE = 1;
+const sal_uInt16 OOBIN_EXTERNALBOOK_OLE = 2;
+
+const sal_uInt16 OOBIN_EXTNAME_AUTOMATIC = 0x0002;
+const sal_uInt16 OOBIN_EXTNAME_PREFERPIC = 0x0004;
+const sal_uInt16 OOBIN_EXTNAME_STDDOCNAME = 0x0008;
+const sal_uInt16 OOBIN_EXTNAME_OLEOBJECT = 0x0010;
+const sal_uInt16 OOBIN_EXTNAME_ICONIFIED = 0x0020;
+
+const sal_uInt16 BIFF_EXTNAME_BUILTIN = 0x0001;
+const sal_uInt16 BIFF_EXTNAME_AUTOMATIC = 0x0002;
+const sal_uInt16 BIFF_EXTNAME_PREFERPIC = 0x0004;
+const sal_uInt16 BIFF_EXTNAME_STDDOCNAME = 0x0008;
+const sal_uInt16 BIFF_EXTNAME_OLEOBJECT = 0x0010;
+const sal_uInt16 BIFF_EXTNAME_ICONIFIED = 0x8000;
+
+} // namespace
+
+// ============================================================================
+
+ExternalNameModel::ExternalNameModel() :
+ mbBuiltIn( false ),
+ mbNotify( false ),
+ mbPreferPic( false ),
+ mbStdDocName( false ),
+ mbOleObj( false ),
+ mbIconified( false )
+{
+}
+
+// ============================================================================
+
+ExternalName::ExternalName( const ExternalLink& rParentLink ) :
+ DefinedNameBase( rParentLink ),
+ mrParentLink( rParentLink ),
+ mnStorageId( 0 ),
+ mbDdeLinkCreated( false )
+{
+}
+
+void ExternalName::importDefinedName( const AttributeList& rAttribs )
+{
+ maModel.maName = rAttribs.getXString( XML_name, OUString() );
+ OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDefinedName - empty name" );
+ // zero-based index into sheet list of externalBook
+ maModel.mnSheet = rAttribs.getInteger( XML_sheetId, -1 );
+}
+
+void ExternalName::importDdeItem( const AttributeList& rAttribs )
+{
+ maModel.maName = rAttribs.getXString( XML_name, OUString() );
+ OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importDdeItem - empty name" );
+ maExtNameModel.mbOleObj = false;
+ maExtNameModel.mbStdDocName = rAttribs.getBool( XML_ole, false );
+ maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
+ maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
+}
+
+void ExternalName::importValues( const AttributeList& rAttribs )
+{
+ setResultSize( rAttribs.getInteger( XML_cols, 1 ), rAttribs.getInteger( XML_rows, 1 ) );
+}
+
+void ExternalName::importOleItem( const AttributeList& rAttribs )
+{
+ maModel.maName = rAttribs.getXString( XML_name, OUString() );
+ OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importOleItem - empty name" );
+ maExtNameModel.mbOleObj = true;
+ maExtNameModel.mbNotify = rAttribs.getBool( XML_advise, false );
+ maExtNameModel.mbPreferPic = rAttribs.getBool( XML_preferPic, false );
+ maExtNameModel.mbIconified = rAttribs.getBool( XML_icon, false );
+}
+
+void ExternalName::importExternalName( RecordInputStream& rStrm )
+{
+ rStrm >> maModel.maName;
+ OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" );
+}
+
+void ExternalName::importExternalNameFlags( RecordInputStream& rStrm )
+{
+ sal_uInt16 nFlags;
+ sal_Int32 nSheetId;
+ rStrm >> nFlags >> nSheetId;
+ // index into sheet list of EXTSHEETNAMES (one-based in OOBIN)
+ maModel.mnSheet = nSheetId - 1;
+ // no flag for built-in names, as in OOX...
+ maExtNameModel.mbNotify = getFlag( nFlags, OOBIN_EXTNAME_AUTOMATIC );
+ maExtNameModel.mbPreferPic = getFlag( nFlags, OOBIN_EXTNAME_PREFERPIC );
+ maExtNameModel.mbStdDocName = getFlag( nFlags, OOBIN_EXTNAME_STDDOCNAME );
+ maExtNameModel.mbOleObj = getFlag( nFlags, OOBIN_EXTNAME_OLEOBJECT );
+ maExtNameModel.mbIconified = getFlag( nFlags, OOBIN_EXTNAME_ICONIFIED );
+ OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj,
+ "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
+}
+
+void ExternalName::importDdeItemValues( RecordInputStream& rStrm )
+{
+ sal_Int32 nRows, nCols;
+ rStrm >> nRows >> nCols;
+ setResultSize( nCols, nRows );
+}
+
+void ExternalName::importDdeItemBool( RecordInputStream& rStrm )
+{
+ appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
+}
+
+void ExternalName::importDdeItemDouble( RecordInputStream& rStrm )
+{
+ appendResultValue( rStrm.readDouble() );
+}
+
+void ExternalName::importDdeItemError( RecordInputStream& rStrm )
+{
+ appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
+}
+
+void ExternalName::importDdeItemString( RecordInputStream& rStrm )
+{
+ appendResultValue( rStrm.readString() );
+}
+
+void ExternalName::importExternalName( BiffInputStream& rStrm )
+{
+ sal_uInt16 nFlags = 0;
+ if( getBiff() >= BIFF3 )
+ {
+ rStrm >> nFlags;
+ maExtNameModel.mbBuiltIn = getFlag( nFlags, BIFF_EXTNAME_BUILTIN );
+ maExtNameModel.mbNotify = getFlag( nFlags, BIFF_EXTNAME_AUTOMATIC );
+ maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF_EXTNAME_PREFERPIC );
+
+ // BIFF5-BIFF8: sheet index for sheet-local names, OLE settings
+ if( getBiff() >= BIFF5 )
+ {
+ maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF_EXTNAME_STDDOCNAME );
+ maExtNameModel.mbOleObj = getFlag( nFlags, BIFF_EXTNAME_OLEOBJECT );
+ maExtNameModel.mbIconified = getFlag( nFlags, BIFF_EXTNAME_ICONIFIED );
+
+ if( maExtNameModel.mbOleObj )
+ {
+ rStrm >> mnStorageId;
+ }
+ else
+ {
+ /* Import the reference ID for names that are sheet-local in
+ the external document. This index will be resolved later to
+ the index of the external sheet cache which is able to
+ provide the name of the sheet related to this defined name.
+ - BIFF5: one-based index to EXTERNSHEET record containing
+ the document and sheet name
+ - BIFF8: one-based index into EXTERNALBOOK sheet name list
+ The value zero means this external name is a global name.
+ */
+ rStrm.skip( 2 );
+ maModel.mnSheet = rStrm.readuInt16();
+ }
+ }
+ }
+
+ maModel.maName = (getBiff() == BIFF8) ?
+ rStrm.readUniStringBody( rStrm.readuInt8() ) :
+ rStrm.readByteStringUC( false, getTextEncoding() );
+ OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" );
+
+ // load cell references that are stored in hidden external names (seen in BIFF3-BIFF4)
+ bool bHiddenRef = (getBiff() <= BIFF4) && (maModel.maName.getLength() > 1) && (maModel.maName[ 0 ] == '\x01') && (rStrm.getRemaining() > 2);
+ switch( mrParentLink.getLinkType() )
+ {
+ case LINKTYPE_INTERNAL:
+ // cell references to other internal sheets are stored in hidden external names
+ if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() )
+ {
+ TokensFormulaContext aContext( true, true );
+ importBiffFormula( aContext, mrParentLink.getCalcSheetIndex(), rStrm );
+ extractReference( aContext.getTokens() );
+ }
+ break;
+
+ case LINKTYPE_EXTERNAL:
+ // cell references to other documents are stored in hidden external names
+ if( bHiddenRef )
+ {
+ TokensFormulaContext aContext( true, true );
+ importBiffFormula( aContext, 0, rStrm );
+ extractExternalReference( aContext.getTokens() );
+ }
+ break;
+
+ case LINKTYPE_DDE:
+ case LINKTYPE_OLE:
+ case LINKTYPE_MAYBE_DDE_OLE:
+ // DDE/OLE link results
+ if( rStrm.getRemaining() > 3 )
+ {
+ bool bBiff8 = getBiff() == BIFF8;
+ sal_Int32 nCols = rStrm.readuInt8();
+ sal_Int32 nRows = rStrm.readuInt16();
+ if( bBiff8 ) { ++nCols; ++nRows; } else if( nCols == 0 ) nCols = 256;
+ setResultSize( nCols, nRows );
+
+ bool bLoop = true;
+ while( bLoop && !rStrm.isEof() && (maCurrIt != maResults.end()) )
+ {
+ switch( rStrm.readuInt8() )
+ {
+ case BIFF_DATATYPE_EMPTY:
+ appendResultValue( OUString() );
+ rStrm.skip( 8 );
+ break;
+ case BIFF_DATATYPE_DOUBLE:
+ appendResultValue( rStrm.readDouble() );
+ break;
+ case BIFF_DATATYPE_STRING:
+ appendResultValue( bBiff8 ? rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() ) );
+ break;
+ case BIFF_DATATYPE_BOOL:
+ appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 );
+ rStrm.skip( 7 );
+ break;
+ case BIFF_DATATYPE_ERROR:
+ appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) );
+ rStrm.skip( 7 );
+ break;
+ default:
+ bLoop = false;
+ }
+ }
+ OSL_ENSURE( bLoop && !rStrm.isEof() && (maCurrIt == maResults.end()),
+ "ExternalName::importExternalName - stream error in result set" );
+ }
+ break;
+
+ default:;
+ }
+}
+
+#if 0
+sal_Int32 ExternalName::getSheetCacheIndex() const
+{
+ OSL_ENSURE( mrParentLink.getLinkType() == LINKTYPE_DDE, "ExternalName::getSheetCacheIndex - unexpected link type" );
+ sal_Int32 nCacheIdx = -1;
+ switch( getFilterType() )
+ {
+ case FILTER_OOX:
+ // OOXML/OOBIN: zero-based index into sheet list, -1 means global name
+ if( maModel.mnSheet >= 0 )
+ nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
+ break;
+ case FILTER_BIFF:
+ switch( getBiff() )
+ {
+ case BIFF2:
+ case BIFF3:
+ case BIFF4:
+ break;
+ case BIFF5:
+ if( maModel.mnSheet > 0 )
+ if( const ExternalLink* pExtLink = getExternalLinks().getExternalLink( maModel.mnSheet ).get() )
+ if( pExtLink->getLinkType() == LINKTYPE_EXTERNAL )
+ nCacheIdx = pExtLink->getSheetIndex();
+ break;
+ case BIFF8:
+ if( maModel.mnSheet > 0 )
+ nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
+ break;
+ case BIFF_UNKNOWN:
+ break;
+ }
+ break;
+ case FILTER_UNKNOWN:
+ break;
+ }
+ return nCacheIdx;
+}
+#endif
+
+bool ExternalName::getDdeItemInfo( DDEItemInfo& orItemInfo ) const
+{
+ if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maModel.maName.getLength() > 0) )
+ {
+ orItemInfo.Item = maModel.maName;
+ orItemInfo.Results = ContainerHelper::matrixToSequenceSequence( maResults );
+ return true;
+ }
+ return false;
+}
+
+bool ExternalName::getDdeLinkData( OUString& orDdeServer, OUString& orDdeTopic, OUString& orDdeItem )
+{
+ if( (mrParentLink.getLinkType() == LINKTYPE_DDE) && (maModel.maName.getLength() > 0) )
+ {
+ // try to create a DDE link and to set the imported link results
+ if( !mbDdeLinkCreated ) try
+ {
+ Reference< XDDELinks > xDdeLinks( getDdeLinks(), UNO_QUERY_THROW );
+ mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT );
+ if( !maResults.empty() )
+ {
+ Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW );
+ xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) );
+ }
+ mbDdeLinkCreated = true;
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "ExternalName::getDdeLinkData - cannot create DDE link" );
+ }
+ // get link data from created DDE link
+ if( mxDdeLink.is() )
+ {
+ orDdeServer = mxDdeLink->getApplication();
+ orDdeTopic = mxDdeLink->getTopic();
+ orDdeItem = mxDdeLink->getItem();
+ return true;
+ }
+ }
+ return false;
+}
+
+// private --------------------------------------------------------------------
+
+namespace {
+
+void lclSetSheetCacheIndex( SingleReference& orApiRef, sal_Int32 nCacheIdx )
+{
+ using namespace ::com::sun::star::sheet::ReferenceFlags;
+ setFlag( orApiRef.Flags, SHEET_RELATIVE, false );
+ setFlag( orApiRef.Flags, SHEET_3D, true );
+ orApiRef.Sheet = nCacheIdx;
+}
+
+} // namespace
+
+void ExternalName::extractExternalReference( const ApiTokenSequence& rTokens )
+{
+ OSL_ENSURE( (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4), "ExternalName::setExternalReference - unexpected call" );
+ sal_Int32 nDocLinkIdx = mrParentLink.getDocumentLinkIndex();
+ sal_Int32 nCacheIdx = mrParentLink.getSheetCacheIndex();
+ if( (nDocLinkIdx >= 0) && (nCacheIdx >= 0) )
+ {
+ ExternalReference aExtApiRef;
+ aExtApiRef.Index = nDocLinkIdx;
+
+ Any aRefAny = getFormulaParser().extractReference( rTokens );
+ if( aRefAny.has< SingleReference >() )
+ {
+ SingleReference aApiRef;
+ aRefAny >>= aApiRef;
+ lclSetSheetCacheIndex( aApiRef, nCacheIdx );
+ aExtApiRef.Reference <<= aApiRef;
+ maRefAny <<= aExtApiRef;
+ }
+ else if( aRefAny.has< ComplexReference >() )
+ {
+ ComplexReference aApiRef;
+ aRefAny >>= aApiRef;
+ lclSetSheetCacheIndex( aApiRef.Reference1, nCacheIdx );
+ lclSetSheetCacheIndex( aApiRef.Reference2, nCacheIdx );
+ aExtApiRef.Reference <<= aApiRef;
+ maRefAny <<= aExtApiRef;
+ }
+ }
+}
+
+void ExternalName::setResultSize( sal_Int32 nColumns, sal_Int32 nRows )
+{
+ OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_DDE) || (mrParentLink.getLinkType() == LINKTYPE_OLE) ||
+ (mrParentLink.getLinkType() == LINKTYPE_MAYBE_DDE_OLE), "ExternalName::setResultSize - wrong link type" );
+ OSL_ENSURE( (nRows > 0) && (nColumns > 0), "ExternalName::setResultSize - invalid matrix size" );
+ const CellAddress& rMaxPos = getAddressConverter().getMaxApiAddress();
+ if( (0 < nRows) && (nRows <= rMaxPos.Row + 1) && (0 < nColumns) && (nColumns <= rMaxPos.Column + 1) )
+ maResults.resize( static_cast< size_t >( nColumns ), static_cast< size_t >( nRows ), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA ) ) );
+ else
+ maResults.clear();
+ maCurrIt = maResults.begin();
+}
+
+// ============================================================================
+
+void LinkSheetRange::setDeleted()
+{
+ meType = LINKSHEETRANGE_INTERNAL;
+ mnDocLink = mnFirst = mnLast = -1;
+}
+
+void LinkSheetRange::setSameSheet()
+{
+ meType = LINKSHEETRANGE_SAMESHEET;
+ mnDocLink = -1;
+ mnFirst = mnLast = 0;
+}
+
+void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
+{
+ meType = LINKSHEETRANGE_INTERNAL;
+ mnDocLink = -1;
+ mnFirst = ::std::min( nFirst, nLast );
+ mnLast = ::std::max( nFirst, nLast );
+}
+
+void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal_Int32 nLast )
+{
+ if( nDocLink < 0 )
+ {
+ setDeleted();
+ }
+ else
+ {
+ meType = LINKSHEETRANGE_EXTERNAL;
+ mnDocLink = nDocLink;
+ mnFirst = ::std::min( nFirst, nLast );
+ mnLast = ::std::max( nFirst, nLast );
+ }
+}
+
+// ============================================================================
+
+ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper ),
+ meLinkType( LINKTYPE_UNKNOWN ),
+ meFuncLibType( FUNCLIB_UNKNOWN )
+{
+}
+
+void ExternalLink::importExternalReference( const AttributeList& rAttribs )
+{
+ maRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
+}
+
+void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
+{
+ parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
+}
+
+void ExternalLink::importSheetName( const AttributeList& rAttribs )
+{
+ insertExternalSheet( rAttribs.getXString( XML_val, OUString() ) );
+}
+
+void ExternalLink::importDefinedName( const AttributeList& rAttribs )
+{
+ createExternalName()->importDefinedName( rAttribs );
+}
+
+void ExternalLink::importDdeLink( const AttributeList& rAttribs )
+{
+ OUString aDdeService = rAttribs.getXString( XML_ddeService, OUString() );
+ OUString aDdeTopic = rAttribs.getXString( XML_ddeTopic, OUString() );
+ setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
+}
+
+ExternalNameRef ExternalLink::importDdeItem( const AttributeList& rAttribs )
+{
+ ExternalNameRef xExtName = createExternalName();
+ xExtName->importDdeItem( rAttribs );
+ return xExtName;
+}
+
+void ExternalLink::importOleLink( const Relations& rRelations, const AttributeList& rAttribs )
+{
+ OUString aProgId = rAttribs.getXString( XML_progId, OUString() );
+ OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
+ setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
+}
+
+ExternalNameRef ExternalLink::importOleItem( const AttributeList& rAttribs )
+{
+ ExternalNameRef xExtName = createExternalName();
+ xExtName->importOleItem( rAttribs );
+ return xExtName;
+}
+
+void ExternalLink::importExternalRef( RecordInputStream& rStrm )
+{
+ rStrm >> maRelId;
+}
+
+void ExternalLink::importExternalSelf( RecordInputStream& )
+{
+ meLinkType = LINKTYPE_SELF;
+}
+
+void ExternalLink::importExternalSame( RecordInputStream& )
+{
+ meLinkType = LINKTYPE_SAME;
+}
+
+void ExternalLink::importExternalAddin( RecordInputStream& )
+{
+ meLinkType = LINKTYPE_UNKNOWN;
+}
+
+void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputStream& rStrm )
+{
+ switch( rStrm.readuInt16() )
+ {
+ case OOBIN_EXTERNALBOOK_BOOK:
+ parseExternalReference( rRelations, rStrm.readString() );
+ break;
+ case OOBIN_EXTERNALBOOK_DDE:
+ {
+ OUString aDdeService, aDdeTopic;
+ rStrm >> aDdeService >> aDdeTopic;
+ setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
+ }
+ break;
+ case OOBIN_EXTERNALBOOK_OLE:
+ {
+ OUString aTargetUrl = rRelations.getExternalTargetFromRelId( rStrm.readString() );
+ OUString aProgId = rStrm.readString();
+ setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE );
+ }
+ break;
+ default:
+ OSL_ENSURE( false, "ExternalLink::importExternalBook - unknown link type" );
+ }
+}
+
+void ExternalLink::importExtSheetNames( RecordInputStream& rStrm )
+{
+ // load external sheet names and create the sheet caches in the Calc document
+ OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
+ "ExternalLink::importExtSheetNames - invalid link type" );
+ if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries
+ for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
+ insertExternalSheet( rStrm.readString() );
+}
+
+ExternalNameRef ExternalLink::importExternalName( RecordInputStream& rStrm )
+{
+ ExternalNameRef xExtName = createExternalName();
+ xExtName->importExternalName( rStrm );
+ return xExtName;
+}
+
+void ExternalLink::importExternSheet( BiffInputStream& rStrm )
+{
+ OStringBuffer aTargetBuffer( rStrm.readByteString( false, true ) );
+ // references to own sheets have wrong string length field (off by 1)
+ if( (aTargetBuffer.getLength() > 0) && (aTargetBuffer[ 0 ] == 3) )
+ aTargetBuffer.append( static_cast< sal_Char >( rStrm.readuInt8() ) );
+ // parse the encoded URL
+ OUString aBiffTarget = OStringToOUString( aTargetBuffer.makeStringAndClear(), getTextEncoding() );
+ OUString aSheetName = parseBiffTargetUrl( aBiffTarget );
+ switch( meLinkType )
+ {
+ case LINKTYPE_INTERNAL:
+ maCalcSheets.push_back( getWorksheets().getCalcSheetIndex( aSheetName ) );
+ break;
+ case LINKTYPE_EXTERNAL:
+ insertExternalSheet( (aSheetName.getLength() > 0) ? aSheetName : WorksheetBuffer::getBaseFileName( maTargetUrl ) );
+ break;
+ default:;
+ }
+}
+
+void ExternalLink::importExternalBook( BiffInputStream& rStrm )
+{
+ OUString aTarget;
+ sal_uInt16 nSheetCount;
+ rStrm >> nSheetCount;
+ if( rStrm.getRemaining() == 2 )
+ {
+ if( rStrm.readuInt8() == 1 )
+ {
+ sal_Char cChar = static_cast< sal_Char >( rStrm.readuInt8() );
+ if( cChar != 0 )
+ aTarget = OStringToOUString( OString( cChar ), getTextEncoding() );
+ }
+ }
+ else if( rStrm.getRemaining() >= 3 )
+ {
+ // NUL characters may occur
+ aTarget = rStrm.readUniString( true );
+ }
+
+ // parse the encoded URL
+ OUString aDummySheetName = parseBiffTargetUrl( aTarget );
+ OSL_ENSURE( aDummySheetName.getLength() == 0, "ExternalLink::importExternalBook - sheet name in encoded URL" );
+ (void)aDummySheetName; // prevent compiler warning
+
+ // load external sheet names and create the sheet caches in the Calc document
+ if( meLinkType == LINKTYPE_EXTERNAL )
+ for( sal_uInt16 nSheet = 0; !rStrm.isEof() && (nSheet < nSheetCount); ++nSheet )
+ insertExternalSheet( rStrm.readUniString() );
+}
+
+void ExternalLink::importExternalName( BiffInputStream& rStrm )
+{
+ ExternalNameRef xExtName = createExternalName();
+ xExtName->importExternalName( rStrm );
+ switch( meLinkType )
+ {
+ case LINKTYPE_DDE:
+ OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in DDE link" );
+ break;
+ case LINKTYPE_OLE:
+ OSL_ENSURE( xExtName->isOleObject(), "ExternalLink::importExternalName - anything but OLE object in OLE link" );
+ break;
+ case LINKTYPE_MAYBE_DDE_OLE:
+ meLinkType = xExtName->isOleObject() ? LINKTYPE_OLE : LINKTYPE_DDE;
+ break;
+ default:
+ OSL_ENSURE( !xExtName->isOleObject(), "ExternalLink::importExternalName - OLE object in external name" );
+ }
+}
+
+ExternalLinkInfo ExternalLink::getLinkInfo() const
+{
+ ExternalLinkInfo aLinkInfo;
+ switch( meLinkType )
+ {
+ case LINKTYPE_EXTERNAL:
+ aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT;
+ aLinkInfo.Data <<= maTargetUrl;
+ break;
+ case LINKTYPE_DDE:
+ {
+ aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DDE;
+ DDELinkInfo aDdeLinkInfo;
+ aDdeLinkInfo.Service = maClassName;
+ aDdeLinkInfo.Topic = maTargetUrl;
+ ::std::vector< DDEItemInfo > aItemInfos;
+ DDEItemInfo aItemInfo;
+ for( ExternalNameVector::const_iterator aIt = maExtNames.begin(), aEnd = maExtNames.end(); aIt != aEnd; ++aIt )
+ if( (*aIt)->getDdeItemInfo( aItemInfo ) )
+ aItemInfos.push_back( aItemInfo );
+ aDdeLinkInfo.Items = ContainerHelper::vectorToSequence( aItemInfos );
+ aLinkInfo.Data <<= aDdeLinkInfo;
+ }
+ break;
+ default:
+ aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::UNKNOWN;
+ }
+ return aLinkInfo;
+}
+
+FunctionLibraryType ExternalLink::getFuncLibraryType() const
+{
+ return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
+}
+
+sal_Int16 ExternalLink::getCalcSheetIndex( sal_Int32 nTabId ) const
+{
+ OSL_ENSURE( meLinkType == LINKTYPE_INTERNAL, "ExternalLink::getCalcSheetIndex - invalid link type" );
+ OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOX) || (getBiff() == BIFF8),
+ "ExternalLink::getCalcSheetIndex - invalid sheet index" );
+ return ContainerHelper::getVectorElement< sal_Int16 >( maCalcSheets, nTabId, -1 );
+}
+
+sal_Int32 ExternalLink::getDocumentLinkIndex() const
+{
+ OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getDocumentLinkIndex - invalid link type" );
+ return mxDocLink.is() ? mxDocLink->getTokenIndex() : -1;
+}
+
+sal_Int32 ExternalLink::getSheetCacheIndex( sal_Int32 nTabId ) const
+{
+ OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::getSheetCacheIndex - invalid link type" );
+ OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOX) || (getBiff() == BIFF8),
+ "ExternalLink::getSheetCacheIndex - invalid sheet index" );
+ return ContainerHelper::getVectorElement< sal_Int32 >( maSheetCaches, nTabId, -1 );
+}
+
+Reference< XExternalSheetCache > ExternalLink::getSheetCache( sal_Int32 nTabId ) const
+{
+ sal_Int32 nCacheIdx = getSheetCacheIndex( nTabId );
+ if( mxDocLink.is() && (nCacheIdx >= 0) ) try
+ {
+ // existing mxDocLink implies that this is an external link
+ Reference< XExternalSheetCache > xSheetCache( mxDocLink->getByIndex( nCacheIdx ), UNO_QUERY_THROW );
+ return xSheetCache;
+ }
+ catch( Exception& )
+ {
+ }
+ return 0;
+}
+
+void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
+{
+ switch( meLinkType )
+ {
+ case LINKTYPE_SAME:
+ orSheetRange.setSameSheet();
+ break;
+
+ case LINKTYPE_SELF:
+ case LINKTYPE_INTERNAL:
+ orSheetRange.setRange( nTabId1, nTabId2 );
+ break;
+
+ case LINKTYPE_EXTERNAL:
+ {
+ sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
+ switch( getFilterType() )
+ {
+ case FILTER_OOX:
+ // OOBIN: passed indexes point into sheet list of EXTSHEETLIST
+ orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
+ break;
+ case FILTER_BIFF:
+ switch( getBiff() )
+ {
+ case BIFF2:
+ case BIFF3:
+ case BIFF4:
+ orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
+ break;
+ case BIFF5:
+ // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
+ if( const ExternalLink* pExtLink2 = getExternalLinks().getExternalLink( nTabId2 ).get() )
+ if( (pExtLink2->getLinkType() == LINKTYPE_EXTERNAL) && (maTargetUrl == pExtLink2->getTargetUrl()) )
+ orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex(), pExtLink2->getSheetCacheIndex() );
+ break;
+ case BIFF8:
+ // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
+ orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
+ break;
+ case BIFF_UNKNOWN: break;
+ }
+ break;
+ case FILTER_UNKNOWN: break;
+ }
+ }
+ break;
+
+ default:
+ // unsupported/unexpected link type: #REF! error
+ orSheetRange.setDeleted();
+ }
+}
+
+ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
+{
+ return maExtNames.get( nIndex );
+}
+
+// private --------------------------------------------------------------------
+
+#define OOX_TARGETTYPE_EXTLINK CREATE_OFFICEDOC_RELATIONSTYPE( "externalLinkPath" )
+#define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATIONSTYPE( "xlExternalLinkPath/xlLibrary" )
+
+void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
+{
+ meLinkType = LINKTYPE_UNKNOWN;
+ if( rTargetType == OOX_TARGETTYPE_EXTLINK )
+ {
+ maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
+ if( maTargetUrl.getLength() > 0 )
+ meLinkType = LINKTYPE_EXTERNAL;
+ }
+ else if( rTargetType == OOX_TARGETTYPE_LIBRARY )
+ {
+ meLinkType = LINKTYPE_LIBRARY;
+ meFuncLibType = getFormulaParser().getFuncLibTypeFromLibraryName( rTargetUrl );
+ }
+ OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
+
+ // create the external document link API object that will contain the sheet caches
+ if( meLinkType == LINKTYPE_EXTERNAL )
+ {
+ Reference< XExternalDocLinks > xDocLinks = getExternalDocLinks();
+ if( xDocLinks.is() )
+ mxDocLink = xDocLinks->addDocLink( maTargetUrl );
+ }
+}
+
+void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUString& rTargetUrl, ExternalLinkType eLinkType )
+{
+ maClassName = rClassName;
+ maTargetUrl = rTargetUrl;
+ meLinkType = ((maClassName.getLength() > 0) && (maTargetUrl.getLength() > 0)) ? eLinkType : LINKTYPE_UNKNOWN;
+ OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
+}
+
+void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
+{
+ if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
+ setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
+}
+
+OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl )
+{
+ meLinkType = LINKTYPE_UNKNOWN;
+
+ OUString aClassName, aTargetUrl, aSheetName;
+ switch( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) )
+ {
+ case BIFF_TARGETTYPE_URL:
+ if( aTargetUrl.getLength() == 0 )
+ {
+ meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF;
+ }
+ else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') )
+ {
+ if( getBiff() >= BIFF4 )
+ meLinkType = LINKTYPE_ANALYSIS;
+ }
+ else if( (aTargetUrl.getLength() > 1) || (aTargetUrl[ 0 ] != ' ') )
+ {
+ setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_EXTLINK );
+ }
+ break;
+
+ case BIFF_TARGETTYPE_SAMESHEET:
+ OSL_ENSURE( (aTargetUrl.getLength() == 0) && (aSheetName.getLength() == 0), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" );
+ meLinkType = LINKTYPE_SAME;
+ break;
+
+ case BIFF_TARGETTYPE_LIBRARY:
+ OSL_ENSURE( aSheetName.getLength() == 0, "ExternalLink::parseBiffTargetUrl - unexpected sheet name" );
+ setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_LIBRARY );
+ break;
+
+ case BIFF_TARGETTYPE_DDE_OLE:
+ setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE );
+ break;
+
+ case BIFF_TARGETTYPE_UNKNOWN:
+ break;
+ }
+ return aSheetName;
+}
+
+void ExternalLink::insertExternalSheet( const OUString& rSheetName )
+{
+ OSL_ENSURE( rSheetName.getLength() > 0, "ExternalLink::insertExternalSheet - empty sheet name" );
+ if( mxDocLink.is() )
+ {
+ Reference< XExternalSheetCache > xSheetCache = mxDocLink->addSheetCache( rSheetName, false );
+ sal_Int32 nCacheIdx = xSheetCache.is() ? xSheetCache->getTokenIndex() : -1;
+ maSheetCaches.push_back( nCacheIdx );
+ }
+}
+
+ExternalNameRef ExternalLink::createExternalName()
+{
+ ExternalNameRef xExtName( new ExternalName( *this ) );
+ maExtNames.push_back( xExtName );
+ return xExtName;
+}
+
+// ============================================================================
+
+RefSheetsModel::RefSheetsModel() :
+ mnExtRefId( -1 ),
+ mnTabId1( -1 ),
+ mnTabId2( -1 )
+{
+}
+
+void RefSheetsModel::readOobData( RecordInputStream& rStrm )
+{
+ rStrm >> mnExtRefId >> mnTabId1 >> mnTabId2;
+}
+
+void RefSheetsModel::readBiff8Data( BiffInputStream& rStrm )
+{
+ mnExtRefId = rStrm.readuInt16();
+ mnTabId1 = rStrm.readInt16();
+ mnTabId2 = rStrm.readInt16();
+}
+
+// ----------------------------------------------------------------------------
+
+ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper ),
+ mbUseRefSheets( false )
+{
+}
+
+ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs )
+{
+ ExternalLinkRef xExtLink = createExternalLink();
+ xExtLink->importExternalReference( rAttribs );
+ maExtLinks.push_back( xExtLink );
+ return xExtLink;
+}
+
+ExternalLinkRef ExternalLinkBuffer::importExternalRef( RecordInputStream& rStrm )
+{
+ mbUseRefSheets = true;
+ ExternalLinkRef xExtLink = createExternalLink();
+ xExtLink->importExternalRef( rStrm );
+ maExtLinks.push_back( xExtLink );
+ return xExtLink;
+}
+
+void ExternalLinkBuffer::importExternalSelf( RecordInputStream& rStrm )
+{
+ mbUseRefSheets = true;
+ createExternalLink()->importExternalSelf( rStrm );
+}
+
+void ExternalLinkBuffer::importExternalSame( RecordInputStream& rStrm )
+{
+ mbUseRefSheets = true;
+ createExternalLink()->importExternalSame( rStrm );
+}
+
+void ExternalLinkBuffer::importExternalAddin( RecordInputStream& rStrm )
+{
+ mbUseRefSheets = true;
+ createExternalLink()->importExternalAddin( rStrm );
+}
+
+void ExternalLinkBuffer::importExternalSheets( RecordInputStream& rStrm )
+{
+ OSL_ENSURE( mbUseRefSheets, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
+ mbUseRefSheets = true;
+ OSL_ENSURE( maRefSheets.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
+ maRefSheets.clear();
+ sal_Int32 nRefCount;
+ rStrm >> nRefCount;
+ size_t nMaxCount = getLimitedValue< size_t, sal_Int64 >( nRefCount, 0, rStrm.getRemaining() / 12 );
+ maRefSheets.reserve( nMaxCount );
+ for( size_t nRefId = 0; !rStrm.isEof() && (nRefId < nMaxCount); ++nRefId )
+ {
+ RefSheetsModel aRefSheets;
+ aRefSheets.readOobData( rStrm );
+ maRefSheets.push_back( aRefSheets );
+ }
+}
+
+ExternalLinkRef ExternalLinkBuffer::importExternSheet( BiffInputStream& rStrm )
+{
+ OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::importExternSheet - wrong BIFF version" );
+ ExternalLinkRef xExtLink = createExternalLink();
+ xExtLink->importExternSheet( rStrm );
+ return xExtLink;
+}
+
+ExternalLinkRef ExternalLinkBuffer::importExternalBook( BiffInputStream& rStrm )
+{
+ ExternalLinkRef xExtLink = createExternalLink();
+ xExtLink->importExternalBook( rStrm );
+ return xExtLink;
+}
+
+void ExternalLinkBuffer::importExternalName( BiffInputStream& rStrm )
+{
+ if( !maLinks.empty() )
+ maLinks.back()->importExternalName( rStrm );
+}
+
+void ExternalLinkBuffer::importExternSheet8( BiffInputStream& rStrm )
+{
+ OSL_ENSURE( getBiff() == BIFF8, "ExternalLinkBuffer::importExternSheet8 - wrong BIFF version" );
+
+ sal_uInt16 nRefCount;
+ rStrm >> nRefCount;
+ OSL_ENSURE( static_cast< sal_Int64 >( nRefCount * 6 ) == rStrm.getRemaining(), "ExternalLinkBuffer::importExternSheet8 - invalid count" );
+ nRefCount = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nRefCount, rStrm.getRemaining() / 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. */
+ maRefSheets.insert( maRefSheets.begin(), nRefCount, RefSheetsModel() );
+ for( RefSheetsModelVec::iterator aIt = maRefSheets.begin(); !rStrm.isEof() && (nRefCount > 0); --nRefCount )
+ aIt->readBiff8Data( rStrm );
+}
+
+Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const
+{
+ ::std::vector< ExternalLinkInfo > aLinkInfos;
+ // dummy entry for index 0
+ aLinkInfos.push_back( ExternalLinkInfo( ::com::sun::star::sheet::ExternalLinkType::UNKNOWN, Any() ) );
+ for( ExternalLinkVec::const_iterator aIt = maExtLinks.begin(), aEnd = maExtLinks.end(); aIt != aEnd; ++aIt )
+ aLinkInfos.push_back( (*aIt)->getLinkInfo() );
+ return ContainerHelper::vectorToSequence( aLinkInfos );
+}
+
+ExternalLinkRef ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId ) const
+{
+ ExternalLinkRef xExtLink;
+ switch( getFilterType() )
+ {
+ case FILTER_OOX:
+ // OOXML: one-based index
+ if( !mbUseRefSheets )
+ xExtLink = maLinks.get( nRefId - 1 );
+ // OOBIN: zero-based index into ref-sheets list
+ else if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
+ xExtLink = maLinks.get( pRefSheets->mnExtRefId );
+ break;
+ case FILTER_BIFF:
+ switch( getBiff() )
+ {
+ case BIFF2:
+ case BIFF3:
+ case BIFF4:
+ // one-based index to EXTERNSHEET records
+ xExtLink = maLinks.get( nRefId - 1 );
+ break;
+ case BIFF5:
+ if( nRefId < 0 )
+ {
+ // internal links in formula tokens have negative index
+ xExtLink = maLinks.get( -nRefId - 1 );
+ if( xExtLink.get() && !xExtLink->isInternalLink() )
+ xExtLink.reset();
+ }
+ else
+ {
+ // one-based index to EXTERNSHEET records
+ xExtLink = maLinks.get( nRefId - 1 );
+ }
+ break;
+ case BIFF8:
+ // zero-based index into REF list in EXTERNSHEET record
+ if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
+ xExtLink = maLinks.get( pRefSheets->mnExtRefId );
+ break;
+ case BIFF_UNKNOWN: break;
+ }
+ break;
+ case FILTER_UNKNOWN: break;
+ }
+ return xExtLink;
+}
+
+LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId, sal_Int16 nTabId1, sal_Int16 nTabId2 ) const
+{
+ OSL_ENSURE( getBiff() <= BIFF5, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
+ LinkSheetRange aSheetRange;
+ if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
+ pExtLink->getSheetRange( aSheetRange, nTabId1, nTabId2 );
+ return aSheetRange;
+}
+
+LinkSheetRange ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId ) const
+{
+ OSL_ENSURE( ((getFilterType() == FILTER_OOX) && mbUseRefSheets) || (getBiff() == BIFF8), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
+ LinkSheetRange aSheetRange;
+ if( const ExternalLink* pExtLink = getExternalLink( nRefId ).get() )
+ if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
+ pExtLink->getSheetRange( aSheetRange, pRefSheets->mnTabId1, pRefSheets->mnTabId2 );
+ return aSheetRange;
+}
+
+// private --------------------------------------------------------------------
+
+ExternalLinkRef ExternalLinkBuffer::createExternalLink()
+{
+ ExternalLinkRef xExtLink( new ExternalLink( *this ) );
+ maLinks.push_back( xExtLink );
+ return xExtLink;
+}
+
+const RefSheetsModel* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId ) const
+{
+ return ((0 <= nRefId) && (static_cast< size_t >( nRefId ) < maRefSheets.size())) ?
+ &maRefSheets[ static_cast< size_t >( nRefId ) ] : 0;
+}
+
+// ============================================================================
+
+} // namespace xls
+} // namespace oox
+