1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "externallinkbuffer.hxx"
22 #include <com/sun/star/sheet/ComplexReference.hpp>
23 #include <com/sun/star/sheet/DDELinkInfo.hpp>
24 #include <com/sun/star/sheet/ExternalLinkType.hpp>
25 #include <com/sun/star/sheet/ExternalReference.hpp>
26 #include <com/sun/star/sheet/ReferenceFlags.hpp>
27 #include <com/sun/star/sheet/SingleReference.hpp>
28 #include <com/sun/star/sheet/XDDELinks.hpp>
29 #include <com/sun/star/sheet/XDDELink.hpp>
30 #include <com/sun/star/sheet/XDDELinkResults.hpp>
31 #include <com/sun/star/sheet/XExternalDocLink.hpp>
32 #include <com/sun/star/sheet/XExternalDocLinks.hpp>
33 #include <osl/diagnose.h>
34 #include <rtl/strbuf.hxx>
35 #include <oox/core/filterbase.hxx>
36 #include <oox/helper/attributelist.hxx>
37 #include <oox/token/properties.hxx>
38 #include "addressconverter.hxx"
39 #include "biffinputstream.hxx"
40 #include "excelhandlers.hxx"
41 #include "formulaparser.hxx"
42 #include "worksheetbuffer.hxx"
47 using namespace ::com::sun::star::sheet
;
48 using namespace ::com::sun::star::table
;
49 using namespace ::com::sun::star::uno
;
51 using ::oox::core::Relation
;
52 using ::oox::core::Relations
;
56 const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK
= 0;
57 const sal_uInt16 BIFF12_EXTERNALBOOK_DDE
= 1;
58 const sal_uInt16 BIFF12_EXTERNALBOOK_OLE
= 2;
60 const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC
= 0x0002;
61 const sal_uInt16 BIFF12_EXTNAME_PREFERPIC
= 0x0004;
62 const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME
= 0x0008;
63 const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT
= 0x0010;
64 const sal_uInt16 BIFF12_EXTNAME_ICONIFIED
= 0x0020;
68 ExternalNameModel::ExternalNameModel() :
72 mbStdDocName( false ),
78 ExternalName::ExternalName( const ExternalLink
& rParentLink
) :
79 DefinedNameBase( rParentLink
),
80 mrParentLink( rParentLink
),
81 mbDdeLinkCreated( false )
85 void ExternalName::importDefinedName( const AttributeList
& rAttribs
)
87 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
88 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importDefinedName - empty name" );
89 // zero-based index into sheet list of externalBook
90 maModel
.mnSheet
= rAttribs
.getInteger( XML_sheetId
, -1 );
93 void ExternalName::importDdeItem( const AttributeList
& rAttribs
)
95 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
96 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importDdeItem - empty name" );
97 maExtNameModel
.mbOleObj
= false;
98 maExtNameModel
.mbStdDocName
= rAttribs
.getBool( XML_ole
, false );
99 maExtNameModel
.mbNotify
= rAttribs
.getBool( XML_advise
, false );
100 maExtNameModel
.mbPreferPic
= rAttribs
.getBool( XML_preferPic
, false );
103 void ExternalName::importValues( const AttributeList
& rAttribs
)
105 setResultSize( rAttribs
.getInteger( XML_cols
, 1 ), rAttribs
.getInteger( XML_rows
, 1 ) );
108 void ExternalName::importOleItem( const AttributeList
& rAttribs
)
110 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
111 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importOleItem - empty name" );
112 maExtNameModel
.mbOleObj
= true;
113 maExtNameModel
.mbNotify
= rAttribs
.getBool( XML_advise
, false );
114 maExtNameModel
.mbPreferPic
= rAttribs
.getBool( XML_preferPic
, false );
115 maExtNameModel
.mbIconified
= rAttribs
.getBool( XML_icon
, false );
118 void ExternalName::importExternalName( SequenceInputStream
& rStrm
)
120 rStrm
>> maModel
.maName
;
121 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importExternalName - empty name" );
124 void ExternalName::importExternalNameFlags( SequenceInputStream
& rStrm
)
128 nFlags
= rStrm
.readuInt16();
129 nSheetId
= rStrm
.readInt32();
130 // index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
131 maModel
.mnSheet
= nSheetId
- 1;
132 // no flag for built-in names, as in OOXML...
133 maExtNameModel
.mbNotify
= getFlag( nFlags
, BIFF12_EXTNAME_AUTOMATIC
);
134 maExtNameModel
.mbPreferPic
= getFlag( nFlags
, BIFF12_EXTNAME_PREFERPIC
);
135 maExtNameModel
.mbStdDocName
= getFlag( nFlags
, BIFF12_EXTNAME_STDDOCNAME
);
136 maExtNameModel
.mbOleObj
= getFlag( nFlags
, BIFF12_EXTNAME_OLEOBJECT
);
137 maExtNameModel
.mbIconified
= getFlag( nFlags
, BIFF12_EXTNAME_ICONIFIED
);
138 OSL_ENSURE( (mrParentLink
.getLinkType() == LINKTYPE_OLE
) == maExtNameModel
.mbOleObj
,
139 "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
142 void ExternalName::importDdeItemValues( SequenceInputStream
& rStrm
)
144 sal_Int32 nRows
, nCols
;
145 nRows
= rStrm
.readInt32();
146 nCols
= rStrm
.readInt32();
147 setResultSize( nCols
, nRows
);
150 void ExternalName::importDdeItemBool( SequenceInputStream
& rStrm
)
152 appendResultValue
< double >( (rStrm
.readuInt8() == 0) ? 0.0 : 1.0 );
155 void ExternalName::importDdeItemDouble( SequenceInputStream
& rStrm
)
157 appendResultValue( rStrm
.readDouble() );
160 void ExternalName::importDdeItemError( SequenceInputStream
& rStrm
)
162 appendResultValue( BiffHelper::calcDoubleFromError( rStrm
.readuInt8() ) );
165 void ExternalName::importDdeItemString( SequenceInputStream
& rStrm
)
167 appendResultValue( BiffHelper::readString( rStrm
) );
171 sal_Int32
ExternalName::getSheetCacheIndex() const
173 OSL_ENSURE( mrParentLink
.getLinkType() == LINKTYPE_DDE
, "ExternalName::getSheetCacheIndex - unexpected link type" );
174 sal_Int32 nCacheIdx
= -1;
175 switch( getFilterType() )
178 // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
179 if( maModel
.mnSheet
>= 0 )
180 nCacheIdx
= mrParentLink
.getSheetIndex( maModel
.mnSheet
);
190 if( maModel
.mnSheet
> 0 )
191 if( const ExternalLink
* pExtLink
= getExternalLinks().getExternalLink( maModel
.mnSheet
).get() )
192 if( pExtLink
->getLinkType() == LINKTYPE_EXTERNAL
)
193 nCacheIdx
= pExtLink
->getSheetIndex();
196 if( maModel
.mnSheet
> 0 )
197 nCacheIdx
= mrParentLink
.getSheetIndex( maModel
.mnSheet
- 1 );
210 bool ExternalName::getDdeItemInfo( DDEItemInfo
& orItemInfo
) const
212 if( (mrParentLink
.getLinkType() == LINKTYPE_DDE
) && !maModel
.maName
.isEmpty() )
214 orItemInfo
.Item
= maModel
.maName
;
215 orItemInfo
.Results
= ContainerHelper::matrixToSequenceSequence( maResults
);
221 bool ExternalName::getDdeLinkData( OUString
& orDdeServer
, OUString
& orDdeTopic
, OUString
& orDdeItem
)
223 if( (mrParentLink
.getLinkType() == LINKTYPE_DDE
) && !maModel
.maName
.isEmpty() )
225 // try to create a DDE link and to set the imported link results
226 if( !mbDdeLinkCreated
) try
228 PropertySet
aDocProps( getDocument() );
229 Reference
< XDDELinks
> xDdeLinks( aDocProps
.getAnyProperty( PROP_DDELinks
), UNO_QUERY_THROW
);
230 mxDdeLink
= xDdeLinks
->addDDELink( mrParentLink
.getClassName(), mrParentLink
.getTargetUrl(), maModel
.maName
, ::com::sun::star::sheet::DDELinkMode_DEFAULT
);
231 mbDdeLinkCreated
= true; // ignore if setting results fails
232 if( !maResults
.empty() )
234 Reference
< XDDELinkResults
> xResults( mxDdeLink
, UNO_QUERY_THROW
);
235 xResults
->setResults( ContainerHelper::matrixToSequenceSequence( maResults
) );
240 OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
242 // get link data from created DDE link
245 orDdeServer
= mxDdeLink
->getApplication();
246 orDdeTopic
= mxDdeLink
->getTopic();
247 orDdeItem
= mxDdeLink
->getItem();
254 // private --------------------------------------------------------------------
256 void ExternalName::setResultSize( sal_Int32 nColumns
, sal_Int32 nRows
)
258 OSL_ENSURE( (mrParentLink
.getLinkType() == LINKTYPE_DDE
) || (mrParentLink
.getLinkType() == LINKTYPE_OLE
) ||
259 (mrParentLink
.getLinkType() == LINKTYPE_MAYBE_DDE_OLE
), "ExternalName::setResultSize - wrong link type" );
260 OSL_ENSURE( (nRows
> 0) && (nColumns
> 0), "ExternalName::setResultSize - invalid matrix size" );
261 const CellAddress
& rMaxPos
= getAddressConverter().getMaxApiAddress();
262 if( (0 < nRows
) && (nRows
<= rMaxPos
.Row
+ 1) && (0 < nColumns
) && (nColumns
<= rMaxPos
.Column
+ 1) )
263 maResults
.resize( static_cast< size_t >( nColumns
), static_cast< size_t >( nRows
), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA
) ) );
266 maCurrIt
= maResults
.begin();
269 void LinkSheetRange::setDeleted()
271 meType
= LINKSHEETRANGE_INTERNAL
;
272 mnDocLink
= mnFirst
= mnLast
= -1;
275 void LinkSheetRange::setSameSheet()
277 meType
= LINKSHEETRANGE_SAMESHEET
;
279 mnFirst
= mnLast
= 0;
282 void LinkSheetRange::setRange( sal_Int32 nFirst
, sal_Int32 nLast
)
284 meType
= LINKSHEETRANGE_INTERNAL
;
286 mnFirst
= ::std::min( nFirst
, nLast
);
287 mnLast
= ::std::max( nFirst
, nLast
);
290 void LinkSheetRange::setExternalRange( sal_Int32 nDocLink
, sal_Int32 nFirst
, sal_Int32 nLast
)
298 meType
= LINKSHEETRANGE_EXTERNAL
;
299 mnDocLink
= nDocLink
;
300 mnFirst
= ::std::min( nFirst
, nLast
);
301 mnLast
= ::std::max( nFirst
, nLast
);
305 ExternalLink::ExternalLink( const WorkbookHelper
& rHelper
) :
306 WorkbookHelper( rHelper
),
307 meLinkType( LINKTYPE_UNKNOWN
),
308 meFuncLibType( FUNCLIB_UNKNOWN
)
312 void ExternalLink::importExternalReference( const AttributeList
& rAttribs
)
314 maRelId
= rAttribs
.getString( R_TOKEN( id
), OUString() );
317 void ExternalLink::importExternalBook( const Relations
& rRelations
, const AttributeList
& rAttribs
)
319 parseExternalReference( rRelations
, rAttribs
.getString( R_TOKEN( id
), OUString() ) );
322 void ExternalLink::importSheetName( const AttributeList
& rAttribs
)
324 insertExternalSheet( rAttribs
.getXString( XML_val
, OUString() ) );
327 void ExternalLink::importDefinedName( const AttributeList
& rAttribs
)
329 createExternalName()->importDefinedName( rAttribs
);
332 void ExternalLink::importDdeLink( const AttributeList
& rAttribs
)
334 OUString aDdeService
= rAttribs
.getXString( XML_ddeService
, OUString() );
335 OUString aDdeTopic
= rAttribs
.getXString( XML_ddeTopic
, OUString() );
336 setDdeOleTargetUrl( aDdeService
, aDdeTopic
, LINKTYPE_DDE
);
339 ExternalNameRef
ExternalLink::importDdeItem( const AttributeList
& rAttribs
)
341 ExternalNameRef xExtName
= createExternalName();
342 xExtName
->importDdeItem( rAttribs
);
346 void ExternalLink::importOleLink( const Relations
& rRelations
, const AttributeList
& rAttribs
)
348 OUString aProgId
= rAttribs
.getXString( XML_progId
, OUString() );
349 OUString aTargetUrl
= rRelations
.getExternalTargetFromRelId( rAttribs
.getString( R_TOKEN( id
), OUString() ) );
350 setDdeOleTargetUrl( aProgId
, aTargetUrl
, LINKTYPE_OLE
);
353 ExternalNameRef
ExternalLink::importOleItem( const AttributeList
& rAttribs
)
355 ExternalNameRef xExtName
= createExternalName();
356 xExtName
->importOleItem( rAttribs
);
360 void ExternalLink::importExternalRef( SequenceInputStream
& rStrm
)
365 void ExternalLink::importExternalSelf( SequenceInputStream
& )
367 meLinkType
= LINKTYPE_SELF
;
370 void ExternalLink::importExternalSame( SequenceInputStream
& )
372 meLinkType
= LINKTYPE_SAME
;
375 void ExternalLink::importExternalAddin( SequenceInputStream
& )
377 meLinkType
= LINKTYPE_UNKNOWN
;
380 void ExternalLink::importExternalBook( const Relations
& rRelations
, SequenceInputStream
& rStrm
)
382 switch( rStrm
.readuInt16() )
384 case BIFF12_EXTERNALBOOK_BOOK
:
385 parseExternalReference( rRelations
, BiffHelper::readString( rStrm
) );
387 case BIFF12_EXTERNALBOOK_DDE
:
389 OUString aDdeService
, aDdeTopic
;
390 rStrm
>> aDdeService
>> aDdeTopic
;
391 setDdeOleTargetUrl( aDdeService
, aDdeTopic
, LINKTYPE_DDE
);
394 case BIFF12_EXTERNALBOOK_OLE
:
396 OUString aTargetUrl
= rRelations
.getExternalTargetFromRelId( BiffHelper::readString( rStrm
) );
397 OUString aProgId
= BiffHelper::readString( rStrm
);
398 setDdeOleTargetUrl( aProgId
, aTargetUrl
, LINKTYPE_OLE
);
402 OSL_FAIL( "ExternalLink::importExternalBook - unknown link type" );
406 void ExternalLink::importExtSheetNames( SequenceInputStream
& rStrm
)
408 // load external sheet names and create the sheet caches in the Calc document
409 OSL_ENSURE( (meLinkType
== LINKTYPE_EXTERNAL
) || (meLinkType
== LINKTYPE_LIBRARY
),
410 "ExternalLink::importExtSheetNames - invalid link type" );
411 if( meLinkType
== LINKTYPE_EXTERNAL
) // ignore sheets of external libraries
412 for( sal_Int32 nSheet
= 0, nCount
= rStrm
.readInt32(); !rStrm
.isEof() && (nSheet
< nCount
); ++nSheet
)
413 insertExternalSheet( BiffHelper::readString( rStrm
) );
416 ExternalNameRef
ExternalLink::importExternalName( SequenceInputStream
& rStrm
)
418 ExternalNameRef xExtName
= createExternalName();
419 xExtName
->importExternalName( rStrm
);
423 ExternalLinkInfo
ExternalLink::getLinkInfo() const
425 ExternalLinkInfo aLinkInfo
;
430 case LINKTYPE_INTERNAL
:
431 aLinkInfo
.Type
= ::com::sun::star::sheet::ExternalLinkType::SELF
;
433 case LINKTYPE_EXTERNAL
:
434 aLinkInfo
.Type
= ::com::sun::star::sheet::ExternalLinkType::DOCUMENT
;
435 aLinkInfo
.Data
<<= maTargetUrl
;
437 case LINKTYPE_LIBRARY
:
438 // parser will return library function names in OPCODE_BAD string tokens
439 aLinkInfo
.Type
= ::com::sun::star::sheet::ExternalLinkType::SPECIAL
;
443 aLinkInfo
.Type
= ::com::sun::star::sheet::ExternalLinkType::DDE
;
444 DDELinkInfo aDdeLinkInfo
;
445 aDdeLinkInfo
.Service
= maClassName
;
446 aDdeLinkInfo
.Topic
= maTargetUrl
;
447 ::std::vector
< DDEItemInfo
> aItemInfos
;
448 DDEItemInfo aItemInfo
;
449 for( ExternalNameVector::const_iterator aIt
= maExtNames
.begin(), aEnd
= maExtNames
.end(); aIt
!= aEnd
; ++aIt
)
450 if( (*aIt
)->getDdeItemInfo( aItemInfo
) )
451 aItemInfos
.push_back( aItemInfo
);
452 aDdeLinkInfo
.Items
= ContainerHelper::vectorToSequence( aItemInfos
);
453 aLinkInfo
.Data
<<= aDdeLinkInfo
;
457 aLinkInfo
.Type
= ::com::sun::star::sheet::ExternalLinkType::UNKNOWN
;
462 FunctionLibraryType
ExternalLink::getFuncLibraryType() const
464 return (meLinkType
== LINKTYPE_LIBRARY
) ? meFuncLibType
: FUNCLIB_UNKNOWN
;
467 sal_Int32
ExternalLink::getDocumentLinkIndex() const
469 OSL_ENSURE( meLinkType
== LINKTYPE_EXTERNAL
, "ExternalLink::getDocumentLinkIndex - invalid link type" );
470 return mxDocLink
.is() ? mxDocLink
->getTokenIndex() : -1;
473 sal_Int32
ExternalLink::getSheetCacheIndex( sal_Int32 nTabId
) const
475 OSL_ENSURE( meLinkType
== LINKTYPE_EXTERNAL
, "ExternalLink::getSheetCacheIndex - invalid link type" );
476 OSL_ENSURE( (nTabId
== 0) || (getFilterType() == FILTER_OOXML
) || (getBiff() == BIFF8
),
477 "ExternalLink::getSheetCacheIndex - invalid sheet index" );
478 return ContainerHelper::getVectorElement( maSheetCaches
, nTabId
, -1 );
481 Reference
< XExternalSheetCache
> ExternalLink::getSheetCache( sal_Int32 nTabId
) const
483 sal_Int32 nCacheIdx
= getSheetCacheIndex( nTabId
);
484 if( mxDocLink
.is() && (nCacheIdx
>= 0) ) try
486 // existing mxDocLink implies that this is an external link
487 Reference
< XExternalSheetCache
> xSheetCache( mxDocLink
->getByIndex( nCacheIdx
), UNO_QUERY_THROW
);
496 void ExternalLink::getSheetRange( LinkSheetRange
& orSheetRange
, sal_Int32 nTabId1
, sal_Int32 nTabId2
) const
501 orSheetRange
.setSameSheet();
505 case LINKTYPE_INTERNAL
:
506 orSheetRange
.setRange( nTabId1
, nTabId2
);
509 case LINKTYPE_EXTERNAL
:
511 sal_Int32 nDocLinkIdx
= getDocumentLinkIndex();
512 switch( getFilterType() )
515 // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
516 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex( nTabId1
), getSheetCacheIndex( nTabId2
) );
524 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex( nTabId1
), getSheetCacheIndex( nTabId2
) );
527 // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
528 if( const ExternalLink
* pExtLink2
= getExternalLinks().getExternalLink( nTabId2
).get() )
529 if( (pExtLink2
->getLinkType() == LINKTYPE_EXTERNAL
) && (maTargetUrl
== pExtLink2
->getTargetUrl()) )
530 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex(), pExtLink2
->getSheetCacheIndex() );
533 // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
534 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex( nTabId1
), getSheetCacheIndex( nTabId2
) );
536 case BIFF_UNKNOWN
: break;
539 case FILTER_UNKNOWN
: break;
545 // unsupported/unexpected link type: #REF! error
546 orSheetRange
.setDeleted();
550 ExternalNameRef
ExternalLink::getNameByIndex( sal_Int32 nIndex
) const
552 return maExtNames
.get( nIndex
);
555 // private --------------------------------------------------------------------
557 void ExternalLink::setExternalTargetUrl( const OUString
& rTargetUrl
, const OUString
& rTargetType
)
559 meLinkType
= LINKTYPE_UNKNOWN
;
560 if( rTargetType
== CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" ) ||
561 rTargetType
== CREATE_OFFICEDOC_RELATION_TYPE_STRICT( "externalLinkPath" ) )
563 maTargetUrl
= getBaseFilter().getAbsoluteUrl( rTargetUrl
);
564 if( !maTargetUrl
.isEmpty() )
565 meLinkType
= LINKTYPE_EXTERNAL
;
567 else if( rTargetType
== CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" ) )
569 meLinkType
= LINKTYPE_LIBRARY
;
570 meFuncLibType
= FunctionProvider::getFuncLibTypeFromLibraryName( rTargetUrl
);
572 OSL_ENSURE( meLinkType
!= LINKTYPE_UNKNOWN
, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
574 // create the external document link API object that will contain the sheet caches
575 if( meLinkType
== LINKTYPE_EXTERNAL
) try
577 PropertySet
aDocProps( getDocument() );
578 Reference
< XExternalDocLinks
> xDocLinks( aDocProps
.getAnyProperty( PROP_ExternalDocLinks
), UNO_QUERY_THROW
);
579 mxDocLink
= xDocLinks
->addDocLink( maTargetUrl
);
586 void ExternalLink::setDdeOleTargetUrl( const OUString
& rClassName
, const OUString
& rTargetUrl
, ExternalLinkType eLinkType
)
588 maClassName
= rClassName
;
589 maTargetUrl
= rTargetUrl
;
590 meLinkType
= (maClassName
.isEmpty() || maTargetUrl
.isEmpty()) ? LINKTYPE_UNKNOWN
: eLinkType
;
591 OSL_ENSURE( meLinkType
== eLinkType
, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
594 void ExternalLink::parseExternalReference( const Relations
& rRelations
, const OUString
& rRelId
)
596 if( const Relation
* pRelation
= rRelations
.getRelationFromRelId( rRelId
) )
597 setExternalTargetUrl( pRelation
->maTarget
, pRelation
->maType
);
600 void ExternalLink::insertExternalSheet( const OUString
& rSheetName
)
602 OSL_ENSURE( !rSheetName
.isEmpty(), "ExternalLink::insertExternalSheet - empty sheet name" );
605 Reference
< XExternalSheetCache
> xSheetCache
= mxDocLink
->addSheetCache( rSheetName
, false );
606 sal_Int32 nCacheIdx
= xSheetCache
.is() ? xSheetCache
->getTokenIndex() : -1;
607 maSheetCaches
.push_back( nCacheIdx
);
611 ExternalNameRef
ExternalLink::createExternalName()
613 ExternalNameRef
xExtName( new ExternalName( *this ) );
614 maExtNames
.push_back( xExtName
);
618 RefSheetsModel::RefSheetsModel() :
625 void RefSheetsModel::readBiff12Data( SequenceInputStream
& rStrm
)
627 mnExtRefId
= rStrm
.readInt32();
628 mnTabId1
= rStrm
.readInt32();
629 mnTabId2
= rStrm
.readInt32();
632 ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper
& rHelper
) :
633 WorkbookHelper( rHelper
),
634 mxSelfRef( new ExternalLink( rHelper
) ),
635 mbUseRefSheets( false )
637 mxSelfRef
->setSelfLinkType();
640 ExternalLinkRef
ExternalLinkBuffer::importExternalReference( const AttributeList
& rAttribs
)
642 ExternalLinkRef xExtLink
= createExternalLink();
643 xExtLink
->importExternalReference( rAttribs
);
644 maExtLinks
.push_back( xExtLink
);
648 ExternalLinkRef
ExternalLinkBuffer::importExternalRef( SequenceInputStream
& rStrm
)
650 mbUseRefSheets
= true;
651 ExternalLinkRef xExtLink
= createExternalLink();
652 xExtLink
->importExternalRef( rStrm
);
653 maExtLinks
.push_back( xExtLink
);
657 void ExternalLinkBuffer::importExternalSelf( SequenceInputStream
& rStrm
)
659 mbUseRefSheets
= true;
660 createExternalLink()->importExternalSelf( rStrm
);
663 void ExternalLinkBuffer::importExternalSame( SequenceInputStream
& rStrm
)
665 mbUseRefSheets
= true;
666 createExternalLink()->importExternalSame( rStrm
);
669 void ExternalLinkBuffer::importExternalAddin( SequenceInputStream
& rStrm
)
671 mbUseRefSheets
= true;
672 createExternalLink()->importExternalAddin( rStrm
);
675 void ExternalLinkBuffer::importExternalSheets( SequenceInputStream
& rStrm
)
677 OSL_ENSURE( mbUseRefSheets
, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
678 mbUseRefSheets
= true;
679 OSL_ENSURE( maRefSheets
.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
682 nRefCount
= rStrm
.readInt32();
683 size_t nMaxCount
= getLimitedValue
< size_t, sal_Int64
>( nRefCount
, 0, rStrm
.getRemaining() / 12 );
684 maRefSheets
.reserve( nMaxCount
);
685 for( size_t nRefId
= 0; !rStrm
.isEof() && (nRefId
< nMaxCount
); ++nRefId
)
687 RefSheetsModel aRefSheets
;
688 aRefSheets
.readBiff12Data( rStrm
);
689 maRefSheets
.push_back( aRefSheets
);
693 Sequence
< ExternalLinkInfo
> ExternalLinkBuffer::getLinkInfos() const
695 ::std::vector
< ExternalLinkInfo
> aLinkInfos
;
696 // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
697 OSL_ENSURE( getFilterType() == FILTER_OOXML
, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
698 // add entry for implicit index 0 (self reference to this document)
699 aLinkInfos
.push_back( mxSelfRef
->getLinkInfo() );
700 for( ExternalLinkVec::const_iterator aIt
= maExtLinks
.begin(), aEnd
= maExtLinks
.end(); aIt
!= aEnd
; ++aIt
)
701 aLinkInfos
.push_back( (*aIt
)->getLinkInfo() );
702 return ContainerHelper::vectorToSequence( aLinkInfos
);
705 ExternalLinkRef
ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId
, bool bUseRefSheets
) const
707 ExternalLinkRef xExtLink
;
708 switch( getFilterType() )
711 // OOXML: 0 = this document, otherwise one-based index into link list
712 if( !bUseRefSheets
|| !mbUseRefSheets
)
713 xExtLink
= (nRefId
== 0) ? mxSelfRef
: maLinks
.get( nRefId
- 1 );
714 // BIFF12: zero-based index into ref-sheets list
715 else if( const RefSheetsModel
* pRefSheets
= getRefSheets( nRefId
) )
716 xExtLink
= maLinks
.get( pRefSheets
->mnExtRefId
);
724 // one-based index to EXTERNSHEET records
725 xExtLink
= maLinks
.get( nRefId
- 1 );
730 // internal links in formula tokens have negative index
731 xExtLink
= maLinks
.get( -nRefId
- 1 );
732 if( xExtLink
.get() && !xExtLink
->isInternalLink() )
737 // one-based index to EXTERNSHEET records
738 xExtLink
= maLinks
.get( nRefId
- 1 );
742 // zero-based index into REF list in EXTERNSHEET record
743 if( const RefSheetsModel
* pRefSheets
= getRefSheets( nRefId
) )
744 xExtLink
= maLinks
.get( pRefSheets
->mnExtRefId
);
746 case BIFF_UNKNOWN
: break;
749 case FILTER_UNKNOWN
: break;
754 LinkSheetRange
ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId
, sal_Int16 nTabId1
, sal_Int16 nTabId2
) const
756 OSL_ENSURE( getBiff() <= BIFF5
, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
757 LinkSheetRange aSheetRange
;
758 if( const ExternalLink
* pExtLink
= getExternalLink( nRefId
).get() )
759 pExtLink
->getSheetRange( aSheetRange
, nTabId1
, nTabId2
);
763 LinkSheetRange
ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId
) const
765 OSL_ENSURE( ((getFilterType() == FILTER_OOXML
) && mbUseRefSheets
) || (getBiff() == BIFF8
), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
766 LinkSheetRange aSheetRange
;
767 if( const ExternalLink
* pExtLink
= getExternalLink( nRefId
).get() )
768 if( const RefSheetsModel
* pRefSheets
= getRefSheets( nRefId
) )
769 pExtLink
->getSheetRange( aSheetRange
, pRefSheets
->mnTabId1
, pRefSheets
->mnTabId2
);
773 // private --------------------------------------------------------------------
775 ExternalLinkRef
ExternalLinkBuffer::createExternalLink()
777 ExternalLinkRef
xExtLink( new ExternalLink( *this ) );
778 maLinks
.push_back( xExtLink
);
782 const RefSheetsModel
* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId
) const
784 return ((0 <= nRefId
) && (static_cast< size_t >( nRefId
) < maRefSheets
.size())) ?
785 &maRefSheets
[ static_cast< size_t >( nRefId
) ] : 0;
791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */