Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / filter / oox / externallinkbuffer.cxx
blob00defc2184be75dd3a1b531414684c4eb3ff294c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
47 namespace oox {
48 namespace xls {
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;
57 namespace {
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;
69 } // namespace
71 ExternalNameModel::ExternalNameModel() :
72 mbNotify( false ),
73 mbPreferPic( false ),
74 mbStdDocName( false ),
75 mbOleObj( false ),
76 mbIconified( 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 )
128 sal_uInt16 nFlags;
129 sal_Int32 nSheetId;
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 ) );
172 #if 0
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() )
179 case FILTER_OOXML:
180 // OOXML/BIFF12: zero-based index into sheet list, -1 means global name
181 if( maModel.mnSheet >= 0 )
182 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet );
183 break;
184 case FILTER_BIFF:
185 switch( getBiff() )
187 case BIFF2:
188 case BIFF3:
189 case BIFF4:
190 break;
191 case BIFF5:
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();
196 break;
197 case BIFF8:
198 if( maModel.mnSheet > 0 )
199 nCacheIdx = mrParentLink.getSheetIndex( maModel.mnSheet - 1 );
200 break;
201 case BIFF_UNKNOWN:
202 break;
204 break;
205 case FILTER_UNKNOWN:
206 break;
208 return nCacheIdx;
210 #endif
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 );
218 return true;
220 return false;
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 ) );
240 catch( Exception& )
242 OSL_FAIL( "ExternalName::getDdeLinkData - cannot create DDE link" );
244 // get link data from created DDE link
245 if( mxDdeLink.is() )
247 orDdeServer = mxDdeLink->getApplication();
248 orDdeTopic = mxDdeLink->getTopic();
249 orDdeItem = mxDdeLink->getItem();
250 return true;
253 return false;
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 ) ) );
266 else
267 maResults.clear();
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;
280 mnDocLink = -1;
281 mnFirst = mnLast = 0;
284 void LinkSheetRange::setRange( sal_Int32 nFirst, sal_Int32 nLast )
286 meType = LINKSHEETRANGE_INTERNAL;
287 mnDocLink = -1;
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 )
294 if( nDocLink < 0 )
296 setDeleted();
298 else
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 );
345 return xExtName;
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 );
359 return xExtName;
362 void ExternalLink::importExternalRef( SequenceInputStream& rStrm )
364 rStrm >> maRelId;
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 ) );
388 break;
389 case BIFF12_EXTERNALBOOK_DDE:
391 OUString aDdeService, aDdeTopic;
392 rStrm >> aDdeService >> aDdeTopic;
393 setDdeOleTargetUrl( aDdeService, aDdeTopic, LINKTYPE_DDE );
395 break;
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 );
402 break;
403 default:
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 );
422 return xExtName;
425 ExternalLinkInfo ExternalLink::getLinkInfo() const
427 ExternalLinkInfo aLinkInfo;
428 switch( meLinkType )
430 case LINKTYPE_SELF:
431 case LINKTYPE_SAME:
432 case LINKTYPE_INTERNAL:
433 aLinkInfo.Type = css::sheet::ExternalLinkType::SELF;
434 break;
435 case LINKTYPE_EXTERNAL:
436 aLinkInfo.Type = css::sheet::ExternalLinkType::DOCUMENT;
437 aLinkInfo.Data <<= maTargetUrl;
438 break;
439 case LINKTYPE_LIBRARY:
440 // parser will return library function names in OPCODE_BAD string tokens
441 aLinkInfo.Type = css::sheet::ExternalLinkType::SPECIAL;
442 break;
443 case LINKTYPE_DDE:
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;
457 break;
458 default:
459 aLinkInfo.Type = css::sheet::ExternalLinkType::UNKNOWN;
461 return aLinkInfo;
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 );
490 return xSheetCache;
492 catch( Exception& )
495 return nullptr;
498 void ExternalLink::getSheetRange( LinkSheetRange& orSheetRange, sal_Int32 nTabId1, sal_Int32 nTabId2 ) const
500 switch( meLinkType )
502 case LINKTYPE_SAME:
503 orSheetRange.setSameSheet();
504 break;
506 case LINKTYPE_SELF:
507 case LINKTYPE_INTERNAL:
508 orSheetRange.setRange( nTabId1, nTabId2 );
509 break;
511 case LINKTYPE_EXTERNAL:
513 sal_Int32 nDocLinkIdx = getDocumentLinkIndex();
514 switch( getFilterType() )
516 case FILTER_OOXML:
517 // BIFF12: passed indexes point into sheet list of EXTSHEETLIST
518 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
519 break;
520 case FILTER_BIFF:
521 switch( getBiff() )
523 case BIFF2:
524 case BIFF3:
525 case BIFF4:
526 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
527 break;
528 case BIFF5:
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() );
533 break;
534 case BIFF8:
535 // BIFF8: passed indexes point into sheet list of EXTERNALBOOK
536 orSheetRange.setExternalRange( nDocLinkIdx, getSheetCacheIndex( nTabId1 ), getSheetCacheIndex( nTabId2 ) );
537 break;
538 case BIFF_UNKNOWN: break;
540 break;
541 case FILTER_UNKNOWN: break;
544 break;
546 default:
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 );
583 catch( Exception& )
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" );
605 if( mxDocLink.is() )
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 );
617 return xExtName;
620 RefSheetsModel::RefSheetsModel() :
621 mnExtRefId( -1 ),
622 mnTabId1( -1 ),
623 mnTabId2( -1 )
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 );
647 return xExtLink;
650 ExternalLinkRef ExternalLinkBuffer::importExternalRef( SequenceInputStream& rStrm )
652 mbUseRefSheets = true;
653 ExternalLinkRef xExtLink = createExternalLink();
654 xExtLink->importExternalRef( rStrm );
655 maExtLinks.push_back( xExtLink );
656 return 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" );
682 maRefSheets.clear();
683 sal_Int32 nRefCount;
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() )
712 case FILTER_OOXML:
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 );
719 break;
720 case FILTER_BIFF:
721 switch( getBiff() )
723 case BIFF2:
724 case BIFF3:
725 case BIFF4:
726 // one-based index to EXTERNSHEET records
727 xExtLink = maLinks.get( nRefId - 1 );
728 break;
729 case BIFF5:
730 if( nRefId < 0 )
732 // internal links in formula tokens have negative index
733 xExtLink = maLinks.get( -nRefId - 1 );
734 if( xExtLink.get() && !xExtLink->isInternalLink() )
735 xExtLink.reset();
737 else
739 // one-based index to EXTERNSHEET records
740 xExtLink = maLinks.get( nRefId - 1 );
742 break;
743 case BIFF8:
744 // zero-based index into REF list in EXTERNSHEET record
745 if( const RefSheetsModel* pRefSheets = getRefSheets( nRefId ) )
746 xExtLink = maLinks.get( pRefSheets->mnExtRefId );
747 break;
748 case BIFF_UNKNOWN: break;
750 break;
751 case FILTER_UNKNOWN: break;
753 return xExtLink;
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 );
762 return aSheetRange;
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 );
772 return aSheetRange;
775 // private --------------------------------------------------------------------
777 ExternalLinkRef ExternalLinkBuffer::createExternalLink()
779 ExternalLinkRef xExtLink( new ExternalLink( *this ) );
780 maLinks.push_back( xExtLink );
781 return 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;
790 } // namespace xls
791 } // namespace oox
793 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */