| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "oox/xls/externallinkbuffer.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 <rtl/strbuf.hxx> |
| #include "oox/core/filterbase.hxx" |
| #include "oox/helper/attributelist.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" |
| |
| namespace oox { |
| namespace xls { |
| |
| // ============================================================================ |
| |
| using namespace ::com::sun::star::sheet; |
| using namespace ::com::sun::star::table; |
| using namespace ::com::sun::star::uno; |
| |
| using ::oox::core::Relation; |
| using ::oox::core::Relations; |
| using ::rtl::OString; |
| using ::rtl::OStringBuffer; |
| using ::rtl::OStringToOUString; |
| using ::rtl::OUString; |
| |
| // ============================================================================ |
| |
| namespace { |
| |
| const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK = 0; |
| const sal_uInt16 BIFF12_EXTERNALBOOK_DDE = 1; |
| const sal_uInt16 BIFF12_EXTERNALBOOK_OLE = 2; |
| |
| const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC = 0x0002; |
| const sal_uInt16 BIFF12_EXTNAME_PREFERPIC = 0x0004; |
| const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME = 0x0008; |
| const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT = 0x0010; |
| const sal_uInt16 BIFF12_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( SequenceInputStream& rStrm ) |
| { |
| rStrm >> maModel.maName; |
| OSL_ENSURE( maModel.maName.getLength() > 0, "ExternalName::importExternalName - empty name" ); |
| } |
| |
| void ExternalName::importExternalNameFlags( SequenceInputStream& rStrm ) |
| { |
| sal_uInt16 nFlags; |
| sal_Int32 nSheetId; |
| rStrm >> nFlags >> nSheetId; |
| // index into sheet list of EXTSHEETNAMES (one-based in BIFF12) |
| maModel.mnSheet = nSheetId - 1; |
| // no flag for built-in names, as in OOXML... |
| maExtNameModel.mbNotify = getFlag( nFlags, BIFF12_EXTNAME_AUTOMATIC ); |
| maExtNameModel.mbPreferPic = getFlag( nFlags, BIFF12_EXTNAME_PREFERPIC ); |
| maExtNameModel.mbStdDocName = getFlag( nFlags, BIFF12_EXTNAME_STDDOCNAME ); |
| maExtNameModel.mbOleObj = getFlag( nFlags, BIFF12_EXTNAME_OLEOBJECT ); |
| maExtNameModel.mbIconified = getFlag( nFlags, BIFF12_EXTNAME_ICONIFIED ); |
| OSL_ENSURE( (mrParentLink.getLinkType() == LINKTYPE_OLE) == maExtNameModel.mbOleObj, |
| "ExternalName::importExternalNameFlags - wrong OLE flag in external name" ); |
| } |
| |
| void ExternalName::importDdeItemValues( SequenceInputStream& rStrm ) |
| { |
| sal_Int32 nRows, nCols; |
| rStrm >> nRows >> nCols; |
| setResultSize( nCols, nRows ); |
| } |
| |
| void ExternalName::importDdeItemBool( SequenceInputStream& rStrm ) |
| { |
| appendResultValue< double >( (rStrm.readuInt8() == 0) ? 0.0 : 1.0 ); |
| } |
| |
| void ExternalName::importDdeItemDouble( SequenceInputStream& rStrm ) |
| { |
| appendResultValue( rStrm.readDouble() ); |
| } |
| |
| void ExternalName::importDdeItemError( SequenceInputStream& rStrm ) |
| { |
| appendResultValue( BiffHelper::calcDoubleFromError( rStrm.readuInt8() ) ); |
| } |
| |
| void ExternalName::importDdeItemString( SequenceInputStream& rStrm ) |
| { |
| appendResultValue( BiffHelper::readString( rStrm ) ); |
| } |
| |
| 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() ) |
| { |
| ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm ); |
| extractReference( aTokens ); |
| } |
| break; |
| |
| case LINKTYPE_EXTERNAL: |
| // cell references to other documents are stored in hidden external names |
| if( bHiddenRef ) |
| { |
| ApiTokenSequence aTokens = importBiffFormula( 0, rStrm ); |
| extractExternalReference( aTokens ); |
| } |
| 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_OOXML: |
| // OOXML/BIFF12: 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 |
| { |
| PropertySet aDocProps( getDocument() ); |
| Reference< XDDELinks > xDdeLinks( aDocProps.getAnyProperty( PROP_DDELinks ), UNO_QUERY_THROW ); |
| mxDdeLink = xDdeLinks->addDDELink( mrParentLink.getClassName(), mrParentLink.getTargetUrl(), maModel.maName, ::com::sun::star::sheet::DDELinkMode_DEFAULT ); |
| mbDdeLinkCreated = true; // ignore if setting results fails |
| if( !maResults.empty() ) |
| { |
| Reference< XDDELinkResults > xResults( mxDdeLink, UNO_QUERY_THROW ); |
| xResults->setResults( ContainerHelper::matrixToSequenceSequence( maResults ) ); |
| } |
| } |
| 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( SequenceInputStream& rStrm ) |
| { |
| rStrm >> maRelId; |
| } |
| |
| void ExternalLink::importExternalSelf( SequenceInputStream& ) |
| { |
| meLinkType = LINKTYPE_SELF; |
| } |
| |
| void ExternalLink::importExternalSame( SequenceInputStream& ) |
| { |
| meLinkType = LINKTYPE_SAME; |
| } |
| |
| void ExternalLink::importExternalAddin( SequenceInputStream& ) |
| { |
| meLinkType = LINKTYPE_UNKNOWN; |
| } |
| |
| void ExternalLink::importExternalBook( const Relations& rRelations, SequenceInputStream& rStrm ) |
| { |
| switch( rStrm.readuInt16() ) |
| { |
| case BIFF12_EXTERNALBOOK_BOOK: |
| parseExternalReference( rRelations, BiffHelper::readString( rStrm ) ); |
| break; |
| case BIFF12_EXTERNALBOOK_DDE: |
| { |
| OUString aDdeService, aDdeTopic; |
| rStrm >> aDdeService >> aDdeTopic; |
| setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE ); |
| } |
| break; |
| case BIFF12_EXTERNALBOOK_OLE: |
| { |
| OUString aTargetUrl = rRelations.getExternalTargetFromRelId( BiffHelper::readString( rStrm ) ); |
| OUString aProgId = BiffHelper::readString( rStrm ); |
| setDdeOleTargetUrl( aProgId, aTargetUrl, LINKTYPE_OLE ); |
| } |
| break; |
| default: |
| OSL_ENSURE( false, "ExternalLink::importExternalBook - unknown link type" ); |
| } |
| } |
| |
| void ExternalLink::importExtSheetNames( SequenceInputStream& 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( BiffHelper::readString( rStrm ) ); |
| } |
| |
| ExternalNameRef ExternalLink::importExternalName( SequenceInputStream& 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_SELF: |
| case LINKTYPE_SAME: |
| case LINKTYPE_INTERNAL: |
| aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SELF; |
| break; |
| case LINKTYPE_EXTERNAL: |
| aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::DOCUMENT; |
| aLinkInfo.Data <<= maTargetUrl; |
| break; |
| case LINKTYPE_LIBRARY: |
| // parser will return library function names in OPCODE_BAD string tokens |
| aLinkInfo.Type = ::com::sun::star::sheet::ExternalLinkType::SPECIAL; |
| 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_OOXML) || (getBiff() == BIFF8), |
| "ExternalLink::getCalcSheetIndex - invalid sheet index" ); |
| return ContainerHelper::getVectorElement( 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_OOXML) || (getBiff() == BIFF8), |
| "ExternalLink::getSheetCacheIndex - invalid sheet index" ); |
| return ContainerHelper::getVectorElement( 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_OOXML: |
| // BIFF12: 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_RELATION_TYPE( "externalLinkPath" ) |
| #define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATION_TYPE( "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 ) try |
| { |
| PropertySet aDocProps( getDocument() ); |
| Reference< XExternalDocLinks > xDocLinks( aDocProps.getAnyProperty( PROP_ExternalDocLinks ), UNO_QUERY_THROW ); |
| mxDocLink = xDocLinks->addDocLink( maTargetUrl ); |
| } |
| catch( Exception& ) |
| { |
| } |
| } |
| |
| 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::readBiff12Data( SequenceInputStream& 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 ), |
| mxSelfRef( new ExternalLink( rHelper ) ), |
| mbUseRefSheets( false ) |
| { |
| mxSelfRef->setSelfLinkType(); |
| } |
| |
| ExternalLinkRef ExternalLinkBuffer::importExternalReference( const AttributeList& rAttribs ) |
| { |
| ExternalLinkRef xExtLink = createExternalLink(); |
| xExtLink->importExternalReference( rAttribs ); |
| maExtLinks.push_back( xExtLink ); |
| return xExtLink; |
| } |
| |
| ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm ) |
| { |
| mbUseRefSheets = true; |
| ExternalLinkRef xExtLink = createExternalLink(); |
| xExtLink->importExternalRef( rStrm ); |
| maExtLinks.push_back( xExtLink ); |
| return xExtLink; |
| } |
| |
| void ExternalLinkBuffer::importExternalSelf( SequenceInputStream& rStrm ) |
| { |
| mbUseRefSheets = true; |
| createExternalLink()->importExternalSelf( rStrm ); |
| } |
| |
| void ExternalLinkBuffer::importExternalSame( SequenceInputStream& rStrm ) |
| { |
| mbUseRefSheets = true; |
| createExternalLink()->importExternalSame( rStrm ); |
| } |
| |
| void ExternalLinkBuffer::importExternalAddin( SequenceInputStream& rStrm ) |
| { |
| mbUseRefSheets = true; |
| createExternalLink()->importExternalAddin( rStrm ); |
| } |
| |
| void ExternalLinkBuffer::importExternalSheets( SequenceInputStream& 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.readBiff12Data( 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(), aEnd = aIt + nRefCount; !rStrm.isEof() && (aIt != aEnd); ++aIt ) |
| aIt->readBiff8Data( rStrm ); |
| } |
| |
| Sequence< ExternalLinkInfo > ExternalLinkBuffer::getLinkInfos() const |
| { |
| ::std::vector< ExternalLinkInfo > aLinkInfos; |
| // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings |
| OSL_ENSURE( getFilterType() == FILTER_OOXML, "ExternalLinkBuffer::getLinkInfos - unexpected file format" ); |
| // add entry for implicit index 0 (self reference to this document) |
| aLinkInfos.push_back( mxSelfRef->getLinkInfo() ); |
| 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, bool bUseRefSheets ) const |
| { |
| ExternalLinkRef xExtLink; |
| switch( getFilterType() ) |
| { |
| case FILTER_OOXML: |
| // OOXML: 0 = this document, otherwise one-based index into link list |
| if( !bUseRefSheets || !mbUseRefSheets ) |
| xExtLink = (nRefId == 0) ? mxSelfRef : maLinks.get( nRefId - 1 ); |
| // BIFF12: 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_OOXML) && 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 |