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/beans/XPropertySet.hpp>
23 #include <com/sun/star/sheet/ComplexReference.hpp>
24 #include <com/sun/star/sheet/DDELinkInfo.hpp>
25 #include <com/sun/star/sheet/ExternalLinkType.hpp>
26 #include <com/sun/star/sheet/ExternalReference.hpp>
27 #include <com/sun/star/sheet/ReferenceFlags.hpp>
28 #include <com/sun/star/sheet/SingleReference.hpp>
29 #include <com/sun/star/sheet/XDDELinks.hpp>
30 #include <com/sun/star/sheet/XDDELink.hpp>
31 #include <com/sun/star/sheet/XDDELinkResults.hpp>
32 #include <com/sun/star/sheet/XExternalDocLink.hpp>
33 #include <com/sun/star/sheet/XExternalDocLinks.hpp>
34 #include <osl/diagnose.h>
35 #include <rtl/strbuf.hxx>
36 #include <oox/core/filterbase.hxx>
37 #include <oox/helper/attributelist.hxx>
38 #include <oox/token/namespaces.hxx>
39 #include <oox/token/properties.hxx>
40 #include <oox/token/tokens.hxx>
41 #include "addressconverter.hxx"
42 #include "biffinputstream.hxx"
43 #include "excelhandlers.hxx"
44 #include "formulaparser.hxx"
45 #include "worksheetbuffer.hxx"
50 using namespace ::com::sun::star::sheet
;
51 using namespace ::com::sun::star::table
;
52 using namespace ::com::sun::star::uno
;
54 using ::oox::core::Relation
;
55 using ::oox::core::Relations
;
59 const sal_uInt16 BIFF12_EXTERNALBOOK_BOOK
= 0;
60 const sal_uInt16 BIFF12_EXTERNALBOOK_DDE
= 1;
61 const sal_uInt16 BIFF12_EXTERNALBOOK_OLE
= 2;
63 const sal_uInt16 BIFF12_EXTNAME_AUTOMATIC
= 0x0002;
64 const sal_uInt16 BIFF12_EXTNAME_PREFERPIC
= 0x0004;
65 const sal_uInt16 BIFF12_EXTNAME_STDDOCNAME
= 0x0008;
66 const sal_uInt16 BIFF12_EXTNAME_OLEOBJECT
= 0x0010;
67 const sal_uInt16 BIFF12_EXTNAME_ICONIFIED
= 0x0020;
71 ExternalNameModel::ExternalNameModel() :
74 mbStdDocName( false ),
80 ExternalName::ExternalName( const ExternalLink
& rParentLink
) :
81 DefinedNameBase( rParentLink
),
82 mrParentLink( rParentLink
),
83 mbDdeLinkCreated( false )
87 void ExternalName::importDefinedName( const AttributeList
& rAttribs
)
89 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
90 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importDefinedName - empty name" );
91 // zero-based index into sheet list of externalBook
92 maModel
.mnSheet
= rAttribs
.getInteger( XML_sheetId
, -1 );
95 void ExternalName::importDdeItem( const AttributeList
& rAttribs
)
97 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
98 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importDdeItem - empty name" );
99 maExtNameModel
.mbOleObj
= false;
100 maExtNameModel
.mbStdDocName
= rAttribs
.getBool( XML_ole
, false );
101 maExtNameModel
.mbNotify
= rAttribs
.getBool( XML_advise
, false );
102 maExtNameModel
.mbPreferPic
= rAttribs
.getBool( XML_preferPic
, false );
105 void ExternalName::importValues( const AttributeList
& rAttribs
)
107 setResultSize( rAttribs
.getInteger( XML_cols
, 1 ), rAttribs
.getInteger( XML_rows
, 1 ) );
110 void ExternalName::importOleItem( const AttributeList
& rAttribs
)
112 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
113 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importOleItem - empty name" );
114 maExtNameModel
.mbOleObj
= true;
115 maExtNameModel
.mbNotify
= rAttribs
.getBool( XML_advise
, false );
116 maExtNameModel
.mbPreferPic
= rAttribs
.getBool( XML_preferPic
, false );
117 maExtNameModel
.mbIconified
= rAttribs
.getBool( XML_icon
, false );
120 void ExternalName::importExternalName( SequenceInputStream
& rStrm
)
122 rStrm
>> maModel
.maName
;
123 OSL_ENSURE( !maModel
.maName
.isEmpty(), "ExternalName::importExternalName - empty name" );
126 void ExternalName::importExternalNameFlags( SequenceInputStream
& rStrm
)
130 nFlags
= rStrm
.readuInt16();
131 nSheetId
= rStrm
.readInt32();
132 // index into sheet list of EXTSHEETNAMES (one-based in BIFF12)
133 maModel
.mnSheet
= nSheetId
- 1;
134 // no flag for built-in names, as in OOXML...
135 maExtNameModel
.mbNotify
= getFlag( nFlags
, BIFF12_EXTNAME_AUTOMATIC
);
136 maExtNameModel
.mbPreferPic
= getFlag( nFlags
, BIFF12_EXTNAME_PREFERPIC
);
137 maExtNameModel
.mbStdDocName
= getFlag( nFlags
, BIFF12_EXTNAME_STDDOCNAME
);
138 maExtNameModel
.mbOleObj
= getFlag( nFlags
, BIFF12_EXTNAME_OLEOBJECT
);
139 maExtNameModel
.mbIconified
= getFlag( nFlags
, BIFF12_EXTNAME_ICONIFIED
);
140 OSL_ENSURE( (mrParentLink
.getLinkType() == LINKTYPE_OLE
) == maExtNameModel
.mbOleObj
,
141 "ExternalName::importExternalNameFlags - wrong OLE flag in external name" );
144 void ExternalName::importDdeItemValues( SequenceInputStream
& rStrm
)
146 sal_Int32 nRows
, nCols
;
147 nRows
= rStrm
.readInt32();
148 nCols
= rStrm
.readInt32();
149 setResultSize( nCols
, nRows
);
152 void ExternalName::importDdeItemBool( SequenceInputStream
& rStrm
)
154 appendResultValue
< double >( (rStrm
.readuInt8() == 0) ? 0.0 : 1.0 );
157 void ExternalName::importDdeItemDouble( SequenceInputStream
& rStrm
)
159 appendResultValue( rStrm
.readDouble() );
162 void ExternalName::importDdeItemError( SequenceInputStream
& rStrm
)
164 appendResultValue( BiffHelper::calcDoubleFromError( rStrm
.readuInt8() ) );
167 void ExternalName::importDdeItemString( SequenceInputStream
& rStrm
)
169 appendResultValue( BiffHelper::readString( rStrm
) );
173 sal_Int32
ExternalName::getSheetCacheIndex() const
175 OSL_ENSURE( mrParentLink
.getLinkType() == LINKTYPE_DDE
, "ExternalName::getSheetCacheIndex - unexpected link type" );
176 sal_Int32 nCacheIdx
= -1;
177 switch( getFilterType() )
180 // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
181 if( maModel
.mnSheet
>= 0 )
182 nCacheIdx
= mrParentLink
.getSheetIndex( maModel
.mnSheet
);
192 if( maModel
.mnSheet
> 0 )
193 if( const ExternalLink
* pExtLink
= getExternalLinks().getExternalLink( maModel
.mnSheet
).get() )
194 if( pExtLink
->getLinkType() == LINKTYPE_EXTERNAL
)
195 nCacheIdx
= pExtLink
->getSheetIndex();
198 if( maModel
.mnSheet
> 0 )
199 nCacheIdx
= mrParentLink
.getSheetIndex( maModel
.mnSheet
- 1 );
212 bool ExternalName::getDdeItemInfo( DDEItemInfo
& orItemInfo
) const
214 if( (mrParentLink
.getLinkType() == LINKTYPE_DDE
) && !maModel
.maName
.isEmpty() )
216 orItemInfo
.Item
= maModel
.maName
;
217 orItemInfo
.Results
= ContainerHelper::matrixToSequenceSequence( maResults
);
223 bool ExternalName::getDdeLinkData( OUString
& orDdeServer
, OUString
& orDdeTopic
, OUString
& orDdeItem
)
225 if( (mrParentLink
.getLinkType() == LINKTYPE_DDE
) && !maModel
.maName
.isEmpty() )
227 // try to create a DDE link and to set the imported link results
228 if( !mbDdeLinkCreated
) try
230 PropertySet
aDocProps( getDocument() );
231 Reference
< XDDELinks
> xDdeLinks( aDocProps
.getAnyProperty( PROP_DDELinks
), UNO_QUERY_THROW
);
232 mxDdeLink
= xDdeLinks
->addDDELink( mrParentLink
.getClassName(), mrParentLink
.getTargetUrl(), maModel
.maName
, css::sheet::DDELinkMode_DEFAULT
);
233 mbDdeLinkCreated
= true; // ignore if setting results fails
234 if( !maResults
.empty() )
236 Reference
< XDDELinkResults
> xResults( mxDdeLink
, UNO_QUERY_THROW
);
237 xResults
->setResults( ContainerHelper::matrixToSequenceSequence( maResults
) );
242 OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
244 // get link data from created DDE link
247 orDdeServer
= mxDdeLink
->getApplication();
248 orDdeTopic
= mxDdeLink
->getTopic();
249 orDdeItem
= mxDdeLink
->getItem();
256 // private --------------------------------------------------------------------
258 void ExternalName::setResultSize( sal_Int32 nColumns
, sal_Int32 nRows
)
260 OSL_ENSURE( (mrParentLink
.getLinkType() == LINKTYPE_DDE
) || (mrParentLink
.getLinkType() == LINKTYPE_OLE
) ||
261 (mrParentLink
.getLinkType() == LINKTYPE_MAYBE_DDE_OLE
), "ExternalName::setResultSize - wrong link type" );
262 OSL_ENSURE( (nRows
> 0) && (nColumns
> 0), "ExternalName::setResultSize - invalid matrix size" );
263 const ScAddress
& rMaxPos
= getAddressConverter().getMaxApiAddress();
264 if( (0 < nRows
) && (nRows
<= rMaxPos
.Row() + 1) && (0 < nColumns
) && (nColumns
<= rMaxPos
.Col() + 1) )
265 maResults
.resize( static_cast< size_t >( nColumns
), static_cast< size_t >( nRows
), Any( BiffHelper::calcDoubleFromError( BIFF_ERR_NA
) ) );
268 maCurrIt
= maResults
.begin();
271 void LinkSheetRange::setDeleted()
273 meType
= LINKSHEETRANGE_INTERNAL
;
274 mnDocLink
= mnFirst
= mnLast
= -1;
277 void LinkSheetRange::setSameSheet()
279 meType
= LINKSHEETRANGE_SAMESHEET
;
281 mnFirst
= mnLast
= 0;
284 void LinkSheetRange::setRange( sal_Int32 nFirst
, sal_Int32 nLast
)
286 meType
= LINKSHEETRANGE_INTERNAL
;
288 mnFirst
= ::std::min( nFirst
, nLast
);
289 mnLast
= ::std::max( nFirst
, nLast
);
292 void LinkSheetRange::setExternalRange( sal_Int32 nDocLink
, sal_Int32 nFirst
, sal_Int32 nLast
)
300 meType
= LINKSHEETRANGE_EXTERNAL
;
301 mnDocLink
= nDocLink
;
302 mnFirst
= ::std::min( nFirst
, nLast
);
303 mnLast
= ::std::max( nFirst
, nLast
);
307 ExternalLink::ExternalLink( const WorkbookHelper
& rHelper
) :
308 WorkbookHelper( rHelper
),
309 meLinkType( LINKTYPE_UNKNOWN
),
310 meFuncLibType( FUNCLIB_UNKNOWN
)
314 void ExternalLink::importExternalReference( const AttributeList
& rAttribs
)
316 maRelId
= rAttribs
.getString( R_TOKEN( id
), OUString() );
319 void ExternalLink::importExternalBook( const Relations
& rRelations
, const AttributeList
& rAttribs
)
321 parseExternalReference( rRelations
, rAttribs
.getString( R_TOKEN( id
), OUString() ) );
324 void ExternalLink::importSheetName( const AttributeList
& rAttribs
)
326 insertExternalSheet( rAttribs
.getXString( XML_val
, OUString() ) );
329 void ExternalLink::importDefinedName( const AttributeList
& rAttribs
)
331 createExternalName()->importDefinedName( rAttribs
);
334 void ExternalLink::importDdeLink( const AttributeList
& rAttribs
)
336 OUString aDdeService
= rAttribs
.getXString( XML_ddeService
, OUString() );
337 OUString aDdeTopic
= rAttribs
.getXString( XML_ddeTopic
, OUString() );
338 setDdeOleTargetUrl( aDdeService
, aDdeTopic
, LINKTYPE_DDE
);
341 ExternalNameRef
ExternalLink::importDdeItem( const AttributeList
& rAttribs
)
343 ExternalNameRef xExtName
= createExternalName();
344 xExtName
->importDdeItem( rAttribs
);
348 void ExternalLink::importOleLink( const Relations
& rRelations
, const AttributeList
& rAttribs
)
350 OUString aProgId
= rAttribs
.getXString( XML_progId
, OUString() );
351 OUString aTargetUrl
= rRelations
.getExternalTargetFromRelId( rAttribs
.getString( R_TOKEN( id
), OUString() ) );
352 setDdeOleTargetUrl( aProgId
, aTargetUrl
, LINKTYPE_OLE
);
355 ExternalNameRef
ExternalLink::importOleItem( const AttributeList
& rAttribs
)
357 ExternalNameRef xExtName
= createExternalName();
358 xExtName
->importOleItem( rAttribs
);
362 void ExternalLink::importExternalRef( SequenceInputStream
& rStrm
)
367 void ExternalLink::importExternalSelf( SequenceInputStream
& )
369 meLinkType
= LINKTYPE_SELF
;
372 void ExternalLink::importExternalSame( SequenceInputStream
& )
374 meLinkType
= LINKTYPE_SAME
;
377 void ExternalLink::importExternalAddin( SequenceInputStream
& )
379 meLinkType
= LINKTYPE_UNKNOWN
;
382 void ExternalLink::importExternalBook( const Relations
& rRelations
, SequenceInputStream
& rStrm
)
384 switch( rStrm
.readuInt16() )
386 case BIFF12_EXTERNALBOOK_BOOK
:
387 parseExternalReference( rRelations
, BiffHelper::readString( rStrm
) );
389 case BIFF12_EXTERNALBOOK_DDE
:
391 OUString aDdeService
, aDdeTopic
;
392 rStrm
>> aDdeService
>> aDdeTopic
;
393 setDdeOleTargetUrl( aDdeService
, aDdeTopic
, LINKTYPE_DDE
);
396 case BIFF12_EXTERNALBOOK_OLE
:
398 OUString aTargetUrl
= rRelations
.getExternalTargetFromRelId( BiffHelper::readString( rStrm
) );
399 OUString aProgId
= BiffHelper::readString( rStrm
);
400 setDdeOleTargetUrl( aProgId
, aTargetUrl
, LINKTYPE_OLE
);
404 OSL_FAIL( "ExternalLink::importExternalBook - unknown link type" );
408 void ExternalLink::importExtSheetNames( SequenceInputStream
& rStrm
)
410 // load external sheet names and create the sheet caches in the Calc document
411 OSL_ENSURE( (meLinkType
== LINKTYPE_EXTERNAL
) || (meLinkType
== LINKTYPE_LIBRARY
),
412 "ExternalLink::importExtSheetNames - invalid link type" );
413 if( meLinkType
== LINKTYPE_EXTERNAL
) // ignore sheets of external libraries
414 for( sal_Int32 nSheet
= 0, nCount
= rStrm
.readInt32(); !rStrm
.isEof() && (nSheet
< nCount
); ++nSheet
)
415 insertExternalSheet( BiffHelper::readString( rStrm
) );
418 ExternalNameRef
ExternalLink::importExternalName( SequenceInputStream
& rStrm
)
420 ExternalNameRef xExtName
= createExternalName();
421 xExtName
->importExternalName( rStrm
);
425 ExternalLinkInfo
ExternalLink::getLinkInfo() const
427 ExternalLinkInfo aLinkInfo
;
432 case LINKTYPE_INTERNAL
:
433 aLinkInfo
.Type
= css::sheet::ExternalLinkType::SELF
;
435 case LINKTYPE_EXTERNAL
:
436 aLinkInfo
.Type
= css::sheet::ExternalLinkType::DOCUMENT
;
437 aLinkInfo
.Data
<<= maTargetUrl
;
439 case LINKTYPE_LIBRARY
:
440 // parser will return library function names in OPCODE_BAD string tokens
441 aLinkInfo
.Type
= css::sheet::ExternalLinkType::SPECIAL
;
445 aLinkInfo
.Type
= css::sheet::ExternalLinkType::DDE
;
446 DDELinkInfo aDdeLinkInfo
;
447 aDdeLinkInfo
.Service
= maClassName
;
448 aDdeLinkInfo
.Topic
= maTargetUrl
;
449 ::std::vector
< DDEItemInfo
> aItemInfos
;
450 DDEItemInfo aItemInfo
;
451 for( ExternalNameVector::const_iterator aIt
= maExtNames
.begin(), aEnd
= maExtNames
.end(); aIt
!= aEnd
; ++aIt
)
452 if( (*aIt
)->getDdeItemInfo( aItemInfo
) )
453 aItemInfos
.push_back( aItemInfo
);
454 aDdeLinkInfo
.Items
= ContainerHelper::vectorToSequence( aItemInfos
);
455 aLinkInfo
.Data
<<= aDdeLinkInfo
;
459 aLinkInfo
.Type
= css::sheet::ExternalLinkType::UNKNOWN
;
464 FunctionLibraryType
ExternalLink::getFuncLibraryType() const
466 return (meLinkType
== LINKTYPE_LIBRARY
) ? meFuncLibType
: FUNCLIB_UNKNOWN
;
469 sal_Int32
ExternalLink::getDocumentLinkIndex() const
471 OSL_ENSURE( meLinkType
== LINKTYPE_EXTERNAL
, "ExternalLink::getDocumentLinkIndex - invalid link type" );
472 return mxDocLink
.is() ? mxDocLink
->getTokenIndex() : -1;
475 sal_Int32
ExternalLink::getSheetCacheIndex( sal_Int32 nTabId
) const
477 OSL_ENSURE( meLinkType
== LINKTYPE_EXTERNAL
, "ExternalLink::getSheetCacheIndex - invalid link type" );
478 OSL_ENSURE( (nTabId
== 0) || (getFilterType() == FILTER_OOXML
) || (getBiff() == BIFF8
),
479 "ExternalLink::getSheetCacheIndex - invalid sheet index" );
480 return ContainerHelper::getVectorElement( maSheetCaches
, nTabId
, -1 );
483 Reference
< XExternalSheetCache
> ExternalLink::getSheetCache( sal_Int32 nTabId
) const
485 sal_Int32 nCacheIdx
= getSheetCacheIndex( nTabId
);
486 if( mxDocLink
.is() && (nCacheIdx
>= 0) ) try
488 // existing mxDocLink implies that this is an external link
489 Reference
< XExternalSheetCache
> xSheetCache( mxDocLink
->getByIndex( nCacheIdx
), UNO_QUERY_THROW
);
498 void ExternalLink::getSheetRange( LinkSheetRange
& orSheetRange
, sal_Int32 nTabId1
, sal_Int32 nTabId2
) const
503 orSheetRange
.setSameSheet();
507 case LINKTYPE_INTERNAL
:
508 orSheetRange
.setRange( nTabId1
, nTabId2
);
511 case LINKTYPE_EXTERNAL
:
513 sal_Int32 nDocLinkIdx
= getDocumentLinkIndex();
514 switch( getFilterType() )
517 // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
518 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex( nTabId1
), getSheetCacheIndex( nTabId2
) );
526 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex( nTabId1
), getSheetCacheIndex( nTabId2
) );
529 // BIFF5: first sheet from this external link, last sheet is passed in nTabId2
530 if( const ExternalLink
* pExtLink2
= getExternalLinks().getExternalLink( nTabId2
).get() )
531 if( (pExtLink2
->getLinkType() == LINKTYPE_EXTERNAL
) && (maTargetUrl
== pExtLink2
->getTargetUrl()) )
532 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex(), pExtLink2
->getSheetCacheIndex() );
535 // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
536 orSheetRange
.setExternalRange( nDocLinkIdx
, getSheetCacheIndex( nTabId1
), getSheetCacheIndex( nTabId2
) );
538 case BIFF_UNKNOWN
: break;
541 case FILTER_UNKNOWN
: break;
547 // unsupported/unexpected link type: #REF! error
548 orSheetRange
.setDeleted();
552 ExternalNameRef
ExternalLink::getNameByIndex( sal_Int32 nIndex
) const
554 return maExtNames
.get( nIndex
);
557 // private --------------------------------------------------------------------
559 void ExternalLink::setExternalTargetUrl( const OUString
& rTargetUrl
, const OUString
& rTargetType
)
561 meLinkType
= LINKTYPE_UNKNOWN
;
562 if( rTargetType
== CREATE_OFFICEDOC_RELATION_TYPE( "externalLinkPath" ) ||
563 rTargetType
== CREATE_OFFICEDOC_RELATION_TYPE_STRICT( "externalLinkPath" ) )
565 maTargetUrl
= getBaseFilter().getAbsoluteUrl( rTargetUrl
);
566 if( !maTargetUrl
.isEmpty() )
567 meLinkType
= LINKTYPE_EXTERNAL
;
569 else if( rTargetType
== CREATE_MSOFFICE_RELATION_TYPE( "xlExternalLinkPath/xlLibrary" ) )
571 meLinkType
= LINKTYPE_LIBRARY
;
572 meFuncLibType
= FunctionProvider::getFuncLibTypeFromLibraryName( rTargetUrl
);
574 OSL_ENSURE( meLinkType
!= LINKTYPE_UNKNOWN
, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
576 // create the external document link API object that will contain the sheet caches
577 if( meLinkType
== LINKTYPE_EXTERNAL
) try
579 PropertySet
aDocProps( getDocument() );
580 Reference
< XExternalDocLinks
> xDocLinks( aDocProps
.getAnyProperty( PROP_ExternalDocLinks
), UNO_QUERY_THROW
);
581 mxDocLink
= xDocLinks
->addDocLink( maTargetUrl
);
588 void ExternalLink::setDdeOleTargetUrl( const OUString
& rClassName
, const OUString
& rTargetUrl
, ExternalLinkType eLinkType
)
590 maClassName
= rClassName
;
591 maTargetUrl
= rTargetUrl
;
592 meLinkType
= (maClassName
.isEmpty() || maTargetUrl
.isEmpty()) ? LINKTYPE_UNKNOWN
: eLinkType
;
593 OSL_ENSURE( meLinkType
== eLinkType
, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
596 void ExternalLink::parseExternalReference( const Relations
& rRelations
, const OUString
& rRelId
)
598 if( const Relation
* pRelation
= rRelations
.getRelationFromRelId( rRelId
) )
599 setExternalTargetUrl( pRelation
->maTarget
, pRelation
->maType
);
602 void ExternalLink::insertExternalSheet( const OUString
& rSheetName
)
604 OSL_ENSURE( !rSheetName
.isEmpty(), "ExternalLink::insertExternalSheet - empty sheet name" );
607 Reference
< XExternalSheetCache
> xSheetCache
= mxDocLink
->addSheetCache( rSheetName
, false );
608 sal_Int32 nCacheIdx
= xSheetCache
.is() ? xSheetCache
->getTokenIndex() : -1;
609 maSheetCaches
.push_back( nCacheIdx
);
613 ExternalNameRef
ExternalLink::createExternalName()
615 ExternalNameRef
xExtName( new ExternalName( *this ) );
616 maExtNames
.push_back( xExtName
);
620 RefSheetsModel::RefSheetsModel() :
627 void RefSheetsModel::readBiff12Data( SequenceInputStream
& rStrm
)
629 mnExtRefId
= rStrm
.readInt32();
630 mnTabId1
= rStrm
.readInt32();
631 mnTabId2
= rStrm
.readInt32();
634 ExternalLinkBuffer::ExternalLinkBuffer( const WorkbookHelper
& rHelper
) :
635 WorkbookHelper( rHelper
),
636 mxSelfRef( new ExternalLink( rHelper
) ),
637 mbUseRefSheets( false )
639 mxSelfRef
->setSelfLinkType();
642 ExternalLinkRef
ExternalLinkBuffer::importExternalReference( const AttributeList
& rAttribs
)
644 ExternalLinkRef xExtLink
= createExternalLink();
645 xExtLink
->importExternalReference( rAttribs
);
646 maExtLinks
.push_back( xExtLink
);
650 ExternalLinkRef
ExternalLinkBuffer::importExternalRef( SequenceInputStream
& rStrm
)
652 mbUseRefSheets
= true;
653 ExternalLinkRef xExtLink
= createExternalLink();
654 xExtLink
->importExternalRef( rStrm
);
655 maExtLinks
.push_back( xExtLink
);
659 void ExternalLinkBuffer::importExternalSelf( SequenceInputStream
& rStrm
)
661 mbUseRefSheets
= true;
662 createExternalLink()->importExternalSelf( rStrm
);
665 void ExternalLinkBuffer::importExternalSame( SequenceInputStream
& rStrm
)
667 mbUseRefSheets
= true;
668 createExternalLink()->importExternalSame( rStrm
);
671 void ExternalLinkBuffer::importExternalAddin( SequenceInputStream
& rStrm
)
673 mbUseRefSheets
= true;
674 createExternalLink()->importExternalAddin( rStrm
);
677 void ExternalLinkBuffer::importExternalSheets( SequenceInputStream
& rStrm
)
679 OSL_ENSURE( mbUseRefSheets
, "ExternalLinkBuffer::importExternalSheets - missing EXTERNALREFS records" );
680 mbUseRefSheets
= true;
681 OSL_ENSURE( maRefSheets
.empty(), "ExternalLinkBuffer::importExternalSheets - multiple EXTERNALSHEETS records" );
684 nRefCount
= rStrm
.readInt32();
685 size_t nMaxCount
= getLimitedValue
< size_t, sal_Int64
>( nRefCount
, 0, rStrm
.getRemaining() / 12 );
686 maRefSheets
.reserve( nMaxCount
);
687 for( size_t nRefId
= 0; !rStrm
.isEof() && (nRefId
< nMaxCount
); ++nRefId
)
689 RefSheetsModel aRefSheets
;
690 aRefSheets
.readBiff12Data( rStrm
);
691 maRefSheets
.push_back( aRefSheets
);
695 Sequence
< ExternalLinkInfo
> ExternalLinkBuffer::getLinkInfos() const
697 ::std::vector
< ExternalLinkInfo
> aLinkInfos
;
698 // XML formula parser also used in BIFF12 documents, e.g. replacement formulas in unsupported conditional formattings
699 OSL_ENSURE( getFilterType() == FILTER_OOXML
, "ExternalLinkBuffer::getLinkInfos - unexpected file format" );
700 // add entry for implicit index 0 (self reference to this document)
701 aLinkInfos
.push_back( mxSelfRef
->getLinkInfo() );
702 for( ExternalLinkVec::const_iterator aIt
= maExtLinks
.begin(), aEnd
= maExtLinks
.end(); aIt
!= aEnd
; ++aIt
)
703 aLinkInfos
.push_back( (*aIt
)->getLinkInfo() );
704 return ContainerHelper::vectorToSequence( aLinkInfos
);
707 ExternalLinkRef
ExternalLinkBuffer::getExternalLink( sal_Int32 nRefId
, bool bUseRefSheets
) const
709 ExternalLinkRef xExtLink
;
710 switch( getFilterType() )
713 // OOXML: 0 = this document, otherwise one-based index into link list
714 if( !bUseRefSheets
|| !mbUseRefSheets
)
715 xExtLink
= (nRefId
== 0) ? mxSelfRef
: maLinks
.get( nRefId
- 1 );
716 // BIFF12: zero-based index into ref-sheets list
717 else if( const RefSheetsModel
* pRefSheets
= getRefSheets( nRefId
) )
718 xExtLink
= maLinks
.get( pRefSheets
->mnExtRefId
);
726 // one-based index to EXTERNSHEET records
727 xExtLink
= maLinks
.get( nRefId
- 1 );
732 // internal links in formula tokens have negative index
733 xExtLink
= maLinks
.get( -nRefId
- 1 );
734 if( xExtLink
.get() && !xExtLink
->isInternalLink() )
739 // one-based index to EXTERNSHEET records
740 xExtLink
= maLinks
.get( nRefId
- 1 );
744 // zero-based index into REF list in EXTERNSHEET record
745 if( const RefSheetsModel
* pRefSheets
= getRefSheets( nRefId
) )
746 xExtLink
= maLinks
.get( pRefSheets
->mnExtRefId
);
748 case BIFF_UNKNOWN
: break;
751 case FILTER_UNKNOWN
: break;
756 LinkSheetRange
ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId
, sal_Int16 nTabId1
, sal_Int16 nTabId2
) const
758 OSL_ENSURE( getBiff() <= BIFF5
, "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
759 LinkSheetRange aSheetRange
;
760 if( const ExternalLink
* pExtLink
= getExternalLink( nRefId
).get() )
761 pExtLink
->getSheetRange( aSheetRange
, nTabId1
, nTabId2
);
765 LinkSheetRange
ExternalLinkBuffer::getSheetRange( sal_Int32 nRefId
) const
767 OSL_ENSURE( ((getFilterType() == FILTER_OOXML
) && mbUseRefSheets
) || (getBiff() == BIFF8
), "ExternalLinkBuffer::getSheetRange - wrong BIFF version" );
768 LinkSheetRange aSheetRange
;
769 if( const ExternalLink
* pExtLink
= getExternalLink( nRefId
).get() )
770 if( const RefSheetsModel
* pRefSheets
= getRefSheets( nRefId
) )
771 pExtLink
->getSheetRange( aSheetRange
, pRefSheets
->mnTabId1
, pRefSheets
->mnTabId2
);
775 // private --------------------------------------------------------------------
777 ExternalLinkRef
ExternalLinkBuffer::createExternalLink()
779 ExternalLinkRef
xExtLink( new ExternalLink( *this ) );
780 maLinks
.push_back( xExtLink
);
784 const RefSheetsModel
* ExternalLinkBuffer::getRefSheets( sal_Int32 nRefId
) const
786 return ((0 <= nRefId
) && (static_cast< size_t >( nRefId
) < maRefSheets
.size())) ?
787 &maRefSheets
[ static_cast< size_t >( nRefId
) ] : nullptr;
793 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */